@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 +62 -33
- package/dist/THIRD_PARTY_LICENSES.txt +1 -1
- package/dist/agentcomputer.js +1053 -228
- package/dist/sdk.js +27 -7
- package/dist/types/generated/schema.d.ts +102 -9
- package/dist/types/sdk.d.ts +14 -1
- package/package.json +5 -2
package/dist/agentcomputer.js
CHANGED
|
@@ -3752,7 +3752,7 @@ var require_websocket_server = __commonJS({
|
|
|
3752
3752
|
|
|
3753
3753
|
// src/main.ts
|
|
3754
3754
|
import { homedir as homedir2 } from "node:os";
|
|
3755
|
-
import { isAbsolute as
|
|
3755
|
+
import { isAbsolute as isAbsolute3, join as join11, resolve as resolve5 } from "node:path";
|
|
3756
3756
|
import { parseArgs } from "node:util";
|
|
3757
3757
|
import { isMainThread as isMainThread2 } from "node:worker_threads";
|
|
3758
3758
|
|
|
@@ -3767,9 +3767,11 @@ var playwright = () => {
|
|
|
3767
3767
|
loaded ??= createRequire(import.meta.url)("playwright-core");
|
|
3768
3768
|
return loaded;
|
|
3769
3769
|
};
|
|
3770
|
+
var DEFAULT_CHANNEL = "chrome";
|
|
3771
|
+
var channelProgram = (channel) => createRequire(import.meta.url)("playwright-core/lib/coreBundle").registry.registry.findExecutable(channel)?.executablePath("javascript");
|
|
3770
3772
|
|
|
3771
3773
|
// src/browser-host.ts
|
|
3772
|
-
var sandboxFor = (options) => options.sandbox ?? (process.platform !== "linux" || !options.executable && !["chromium", "chrome-for-testing"].includes(options.channel ??
|
|
3774
|
+
var sandboxFor = (options) => options.sandbox ?? (process.platform !== "linux" || !options.executable && !["chromium", "chrome-for-testing"].includes(options.channel ?? DEFAULT_CHANNEL));
|
|
3773
3775
|
async function hostBrowser(options) {
|
|
3774
3776
|
const run3 = mkdtempSync(join("/tmp", "agentcomputer-"));
|
|
3775
3777
|
process.env.XDG_RUNTIME_DIR = run3;
|
|
@@ -3777,7 +3779,7 @@ async function hostBrowser(options) {
|
|
|
3777
3779
|
const context = await playwright().chromium.launchPersistentContext(options.profile, {
|
|
3778
3780
|
headless: true,
|
|
3779
3781
|
chromiumSandbox: sandboxFor(options),
|
|
3780
|
-
...options.executable ? { executablePath: options.executable } : { channel: options.channel ??
|
|
3782
|
+
...options.executable ? { executablePath: options.executable } : { channel: options.channel ?? DEFAULT_CHANNEL }
|
|
3781
3783
|
});
|
|
3782
3784
|
const browser = context.browser();
|
|
3783
3785
|
if (!browser) throw new Error("The browser can't be shared.");
|
|
@@ -18458,13 +18460,13 @@ var require_resolve = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
18458
18460
|
}
|
|
18459
18461
|
return count;
|
|
18460
18462
|
}
|
|
18461
|
-
function getFullPath(
|
|
18463
|
+
function getFullPath(resolver2, id = "", normalize) {
|
|
18462
18464
|
if (normalize !== false) id = normalizeId(id);
|
|
18463
|
-
return _getFullPath(
|
|
18465
|
+
return _getFullPath(resolver2, resolver2.parse(id));
|
|
18464
18466
|
}
|
|
18465
18467
|
exports.getFullPath = getFullPath;
|
|
18466
|
-
function _getFullPath(
|
|
18467
|
-
return
|
|
18468
|
+
function _getFullPath(resolver2, p) {
|
|
18469
|
+
return resolver2.serialize(p).split("#")[0] + "#";
|
|
18468
18470
|
}
|
|
18469
18471
|
exports._getFullPath = _getFullPath;
|
|
18470
18472
|
const TRAILING_SLASH_HASH = /#\/?$/;
|
|
@@ -18472,9 +18474,9 @@ var require_resolve = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
18472
18474
|
return id ? id.replace(TRAILING_SLASH_HASH, "") : "";
|
|
18473
18475
|
}
|
|
18474
18476
|
exports.normalizeId = normalizeId;
|
|
18475
|
-
function resolveUrl(
|
|
18477
|
+
function resolveUrl(resolver2, baseId, id) {
|
|
18476
18478
|
id = normalizeId(id);
|
|
18477
|
-
return
|
|
18479
|
+
return resolver2.resolve(baseId, id);
|
|
18478
18480
|
}
|
|
18479
18481
|
exports.resolveUrl = resolveUrl;
|
|
18480
18482
|
const ANCHOR = /^[a-z_][-a-z0-9._]*$/i;
|
|
@@ -18956,10 +18958,10 @@ var require_ref_error = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
18956
18958
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18957
18959
|
const resolve_1 = require_resolve();
|
|
18958
18960
|
var MissingRefError = class extends Error {
|
|
18959
|
-
constructor(
|
|
18961
|
+
constructor(resolver2, baseId, ref, msg) {
|
|
18960
18962
|
super(msg || `can't resolve reference ${ref} from id ${baseId}`);
|
|
18961
|
-
this.missingRef = (0, resolve_1.resolveUrl)(
|
|
18962
|
-
this.missingSchema = (0, resolve_1.normalizeId)((0, resolve_1.getFullPath)(
|
|
18963
|
+
this.missingRef = (0, resolve_1.resolveUrl)(resolver2, baseId, ref);
|
|
18964
|
+
this.missingSchema = (0, resolve_1.normalizeId)((0, resolve_1.getFullPath)(resolver2, this.missingRef));
|
|
18963
18965
|
}
|
|
18964
18966
|
};
|
|
18965
18967
|
exports.default = MissingRefError;
|
|
@@ -19203,10 +19205,10 @@ var require_utils = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
19203
19205
|
const HEX_DIGITS = "0123456789ABCDEF";
|
|
19204
19206
|
for (let i = 0; i < 256; i++) BYTE_HEX[i] = "%" + HEX_DIGITS[i >> 4] + HEX_DIGITS[i & 15];
|
|
19205
19207
|
}
|
|
19206
|
-
function percentEncodeNonAscii(
|
|
19207
|
-
if (
|
|
19208
|
-
if (
|
|
19209
|
-
return BYTE_HEX[240 |
|
|
19208
|
+
function percentEncodeNonAscii(cp2) {
|
|
19209
|
+
if (cp2 < 2048) return BYTE_HEX[192 | cp2 >> 6] + BYTE_HEX[128 | cp2 & 63];
|
|
19210
|
+
if (cp2 < 65536) return BYTE_HEX[224 | cp2 >> 12] + BYTE_HEX[128 | cp2 >> 6 & 63] + BYTE_HEX[128 | cp2 & 63];
|
|
19211
|
+
return BYTE_HEX[240 | cp2 >> 18] + BYTE_HEX[128 | cp2 >> 12 & 63] + BYTE_HEX[128 | cp2 >> 6 & 63] + BYTE_HEX[128 | cp2 & 63];
|
|
19210
19212
|
}
|
|
19211
19213
|
function stringArrayToHexStripped(input2) {
|
|
19212
19214
|
let acc = "";
|
|
@@ -19546,8 +19548,8 @@ var require_utils = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
19546
19548
|
function encodeFragment(input2) {
|
|
19547
19549
|
return encodeComponent(input2, isQueryFragmentCharacter);
|
|
19548
19550
|
}
|
|
19549
|
-
function isEscapeSafe(
|
|
19550
|
-
return
|
|
19551
|
+
function isEscapeSafe(cp2) {
|
|
19552
|
+
return cp2 >= 48 && cp2 <= 57 || cp2 >= 65 && cp2 <= 90 || cp2 >= 97 && cp2 <= 122 || cp2 === 42 || cp2 === 43 || cp2 === 45 || cp2 === 46 || cp2 === 47 || cp2 === 64 || cp2 === 95;
|
|
19551
19553
|
}
|
|
19552
19554
|
function normalizeQueryFragmentEncoding(input2) {
|
|
19553
19555
|
let output2 = "";
|
|
@@ -28109,7 +28111,7 @@ var Browser = class {
|
|
|
28109
28111
|
"browser-host",
|
|
28110
28112
|
"--profile",
|
|
28111
28113
|
join3(folder, "profile"),
|
|
28112
|
-
...config3.path ? ["--executable", config3.path] : ["--channel", config3.browser ??
|
|
28114
|
+
...config3.path ? ["--executable", config3.path] : ["--channel", config3.browser ?? DEFAULT_CHANNEL],
|
|
28113
28115
|
...config3.sandbox === false ? ["--no-sandbox"] : []
|
|
28114
28116
|
],
|
|
28115
28117
|
{ stdio: ["ignore", "pipe", "pipe"] }
|
|
@@ -28293,7 +28295,7 @@ import { spawn as spawn2 } from "node:child_process";
|
|
|
28293
28295
|
import { randomBytes } from "node:crypto";
|
|
28294
28296
|
import { StringDecoder } from "node:string_decoder";
|
|
28295
28297
|
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
28296
|
-
import { join as join22, relative, resolve as resolve2, sep as sep22 } from "node:path";
|
|
28298
|
+
import { isAbsolute, join as join22, relative, resolve as resolve2, sep as sep22 } from "node:path";
|
|
28297
28299
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
28298
28300
|
import { isMainThread, parentPort, Worker, workerData } from "node:worker_threads";
|
|
28299
28301
|
var __create3 = Object.create;
|
|
@@ -56252,13 +56254,13 @@ var require_resolve2 = /* @__PURE__ */ __commonJSMin2(((exports) => {
|
|
|
56252
56254
|
}
|
|
56253
56255
|
return count;
|
|
56254
56256
|
}
|
|
56255
|
-
function getFullPath(
|
|
56257
|
+
function getFullPath(resolver2, id = "", normalize) {
|
|
56256
56258
|
if (normalize !== false) id = normalizeId(id);
|
|
56257
|
-
return _getFullPath(
|
|
56259
|
+
return _getFullPath(resolver2, resolver2.parse(id));
|
|
56258
56260
|
}
|
|
56259
56261
|
exports.getFullPath = getFullPath;
|
|
56260
|
-
function _getFullPath(
|
|
56261
|
-
return
|
|
56262
|
+
function _getFullPath(resolver2, p) {
|
|
56263
|
+
return resolver2.serialize(p).split("#")[0] + "#";
|
|
56262
56264
|
}
|
|
56263
56265
|
exports._getFullPath = _getFullPath;
|
|
56264
56266
|
const TRAILING_SLASH_HASH = /#\/?$/;
|
|
@@ -56266,9 +56268,9 @@ var require_resolve2 = /* @__PURE__ */ __commonJSMin2(((exports) => {
|
|
|
56266
56268
|
return id ? id.replace(TRAILING_SLASH_HASH, "") : "";
|
|
56267
56269
|
}
|
|
56268
56270
|
exports.normalizeId = normalizeId;
|
|
56269
|
-
function resolveUrl(
|
|
56271
|
+
function resolveUrl(resolver2, baseId, id) {
|
|
56270
56272
|
id = normalizeId(id);
|
|
56271
|
-
return
|
|
56273
|
+
return resolver2.resolve(baseId, id);
|
|
56272
56274
|
}
|
|
56273
56275
|
exports.resolveUrl = resolveUrl;
|
|
56274
56276
|
const ANCHOR = /^[a-z_][-a-z0-9._]*$/i;
|
|
@@ -56750,10 +56752,10 @@ var require_ref_error2 = /* @__PURE__ */ __commonJSMin2(((exports) => {
|
|
|
56750
56752
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
56751
56753
|
const resolve_1 = require_resolve2();
|
|
56752
56754
|
var MissingRefError = class extends Error {
|
|
56753
|
-
constructor(
|
|
56755
|
+
constructor(resolver2, baseId, ref, msg) {
|
|
56754
56756
|
super(msg || `can't resolve reference ${ref} from id ${baseId}`);
|
|
56755
|
-
this.missingRef = (0, resolve_1.resolveUrl)(
|
|
56756
|
-
this.missingSchema = (0, resolve_1.normalizeId)((0, resolve_1.getFullPath)(
|
|
56757
|
+
this.missingRef = (0, resolve_1.resolveUrl)(resolver2, baseId, ref);
|
|
56758
|
+
this.missingSchema = (0, resolve_1.normalizeId)((0, resolve_1.getFullPath)(resolver2, this.missingRef));
|
|
56757
56759
|
}
|
|
56758
56760
|
};
|
|
56759
56761
|
exports.default = MissingRefError;
|
|
@@ -56997,10 +56999,10 @@ var require_utils2 = /* @__PURE__ */ __commonJSMin2(((exports, module) => {
|
|
|
56997
56999
|
const HEX_DIGITS = "0123456789ABCDEF";
|
|
56998
57000
|
for (let i = 0; i < 256; i++) BYTE_HEX[i] = "%" + HEX_DIGITS[i >> 4] + HEX_DIGITS[i & 15];
|
|
56999
57001
|
}
|
|
57000
|
-
function percentEncodeNonAscii(
|
|
57001
|
-
if (
|
|
57002
|
-
if (
|
|
57003
|
-
return BYTE_HEX[240 |
|
|
57002
|
+
function percentEncodeNonAscii(cp2) {
|
|
57003
|
+
if (cp2 < 2048) return BYTE_HEX[192 | cp2 >> 6] + BYTE_HEX[128 | cp2 & 63];
|
|
57004
|
+
if (cp2 < 65536) return BYTE_HEX[224 | cp2 >> 12] + BYTE_HEX[128 | cp2 >> 6 & 63] + BYTE_HEX[128 | cp2 & 63];
|
|
57005
|
+
return BYTE_HEX[240 | cp2 >> 18] + BYTE_HEX[128 | cp2 >> 12 & 63] + BYTE_HEX[128 | cp2 >> 6 & 63] + BYTE_HEX[128 | cp2 & 63];
|
|
57004
57006
|
}
|
|
57005
57007
|
function stringArrayToHexStripped(input2) {
|
|
57006
57008
|
let acc = "";
|
|
@@ -57340,8 +57342,8 @@ var require_utils2 = /* @__PURE__ */ __commonJSMin2(((exports, module) => {
|
|
|
57340
57342
|
function encodeFragment(input2) {
|
|
57341
57343
|
return encodeComponent(input2, isQueryFragmentCharacter);
|
|
57342
57344
|
}
|
|
57343
|
-
function isEscapeSafe(
|
|
57344
|
-
return
|
|
57345
|
+
function isEscapeSafe(cp2) {
|
|
57346
|
+
return cp2 >= 48 && cp2 <= 57 || cp2 >= 65 && cp2 <= 90 || cp2 >= 97 && cp2 <= 122 || cp2 === 42 || cp2 === 43 || cp2 === 45 || cp2 === 46 || cp2 === 47 || cp2 === 64 || cp2 === 95;
|
|
57345
57347
|
}
|
|
57346
57348
|
function normalizeQueryFragmentEncoding(input2) {
|
|
57347
57349
|
let output2 = "";
|
|
@@ -63489,8 +63491,8 @@ var WebStandardStreamableHTTPServerTransport = class {
|
|
|
63489
63491
|
return timer;
|
|
63490
63492
|
}
|
|
63491
63493
|
/** Sets the scope challenge resolver for parsed JSON-RPC requests. */
|
|
63492
|
-
setScopeChallengeResolver(
|
|
63493
|
-
this._scopeChallengeResolver =
|
|
63494
|
+
setScopeChallengeResolver(resolver2) {
|
|
63495
|
+
this._scopeChallengeResolver = resolver2;
|
|
63494
63496
|
}
|
|
63495
63497
|
/**
|
|
63496
63498
|
* Starts the transport. This is required by the {@linkcode Transport} interface but is a no-op
|
|
@@ -65373,8 +65375,8 @@ var NodeStreamableHTTPServerTransport = class {
|
|
|
65373
65375
|
this._webStandardTransport.setSupportedProtocolVersions(versions);
|
|
65374
65376
|
}
|
|
65375
65377
|
/** Sets the scope challenge resolver used by the wrapped Web Standard transport. */
|
|
65376
|
-
setScopeChallengeResolver(
|
|
65377
|
-
this._webStandardTransport.setScopeChallengeResolver(
|
|
65378
|
+
setScopeChallengeResolver(resolver2) {
|
|
65379
|
+
this._webStandardTransport.setScopeChallengeResolver(resolver2);
|
|
65378
65380
|
}
|
|
65379
65381
|
/**
|
|
65380
65382
|
* Handles an incoming HTTP request, whether `GET` or `POST`.
|
|
@@ -66307,28 +66309,33 @@ var refusing = async (work) => {
|
|
|
66307
66309
|
}
|
|
66308
66310
|
};
|
|
66309
66311
|
var foldersFirst = (a, b) => Number(b.isDirectory()) - Number(a.isDirectory()) || a.name.localeCompare(b.name);
|
|
66310
|
-
|
|
66311
|
-
const
|
|
66312
|
-
|
|
66313
|
-
|
|
66314
|
-
|
|
66315
|
-
|
|
66316
|
-
|
|
66317
|
-
|
|
66318
|
-
if (code !== "ENOENT" && code !== "ENOTDIR") throw error62;
|
|
66319
|
-
if (await lstat(at).then(
|
|
66320
|
-
() => true,
|
|
66321
|
-
() => false
|
|
66322
|
-
))
|
|
66323
|
-
throw refused2();
|
|
66324
|
-
const above = dirname3(at);
|
|
66325
|
-
if (above === at) throw refused2();
|
|
66326
|
-
return join4(await real(above), basename(at));
|
|
66327
|
-
}
|
|
66328
|
-
};
|
|
66329
|
-
const found = await real(wanted);
|
|
66330
|
-
if (found !== root && !found.startsWith(root + sep2)) throw refused2();
|
|
66312
|
+
var resolver = (root, reach) => async (path) => {
|
|
66313
|
+
const found = await real(resolve(root, path));
|
|
66314
|
+
if (reach === "machine") {
|
|
66315
|
+
if (found === void 0) throw new ExecRefused(`${path} is a link to nothing.`);
|
|
66316
|
+
return found;
|
|
66317
|
+
}
|
|
66318
|
+
if (found === void 0 || found !== root && !found.startsWith(root + sep2))
|
|
66319
|
+
throw new ExecRefused(`${path} is outside the workspace.`);
|
|
66331
66320
|
return found;
|
|
66321
|
+
};
|
|
66322
|
+
var inside = (root, path) => resolver(root, "workspace")(path);
|
|
66323
|
+
async function real(at) {
|
|
66324
|
+
try {
|
|
66325
|
+
return await realpath(at);
|
|
66326
|
+
} catch (error62) {
|
|
66327
|
+
const { code } = error62;
|
|
66328
|
+
if (code !== "ENOENT" && code !== "ENOTDIR") throw error62;
|
|
66329
|
+
if (await lstat(at).then(
|
|
66330
|
+
() => true,
|
|
66331
|
+
() => false
|
|
66332
|
+
))
|
|
66333
|
+
return void 0;
|
|
66334
|
+
const above = dirname3(at);
|
|
66335
|
+
if (above === at) return void 0;
|
|
66336
|
+
const placed = await real(above);
|
|
66337
|
+
return placed === void 0 ? void 0 : join4(placed, basename(at));
|
|
66338
|
+
}
|
|
66332
66339
|
}
|
|
66333
66340
|
async function aFile(path, given) {
|
|
66334
66341
|
const found = await stat(path);
|
|
@@ -66336,8 +66343,7 @@ async function aFile(path, given) {
|
|
|
66336
66343
|
if (!found.isFile()) throw new ExecRefused(`${given} isn't a file that can be read.`);
|
|
66337
66344
|
return found;
|
|
66338
66345
|
}
|
|
66339
|
-
function createFiles(
|
|
66340
|
-
const at = (path) => inside(root, path);
|
|
66346
|
+
function createFiles(at) {
|
|
66341
66347
|
const text22 = async (path, given) => {
|
|
66342
66348
|
await aFile(path, given);
|
|
66343
66349
|
const bytes = await readFile(path);
|
|
@@ -66462,7 +66468,10 @@ function searched(job) {
|
|
|
66462
66468
|
const matcher = new RegExp(pattern, job.ignore_case ? "i" : "");
|
|
66463
66469
|
const limit = job.limit ?? DEFAULT_MATCHES;
|
|
66464
66470
|
const out = [];
|
|
66465
|
-
const name = (path) =>
|
|
66471
|
+
const name = (path) => {
|
|
66472
|
+
const from = relative(job.root, path);
|
|
66473
|
+
return from === ".." || from.startsWith(`..${sep22}`) || isAbsolute(from) ? path : from || path;
|
|
66474
|
+
};
|
|
66466
66475
|
const scan = (file2) => {
|
|
66467
66476
|
const found = statSync(file2);
|
|
66468
66477
|
if (!found.isFile() || found.size > MAX_FILE_BYTES) return;
|
|
@@ -66526,8 +66535,8 @@ function onThread(job, what) {
|
|
|
66526
66535
|
});
|
|
66527
66536
|
});
|
|
66528
66537
|
}
|
|
66529
|
-
async function search(root, input2) {
|
|
66530
|
-
const path = await
|
|
66538
|
+
async function search(root, at, input2) {
|
|
66539
|
+
const path = await at(input2.path ?? ".");
|
|
66531
66540
|
return onThread({ ...input2, path, root, agentexecSearch: true }, "That search");
|
|
66532
66541
|
}
|
|
66533
66542
|
function changedSince(root, since) {
|
|
@@ -66565,9 +66574,9 @@ function createHostFiles(root, level) {
|
|
|
66565
66574
|
read: (path, offset, length) => refusing(async () => {
|
|
66566
66575
|
if (!Number.isSafeInteger(offset) || offset < 0 || !Number.isSafeInteger(length) || length < 1 || length > MAX_READ_BYTES)
|
|
66567
66576
|
throw new ExecRefused("A read starts at 0 or later and takes 1 to 1,048,576 bytes.");
|
|
66568
|
-
const
|
|
66569
|
-
const found = await aFile(
|
|
66570
|
-
const file2 = await open3(
|
|
66577
|
+
const real2 = await inside(root, path);
|
|
66578
|
+
const found = await aFile(real2, path);
|
|
66579
|
+
const file2 = await open3(real2, "r");
|
|
66571
66580
|
try {
|
|
66572
66581
|
const bytes = Buffer.alloc(Math.max(0, Math.min(length, found.size - offset)));
|
|
66573
66582
|
const { bytesRead } = await file2.read(bytes, 0, bytes.length, offset);
|
|
@@ -66708,9 +66717,12 @@ var TOOLS = [
|
|
|
66708
66717
|
"search",
|
|
66709
66718
|
"edit"
|
|
66710
66719
|
];
|
|
66711
|
-
function createServer2(root, sessions, version22, level, extraTools = []) {
|
|
66720
|
+
function createServer2(root, sessions, version22, level, extraTools = [], reach = "workspace") {
|
|
66712
66721
|
const server = new McpServer({ name: "agentexec", version: version22 });
|
|
66713
|
-
const
|
|
66722
|
+
const at = resolver(root, reach);
|
|
66723
|
+
const files = createFiles(at);
|
|
66724
|
+
const where = reach === "machine" ? "Relative to the workspace, or absolute, anywhere on the machine." : "Inside the workspace; relative to it, or absolute.";
|
|
66725
|
+
const orWorkspace = `${where} The workspace by default.`;
|
|
66714
66726
|
for (const { name, description, readOnly, call } of extraTools)
|
|
66715
66727
|
server.registerTool(
|
|
66716
66728
|
name,
|
|
@@ -66789,7 +66801,7 @@ function createServer2(root, sessions, version22, level, extraTools = []) {
|
|
|
66789
66801
|
{
|
|
66790
66802
|
description: "Reads a text file as numbered lines, or shows a PNG, JPEG, GIF or WebP of up to 3 MiB as an image; offset and limit are for text.",
|
|
66791
66803
|
inputSchema: {
|
|
66792
|
-
path: external_exports.string().min(1).describe(
|
|
66804
|
+
path: external_exports.string().min(1).describe(where),
|
|
66793
66805
|
offset: external_exports.number().int().positive().optional().describe("The first line, from 1."),
|
|
66794
66806
|
limit: external_exports.number().int().positive().optional().describe("How many lines; 2000 by default.")
|
|
66795
66807
|
},
|
|
@@ -66808,7 +66820,7 @@ function createServer2(root, sessions, version22, level, extraTools = []) {
|
|
|
66808
66820
|
"list",
|
|
66809
66821
|
{
|
|
66810
66822
|
description: "Lists a folder: folders end in /, and files give their size in bytes.",
|
|
66811
|
-
inputSchema: { path: external_exports.string().optional().describe(
|
|
66823
|
+
inputSchema: { path: external_exports.string().optional().describe(orWorkspace) },
|
|
66812
66824
|
annotations: READ_ONLY
|
|
66813
66825
|
},
|
|
66814
66826
|
(input2) => saying(() => files.list(input2))
|
|
@@ -66816,17 +66828,17 @@ function createServer2(root, sessions, version22, level, extraTools = []) {
|
|
|
66816
66828
|
server.registerTool(
|
|
66817
66829
|
"search",
|
|
66818
66830
|
{
|
|
66819
|
-
description:
|
|
66831
|
+
description: `Searches text files under a folder, as path:line:text, the path from the workspace${reach === "machine" ? ", or whole for a file outside it" : ""}. Skips what .gitignore ignores, .git and node_modules.`,
|
|
66820
66832
|
inputSchema: {
|
|
66821
66833
|
pattern: external_exports.string().min(1).describe("Exact text, or a regular expression with regex."),
|
|
66822
|
-
path: external_exports.string().optional().describe(
|
|
66834
|
+
path: external_exports.string().optional().describe(`A folder or file. ${orWorkspace}`),
|
|
66823
66835
|
regex: external_exports.boolean().optional(),
|
|
66824
66836
|
ignore_case: external_exports.boolean().optional(),
|
|
66825
66837
|
limit: external_exports.number().int().positive().optional().describe("Most matches; 200 by default.")
|
|
66826
66838
|
},
|
|
66827
66839
|
annotations: READ_ONLY
|
|
66828
66840
|
},
|
|
66829
|
-
(input2) => saying(() => search(root, input2))
|
|
66841
|
+
(input2) => saying(() => search(root, at, input2))
|
|
66830
66842
|
);
|
|
66831
66843
|
if (level !== "read")
|
|
66832
66844
|
server.registerTool(
|
|
@@ -66834,7 +66846,7 @@ function createServer2(root, sessions, version22, level, extraTools = []) {
|
|
|
66834
66846
|
{
|
|
66835
66847
|
description: "Replaces exact text in a file and answers with a unified diff. old_text must appear exactly once unless replace_all. An empty old_text creates a new file.",
|
|
66836
66848
|
inputSchema: {
|
|
66837
|
-
path: external_exports.string().min(1).describe(
|
|
66849
|
+
path: external_exports.string().min(1).describe(where),
|
|
66838
66850
|
old_text: external_exports.string().describe("The exact text to replace, whitespace included."),
|
|
66839
66851
|
new_text: external_exports.string().describe("What to put in its place."),
|
|
66840
66852
|
replace_all: external_exports.boolean().optional()
|
|
@@ -66845,7 +66857,7 @@ function createServer2(root, sessions, version22, level, extraTools = []) {
|
|
|
66845
66857
|
);
|
|
66846
66858
|
return server;
|
|
66847
66859
|
}
|
|
66848
|
-
var VERSION = "0.0.
|
|
66860
|
+
var VERSION = "0.0.9";
|
|
66849
66861
|
function createAgentExec(options) {
|
|
66850
66862
|
const root = realpathSync(resolve3(options.workspace));
|
|
66851
66863
|
const level = options.level ?? "read";
|
|
@@ -66870,7 +66882,7 @@ function createAgentExec(options) {
|
|
|
66870
66882
|
}
|
|
66871
66883
|
return {
|
|
66872
66884
|
async handle(request, response, body) {
|
|
66873
|
-
const server = createServer2(root, sessions, VERSION, level, extraTools);
|
|
66885
|
+
const server = createServer2(root, sessions, VERSION, level, extraTools, options.reach);
|
|
66874
66886
|
const transport = new NodeStreamableHTTPServerTransport({ sessionIdGenerator: void 0 });
|
|
66875
66887
|
response.once("close", () => {
|
|
66876
66888
|
void transport.close();
|
|
@@ -66922,7 +66934,11 @@ function aboutTool(facts, load) {
|
|
|
66922
66934
|
// In a container its commands find the folder somewhere else, so the row says both.
|
|
66923
66935
|
inside2 === outside ? { label: "Folder", value: outside, path: true } : { label: "Folder", value: `${outside} on the machine, mounted at ${inside2} in it` },
|
|
66924
66936
|
{ label: "Reaches", value: REACHES[facts.access] + (facts.browser ? ", Browser" : "") },
|
|
66925
|
-
facts.contained ? { label: "Isolation", value: "A container of its own" } : {
|
|
66937
|
+
facts.contained ? { label: "Isolation", value: "A container of its own" } : {
|
|
66938
|
+
label: "Isolation",
|
|
66939
|
+
value: "None: it acts as you, on the whole machine",
|
|
66940
|
+
caution: true
|
|
66941
|
+
}
|
|
66926
66942
|
];
|
|
66927
66943
|
const reading = await load.now();
|
|
66928
66944
|
if (reading)
|
|
@@ -67864,16 +67880,44 @@ var loadPty = () => {
|
|
|
67864
67880
|
})();
|
|
67865
67881
|
return pty;
|
|
67866
67882
|
};
|
|
67883
|
+
function browserProgram(config3) {
|
|
67884
|
+
const channel = config3.browser ?? DEFAULT_CHANNEL;
|
|
67885
|
+
let path;
|
|
67886
|
+
try {
|
|
67887
|
+
playwright();
|
|
67888
|
+
path = config3.path ?? channelProgram(channel);
|
|
67889
|
+
} catch {
|
|
67890
|
+
return { ready: false, reason: "Playwright isn't installed with this service." };
|
|
67891
|
+
}
|
|
67892
|
+
if (path && existsSync(path)) return { ready: true };
|
|
67893
|
+
return {
|
|
67894
|
+
ready: false,
|
|
67895
|
+
reason: config3.path ? `There's no browser at ${config3.path}. Start the service with a --browser-path that exists.` : `The browser ${channel} isn't installed on this machine. Install it, or start the service with --browser-name or --browser-path.`
|
|
67896
|
+
};
|
|
67897
|
+
}
|
|
67867
67898
|
var ProcessRuntime = class {
|
|
67868
67899
|
#config;
|
|
67869
67900
|
#contained;
|
|
67870
|
-
/**
|
|
67901
|
+
/**
|
|
67902
|
+
* Outside a container it is this computer, its files reaching the whole machine. `contained` is
|
|
67903
|
+
* for inside one, where the computer and its load are its own and its files stay in its
|
|
67904
|
+
* workspace.
|
|
67905
|
+
*/
|
|
67871
67906
|
constructor(config3, contained = false) {
|
|
67872
67907
|
this.#config = config3;
|
|
67873
67908
|
this.#contained = contained;
|
|
67874
67909
|
}
|
|
67875
|
-
async
|
|
67876
|
-
return
|
|
67910
|
+
async offer() {
|
|
67911
|
+
return {
|
|
67912
|
+
ready: true,
|
|
67913
|
+
capabilities: [
|
|
67914
|
+
{ capability: "about", ready: true },
|
|
67915
|
+
{ capability: "terminal", ready: true },
|
|
67916
|
+
{ capability: "files", ready: true },
|
|
67917
|
+
{ capability: "screen", ready: false, reason: "This service can't reach the screen yet." }
|
|
67918
|
+
],
|
|
67919
|
+
browsers: [{ kind: "headless", ...browserProgram(this.#config) }]
|
|
67920
|
+
};
|
|
67877
67921
|
}
|
|
67878
67922
|
async prepare() {
|
|
67879
67923
|
}
|
|
@@ -67899,6 +67943,7 @@ var ProcessRuntime = class {
|
|
|
67899
67943
|
exec = createAgentExec({
|
|
67900
67944
|
workspace,
|
|
67901
67945
|
level: spec.access,
|
|
67946
|
+
reach: this.#contained ? "workspace" : "machine",
|
|
67902
67947
|
pty: await loadPty(),
|
|
67903
67948
|
extraTools: [about]
|
|
67904
67949
|
});
|
|
@@ -67959,16 +68004,13 @@ var ProcessRuntime = class {
|
|
|
67959
68004
|
};
|
|
67960
68005
|
|
|
67961
68006
|
// src/handlers.ts
|
|
67962
|
-
var VERSION2 = "0.0.
|
|
68007
|
+
var VERSION2 = "0.0.19";
|
|
67963
68008
|
function createHandlers(computers) {
|
|
67964
68009
|
return {
|
|
67965
|
-
getInfo: async () => ({
|
|
67966
|
-
version: VERSION2,
|
|
67967
|
-
isolation: computers.isolation,
|
|
67968
|
-
isolationsAvailable: await computers.available()
|
|
67969
|
-
}),
|
|
68010
|
+
getInfo: async () => ({ version: VERSION2, ...await computers.offers() }),
|
|
67970
68011
|
listComputers: async ({ state }) => computers.list(state),
|
|
67971
68012
|
createComputer: (input2) => computers.create(input2),
|
|
68013
|
+
attachComputer: (input2) => computers.attach(input2),
|
|
67972
68014
|
getComputer: async ({ computerID }) => computers.get(computerID),
|
|
67973
68015
|
killComputer: async ({ computerID }) => {
|
|
67974
68016
|
await computers.kill(computerID);
|
|
@@ -68059,6 +68101,7 @@ async function serveInside(options) {
|
|
|
68059
68101
|
var run2 = promisify2(execFile2);
|
|
68060
68102
|
var START_MS2 = 6e4;
|
|
68061
68103
|
var STOP_SECONDS = "5";
|
|
68104
|
+
var NO_DOCKER = "A container needs Docker, which isn't answering on this machine.";
|
|
68062
68105
|
var NOT_FORWARDED = /* @__PURE__ */ new Set([
|
|
68063
68106
|
"authorization",
|
|
68064
68107
|
"connection",
|
|
@@ -68105,14 +68148,22 @@ var ContainerRuntime = class {
|
|
|
68105
68148
|
return false;
|
|
68106
68149
|
}
|
|
68107
68150
|
}
|
|
68108
|
-
//
|
|
68109
|
-
|
|
68110
|
-
|
|
68151
|
+
// Docker is asked for a second each time the service says what it offers, so that doesn't wait
|
|
68152
|
+
// on a Docker that hangs. Its image has its own browser.
|
|
68153
|
+
async offer() {
|
|
68154
|
+
return {
|
|
68155
|
+
...await this.#answers(1e3) ? { ready: true } : { ready: false, reason: NO_DOCKER },
|
|
68156
|
+
capabilities: [
|
|
68157
|
+
{ capability: "about", ready: true },
|
|
68158
|
+
{ capability: "terminal", ready: true },
|
|
68159
|
+
{ capability: "files", ready: true }
|
|
68160
|
+
],
|
|
68161
|
+
browsers: [{ kind: "headless", ready: true }]
|
|
68162
|
+
};
|
|
68111
68163
|
}
|
|
68112
68164
|
/** Docker, or the refusal of what can't be done without it. */
|
|
68113
68165
|
async #docker() {
|
|
68114
|
-
if (!await this.#answers(1e4))
|
|
68115
|
-
throw new ApiError(409, "A container needs Docker, which isn't answering on this machine.");
|
|
68166
|
+
if (!await this.#answers(1e4)) throw new ApiError(409, NO_DOCKER);
|
|
68116
68167
|
}
|
|
68117
68168
|
async prepare() {
|
|
68118
68169
|
await this.#docker();
|
|
@@ -68375,8 +68426,8 @@ async function running(data, said = recorded(data)) {
|
|
|
68375
68426
|
signal: AbortSignal.timeout(3e3)
|
|
68376
68427
|
});
|
|
68377
68428
|
if (!answer.ok) return void 0;
|
|
68378
|
-
const { version: version3
|
|
68379
|
-
return { url: said.url, pid: said.pid, version: version3
|
|
68429
|
+
const { version: version3 } = await answer.json();
|
|
68430
|
+
return { url: said.url, pid: said.pid, version: version3 };
|
|
68380
68431
|
} catch {
|
|
68381
68432
|
return void 0;
|
|
68382
68433
|
}
|
|
@@ -68912,6 +68963,19 @@ var ComputerError = class extends Error {
|
|
|
68912
68963
|
}
|
|
68913
68964
|
};
|
|
68914
68965
|
var seconds = (ms) => Math.max(1, Math.ceil(ms / 1e3));
|
|
68966
|
+
function requestOf(opts) {
|
|
68967
|
+
const { access, browser, name, timeoutMs, metadata, apiKey, apiUrl } = opts;
|
|
68968
|
+
return {
|
|
68969
|
+
connection: { ...apiKey ? { apiKey } : {}, ...apiUrl ? { apiUrl } : {} },
|
|
68970
|
+
body: {
|
|
68971
|
+
access,
|
|
68972
|
+
browser: browser ?? false,
|
|
68973
|
+
...name === void 0 ? {} : { name },
|
|
68974
|
+
...timeoutMs === void 0 ? {} : { timeout: seconds(timeoutMs) },
|
|
68975
|
+
...metadata === void 0 ? {} : { metadata }
|
|
68976
|
+
}
|
|
68977
|
+
};
|
|
68978
|
+
}
|
|
68915
68979
|
function apiOf(opts = {}) {
|
|
68916
68980
|
const apiKey = opts.apiKey ?? process.env.AGENTCOMPUTER_API_KEY;
|
|
68917
68981
|
if (!apiKey) throw new ComputerError(401, "Pass apiKey, or set AGENTCOMPUTER_API_KEY.");
|
|
@@ -69111,23 +69175,30 @@ var Computer = class _Computer {
|
|
|
69111
69175
|
this.files = new Files(this.#computer);
|
|
69112
69176
|
}
|
|
69113
69177
|
static async create(opts) {
|
|
69114
|
-
const {
|
|
69115
|
-
const
|
|
69178
|
+
const { isolation, workspace, copyFrom } = opts;
|
|
69179
|
+
const { connection, body } = requestOf(opts);
|
|
69116
69180
|
const created = answered(
|
|
69117
69181
|
await apiOf(connection).POST("/v1/computers", {
|
|
69118
69182
|
body: {
|
|
69119
|
-
|
|
69120
|
-
browser: browser ?? false,
|
|
69183
|
+
...body,
|
|
69121
69184
|
...isolation === void 0 ? {} : { isolation },
|
|
69122
69185
|
...workspace === void 0 ? {} : { workspace },
|
|
69123
|
-
...
|
|
69124
|
-
...timeoutMs === void 0 ? {} : { timeout: seconds(timeoutMs) },
|
|
69125
|
-
...metadata === void 0 ? {} : { metadata }
|
|
69186
|
+
...copyFrom === void 0 ? {} : { copyFrom }
|
|
69126
69187
|
}
|
|
69127
69188
|
})
|
|
69128
69189
|
);
|
|
69129
69190
|
return new _Computer(connection, created, created.accessToken);
|
|
69130
69191
|
}
|
|
69192
|
+
/** This computer, attached whole. Killing it detaches it and removes nothing of the machine's. */
|
|
69193
|
+
static async attach(opts) {
|
|
69194
|
+
const { connection, body } = requestOf(opts);
|
|
69195
|
+
const attached = answered(
|
|
69196
|
+
await apiOf(connection).POST("/v1/computers/attach", {
|
|
69197
|
+
body: { ...body, workspace: opts.workspace }
|
|
69198
|
+
})
|
|
69199
|
+
);
|
|
69200
|
+
return new _Computer(connection, attached, attached.accessToken);
|
|
69201
|
+
}
|
|
69131
69202
|
/** A computer made earlier. Its token was shown when it was made, and only then. */
|
|
69132
69203
|
static async connect(computerID, opts) {
|
|
69133
69204
|
const { accessToken, ...connection } = opts;
|
|
@@ -75860,13 +75931,13 @@ var require_resolve3 = /* @__PURE__ */ __commonJSMin3(((exports) => {
|
|
|
75860
75931
|
}
|
|
75861
75932
|
return count;
|
|
75862
75933
|
}
|
|
75863
|
-
function getFullPath(
|
|
75934
|
+
function getFullPath(resolver2, id = "", normalize) {
|
|
75864
75935
|
if (normalize !== false) id = normalizeId(id);
|
|
75865
|
-
return _getFullPath(
|
|
75936
|
+
return _getFullPath(resolver2, resolver2.parse(id));
|
|
75866
75937
|
}
|
|
75867
75938
|
exports.getFullPath = getFullPath;
|
|
75868
|
-
function _getFullPath(
|
|
75869
|
-
return
|
|
75939
|
+
function _getFullPath(resolver2, p) {
|
|
75940
|
+
return resolver2.serialize(p).split("#")[0] + "#";
|
|
75870
75941
|
}
|
|
75871
75942
|
exports._getFullPath = _getFullPath;
|
|
75872
75943
|
const TRAILING_SLASH_HASH = /#\/?$/;
|
|
@@ -75874,9 +75945,9 @@ var require_resolve3 = /* @__PURE__ */ __commonJSMin3(((exports) => {
|
|
|
75874
75945
|
return id ? id.replace(TRAILING_SLASH_HASH, "") : "";
|
|
75875
75946
|
}
|
|
75876
75947
|
exports.normalizeId = normalizeId;
|
|
75877
|
-
function resolveUrl(
|
|
75948
|
+
function resolveUrl(resolver2, baseId, id) {
|
|
75878
75949
|
id = normalizeId(id);
|
|
75879
|
-
return
|
|
75950
|
+
return resolver2.resolve(baseId, id);
|
|
75880
75951
|
}
|
|
75881
75952
|
exports.resolveUrl = resolveUrl;
|
|
75882
75953
|
const ANCHOR = /^[a-z_][-a-z0-9._]*$/i;
|
|
@@ -76358,10 +76429,10 @@ var require_ref_error3 = /* @__PURE__ */ __commonJSMin3(((exports) => {
|
|
|
76358
76429
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
76359
76430
|
const resolve_1 = require_resolve3();
|
|
76360
76431
|
var MissingRefError = class extends Error {
|
|
76361
|
-
constructor(
|
|
76432
|
+
constructor(resolver2, baseId, ref, msg) {
|
|
76362
76433
|
super(msg || `can't resolve reference ${ref} from id ${baseId}`);
|
|
76363
|
-
this.missingRef = (0, resolve_1.resolveUrl)(
|
|
76364
|
-
this.missingSchema = (0, resolve_1.normalizeId)((0, resolve_1.getFullPath)(
|
|
76434
|
+
this.missingRef = (0, resolve_1.resolveUrl)(resolver2, baseId, ref);
|
|
76435
|
+
this.missingSchema = (0, resolve_1.normalizeId)((0, resolve_1.getFullPath)(resolver2, this.missingRef));
|
|
76365
76436
|
}
|
|
76366
76437
|
};
|
|
76367
76438
|
exports.default = MissingRefError;
|
|
@@ -76605,10 +76676,10 @@ var require_utils3 = /* @__PURE__ */ __commonJSMin3(((exports, module) => {
|
|
|
76605
76676
|
const HEX_DIGITS = "0123456789ABCDEF";
|
|
76606
76677
|
for (let i = 0; i < 256; i++) BYTE_HEX[i] = "%" + HEX_DIGITS[i >> 4] + HEX_DIGITS[i & 15];
|
|
76607
76678
|
}
|
|
76608
|
-
function percentEncodeNonAscii(
|
|
76609
|
-
if (
|
|
76610
|
-
if (
|
|
76611
|
-
return BYTE_HEX[240 |
|
|
76679
|
+
function percentEncodeNonAscii(cp2) {
|
|
76680
|
+
if (cp2 < 2048) return BYTE_HEX[192 | cp2 >> 6] + BYTE_HEX[128 | cp2 & 63];
|
|
76681
|
+
if (cp2 < 65536) return BYTE_HEX[224 | cp2 >> 12] + BYTE_HEX[128 | cp2 >> 6 & 63] + BYTE_HEX[128 | cp2 & 63];
|
|
76682
|
+
return BYTE_HEX[240 | cp2 >> 18] + BYTE_HEX[128 | cp2 >> 12 & 63] + BYTE_HEX[128 | cp2 >> 6 & 63] + BYTE_HEX[128 | cp2 & 63];
|
|
76612
76683
|
}
|
|
76613
76684
|
function stringArrayToHexStripped(input2) {
|
|
76614
76685
|
let acc = "";
|
|
@@ -76948,8 +77019,8 @@ var require_utils3 = /* @__PURE__ */ __commonJSMin3(((exports, module) => {
|
|
|
76948
77019
|
function encodeFragment(input2) {
|
|
76949
77020
|
return encodeComponent(input2, isQueryFragmentCharacter);
|
|
76950
77021
|
}
|
|
76951
|
-
function isEscapeSafe(
|
|
76952
|
-
return
|
|
77022
|
+
function isEscapeSafe(cp2) {
|
|
77023
|
+
return cp2 >= 48 && cp2 <= 57 || cp2 >= 65 && cp2 <= 90 || cp2 >= 97 && cp2 <= 122 || cp2 === 42 || cp2 === 43 || cp2 === 45 || cp2 === 46 || cp2 === 47 || cp2 === 64 || cp2 === 95;
|
|
76953
77024
|
}
|
|
76954
77025
|
function normalizeQueryFragmentEncoding(input2) {
|
|
76955
77026
|
let output2 = "";
|
|
@@ -83101,8 +83172,8 @@ var WebStandardStreamableHTTPServerTransport2 = class {
|
|
|
83101
83172
|
return timer;
|
|
83102
83173
|
}
|
|
83103
83174
|
/** Sets the scope challenge resolver for parsed JSON-RPC requests. */
|
|
83104
|
-
setScopeChallengeResolver(
|
|
83105
|
-
this._scopeChallengeResolver =
|
|
83175
|
+
setScopeChallengeResolver(resolver2) {
|
|
83176
|
+
this._scopeChallengeResolver = resolver2;
|
|
83106
83177
|
}
|
|
83107
83178
|
/**
|
|
83108
83179
|
* Starts the transport. This is required by the {@linkcode Transport} interface but is a no-op
|
|
@@ -85002,8 +85073,8 @@ var NodeStreamableHTTPServerTransport2 = class {
|
|
|
85002
85073
|
this._webStandardTransport.setSupportedProtocolVersions(versions);
|
|
85003
85074
|
}
|
|
85004
85075
|
/** Sets the scope challenge resolver used by the wrapped Web Standard transport. */
|
|
85005
|
-
setScopeChallengeResolver(
|
|
85006
|
-
this._webStandardTransport.setScopeChallengeResolver(
|
|
85076
|
+
setScopeChallengeResolver(resolver2) {
|
|
85077
|
+
this._webStandardTransport.setScopeChallengeResolver(resolver2);
|
|
85007
85078
|
}
|
|
85008
85079
|
/**
|
|
85009
85080
|
* Handles an incoming HTTP request, whether `GET` or `POST`.
|
|
@@ -85043,8 +85114,19 @@ var NodeStreamableHTTPServerTransport2 = class {
|
|
|
85043
85114
|
|
|
85044
85115
|
// src/computers.ts
|
|
85045
85116
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
85046
|
-
import {
|
|
85047
|
-
|
|
85117
|
+
import {
|
|
85118
|
+
appendFileSync,
|
|
85119
|
+
chmodSync as chmodSync4,
|
|
85120
|
+
existsSync as existsSync2,
|
|
85121
|
+
mkdirSync as mkdirSync3,
|
|
85122
|
+
readdirSync as readdirSync2,
|
|
85123
|
+
readFileSync as readFileSync5,
|
|
85124
|
+
realpathSync as realpathSync2,
|
|
85125
|
+
rmSync as rmSync5,
|
|
85126
|
+
statSync as statSync4
|
|
85127
|
+
} from "node:fs";
|
|
85128
|
+
import { cp, lstat as lstat3 } from "node:fs/promises";
|
|
85129
|
+
import { isAbsolute as isAbsolute2, join as join10, resolve as resolve4 } from "node:path";
|
|
85048
85130
|
var READ = ["about", "read", "list", "search"];
|
|
85049
85131
|
var FILES = [...READ, "edit"];
|
|
85050
85132
|
var TOOLS2 = {
|
|
@@ -85057,32 +85139,59 @@ var MAX_TIMER_S = 2e6;
|
|
|
85057
85139
|
var TICKET_MS = 6e4;
|
|
85058
85140
|
var expiry = (seconds2) => new Date(Date.now() + seconds2 * 1e3).toISOString();
|
|
85059
85141
|
var messageOf2 = (error62) => error62 instanceof Error ? error62.message : String(error62);
|
|
85142
|
+
var noLongerMade = (stored) => "A computer with no isolation is no longer made. " + (stored.workspace ? `Its folder is kept at ${stored.workspace}. Attach this computer with that folder as its work folder, or make a container whose workspace starts as a copy of it.` : "Attach this computer, or make a container.");
|
|
85143
|
+
function removeFolder(path) {
|
|
85144
|
+
try {
|
|
85145
|
+
rmSync5(path, { recursive: true, force: true });
|
|
85146
|
+
} catch {
|
|
85147
|
+
const open5 = (at) => {
|
|
85148
|
+
chmodSync4(at, 448);
|
|
85149
|
+
for (const entry of readdirSync2(at, { withFileTypes: true }))
|
|
85150
|
+
if (entry.isDirectory()) open5(join10(at, entry.name));
|
|
85151
|
+
};
|
|
85152
|
+
open5(path);
|
|
85153
|
+
rmSync5(path, { recursive: true, force: true });
|
|
85154
|
+
}
|
|
85155
|
+
}
|
|
85156
|
+
function folderAt(path) {
|
|
85157
|
+
let folder = false;
|
|
85158
|
+
try {
|
|
85159
|
+
folder = isAbsolute2(path) && statSync4(path).isDirectory();
|
|
85160
|
+
} catch {
|
|
85161
|
+
}
|
|
85162
|
+
if (!folder) throw new ApiError(400, `There's no folder at ${path}.`);
|
|
85163
|
+
return resolve4(path);
|
|
85164
|
+
}
|
|
85060
85165
|
var refusalOf = (error62) => error62 instanceof ApiError ? error62 : new ApiError(500, messageOf2(error62));
|
|
85061
85166
|
var Computers = class {
|
|
85062
85167
|
#data;
|
|
85063
85168
|
#base;
|
|
85169
|
+
/** This computer's way of running, as `none`, and each way of making one. */
|
|
85064
85170
|
#runtimes;
|
|
85065
|
-
/**
|
|
85066
|
-
|
|
85171
|
+
/** Why this computer isn't offered here, where it isn't. */
|
|
85172
|
+
#notHere;
|
|
85067
85173
|
#stored = /* @__PURE__ */ new Map();
|
|
85068
85174
|
#live = /* @__PURE__ */ new Map();
|
|
85069
85175
|
#tickets = /* @__PURE__ */ new Map();
|
|
85070
85176
|
#file;
|
|
85071
|
-
constructor(data, base, runtimes,
|
|
85177
|
+
constructor(data, base, runtimes, notHere) {
|
|
85072
85178
|
this.#data = data;
|
|
85073
85179
|
this.#base = base;
|
|
85074
85180
|
this.#runtimes = runtimes;
|
|
85075
|
-
this
|
|
85181
|
+
this.#notHere = notHere;
|
|
85076
85182
|
this.#file = join10(data, "computers.json");
|
|
85077
85183
|
if (existsSync2(this.#file))
|
|
85078
85184
|
for (const entry of JSON.parse(readFileSync5(this.#file, "utf8")))
|
|
85079
|
-
this.#stored.set(entry.id, { ...entry, isolation: entry.isolation ??
|
|
85080
|
-
}
|
|
85081
|
-
/**
|
|
85082
|
-
async
|
|
85083
|
-
const
|
|
85084
|
-
const
|
|
85085
|
-
|
|
85185
|
+
this.#stored.set(entry.id, { ...entry, isolation: entry.isolation ?? "none" });
|
|
85186
|
+
}
|
|
85187
|
+
/** What it offers: this computer, and each kind it makes, with whether it can be now. */
|
|
85188
|
+
async offers() {
|
|
85189
|
+
const offered = await this.#runtimes.none.offer();
|
|
85190
|
+
const thisComputer = this.#notHere ? { ...offered, ready: false, reason: this.#notHere } : offered;
|
|
85191
|
+
const made = await Promise.all(
|
|
85192
|
+
Object.keys(this.#runtimes).filter((isolation) => isolation !== "none").map(async (isolation) => ({ isolation, ...await this.#runtimes[isolation].offer() }))
|
|
85193
|
+
);
|
|
85194
|
+
return { thisComputer, made };
|
|
85086
85195
|
}
|
|
85087
85196
|
/** Bring back what was running when the service last stopped. */
|
|
85088
85197
|
async resume() {
|
|
@@ -85105,20 +85214,34 @@ var Computers = class {
|
|
|
85105
85214
|
this.#save();
|
|
85106
85215
|
}
|
|
85107
85216
|
async create(input2) {
|
|
85217
|
+
if (input2.isolation === "none")
|
|
85218
|
+
throw new ApiError(
|
|
85219
|
+
400,
|
|
85220
|
+
"A computer with no isolation is no longer made. Attach this computer, or make a container."
|
|
85221
|
+
);
|
|
85222
|
+
return this.#make(input2, input2.isolation ?? "container");
|
|
85223
|
+
}
|
|
85224
|
+
/** This computer, attached with its work folder. Nothing is made for it. */
|
|
85225
|
+
attach(input2) {
|
|
85226
|
+
return this.#make(input2, "none");
|
|
85227
|
+
}
|
|
85228
|
+
async #make(input2, isolation) {
|
|
85108
85229
|
const { access, name, timeout, metadata } = input2;
|
|
85109
85230
|
const browser = input2.browser === true;
|
|
85110
85231
|
if (access === "none" && !browser)
|
|
85111
85232
|
throw new ApiError(400, "With no files, no commands and no browser, there's no computer.");
|
|
85112
|
-
|
|
85113
|
-
|
|
85114
|
-
|
|
85115
|
-
|
|
85116
|
-
|
|
85117
|
-
|
|
85118
|
-
|
|
85119
|
-
|
|
85120
|
-
|
|
85121
|
-
|
|
85233
|
+
if (input2.copyFrom !== void 0 && input2.workspace !== void 0)
|
|
85234
|
+
throw new ApiError(
|
|
85235
|
+
400,
|
|
85236
|
+
"Give workspace or copyFrom, not both: copyFrom fills a workspace the service makes."
|
|
85237
|
+
);
|
|
85238
|
+
if (input2.copyFrom !== void 0 && access === "none")
|
|
85239
|
+
throw new ApiError(
|
|
85240
|
+
400,
|
|
85241
|
+
"With access none there is no workspace. Give access read, files or terminal, or leave out copyFrom."
|
|
85242
|
+
);
|
|
85243
|
+
const workspace = input2.workspace === void 0 ? void 0 : folderAt(input2.workspace);
|
|
85244
|
+
const from = input2.copyFrom === void 0 ? void 0 : realpathSync2(folderAt(input2.copyFrom));
|
|
85122
85245
|
const id = `c_${randomBytes5(9).toString("hex")}`;
|
|
85123
85246
|
const token = newToken();
|
|
85124
85247
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -85126,7 +85249,8 @@ var Computers = class {
|
|
|
85126
85249
|
id,
|
|
85127
85250
|
name: name ?? id,
|
|
85128
85251
|
access,
|
|
85129
|
-
isolation
|
|
85252
|
+
isolation,
|
|
85253
|
+
...isolation === "none" ? { attached: true } : {},
|
|
85130
85254
|
browser,
|
|
85131
85255
|
...workspace ? { workspace } : {},
|
|
85132
85256
|
metadata: metadata ?? {},
|
|
@@ -85137,8 +85261,21 @@ var Computers = class {
|
|
|
85137
85261
|
...timeout === void 0 ? {} : { endAt: expiry(timeout) }
|
|
85138
85262
|
};
|
|
85139
85263
|
if (!workspace && access !== "none") {
|
|
85140
|
-
|
|
85141
|
-
mkdirSync3(
|
|
85264
|
+
const own3 = join10(this.#folder(id), "workspace");
|
|
85265
|
+
mkdirSync3(own3, { recursive: true, mode: 448 });
|
|
85266
|
+
stored.workspace = own3;
|
|
85267
|
+
if (from)
|
|
85268
|
+
await cp(from, own3, {
|
|
85269
|
+
recursive: true,
|
|
85270
|
+
verbatimSymlinks: true,
|
|
85271
|
+
filter: async (path) => {
|
|
85272
|
+
const found = await lstat3(path);
|
|
85273
|
+
return found.isFile() || found.isDirectory() || found.isSymbolicLink();
|
|
85274
|
+
}
|
|
85275
|
+
}).catch((error62) => {
|
|
85276
|
+
removeFolder(this.#folder(id));
|
|
85277
|
+
throw refusalOf(error62);
|
|
85278
|
+
});
|
|
85142
85279
|
}
|
|
85143
85280
|
this.#stored.set(id, stored);
|
|
85144
85281
|
try {
|
|
@@ -85148,7 +85285,10 @@ var Computers = class {
|
|
|
85148
85285
|
this.#stored.delete(id);
|
|
85149
85286
|
await this.#runtimes[stored.isolation].remove(id).catch(() => {
|
|
85150
85287
|
});
|
|
85151
|
-
|
|
85288
|
+
try {
|
|
85289
|
+
removeFolder(this.#folder(id));
|
|
85290
|
+
} catch {
|
|
85291
|
+
}
|
|
85152
85292
|
throw refusalOf(error62);
|
|
85153
85293
|
}
|
|
85154
85294
|
this.#save();
|
|
@@ -85222,7 +85362,12 @@ var Computers = class {
|
|
|
85222
85362
|
}
|
|
85223
85363
|
this.#stored.delete(id);
|
|
85224
85364
|
this.#save();
|
|
85225
|
-
|
|
85365
|
+
const folder = this.#folder(id);
|
|
85366
|
+
if (stored.isolation === "none" && !stored.attached && existsSync2(join10(folder, "workspace")))
|
|
85367
|
+
for (const entry of readdirSync2(folder)) {
|
|
85368
|
+
if (entry !== "workspace") removeFolder(join10(folder, entry));
|
|
85369
|
+
}
|
|
85370
|
+
else removeFolder(folder);
|
|
85226
85371
|
}
|
|
85227
85372
|
logs(id) {
|
|
85228
85373
|
this.#found(id);
|
|
@@ -85323,6 +85468,7 @@ var Computers = class {
|
|
|
85323
85468
|
state: stored.state === "running" && down2 ? "failed" : stored.state,
|
|
85324
85469
|
access: stored.access,
|
|
85325
85470
|
isolation: stored.isolation,
|
|
85471
|
+
attached: stored.attached === true,
|
|
85326
85472
|
version: stored.version ?? null,
|
|
85327
85473
|
browser: stored.browser,
|
|
85328
85474
|
workspace: stored.workspace ?? null,
|
|
@@ -85338,6 +85484,9 @@ var Computers = class {
|
|
|
85338
85484
|
async #start(stored) {
|
|
85339
85485
|
const live = {};
|
|
85340
85486
|
this.#live.set(stored.id, live);
|
|
85487
|
+
if (stored.isolation === "none" && !stored.attached)
|
|
85488
|
+
throw new ApiError(409, noLongerMade(stored));
|
|
85489
|
+
if (stored.attached && this.#notHere) throw new ApiError(409, this.#notHere);
|
|
85341
85490
|
stored.startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
85342
85491
|
const runtime = this.#runtimes[stored.isolation];
|
|
85343
85492
|
await runtime.prepare();
|
|
@@ -85397,7 +85546,7 @@ var OPENAPI = {
|
|
|
85397
85546
|
"openapi": "3.1.0",
|
|
85398
85547
|
"info": {
|
|
85399
85548
|
"title": "AgentComputer",
|
|
85400
|
-
"version": "0.0.
|
|
85549
|
+
"version": "0.0.19",
|
|
85401
85550
|
"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.",
|
|
85402
85551
|
"license": {
|
|
85403
85552
|
"name": "Apache-2.0",
|
|
@@ -85420,7 +85569,7 @@ var OPENAPI = {
|
|
|
85420
85569
|
"get": {
|
|
85421
85570
|
"operationId": "getInfo",
|
|
85422
85571
|
"x-mcp-tool": "service_info",
|
|
85423
|
-
"summary": "What this service
|
|
85572
|
+
"summary": "What this service offers: this computer, the kinds of computer it can make, and the browsers that can go with each, every one ready or not and why.",
|
|
85424
85573
|
"responses": {
|
|
85425
85574
|
"200": {
|
|
85426
85575
|
"description": "The service.",
|
|
@@ -85502,6 +85651,47 @@ var OPENAPI = {
|
|
|
85502
85651
|
},
|
|
85503
85652
|
"401": {
|
|
85504
85653
|
"$ref": "#/components/responses/Unauthorized"
|
|
85654
|
+
},
|
|
85655
|
+
"409": {
|
|
85656
|
+
"$ref": "#/components/responses/Error"
|
|
85657
|
+
}
|
|
85658
|
+
}
|
|
85659
|
+
}
|
|
85660
|
+
},
|
|
85661
|
+
"/v1/computers/attach": {
|
|
85662
|
+
"post": {
|
|
85663
|
+
"operationId": "attachComputer",
|
|
85664
|
+
"x-mcp-tool": "computer_attach",
|
|
85665
|
+
"summary": "Attach this computer, the machine the service runs on, whole: its files and commands reach all of it, as whoever started the service. Each call attaches it as a computer of its own, with its own id and token. Killing one detaches it and removes nothing of the machine's. Refused with 409 by a service that other machines can reach, which doesn't offer it.",
|
|
85666
|
+
"requestBody": {
|
|
85667
|
+
"required": true,
|
|
85668
|
+
"content": {
|
|
85669
|
+
"application/json": {
|
|
85670
|
+
"schema": {
|
|
85671
|
+
"$ref": "#/components/schemas/AttachComputer"
|
|
85672
|
+
}
|
|
85673
|
+
}
|
|
85674
|
+
}
|
|
85675
|
+
},
|
|
85676
|
+
"responses": {
|
|
85677
|
+
"201": {
|
|
85678
|
+
"description": "It, with its access token, shown only now.",
|
|
85679
|
+
"content": {
|
|
85680
|
+
"application/json": {
|
|
85681
|
+
"schema": {
|
|
85682
|
+
"$ref": "#/components/schemas/CreatedComputer"
|
|
85683
|
+
}
|
|
85684
|
+
}
|
|
85685
|
+
}
|
|
85686
|
+
},
|
|
85687
|
+
"400": {
|
|
85688
|
+
"$ref": "#/components/responses/Error"
|
|
85689
|
+
},
|
|
85690
|
+
"401": {
|
|
85691
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
85692
|
+
},
|
|
85693
|
+
"409": {
|
|
85694
|
+
"$ref": "#/components/responses/Error"
|
|
85505
85695
|
}
|
|
85506
85696
|
}
|
|
85507
85697
|
}
|
|
@@ -85675,6 +85865,9 @@ var OPENAPI = {
|
|
|
85675
85865
|
},
|
|
85676
85866
|
"404": {
|
|
85677
85867
|
"$ref": "#/components/responses/Error"
|
|
85868
|
+
},
|
|
85869
|
+
"409": {
|
|
85870
|
+
"$ref": "#/components/responses/Error"
|
|
85678
85871
|
}
|
|
85679
85872
|
}
|
|
85680
85873
|
}
|
|
@@ -85899,9 +86092,48 @@ var OPENAPI = {
|
|
|
85899
86092
|
"maxLength": 4096,
|
|
85900
86093
|
"description": "The full path of a folder that exists, on the service's machine. With none, the service makes a folder, which goes when the computer is killed. A folder named here never does."
|
|
85901
86094
|
},
|
|
86095
|
+
"copyFrom": {
|
|
86096
|
+
"type": "string",
|
|
86097
|
+
"maxLength": 4096,
|
|
86098
|
+
"description": "The full path of a folder on the service's machine. The workspace the service makes starts with a copy of what is in it, taken once when the computer is made; the folder itself is never mounted or changed. Links are copied as they are, and sockets, pipes and devices are left out. Use it instead of workspace; it needs access other than none."
|
|
86099
|
+
},
|
|
85902
86100
|
"isolation": {
|
|
85903
86101
|
"$ref": "#/components/schemas/Isolation",
|
|
85904
|
-
"description": "How it is isolated, which it keeps for as long as it exists.
|
|
86102
|
+
"description": "How it is isolated, which it keeps for as long as it exists: container, the default. One with no isolation is no longer made, and asking for one is refused: attach this computer instead."
|
|
86103
|
+
},
|
|
86104
|
+
"timeout": {
|
|
86105
|
+
"$ref": "#/components/schemas/Timeout"
|
|
86106
|
+
},
|
|
86107
|
+
"metadata": {
|
|
86108
|
+
"$ref": "#/components/schemas/Metadata"
|
|
86109
|
+
}
|
|
86110
|
+
}
|
|
86111
|
+
},
|
|
86112
|
+
"AttachComputer": {
|
|
86113
|
+
"type": "object",
|
|
86114
|
+
"additionalProperties": false,
|
|
86115
|
+
"required": [
|
|
86116
|
+
"access",
|
|
86117
|
+
"workspace"
|
|
86118
|
+
],
|
|
86119
|
+
"properties": {
|
|
86120
|
+
"name": {
|
|
86121
|
+
"type": "string",
|
|
86122
|
+
"minLength": 1,
|
|
86123
|
+
"maxLength": 128
|
|
86124
|
+
},
|
|
86125
|
+
"access": {
|
|
86126
|
+
"$ref": "#/components/schemas/Access"
|
|
86127
|
+
},
|
|
86128
|
+
"browser": {
|
|
86129
|
+
"type": "boolean",
|
|
86130
|
+
"default": false,
|
|
86131
|
+
"description": "Whether it has a headless browser of its own. With access none, it must."
|
|
86132
|
+
},
|
|
86133
|
+
"workspace": {
|
|
86134
|
+
"type": "string",
|
|
86135
|
+
"maxLength": 4096,
|
|
86136
|
+
"description": "Its work folder: the full path of a folder that exists. Commands and relative paths start there and its agent is told to work there, but nothing keeps its files inside it. Detaching never removes it."
|
|
85905
86137
|
},
|
|
85906
86138
|
"timeout": {
|
|
85907
86139
|
"$ref": "#/components/schemas/Timeout"
|
|
@@ -85917,7 +86149,7 @@ var OPENAPI = {
|
|
|
85917
86149
|
"none",
|
|
85918
86150
|
"container"
|
|
85919
86151
|
],
|
|
85920
|
-
"description": "none: processes of whoever started the service. container: a container of its own, which needs Docker on the service's machine."
|
|
86152
|
+
"description": "none: processes of whoever started the service, which only this computer has now; a computer made with no isolation before can't start again. container: a container of its own, which needs Docker on the service's machine."
|
|
85921
86153
|
},
|
|
85922
86154
|
"Endpoints": {
|
|
85923
86155
|
"type": "object",
|
|
@@ -85951,6 +86183,7 @@ var OPENAPI = {
|
|
|
85951
86183
|
"state",
|
|
85952
86184
|
"access",
|
|
85953
86185
|
"isolation",
|
|
86186
|
+
"attached",
|
|
85954
86187
|
"version",
|
|
85955
86188
|
"browser",
|
|
85956
86189
|
"workspace",
|
|
@@ -85976,12 +86209,16 @@ var OPENAPI = {
|
|
|
85976
86209
|
"$ref": "#/components/schemas/Isolation",
|
|
85977
86210
|
"description": "The isolation it was made in. It is never run in another."
|
|
85978
86211
|
},
|
|
86212
|
+
"attached": {
|
|
86213
|
+
"type": "boolean",
|
|
86214
|
+
"description": "Whether it is this computer, attached rather than made: the service's machine, whole, acting as whoever started the service, with no isolation. False with isolation none marks a computer made with no isolation by an earlier version, which can't start again; its workspace is kept."
|
|
86215
|
+
},
|
|
85979
86216
|
"version": {
|
|
85980
86217
|
"type": [
|
|
85981
86218
|
"string",
|
|
85982
86219
|
"null"
|
|
85983
86220
|
],
|
|
85984
|
-
"description": "The version of the program it ran at its last start.
|
|
86221
|
+
"description": "The version of the program it ran at its last start. For this computer 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."
|
|
85985
86222
|
},
|
|
85986
86223
|
"browser": {
|
|
85987
86224
|
"type": "boolean"
|
|
@@ -86765,7 +87002,7 @@ var OPENAPI = {
|
|
|
86765
87002
|
"computer",
|
|
86766
87003
|
"machine"
|
|
86767
87004
|
],
|
|
86768
|
-
"description": "Whose numbers these are. computer:
|
|
87005
|
+
"description": "Whose numbers these are. computer: the computer's own, as a container's are. machine: the whole machine's, as this computer's are, which it shares with whatever else runs there; and a container's where it can't read its own."
|
|
86769
87006
|
},
|
|
86770
87007
|
"cpuUsedPct": {
|
|
86771
87008
|
"type": "number",
|
|
@@ -87137,27 +87374,143 @@ var OPENAPI = {
|
|
|
87137
87374
|
}
|
|
87138
87375
|
}
|
|
87139
87376
|
},
|
|
87377
|
+
"Readiness": {
|
|
87378
|
+
"type": "object",
|
|
87379
|
+
"required": [
|
|
87380
|
+
"ready"
|
|
87381
|
+
],
|
|
87382
|
+
"properties": {
|
|
87383
|
+
"ready": {
|
|
87384
|
+
"type": "boolean"
|
|
87385
|
+
},
|
|
87386
|
+
"reason": {
|
|
87387
|
+
"type": "string",
|
|
87388
|
+
"description": "Why it isn't ready, in a line a person reads. Only when it isn't."
|
|
87389
|
+
}
|
|
87390
|
+
}
|
|
87391
|
+
},
|
|
87392
|
+
"Capability": {
|
|
87393
|
+
"type": "string",
|
|
87394
|
+
"enum": [
|
|
87395
|
+
"about",
|
|
87396
|
+
"terminal",
|
|
87397
|
+
"files",
|
|
87398
|
+
"screen"
|
|
87399
|
+
],
|
|
87400
|
+
"description": "What a computer offers its agent and the person: what it is, its terminals, its files and its screen."
|
|
87401
|
+
},
|
|
87402
|
+
"CapabilityState": {
|
|
87403
|
+
"allOf": [
|
|
87404
|
+
{
|
|
87405
|
+
"$ref": "#/components/schemas/Readiness"
|
|
87406
|
+
},
|
|
87407
|
+
{
|
|
87408
|
+
"type": "object",
|
|
87409
|
+
"required": [
|
|
87410
|
+
"capability"
|
|
87411
|
+
],
|
|
87412
|
+
"properties": {
|
|
87413
|
+
"capability": {
|
|
87414
|
+
"$ref": "#/components/schemas/Capability"
|
|
87415
|
+
}
|
|
87416
|
+
}
|
|
87417
|
+
}
|
|
87418
|
+
]
|
|
87419
|
+
},
|
|
87420
|
+
"BrowserKind": {
|
|
87421
|
+
"type": "string",
|
|
87422
|
+
"enum": [
|
|
87423
|
+
"headless"
|
|
87424
|
+
],
|
|
87425
|
+
"description": "headless: a headless browser with a profile of its own, beside the computer, which a person watches and controls through its live view."
|
|
87426
|
+
},
|
|
87427
|
+
"BrowserState": {
|
|
87428
|
+
"allOf": [
|
|
87429
|
+
{
|
|
87430
|
+
"$ref": "#/components/schemas/Readiness"
|
|
87431
|
+
},
|
|
87432
|
+
{
|
|
87433
|
+
"type": "object",
|
|
87434
|
+
"required": [
|
|
87435
|
+
"kind"
|
|
87436
|
+
],
|
|
87437
|
+
"properties": {
|
|
87438
|
+
"kind": {
|
|
87439
|
+
"$ref": "#/components/schemas/BrowserKind"
|
|
87440
|
+
}
|
|
87441
|
+
}
|
|
87442
|
+
}
|
|
87443
|
+
]
|
|
87444
|
+
},
|
|
87445
|
+
"Offer": {
|
|
87446
|
+
"allOf": [
|
|
87447
|
+
{
|
|
87448
|
+
"$ref": "#/components/schemas/Readiness"
|
|
87449
|
+
},
|
|
87450
|
+
{
|
|
87451
|
+
"type": "object",
|
|
87452
|
+
"required": [
|
|
87453
|
+
"capabilities",
|
|
87454
|
+
"browsers"
|
|
87455
|
+
],
|
|
87456
|
+
"properties": {
|
|
87457
|
+
"capabilities": {
|
|
87458
|
+
"type": "array",
|
|
87459
|
+
"description": "What such a computer has, each ready or not.",
|
|
87460
|
+
"items": {
|
|
87461
|
+
"$ref": "#/components/schemas/CapabilityState"
|
|
87462
|
+
}
|
|
87463
|
+
},
|
|
87464
|
+
"browsers": {
|
|
87465
|
+
"type": "array",
|
|
87466
|
+
"description": "The browsers that can go with it, each ready or not.",
|
|
87467
|
+
"items": {
|
|
87468
|
+
"$ref": "#/components/schemas/BrowserState"
|
|
87469
|
+
}
|
|
87470
|
+
}
|
|
87471
|
+
}
|
|
87472
|
+
}
|
|
87473
|
+
]
|
|
87474
|
+
},
|
|
87475
|
+
"MadeKind": {
|
|
87476
|
+
"allOf": [
|
|
87477
|
+
{
|
|
87478
|
+
"$ref": "#/components/schemas/Offer"
|
|
87479
|
+
},
|
|
87480
|
+
{
|
|
87481
|
+
"type": "object",
|
|
87482
|
+
"required": [
|
|
87483
|
+
"isolation"
|
|
87484
|
+
],
|
|
87485
|
+
"properties": {
|
|
87486
|
+
"isolation": {
|
|
87487
|
+
"$ref": "#/components/schemas/Isolation"
|
|
87488
|
+
}
|
|
87489
|
+
}
|
|
87490
|
+
}
|
|
87491
|
+
]
|
|
87492
|
+
},
|
|
87140
87493
|
"ServiceInfo": {
|
|
87141
87494
|
"type": "object",
|
|
87142
87495
|
"required": [
|
|
87143
87496
|
"version",
|
|
87144
|
-
"
|
|
87145
|
-
"
|
|
87497
|
+
"thisComputer",
|
|
87498
|
+
"made"
|
|
87146
87499
|
],
|
|
87147
87500
|
"properties": {
|
|
87148
87501
|
"version": {
|
|
87149
87502
|
"type": "string"
|
|
87150
87503
|
},
|
|
87151
|
-
"
|
|
87152
|
-
"$ref": "#/components/schemas/
|
|
87153
|
-
"description": "
|
|
87504
|
+
"thisComputer": {
|
|
87505
|
+
"$ref": "#/components/schemas/Offer",
|
|
87506
|
+
"description": "This computer, the machine the service runs on, attached whole, as whoever started the service. It can be attached while ready: only where the service listens on loopback, with no proxy in front and no public address. Elsewhere it isn't offered, and one attached before is refused at start."
|
|
87154
87507
|
},
|
|
87155
|
-
"
|
|
87508
|
+
"made": {
|
|
87156
87509
|
"type": "array",
|
|
87510
|
+
"description": "Each kind of computer it makes, ready while it can be made now. A container is ready while Docker answers on the service's machine: asked for a second here and for ten when one is made, so one that is slow can be not ready here and still be made.",
|
|
87157
87511
|
"items": {
|
|
87158
|
-
"$ref": "#/components/schemas/
|
|
87159
|
-
}
|
|
87160
|
-
"description": "The isolations a computer can be made in now, `none` first. `container` is among them while Docker answers on the service's machine. It is what to offer, not a promise: Docker is asked for a second here and for ten when a container is made, so one that is slow can be missing here and still be made. If `isolation` itself is missing, a computer made without saying which is refused with 409."
|
|
87512
|
+
"$ref": "#/components/schemas/MadeKind"
|
|
87513
|
+
}
|
|
87161
87514
|
}
|
|
87162
87515
|
}
|
|
87163
87516
|
}
|
|
@@ -87170,7 +87523,7 @@ var OPERATIONS = [
|
|
|
87170
87523
|
"method": "GET",
|
|
87171
87524
|
"path": "/v1/info",
|
|
87172
87525
|
"tool": "service_info",
|
|
87173
|
-
"summary": "What this service
|
|
87526
|
+
"summary": "What this service offers: this computer, the kinds of computer it can make, and the browsers that can go with each, every one ready or not and why.",
|
|
87174
87527
|
"status": 200,
|
|
87175
87528
|
"hasBody": false,
|
|
87176
87529
|
"pathParameters": [],
|
|
@@ -87185,32 +87538,251 @@ var OPERATIONS = [
|
|
|
87185
87538
|
"type": "object",
|
|
87186
87539
|
"required": [
|
|
87187
87540
|
"version",
|
|
87188
|
-
"
|
|
87189
|
-
"
|
|
87541
|
+
"thisComputer",
|
|
87542
|
+
"made"
|
|
87190
87543
|
],
|
|
87191
87544
|
"properties": {
|
|
87192
87545
|
"version": {
|
|
87193
87546
|
"type": "string"
|
|
87194
87547
|
},
|
|
87195
|
-
"
|
|
87196
|
-
"
|
|
87197
|
-
|
|
87198
|
-
|
|
87199
|
-
|
|
87548
|
+
"thisComputer": {
|
|
87549
|
+
"allOf": [
|
|
87550
|
+
{
|
|
87551
|
+
"type": "object",
|
|
87552
|
+
"required": [
|
|
87553
|
+
"ready"
|
|
87554
|
+
],
|
|
87555
|
+
"properties": {
|
|
87556
|
+
"ready": {
|
|
87557
|
+
"type": "boolean"
|
|
87558
|
+
},
|
|
87559
|
+
"reason": {
|
|
87560
|
+
"type": "string",
|
|
87561
|
+
"description": "Why it isn't ready, in a line a person reads. Only when it isn't."
|
|
87562
|
+
}
|
|
87563
|
+
}
|
|
87564
|
+
},
|
|
87565
|
+
{
|
|
87566
|
+
"type": "object",
|
|
87567
|
+
"required": [
|
|
87568
|
+
"capabilities",
|
|
87569
|
+
"browsers"
|
|
87570
|
+
],
|
|
87571
|
+
"properties": {
|
|
87572
|
+
"capabilities": {
|
|
87573
|
+
"type": "array",
|
|
87574
|
+
"description": "What such a computer has, each ready or not.",
|
|
87575
|
+
"items": {
|
|
87576
|
+
"allOf": [
|
|
87577
|
+
{
|
|
87578
|
+
"type": "object",
|
|
87579
|
+
"required": [
|
|
87580
|
+
"ready"
|
|
87581
|
+
],
|
|
87582
|
+
"properties": {
|
|
87583
|
+
"ready": {
|
|
87584
|
+
"type": "boolean"
|
|
87585
|
+
},
|
|
87586
|
+
"reason": {
|
|
87587
|
+
"type": "string",
|
|
87588
|
+
"description": "Why it isn't ready, in a line a person reads. Only when it isn't."
|
|
87589
|
+
}
|
|
87590
|
+
}
|
|
87591
|
+
},
|
|
87592
|
+
{
|
|
87593
|
+
"type": "object",
|
|
87594
|
+
"required": [
|
|
87595
|
+
"capability"
|
|
87596
|
+
],
|
|
87597
|
+
"properties": {
|
|
87598
|
+
"capability": {
|
|
87599
|
+
"type": "string",
|
|
87600
|
+
"enum": [
|
|
87601
|
+
"about",
|
|
87602
|
+
"terminal",
|
|
87603
|
+
"files",
|
|
87604
|
+
"screen"
|
|
87605
|
+
],
|
|
87606
|
+
"description": "What a computer offers its agent and the person: what it is, its terminals, its files and its screen."
|
|
87607
|
+
}
|
|
87608
|
+
}
|
|
87609
|
+
}
|
|
87610
|
+
]
|
|
87611
|
+
}
|
|
87612
|
+
},
|
|
87613
|
+
"browsers": {
|
|
87614
|
+
"type": "array",
|
|
87615
|
+
"description": "The browsers that can go with it, each ready or not.",
|
|
87616
|
+
"items": {
|
|
87617
|
+
"allOf": [
|
|
87618
|
+
{
|
|
87619
|
+
"type": "object",
|
|
87620
|
+
"required": [
|
|
87621
|
+
"ready"
|
|
87622
|
+
],
|
|
87623
|
+
"properties": {
|
|
87624
|
+
"ready": {
|
|
87625
|
+
"type": "boolean"
|
|
87626
|
+
},
|
|
87627
|
+
"reason": {
|
|
87628
|
+
"type": "string",
|
|
87629
|
+
"description": "Why it isn't ready, in a line a person reads. Only when it isn't."
|
|
87630
|
+
}
|
|
87631
|
+
}
|
|
87632
|
+
},
|
|
87633
|
+
{
|
|
87634
|
+
"type": "object",
|
|
87635
|
+
"required": [
|
|
87636
|
+
"kind"
|
|
87637
|
+
],
|
|
87638
|
+
"properties": {
|
|
87639
|
+
"kind": {
|
|
87640
|
+
"type": "string",
|
|
87641
|
+
"enum": [
|
|
87642
|
+
"headless"
|
|
87643
|
+
],
|
|
87644
|
+
"description": "headless: a headless browser with a profile of its own, beside the computer, which a person watches and controls through its live view."
|
|
87645
|
+
}
|
|
87646
|
+
}
|
|
87647
|
+
}
|
|
87648
|
+
]
|
|
87649
|
+
}
|
|
87650
|
+
}
|
|
87651
|
+
}
|
|
87652
|
+
}
|
|
87200
87653
|
],
|
|
87201
|
-
"description": "
|
|
87654
|
+
"description": "This computer, the machine the service runs on, attached whole, as whoever started the service. It can be attached while ready: only where the service listens on loopback, with no proxy in front and no public address. Elsewhere it isn't offered, and one attached before is refused at start."
|
|
87202
87655
|
},
|
|
87203
|
-
"
|
|
87656
|
+
"made": {
|
|
87204
87657
|
"type": "array",
|
|
87658
|
+
"description": "Each kind of computer it makes, ready while it can be made now. A container is ready while Docker answers on the service's machine: asked for a second here and for ten when one is made, so one that is slow can be not ready here and still be made.",
|
|
87205
87659
|
"items": {
|
|
87206
|
-
"
|
|
87207
|
-
|
|
87208
|
-
|
|
87209
|
-
|
|
87210
|
-
|
|
87211
|
-
|
|
87212
|
-
|
|
87213
|
-
|
|
87660
|
+
"allOf": [
|
|
87661
|
+
{
|
|
87662
|
+
"allOf": [
|
|
87663
|
+
{
|
|
87664
|
+
"type": "object",
|
|
87665
|
+
"required": [
|
|
87666
|
+
"ready"
|
|
87667
|
+
],
|
|
87668
|
+
"properties": {
|
|
87669
|
+
"ready": {
|
|
87670
|
+
"type": "boolean"
|
|
87671
|
+
},
|
|
87672
|
+
"reason": {
|
|
87673
|
+
"type": "string",
|
|
87674
|
+
"description": "Why it isn't ready, in a line a person reads. Only when it isn't."
|
|
87675
|
+
}
|
|
87676
|
+
}
|
|
87677
|
+
},
|
|
87678
|
+
{
|
|
87679
|
+
"type": "object",
|
|
87680
|
+
"required": [
|
|
87681
|
+
"capabilities",
|
|
87682
|
+
"browsers"
|
|
87683
|
+
],
|
|
87684
|
+
"properties": {
|
|
87685
|
+
"capabilities": {
|
|
87686
|
+
"type": "array",
|
|
87687
|
+
"description": "What such a computer has, each ready or not.",
|
|
87688
|
+
"items": {
|
|
87689
|
+
"allOf": [
|
|
87690
|
+
{
|
|
87691
|
+
"type": "object",
|
|
87692
|
+
"required": [
|
|
87693
|
+
"ready"
|
|
87694
|
+
],
|
|
87695
|
+
"properties": {
|
|
87696
|
+
"ready": {
|
|
87697
|
+
"type": "boolean"
|
|
87698
|
+
},
|
|
87699
|
+
"reason": {
|
|
87700
|
+
"type": "string",
|
|
87701
|
+
"description": "Why it isn't ready, in a line a person reads. Only when it isn't."
|
|
87702
|
+
}
|
|
87703
|
+
}
|
|
87704
|
+
},
|
|
87705
|
+
{
|
|
87706
|
+
"type": "object",
|
|
87707
|
+
"required": [
|
|
87708
|
+
"capability"
|
|
87709
|
+
],
|
|
87710
|
+
"properties": {
|
|
87711
|
+
"capability": {
|
|
87712
|
+
"type": "string",
|
|
87713
|
+
"enum": [
|
|
87714
|
+
"about",
|
|
87715
|
+
"terminal",
|
|
87716
|
+
"files",
|
|
87717
|
+
"screen"
|
|
87718
|
+
],
|
|
87719
|
+
"description": "What a computer offers its agent and the person: what it is, its terminals, its files and its screen."
|
|
87720
|
+
}
|
|
87721
|
+
}
|
|
87722
|
+
}
|
|
87723
|
+
]
|
|
87724
|
+
}
|
|
87725
|
+
},
|
|
87726
|
+
"browsers": {
|
|
87727
|
+
"type": "array",
|
|
87728
|
+
"description": "The browsers that can go with it, each ready or not.",
|
|
87729
|
+
"items": {
|
|
87730
|
+
"allOf": [
|
|
87731
|
+
{
|
|
87732
|
+
"type": "object",
|
|
87733
|
+
"required": [
|
|
87734
|
+
"ready"
|
|
87735
|
+
],
|
|
87736
|
+
"properties": {
|
|
87737
|
+
"ready": {
|
|
87738
|
+
"type": "boolean"
|
|
87739
|
+
},
|
|
87740
|
+
"reason": {
|
|
87741
|
+
"type": "string",
|
|
87742
|
+
"description": "Why it isn't ready, in a line a person reads. Only when it isn't."
|
|
87743
|
+
}
|
|
87744
|
+
}
|
|
87745
|
+
},
|
|
87746
|
+
{
|
|
87747
|
+
"type": "object",
|
|
87748
|
+
"required": [
|
|
87749
|
+
"kind"
|
|
87750
|
+
],
|
|
87751
|
+
"properties": {
|
|
87752
|
+
"kind": {
|
|
87753
|
+
"type": "string",
|
|
87754
|
+
"enum": [
|
|
87755
|
+
"headless"
|
|
87756
|
+
],
|
|
87757
|
+
"description": "headless: a headless browser with a profile of its own, beside the computer, which a person watches and controls through its live view."
|
|
87758
|
+
}
|
|
87759
|
+
}
|
|
87760
|
+
}
|
|
87761
|
+
]
|
|
87762
|
+
}
|
|
87763
|
+
}
|
|
87764
|
+
}
|
|
87765
|
+
}
|
|
87766
|
+
]
|
|
87767
|
+
},
|
|
87768
|
+
{
|
|
87769
|
+
"type": "object",
|
|
87770
|
+
"required": [
|
|
87771
|
+
"isolation"
|
|
87772
|
+
],
|
|
87773
|
+
"properties": {
|
|
87774
|
+
"isolation": {
|
|
87775
|
+
"type": "string",
|
|
87776
|
+
"enum": [
|
|
87777
|
+
"none",
|
|
87778
|
+
"container"
|
|
87779
|
+
],
|
|
87780
|
+
"description": "none: processes of whoever started the service, which only this computer has now; a computer made with no isolation before can't start again. container: a container of its own, which needs Docker on the service's machine."
|
|
87781
|
+
}
|
|
87782
|
+
}
|
|
87783
|
+
}
|
|
87784
|
+
]
|
|
87785
|
+
}
|
|
87214
87786
|
}
|
|
87215
87787
|
}
|
|
87216
87788
|
},
|
|
@@ -87254,6 +87826,7 @@ var OPERATIONS = [
|
|
|
87254
87826
|
"state",
|
|
87255
87827
|
"access",
|
|
87256
87828
|
"isolation",
|
|
87829
|
+
"attached",
|
|
87257
87830
|
"version",
|
|
87258
87831
|
"browser",
|
|
87259
87832
|
"workspace",
|
|
@@ -87296,12 +87869,16 @@ var OPERATIONS = [
|
|
|
87296
87869
|
],
|
|
87297
87870
|
"description": "The isolation it was made in. It is never run in another."
|
|
87298
87871
|
},
|
|
87872
|
+
"attached": {
|
|
87873
|
+
"type": "boolean",
|
|
87874
|
+
"description": "Whether it is this computer, attached rather than made: the service's machine, whole, acting as whoever started the service, with no isolation. False with isolation none marks a computer made with no isolation by an earlier version, which can't start again; its workspace is kept."
|
|
87875
|
+
},
|
|
87299
87876
|
"version": {
|
|
87300
87877
|
"type": [
|
|
87301
87878
|
"string",
|
|
87302
87879
|
"null"
|
|
87303
87880
|
],
|
|
87304
|
-
"description": "The version of the program it ran at its last start.
|
|
87881
|
+
"description": "The version of the program it ran at its last start. For this computer 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."
|
|
87305
87882
|
},
|
|
87306
87883
|
"browser": {
|
|
87307
87884
|
"type": "boolean"
|
|
@@ -87402,13 +87979,18 @@ var OPERATIONS = [
|
|
|
87402
87979
|
"maxLength": 4096,
|
|
87403
87980
|
"description": "The full path of a folder that exists, on the service's machine. With none, the service makes a folder, which goes when the computer is killed. A folder named here never does."
|
|
87404
87981
|
},
|
|
87982
|
+
"copyFrom": {
|
|
87983
|
+
"type": "string",
|
|
87984
|
+
"maxLength": 4096,
|
|
87985
|
+
"description": "The full path of a folder on the service's machine. The workspace the service makes starts with a copy of what is in it, taken once when the computer is made; the folder itself is never mounted or changed. Links are copied as they are, and sockets, pipes and devices are left out. Use it instead of workspace; it needs access other than none."
|
|
87986
|
+
},
|
|
87405
87987
|
"isolation": {
|
|
87406
87988
|
"type": "string",
|
|
87407
87989
|
"enum": [
|
|
87408
87990
|
"none",
|
|
87409
87991
|
"container"
|
|
87410
87992
|
],
|
|
87411
|
-
"description": "How it is isolated, which it keeps for as long as it exists.
|
|
87993
|
+
"description": "How it is isolated, which it keeps for as long as it exists: container, the default. One with no isolation is no longer made, and asking for one is refused: attach this computer instead."
|
|
87412
87994
|
},
|
|
87413
87995
|
"timeout": {
|
|
87414
87996
|
"type": "integer",
|
|
@@ -87439,6 +88021,7 @@ var OPERATIONS = [
|
|
|
87439
88021
|
"state",
|
|
87440
88022
|
"access",
|
|
87441
88023
|
"isolation",
|
|
88024
|
+
"attached",
|
|
87442
88025
|
"version",
|
|
87443
88026
|
"browser",
|
|
87444
88027
|
"workspace",
|
|
@@ -87481,12 +88064,212 @@ var OPERATIONS = [
|
|
|
87481
88064
|
],
|
|
87482
88065
|
"description": "The isolation it was made in. It is never run in another."
|
|
87483
88066
|
},
|
|
88067
|
+
"attached": {
|
|
88068
|
+
"type": "boolean",
|
|
88069
|
+
"description": "Whether it is this computer, attached rather than made: the service's machine, whole, acting as whoever started the service, with no isolation. False with isolation none marks a computer made with no isolation by an earlier version, which can't start again; its workspace is kept."
|
|
88070
|
+
},
|
|
87484
88071
|
"version": {
|
|
87485
88072
|
"type": [
|
|
87486
88073
|
"string",
|
|
87487
88074
|
"null"
|
|
87488
88075
|
],
|
|
87489
|
-
"description": "The version of the program it ran at its last start.
|
|
88076
|
+
"description": "The version of the program it ran at its last start. For this computer 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."
|
|
88077
|
+
},
|
|
88078
|
+
"browser": {
|
|
88079
|
+
"type": "boolean"
|
|
88080
|
+
},
|
|
88081
|
+
"workspace": {
|
|
88082
|
+
"type": [
|
|
88083
|
+
"string",
|
|
88084
|
+
"null"
|
|
88085
|
+
]
|
|
88086
|
+
},
|
|
88087
|
+
"startedAt": {
|
|
88088
|
+
"type": "string",
|
|
88089
|
+
"format": "date-time",
|
|
88090
|
+
"description": "When it last started."
|
|
88091
|
+
},
|
|
88092
|
+
"endAt": {
|
|
88093
|
+
"type": [
|
|
88094
|
+
"string",
|
|
88095
|
+
"null"
|
|
88096
|
+
],
|
|
88097
|
+
"format": "date-time",
|
|
88098
|
+
"description": "When it will stop; null if it has no timeout."
|
|
88099
|
+
},
|
|
88100
|
+
"metadata": {
|
|
88101
|
+
"type": "object",
|
|
88102
|
+
"additionalProperties": {
|
|
88103
|
+
"type": "string",
|
|
88104
|
+
"maxLength": 1024
|
|
88105
|
+
},
|
|
88106
|
+
"maxProperties": 64,
|
|
88107
|
+
"description": "Your own labels, kept and returned as given."
|
|
88108
|
+
},
|
|
88109
|
+
"endpoints": {
|
|
88110
|
+
"type": "object",
|
|
88111
|
+
"required": [
|
|
88112
|
+
"computer",
|
|
88113
|
+
"browser"
|
|
88114
|
+
],
|
|
88115
|
+
"description": "MCP over Streamable HTTP, each taking the computer's access token as a bearer.",
|
|
88116
|
+
"properties": {
|
|
88117
|
+
"computer": {
|
|
88118
|
+
"type": [
|
|
88119
|
+
"string",
|
|
88120
|
+
"null"
|
|
88121
|
+
],
|
|
88122
|
+
"description": "The terminal and files."
|
|
88123
|
+
},
|
|
88124
|
+
"browser": {
|
|
88125
|
+
"type": [
|
|
88126
|
+
"string",
|
|
88127
|
+
"null"
|
|
88128
|
+
],
|
|
88129
|
+
"description": "The browser."
|
|
88130
|
+
}
|
|
88131
|
+
}
|
|
88132
|
+
}
|
|
88133
|
+
}
|
|
88134
|
+
},
|
|
88135
|
+
{
|
|
88136
|
+
"type": "object",
|
|
88137
|
+
"required": [
|
|
88138
|
+
"accessToken"
|
|
88139
|
+
],
|
|
88140
|
+
"properties": {
|
|
88141
|
+
"accessToken": {
|
|
88142
|
+
"type": "string",
|
|
88143
|
+
"description": "Good only for this computer's endpoints. Shown only now."
|
|
88144
|
+
}
|
|
88145
|
+
}
|
|
88146
|
+
}
|
|
88147
|
+
]
|
|
88148
|
+
},
|
|
88149
|
+
"websocket": false
|
|
88150
|
+
},
|
|
88151
|
+
{
|
|
88152
|
+
"operationId": "attachComputer",
|
|
88153
|
+
"method": "POST",
|
|
88154
|
+
"path": "/v1/computers/attach",
|
|
88155
|
+
"tool": "computer_attach",
|
|
88156
|
+
"summary": "Attach this computer, the machine the service runs on, whole: its files and commands reach all of it, as whoever started the service. Each call attaches it as a computer of its own, with its own id and token. Killing one detaches it and removes nothing of the machine's. Refused with 409 by a service that other machines can reach, which doesn't offer it.",
|
|
88157
|
+
"status": 201,
|
|
88158
|
+
"hasBody": true,
|
|
88159
|
+
"pathParameters": [],
|
|
88160
|
+
"queryParameters": [],
|
|
88161
|
+
"input": {
|
|
88162
|
+
"type": "object",
|
|
88163
|
+
"additionalProperties": false,
|
|
88164
|
+
"properties": {
|
|
88165
|
+
"name": {
|
|
88166
|
+
"type": "string",
|
|
88167
|
+
"minLength": 1,
|
|
88168
|
+
"maxLength": 128
|
|
88169
|
+
},
|
|
88170
|
+
"access": {
|
|
88171
|
+
"type": "string",
|
|
88172
|
+
"enum": [
|
|
88173
|
+
"none",
|
|
88174
|
+
"read",
|
|
88175
|
+
"files",
|
|
88176
|
+
"terminal"
|
|
88177
|
+
],
|
|
88178
|
+
"description": "How far it reaches into files and commands, each level containing the one before: `read` has about, read, list and search; `files` adds edit; `terminal` adds exec_command, write_stdin and list_sessions. Below terminal, the browser's code-running tool is hidden."
|
|
88179
|
+
},
|
|
88180
|
+
"browser": {
|
|
88181
|
+
"type": "boolean",
|
|
88182
|
+
"default": false,
|
|
88183
|
+
"description": "Whether it has a headless browser of its own. With access none, it must."
|
|
88184
|
+
},
|
|
88185
|
+
"workspace": {
|
|
88186
|
+
"type": "string",
|
|
88187
|
+
"maxLength": 4096,
|
|
88188
|
+
"description": "Its work folder: the full path of a folder that exists. Commands and relative paths start there and its agent is told to work there, but nothing keeps its files inside it. Detaching never removes it."
|
|
88189
|
+
},
|
|
88190
|
+
"timeout": {
|
|
88191
|
+
"type": "integer",
|
|
88192
|
+
"minimum": 1,
|
|
88193
|
+
"description": "Seconds from now until the computer stops."
|
|
88194
|
+
},
|
|
88195
|
+
"metadata": {
|
|
88196
|
+
"type": "object",
|
|
88197
|
+
"additionalProperties": {
|
|
88198
|
+
"type": "string",
|
|
88199
|
+
"maxLength": 1024
|
|
88200
|
+
},
|
|
88201
|
+
"maxProperties": 64,
|
|
88202
|
+
"description": "Your own labels, kept and returned as given."
|
|
88203
|
+
}
|
|
88204
|
+
},
|
|
88205
|
+
"required": [
|
|
88206
|
+
"access",
|
|
88207
|
+
"workspace"
|
|
88208
|
+
]
|
|
88209
|
+
},
|
|
88210
|
+
"output": {
|
|
88211
|
+
"allOf": [
|
|
88212
|
+
{
|
|
88213
|
+
"type": "object",
|
|
88214
|
+
"required": [
|
|
88215
|
+
"computerID",
|
|
88216
|
+
"name",
|
|
88217
|
+
"state",
|
|
88218
|
+
"access",
|
|
88219
|
+
"isolation",
|
|
88220
|
+
"attached",
|
|
88221
|
+
"version",
|
|
88222
|
+
"browser",
|
|
88223
|
+
"workspace",
|
|
88224
|
+
"startedAt",
|
|
88225
|
+
"endAt",
|
|
88226
|
+
"metadata",
|
|
88227
|
+
"endpoints"
|
|
88228
|
+
],
|
|
88229
|
+
"properties": {
|
|
88230
|
+
"computerID": {
|
|
88231
|
+
"type": "string"
|
|
88232
|
+
},
|
|
88233
|
+
"name": {
|
|
88234
|
+
"type": "string"
|
|
88235
|
+
},
|
|
88236
|
+
"state": {
|
|
88237
|
+
"type": "string",
|
|
88238
|
+
"enum": [
|
|
88239
|
+
"running",
|
|
88240
|
+
"stopped",
|
|
88241
|
+
"failed"
|
|
88242
|
+
],
|
|
88243
|
+
"description": "failed: it was to be running and isn't, because its browser or container ended by itself, or because it couldn't be brought back when the service started. Its logs say why. Stop it and start it again."
|
|
88244
|
+
},
|
|
88245
|
+
"access": {
|
|
88246
|
+
"type": "string",
|
|
88247
|
+
"enum": [
|
|
88248
|
+
"none",
|
|
88249
|
+
"read",
|
|
88250
|
+
"files",
|
|
88251
|
+
"terminal"
|
|
88252
|
+
],
|
|
88253
|
+
"description": "How far it reaches into files and commands, each level containing the one before: `read` has about, read, list and search; `files` adds edit; `terminal` adds exec_command, write_stdin and list_sessions. Below terminal, the browser's code-running tool is hidden."
|
|
88254
|
+
},
|
|
88255
|
+
"isolation": {
|
|
88256
|
+
"type": "string",
|
|
88257
|
+
"enum": [
|
|
88258
|
+
"none",
|
|
88259
|
+
"container"
|
|
88260
|
+
],
|
|
88261
|
+
"description": "The isolation it was made in. It is never run in another."
|
|
88262
|
+
},
|
|
88263
|
+
"attached": {
|
|
88264
|
+
"type": "boolean",
|
|
88265
|
+
"description": "Whether it is this computer, attached rather than made: the service's machine, whole, acting as whoever started the service, with no isolation. False with isolation none marks a computer made with no isolation by an earlier version, which can't start again; its workspace is kept."
|
|
88266
|
+
},
|
|
88267
|
+
"version": {
|
|
88268
|
+
"type": [
|
|
88269
|
+
"string",
|
|
88270
|
+
"null"
|
|
88271
|
+
],
|
|
88272
|
+
"description": "The version of the program it ran at its last start. For this computer 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."
|
|
87490
88273
|
},
|
|
87491
88274
|
"browser": {
|
|
87492
88275
|
"type": "boolean"
|
|
@@ -87597,6 +88380,7 @@ var OPERATIONS = [
|
|
|
87597
88380
|
"state",
|
|
87598
88381
|
"access",
|
|
87599
88382
|
"isolation",
|
|
88383
|
+
"attached",
|
|
87600
88384
|
"version",
|
|
87601
88385
|
"browser",
|
|
87602
88386
|
"workspace",
|
|
@@ -87639,12 +88423,16 @@ var OPERATIONS = [
|
|
|
87639
88423
|
],
|
|
87640
88424
|
"description": "The isolation it was made in. It is never run in another."
|
|
87641
88425
|
},
|
|
88426
|
+
"attached": {
|
|
88427
|
+
"type": "boolean",
|
|
88428
|
+
"description": "Whether it is this computer, attached rather than made: the service's machine, whole, acting as whoever started the service, with no isolation. False with isolation none marks a computer made with no isolation by an earlier version, which can't start again; its workspace is kept."
|
|
88429
|
+
},
|
|
87642
88430
|
"version": {
|
|
87643
88431
|
"type": [
|
|
87644
88432
|
"string",
|
|
87645
88433
|
"null"
|
|
87646
88434
|
],
|
|
87647
|
-
"description": "The version of the program it ran at its last start.
|
|
88435
|
+
"description": "The version of the program it ran at its last start. For this computer 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."
|
|
87648
88436
|
},
|
|
87649
88437
|
"browser": {
|
|
87650
88438
|
"type": "boolean"
|
|
@@ -87846,6 +88634,7 @@ var OPERATIONS = [
|
|
|
87846
88634
|
"state",
|
|
87847
88635
|
"access",
|
|
87848
88636
|
"isolation",
|
|
88637
|
+
"attached",
|
|
87849
88638
|
"version",
|
|
87850
88639
|
"browser",
|
|
87851
88640
|
"workspace",
|
|
@@ -87888,12 +88677,16 @@ var OPERATIONS = [
|
|
|
87888
88677
|
],
|
|
87889
88678
|
"description": "The isolation it was made in. It is never run in another."
|
|
87890
88679
|
},
|
|
88680
|
+
"attached": {
|
|
88681
|
+
"type": "boolean",
|
|
88682
|
+
"description": "Whether it is this computer, attached rather than made: the service's machine, whole, acting as whoever started the service, with no isolation. False with isolation none marks a computer made with no isolation by an earlier version, which can't start again; its workspace is kept."
|
|
88683
|
+
},
|
|
87891
88684
|
"version": {
|
|
87892
88685
|
"type": [
|
|
87893
88686
|
"string",
|
|
87894
88687
|
"null"
|
|
87895
88688
|
],
|
|
87896
|
-
"description": "The version of the program it ran at its last start.
|
|
88689
|
+
"description": "The version of the program it ran at its last start. For this computer 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."
|
|
87897
88690
|
},
|
|
87898
88691
|
"browser": {
|
|
87899
88692
|
"type": "boolean"
|
|
@@ -87988,6 +88781,7 @@ var OPERATIONS = [
|
|
|
87988
88781
|
"state",
|
|
87989
88782
|
"access",
|
|
87990
88783
|
"isolation",
|
|
88784
|
+
"attached",
|
|
87991
88785
|
"version",
|
|
87992
88786
|
"browser",
|
|
87993
88787
|
"workspace",
|
|
@@ -88030,12 +88824,16 @@ var OPERATIONS = [
|
|
|
88030
88824
|
],
|
|
88031
88825
|
"description": "The isolation it was made in. It is never run in another."
|
|
88032
88826
|
},
|
|
88827
|
+
"attached": {
|
|
88828
|
+
"type": "boolean",
|
|
88829
|
+
"description": "Whether it is this computer, attached rather than made: the service's machine, whole, acting as whoever started the service, with no isolation. False with isolation none marks a computer made with no isolation by an earlier version, which can't start again; its workspace is kept."
|
|
88830
|
+
},
|
|
88033
88831
|
"version": {
|
|
88034
88832
|
"type": [
|
|
88035
88833
|
"string",
|
|
88036
88834
|
"null"
|
|
88037
88835
|
],
|
|
88038
|
-
"description": "The version of the program it ran at its last start.
|
|
88836
|
+
"description": "The version of the program it ran at its last start. For this computer 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."
|
|
88039
88837
|
},
|
|
88040
88838
|
"browser": {
|
|
88041
88839
|
"type": "boolean"
|
|
@@ -88135,6 +88933,7 @@ var OPERATIONS = [
|
|
|
88135
88933
|
"state",
|
|
88136
88934
|
"access",
|
|
88137
88935
|
"isolation",
|
|
88936
|
+
"attached",
|
|
88138
88937
|
"version",
|
|
88139
88938
|
"browser",
|
|
88140
88939
|
"workspace",
|
|
@@ -88177,12 +88976,16 @@ var OPERATIONS = [
|
|
|
88177
88976
|
],
|
|
88178
88977
|
"description": "The isolation it was made in. It is never run in another."
|
|
88179
88978
|
},
|
|
88979
|
+
"attached": {
|
|
88980
|
+
"type": "boolean",
|
|
88981
|
+
"description": "Whether it is this computer, attached rather than made: the service's machine, whole, acting as whoever started the service, with no isolation. False with isolation none marks a computer made with no isolation by an earlier version, which can't start again; its workspace is kept."
|
|
88982
|
+
},
|
|
88180
88983
|
"version": {
|
|
88181
88984
|
"type": [
|
|
88182
88985
|
"string",
|
|
88183
88986
|
"null"
|
|
88184
88987
|
],
|
|
88185
|
-
"description": "The version of the program it ran at its last start.
|
|
88988
|
+
"description": "The version of the program it ran at its last start. For this computer 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."
|
|
88186
88989
|
},
|
|
88187
88990
|
"browser": {
|
|
88188
88991
|
"type": "boolean"
|
|
@@ -88426,6 +89229,8 @@ var OPERATIONS = [
|
|
|
88426
89229
|
var LOOPBACK = /* @__PURE__ */ new Set(["127.0.0.1", "localhost", "::1"]);
|
|
88427
89230
|
var WILDCARD = /* @__PURE__ */ new Set(["0.0.0.0", "::"]);
|
|
88428
89231
|
var MAX_BODY2 = 64 * 1024;
|
|
89232
|
+
var NOT_HERE = "This service can be reached from other machines, so it doesn't offer the machine it runs on. Make a computer in a container, or attach this computer through a service that only this machine reaches.";
|
|
89233
|
+
var onlyThisMachine = (host, options) => LOOPBACK.has(host) && !options.tlsProxy && !options.publicUrl;
|
|
88429
89234
|
function checkExposure(host, options) {
|
|
88430
89235
|
const { tls, tlsProxy, publicUrl } = options;
|
|
88431
89236
|
if (tls && tlsProxy) throw new Error("--tls-cert and --tls-proxy are alternatives.");
|
|
@@ -88475,8 +89280,12 @@ async function serve(options) {
|
|
|
88475
89280
|
if (live)
|
|
88476
89281
|
throw new Error(`A service is already running with its data in ${data}, at ${live.url}.`);
|
|
88477
89282
|
let base = "";
|
|
88478
|
-
|
|
88479
|
-
|
|
89283
|
+
const computers = new Computers(
|
|
89284
|
+
data,
|
|
89285
|
+
() => base,
|
|
89286
|
+
options.runtimes,
|
|
89287
|
+
onlyThisMachine(host, options) ? void 0 : NOT_HERE
|
|
89288
|
+
);
|
|
88480
89289
|
const handlers = createHandlers(computers);
|
|
88481
89290
|
const routes = OPERATIONS.map((operation) => ({
|
|
88482
89291
|
operation,
|
|
@@ -88599,10 +89408,7 @@ ${JSON.stringify({ code: status, message })}
|
|
|
88599
89408
|
const record3 = recordOf(data);
|
|
88600
89409
|
rmSync6(record3, { force: true });
|
|
88601
89410
|
await computers.resume();
|
|
88602
|
-
writePrivate(
|
|
88603
|
-
record3,
|
|
88604
|
-
JSON.stringify({ url: base, pid: process.pid, isolation: options.isolation })
|
|
88605
|
-
);
|
|
89411
|
+
writePrivate(record3, JSON.stringify({ url: base, pid: process.pid }));
|
|
88606
89412
|
process.stdout.write(`AgentComputer on ${base}, data in ${data}
|
|
88607
89413
|
`);
|
|
88608
89414
|
let stopping = false;
|
|
@@ -88622,7 +89428,7 @@ ${JSON.stringify({ code: status, message })}
|
|
|
88622
89428
|
// src/main.ts
|
|
88623
89429
|
var USAGE = `Usage: agentcomputer <command> [--data DIR]
|
|
88624
89430
|
|
|
88625
|
-
serve [--listen HOST:PORT] [--
|
|
89431
|
+
serve [--listen HOST:PORT] [--image IMAGE]
|
|
88626
89432
|
[--tls-cert FILE --tls-key FILE | --tls-proxy] [--public-url URL] [--allow-origin ORIGIN]...
|
|
88627
89433
|
[--browser-name NAME] [--browser-path PATH]
|
|
88628
89434
|
run the service; 127.0.0.1:7878 by default, and
|
|
@@ -88631,11 +89437,16 @@ var USAGE = `Usage: agentcomputer <command> [--data DIR]
|
|
|
88631
89437
|
answers, printing where; one running is left as it is
|
|
88632
89438
|
down stop the service, and its computers with it
|
|
88633
89439
|
status where the service is running, if it is
|
|
88634
|
-
info the service's version
|
|
88635
|
-
|
|
88636
|
-
create --access none|read|files|terminal [--browser] [--workspace DIR
|
|
88637
|
-
[--isolation
|
|
88638
|
-
make a computer; prints its endpoints and
|
|
89440
|
+
info the service's version and what it offers: this computer,
|
|
89441
|
+
the kinds it makes, and their browsers, each ready or not
|
|
89442
|
+
create --access none|read|files|terminal [--browser] [--workspace DIR | --copy-from DIR]
|
|
89443
|
+
[--name NAME] [--isolation container] [--timeout SECONDS] [--metadata KEY=VALUE]...
|
|
89444
|
+
make a computer, in a container; prints its endpoints and
|
|
89445
|
+
token, once
|
|
89446
|
+
attach --access none|read|files|terminal --workspace DIR [--browser] [--name NAME]
|
|
89447
|
+
[--timeout SECONDS] [--metadata KEY=VALUE]...
|
|
89448
|
+
attach this computer, whole and acting as you, with DIR its
|
|
89449
|
+
work folder; prints its endpoints and token, once
|
|
88639
89450
|
list [--state running|stopped|failed]
|
|
88640
89451
|
the computers
|
|
88641
89452
|
get <id> one computer
|
|
@@ -88645,7 +89456,8 @@ var USAGE = `Usage: agentcomputer <command> [--data DIR]
|
|
|
88645
89456
|
logs <id> what its servers wrote
|
|
88646
89457
|
live <id> --surface terminal|files|browser|load [--mode watch|operate]
|
|
88647
89458
|
a one-time ticket to open one live, as a WebSocket
|
|
88648
|
-
kill <id> stop it and remove what the service made
|
|
89459
|
+
kill <id> stop it and remove what the service made, or detach this
|
|
89460
|
+
computer
|
|
88649
89461
|
|
|
88650
89462
|
--version prints this program's version, with no service.
|
|
88651
89463
|
|
|
@@ -88658,7 +89470,7 @@ var UsageError = class extends Error {
|
|
|
88658
89470
|
function dataFolder(given) {
|
|
88659
89471
|
const xdg = process.env.XDG_DATA_HOME;
|
|
88660
89472
|
return resolve5(
|
|
88661
|
-
given ?? process.env.AGENTCOMPUTER_DATA ?? (xdg &&
|
|
89473
|
+
given ?? process.env.AGENTCOMPUTER_DATA ?? (xdg && isAbsolute3(xdg) ? join11(xdg, "agentcomputer") : join11(homedir2(), ".local", "share", "agentcomputer"))
|
|
88662
89474
|
);
|
|
88663
89475
|
}
|
|
88664
89476
|
var none = (data) => `No service is running with its data in ${data}. Start one: agentcomputer up`;
|
|
@@ -88695,6 +89507,7 @@ async function main() {
|
|
|
88695
89507
|
output: { type: "string" },
|
|
88696
89508
|
access: { type: "string" },
|
|
88697
89509
|
workspace: { type: "string" },
|
|
89510
|
+
"copy-from": { type: "string" },
|
|
88698
89511
|
name: { type: "string" },
|
|
88699
89512
|
timeout: { type: "string" },
|
|
88700
89513
|
state: { type: "string" },
|
|
@@ -88732,8 +89545,9 @@ async function main() {
|
|
|
88732
89545
|
};
|
|
88733
89546
|
const milliseconds = (seconds2) => Number(seconds2) * 1e3;
|
|
88734
89547
|
const { isolation } = values;
|
|
88735
|
-
|
|
88736
|
-
|
|
89548
|
+
for (const flag of ["isolation", "copy-from"])
|
|
89549
|
+
if (values[flag] !== void 0 && command !== "create")
|
|
89550
|
+
throw new UsageError(`Only create takes --${flag}.`);
|
|
88737
89551
|
if (command === "serve") {
|
|
88738
89552
|
const { "tls-cert": cert, "tls-key": key } = values;
|
|
88739
89553
|
if (Boolean(cert) !== Boolean(key))
|
|
@@ -88745,7 +89559,6 @@ async function main() {
|
|
|
88745
89559
|
tlsProxy: values["tls-proxy"],
|
|
88746
89560
|
publicUrl: values["public-url"],
|
|
88747
89561
|
allowOrigins: values["allow-origin"],
|
|
88748
|
-
isolation: isolation ?? "none",
|
|
88749
89562
|
runtimes: {
|
|
88750
89563
|
none: new ProcessRuntime({ browser: values["browser-name"], path: values["browser-path"] }),
|
|
88751
89564
|
container: new ContainerRuntime(values.image ?? `${IMAGE}:${VERSION2}`)
|
|
@@ -88770,31 +89583,43 @@ async function main() {
|
|
|
88770
89583
|
browser: values.browser === true
|
|
88771
89584
|
});
|
|
88772
89585
|
const connection = connectionTo(data);
|
|
89586
|
+
const making = () => {
|
|
89587
|
+
if (!values.access) throw new UsageError(`${command} takes --access.`);
|
|
89588
|
+
return {
|
|
89589
|
+
...connection,
|
|
89590
|
+
access: values.access,
|
|
89591
|
+
...values.browser ? { browser: true } : {},
|
|
89592
|
+
...values.name ? { name: values.name } : {},
|
|
89593
|
+
...values.timeout ? { timeoutMs: milliseconds(values.timeout) } : {},
|
|
89594
|
+
...values.metadata ? {
|
|
89595
|
+
metadata: Object.fromEntries(
|
|
89596
|
+
values.metadata.map((pair) => {
|
|
89597
|
+
const at = pair.indexOf("=");
|
|
89598
|
+
if (at < 1) throw new UsageError("--metadata takes KEY=VALUE.");
|
|
89599
|
+
return [pair.slice(0, at), pair.slice(at + 1)];
|
|
89600
|
+
})
|
|
89601
|
+
)
|
|
89602
|
+
} : {}
|
|
89603
|
+
};
|
|
89604
|
+
};
|
|
89605
|
+
const printMade = async (computer) => out({ ...await computer.getInfo(), accessToken: computer.getMcpToken() });
|
|
88773
89606
|
switch (command) {
|
|
88774
89607
|
case "info":
|
|
88775
89608
|
return out(await Computer.serviceInfo(connection));
|
|
88776
|
-
case "create":
|
|
88777
|
-
|
|
88778
|
-
|
|
88779
|
-
|
|
88780
|
-
|
|
88781
|
-
|
|
88782
|
-
|
|
88783
|
-
|
|
88784
|
-
|
|
88785
|
-
|
|
88786
|
-
|
|
88787
|
-
|
|
88788
|
-
|
|
88789
|
-
|
|
88790
|
-
if (at < 1) throw new UsageError("--metadata takes KEY=VALUE.");
|
|
88791
|
-
return [pair.slice(0, at), pair.slice(at + 1)];
|
|
88792
|
-
})
|
|
88793
|
-
)
|
|
88794
|
-
} : {}
|
|
88795
|
-
});
|
|
88796
|
-
return out({ ...await computer.getInfo(), accessToken: computer.getMcpToken() });
|
|
88797
|
-
}
|
|
89609
|
+
case "create":
|
|
89610
|
+
return printMade(
|
|
89611
|
+
await Computer.create({
|
|
89612
|
+
...making(),
|
|
89613
|
+
...isolation ? { isolation } : {},
|
|
89614
|
+
...values.workspace ? { workspace: resolve5(values.workspace) } : {},
|
|
89615
|
+
...values["copy-from"] ? { copyFrom: resolve5(values["copy-from"]) } : {}
|
|
89616
|
+
})
|
|
89617
|
+
);
|
|
89618
|
+
case "attach":
|
|
89619
|
+
if (!values.workspace) throw new UsageError("attach takes --workspace.");
|
|
89620
|
+
return printMade(
|
|
89621
|
+
await Computer.attach({ ...making(), workspace: resolve5(values.workspace) })
|
|
89622
|
+
);
|
|
88798
89623
|
case "list":
|
|
88799
89624
|
return out(
|
|
88800
89625
|
await Computer.list({
|