@agentorg/computer 0.0.17 → 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 +1059 -233
- 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)
|
|
@@ -67031,6 +67047,7 @@ var BrowserLive = class {
|
|
|
67031
67047
|
} catch {
|
|
67032
67048
|
return;
|
|
67033
67049
|
}
|
|
67050
|
+
if (typeof message !== "object" || message === null) return;
|
|
67034
67051
|
this.#input(ws, viewer, message);
|
|
67035
67052
|
});
|
|
67036
67053
|
this.#begin().then(
|
|
@@ -67863,16 +67880,44 @@ var loadPty = () => {
|
|
|
67863
67880
|
})();
|
|
67864
67881
|
return pty;
|
|
67865
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
|
+
}
|
|
67866
67898
|
var ProcessRuntime = class {
|
|
67867
67899
|
#config;
|
|
67868
67900
|
#contained;
|
|
67869
|
-
/**
|
|
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
|
+
*/
|
|
67870
67906
|
constructor(config3, contained = false) {
|
|
67871
67907
|
this.#config = config3;
|
|
67872
67908
|
this.#contained = contained;
|
|
67873
67909
|
}
|
|
67874
|
-
async
|
|
67875
|
-
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
|
+
};
|
|
67876
67921
|
}
|
|
67877
67922
|
async prepare() {
|
|
67878
67923
|
}
|
|
@@ -67898,6 +67943,7 @@ var ProcessRuntime = class {
|
|
|
67898
67943
|
exec = createAgentExec({
|
|
67899
67944
|
workspace,
|
|
67900
67945
|
level: spec.access,
|
|
67946
|
+
reach: this.#contained ? "workspace" : "machine",
|
|
67901
67947
|
pty: await loadPty(),
|
|
67902
67948
|
extraTools: [about]
|
|
67903
67949
|
});
|
|
@@ -67958,16 +68004,13 @@ var ProcessRuntime = class {
|
|
|
67958
68004
|
};
|
|
67959
68005
|
|
|
67960
68006
|
// src/handlers.ts
|
|
67961
|
-
var VERSION2 = "0.0.
|
|
68007
|
+
var VERSION2 = "0.0.19";
|
|
67962
68008
|
function createHandlers(computers) {
|
|
67963
68009
|
return {
|
|
67964
|
-
getInfo: async () => ({
|
|
67965
|
-
version: VERSION2,
|
|
67966
|
-
isolation: computers.isolation,
|
|
67967
|
-
isolationsAvailable: await computers.available()
|
|
67968
|
-
}),
|
|
68010
|
+
getInfo: async () => ({ version: VERSION2, ...await computers.offers() }),
|
|
67969
68011
|
listComputers: async ({ state }) => computers.list(state),
|
|
67970
68012
|
createComputer: (input2) => computers.create(input2),
|
|
68013
|
+
attachComputer: (input2) => computers.attach(input2),
|
|
67971
68014
|
getComputer: async ({ computerID }) => computers.get(computerID),
|
|
67972
68015
|
killComputer: async ({ computerID }) => {
|
|
67973
68016
|
await computers.kill(computerID);
|
|
@@ -68039,9 +68082,9 @@ async function serveInside(options) {
|
|
|
68039
68082
|
server.on("upgrade", (request, socket, head) => {
|
|
68040
68083
|
socket.on("error", () => socket.destroy());
|
|
68041
68084
|
const given = /^Bearer (\S+)$/.exec(request.headers.authorization ?? "")?.[1];
|
|
68042
|
-
const url3 =
|
|
68043
|
-
const surface = /^\/live\/(terminal|files|browser|load)$/.exec(url3
|
|
68044
|
-
const mode = url3
|
|
68085
|
+
const url3 = URL.parse(request.url ?? "/", "http://localhost");
|
|
68086
|
+
const surface = /^\/live\/(terminal|files|browser|load)$/.exec(url3?.pathname ?? "")?.[1];
|
|
68087
|
+
const mode = url3?.searchParams.get("mode");
|
|
68045
68088
|
if (!given || !sameToken(given, digest) || !surface || mode !== "watch" && mode !== "operate")
|
|
68046
68089
|
return void socket.end("HTTP/1.1 401 Unauthorized\r\nConnection: close\r\n\r\n");
|
|
68047
68090
|
running2.then((computer) => computer.openLive(surface, mode, request, socket, head)).catch(() => socket.destroy());
|
|
@@ -68058,6 +68101,7 @@ async function serveInside(options) {
|
|
|
68058
68101
|
var run2 = promisify2(execFile2);
|
|
68059
68102
|
var START_MS2 = 6e4;
|
|
68060
68103
|
var STOP_SECONDS = "5";
|
|
68104
|
+
var NO_DOCKER = "A container needs Docker, which isn't answering on this machine.";
|
|
68061
68105
|
var NOT_FORWARDED = /* @__PURE__ */ new Set([
|
|
68062
68106
|
"authorization",
|
|
68063
68107
|
"connection",
|
|
@@ -68104,14 +68148,22 @@ var ContainerRuntime = class {
|
|
|
68104
68148
|
return false;
|
|
68105
68149
|
}
|
|
68106
68150
|
}
|
|
68107
|
-
//
|
|
68108
|
-
|
|
68109
|
-
|
|
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
|
+
};
|
|
68110
68163
|
}
|
|
68111
68164
|
/** Docker, or the refusal of what can't be done without it. */
|
|
68112
68165
|
async #docker() {
|
|
68113
|
-
if (!await this.#answers(1e4))
|
|
68114
|
-
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);
|
|
68115
68167
|
}
|
|
68116
68168
|
async prepare() {
|
|
68117
68169
|
await this.#docker();
|
|
@@ -68374,8 +68426,8 @@ async function running(data, said = recorded(data)) {
|
|
|
68374
68426
|
signal: AbortSignal.timeout(3e3)
|
|
68375
68427
|
});
|
|
68376
68428
|
if (!answer.ok) return void 0;
|
|
68377
|
-
const { version: version3
|
|
68378
|
-
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 };
|
|
68379
68431
|
} catch {
|
|
68380
68432
|
return void 0;
|
|
68381
68433
|
}
|
|
@@ -68911,6 +68963,19 @@ var ComputerError = class extends Error {
|
|
|
68911
68963
|
}
|
|
68912
68964
|
};
|
|
68913
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
|
+
}
|
|
68914
68979
|
function apiOf(opts = {}) {
|
|
68915
68980
|
const apiKey = opts.apiKey ?? process.env.AGENTCOMPUTER_API_KEY;
|
|
68916
68981
|
if (!apiKey) throw new ComputerError(401, "Pass apiKey, or set AGENTCOMPUTER_API_KEY.");
|
|
@@ -69110,23 +69175,30 @@ var Computer = class _Computer {
|
|
|
69110
69175
|
this.files = new Files(this.#computer);
|
|
69111
69176
|
}
|
|
69112
69177
|
static async create(opts) {
|
|
69113
|
-
const {
|
|
69114
|
-
const
|
|
69178
|
+
const { isolation, workspace, copyFrom } = opts;
|
|
69179
|
+
const { connection, body } = requestOf(opts);
|
|
69115
69180
|
const created = answered(
|
|
69116
69181
|
await apiOf(connection).POST("/v1/computers", {
|
|
69117
69182
|
body: {
|
|
69118
|
-
|
|
69119
|
-
browser: browser ?? false,
|
|
69183
|
+
...body,
|
|
69120
69184
|
...isolation === void 0 ? {} : { isolation },
|
|
69121
69185
|
...workspace === void 0 ? {} : { workspace },
|
|
69122
|
-
...
|
|
69123
|
-
...timeoutMs === void 0 ? {} : { timeout: seconds(timeoutMs) },
|
|
69124
|
-
...metadata === void 0 ? {} : { metadata }
|
|
69186
|
+
...copyFrom === void 0 ? {} : { copyFrom }
|
|
69125
69187
|
}
|
|
69126
69188
|
})
|
|
69127
69189
|
);
|
|
69128
69190
|
return new _Computer(connection, created, created.accessToken);
|
|
69129
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
|
+
}
|
|
69130
69202
|
/** A computer made earlier. Its token was shown when it was made, and only then. */
|
|
69131
69203
|
static async connect(computerID, opts) {
|
|
69132
69204
|
const { accessToken, ...connection } = opts;
|
|
@@ -75859,13 +75931,13 @@ var require_resolve3 = /* @__PURE__ */ __commonJSMin3(((exports) => {
|
|
|
75859
75931
|
}
|
|
75860
75932
|
return count;
|
|
75861
75933
|
}
|
|
75862
|
-
function getFullPath(
|
|
75934
|
+
function getFullPath(resolver2, id = "", normalize) {
|
|
75863
75935
|
if (normalize !== false) id = normalizeId(id);
|
|
75864
|
-
return _getFullPath(
|
|
75936
|
+
return _getFullPath(resolver2, resolver2.parse(id));
|
|
75865
75937
|
}
|
|
75866
75938
|
exports.getFullPath = getFullPath;
|
|
75867
|
-
function _getFullPath(
|
|
75868
|
-
return
|
|
75939
|
+
function _getFullPath(resolver2, p) {
|
|
75940
|
+
return resolver2.serialize(p).split("#")[0] + "#";
|
|
75869
75941
|
}
|
|
75870
75942
|
exports._getFullPath = _getFullPath;
|
|
75871
75943
|
const TRAILING_SLASH_HASH = /#\/?$/;
|
|
@@ -75873,9 +75945,9 @@ var require_resolve3 = /* @__PURE__ */ __commonJSMin3(((exports) => {
|
|
|
75873
75945
|
return id ? id.replace(TRAILING_SLASH_HASH, "") : "";
|
|
75874
75946
|
}
|
|
75875
75947
|
exports.normalizeId = normalizeId;
|
|
75876
|
-
function resolveUrl(
|
|
75948
|
+
function resolveUrl(resolver2, baseId, id) {
|
|
75877
75949
|
id = normalizeId(id);
|
|
75878
|
-
return
|
|
75950
|
+
return resolver2.resolve(baseId, id);
|
|
75879
75951
|
}
|
|
75880
75952
|
exports.resolveUrl = resolveUrl;
|
|
75881
75953
|
const ANCHOR = /^[a-z_][-a-z0-9._]*$/i;
|
|
@@ -76357,10 +76429,10 @@ var require_ref_error3 = /* @__PURE__ */ __commonJSMin3(((exports) => {
|
|
|
76357
76429
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
76358
76430
|
const resolve_1 = require_resolve3();
|
|
76359
76431
|
var MissingRefError = class extends Error {
|
|
76360
|
-
constructor(
|
|
76432
|
+
constructor(resolver2, baseId, ref, msg) {
|
|
76361
76433
|
super(msg || `can't resolve reference ${ref} from id ${baseId}`);
|
|
76362
|
-
this.missingRef = (0, resolve_1.resolveUrl)(
|
|
76363
|
-
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));
|
|
76364
76436
|
}
|
|
76365
76437
|
};
|
|
76366
76438
|
exports.default = MissingRefError;
|
|
@@ -76604,10 +76676,10 @@ var require_utils3 = /* @__PURE__ */ __commonJSMin3(((exports, module) => {
|
|
|
76604
76676
|
const HEX_DIGITS = "0123456789ABCDEF";
|
|
76605
76677
|
for (let i = 0; i < 256; i++) BYTE_HEX[i] = "%" + HEX_DIGITS[i >> 4] + HEX_DIGITS[i & 15];
|
|
76606
76678
|
}
|
|
76607
|
-
function percentEncodeNonAscii(
|
|
76608
|
-
if (
|
|
76609
|
-
if (
|
|
76610
|
-
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];
|
|
76611
76683
|
}
|
|
76612
76684
|
function stringArrayToHexStripped(input2) {
|
|
76613
76685
|
let acc = "";
|
|
@@ -76947,8 +77019,8 @@ var require_utils3 = /* @__PURE__ */ __commonJSMin3(((exports, module) => {
|
|
|
76947
77019
|
function encodeFragment(input2) {
|
|
76948
77020
|
return encodeComponent(input2, isQueryFragmentCharacter);
|
|
76949
77021
|
}
|
|
76950
|
-
function isEscapeSafe(
|
|
76951
|
-
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;
|
|
76952
77024
|
}
|
|
76953
77025
|
function normalizeQueryFragmentEncoding(input2) {
|
|
76954
77026
|
let output2 = "";
|
|
@@ -83100,8 +83172,8 @@ var WebStandardStreamableHTTPServerTransport2 = class {
|
|
|
83100
83172
|
return timer;
|
|
83101
83173
|
}
|
|
83102
83174
|
/** Sets the scope challenge resolver for parsed JSON-RPC requests. */
|
|
83103
|
-
setScopeChallengeResolver(
|
|
83104
|
-
this._scopeChallengeResolver =
|
|
83175
|
+
setScopeChallengeResolver(resolver2) {
|
|
83176
|
+
this._scopeChallengeResolver = resolver2;
|
|
83105
83177
|
}
|
|
83106
83178
|
/**
|
|
83107
83179
|
* Starts the transport. This is required by the {@linkcode Transport} interface but is a no-op
|
|
@@ -85001,8 +85073,8 @@ var NodeStreamableHTTPServerTransport2 = class {
|
|
|
85001
85073
|
this._webStandardTransport.setSupportedProtocolVersions(versions);
|
|
85002
85074
|
}
|
|
85003
85075
|
/** Sets the scope challenge resolver used by the wrapped Web Standard transport. */
|
|
85004
|
-
setScopeChallengeResolver(
|
|
85005
|
-
this._webStandardTransport.setScopeChallengeResolver(
|
|
85076
|
+
setScopeChallengeResolver(resolver2) {
|
|
85077
|
+
this._webStandardTransport.setScopeChallengeResolver(resolver2);
|
|
85006
85078
|
}
|
|
85007
85079
|
/**
|
|
85008
85080
|
* Handles an incoming HTTP request, whether `GET` or `POST`.
|
|
@@ -85042,8 +85114,19 @@ var NodeStreamableHTTPServerTransport2 = class {
|
|
|
85042
85114
|
|
|
85043
85115
|
// src/computers.ts
|
|
85044
85116
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
85045
|
-
import {
|
|
85046
|
-
|
|
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";
|
|
85047
85130
|
var READ = ["about", "read", "list", "search"];
|
|
85048
85131
|
var FILES = [...READ, "edit"];
|
|
85049
85132
|
var TOOLS2 = {
|
|
@@ -85056,32 +85139,59 @@ var MAX_TIMER_S = 2e6;
|
|
|
85056
85139
|
var TICKET_MS = 6e4;
|
|
85057
85140
|
var expiry = (seconds2) => new Date(Date.now() + seconds2 * 1e3).toISOString();
|
|
85058
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
|
+
}
|
|
85059
85165
|
var refusalOf = (error62) => error62 instanceof ApiError ? error62 : new ApiError(500, messageOf2(error62));
|
|
85060
85166
|
var Computers = class {
|
|
85061
85167
|
#data;
|
|
85062
85168
|
#base;
|
|
85169
|
+
/** This computer's way of running, as `none`, and each way of making one. */
|
|
85063
85170
|
#runtimes;
|
|
85064
|
-
/**
|
|
85065
|
-
|
|
85171
|
+
/** Why this computer isn't offered here, where it isn't. */
|
|
85172
|
+
#notHere;
|
|
85066
85173
|
#stored = /* @__PURE__ */ new Map();
|
|
85067
85174
|
#live = /* @__PURE__ */ new Map();
|
|
85068
85175
|
#tickets = /* @__PURE__ */ new Map();
|
|
85069
85176
|
#file;
|
|
85070
|
-
constructor(data, base, runtimes,
|
|
85177
|
+
constructor(data, base, runtimes, notHere) {
|
|
85071
85178
|
this.#data = data;
|
|
85072
85179
|
this.#base = base;
|
|
85073
85180
|
this.#runtimes = runtimes;
|
|
85074
|
-
this
|
|
85181
|
+
this.#notHere = notHere;
|
|
85075
85182
|
this.#file = join10(data, "computers.json");
|
|
85076
85183
|
if (existsSync2(this.#file))
|
|
85077
85184
|
for (const entry of JSON.parse(readFileSync5(this.#file, "utf8")))
|
|
85078
|
-
this.#stored.set(entry.id, { ...entry, isolation: entry.isolation ??
|
|
85079
|
-
}
|
|
85080
|
-
/**
|
|
85081
|
-
async
|
|
85082
|
-
const
|
|
85083
|
-
const
|
|
85084
|
-
|
|
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 };
|
|
85085
85195
|
}
|
|
85086
85196
|
/** Bring back what was running when the service last stopped. */
|
|
85087
85197
|
async resume() {
|
|
@@ -85104,20 +85214,34 @@ var Computers = class {
|
|
|
85104
85214
|
this.#save();
|
|
85105
85215
|
}
|
|
85106
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) {
|
|
85107
85229
|
const { access, name, timeout, metadata } = input2;
|
|
85108
85230
|
const browser = input2.browser === true;
|
|
85109
85231
|
if (access === "none" && !browser)
|
|
85110
85232
|
throw new ApiError(400, "With no files, no commands and no browser, there's no computer.");
|
|
85111
|
-
|
|
85112
|
-
|
|
85113
|
-
|
|
85114
|
-
|
|
85115
|
-
|
|
85116
|
-
|
|
85117
|
-
|
|
85118
|
-
|
|
85119
|
-
|
|
85120
|
-
|
|
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));
|
|
85121
85245
|
const id = `c_${randomBytes5(9).toString("hex")}`;
|
|
85122
85246
|
const token = newToken();
|
|
85123
85247
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -85125,7 +85249,8 @@ var Computers = class {
|
|
|
85125
85249
|
id,
|
|
85126
85250
|
name: name ?? id,
|
|
85127
85251
|
access,
|
|
85128
|
-
isolation
|
|
85252
|
+
isolation,
|
|
85253
|
+
...isolation === "none" ? { attached: true } : {},
|
|
85129
85254
|
browser,
|
|
85130
85255
|
...workspace ? { workspace } : {},
|
|
85131
85256
|
metadata: metadata ?? {},
|
|
@@ -85136,8 +85261,21 @@ var Computers = class {
|
|
|
85136
85261
|
...timeout === void 0 ? {} : { endAt: expiry(timeout) }
|
|
85137
85262
|
};
|
|
85138
85263
|
if (!workspace && access !== "none") {
|
|
85139
|
-
|
|
85140
|
-
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
|
+
});
|
|
85141
85279
|
}
|
|
85142
85280
|
this.#stored.set(id, stored);
|
|
85143
85281
|
try {
|
|
@@ -85147,7 +85285,10 @@ var Computers = class {
|
|
|
85147
85285
|
this.#stored.delete(id);
|
|
85148
85286
|
await this.#runtimes[stored.isolation].remove(id).catch(() => {
|
|
85149
85287
|
});
|
|
85150
|
-
|
|
85288
|
+
try {
|
|
85289
|
+
removeFolder(this.#folder(id));
|
|
85290
|
+
} catch {
|
|
85291
|
+
}
|
|
85151
85292
|
throw refusalOf(error62);
|
|
85152
85293
|
}
|
|
85153
85294
|
this.#save();
|
|
@@ -85221,7 +85362,12 @@ var Computers = class {
|
|
|
85221
85362
|
}
|
|
85222
85363
|
this.#stored.delete(id);
|
|
85223
85364
|
this.#save();
|
|
85224
|
-
|
|
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);
|
|
85225
85371
|
}
|
|
85226
85372
|
logs(id) {
|
|
85227
85373
|
this.#found(id);
|
|
@@ -85322,6 +85468,7 @@ var Computers = class {
|
|
|
85322
85468
|
state: stored.state === "running" && down2 ? "failed" : stored.state,
|
|
85323
85469
|
access: stored.access,
|
|
85324
85470
|
isolation: stored.isolation,
|
|
85471
|
+
attached: stored.attached === true,
|
|
85325
85472
|
version: stored.version ?? null,
|
|
85326
85473
|
browser: stored.browser,
|
|
85327
85474
|
workspace: stored.workspace ?? null,
|
|
@@ -85337,6 +85484,9 @@ var Computers = class {
|
|
|
85337
85484
|
async #start(stored) {
|
|
85338
85485
|
const live = {};
|
|
85339
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);
|
|
85340
85490
|
stored.startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
85341
85491
|
const runtime = this.#runtimes[stored.isolation];
|
|
85342
85492
|
await runtime.prepare();
|
|
@@ -85396,7 +85546,7 @@ var OPENAPI = {
|
|
|
85396
85546
|
"openapi": "3.1.0",
|
|
85397
85547
|
"info": {
|
|
85398
85548
|
"title": "AgentComputer",
|
|
85399
|
-
"version": "0.0.
|
|
85549
|
+
"version": "0.0.19",
|
|
85400
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.",
|
|
85401
85551
|
"license": {
|
|
85402
85552
|
"name": "Apache-2.0",
|
|
@@ -85419,7 +85569,7 @@ var OPENAPI = {
|
|
|
85419
85569
|
"get": {
|
|
85420
85570
|
"operationId": "getInfo",
|
|
85421
85571
|
"x-mcp-tool": "service_info",
|
|
85422
|
-
"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.",
|
|
85423
85573
|
"responses": {
|
|
85424
85574
|
"200": {
|
|
85425
85575
|
"description": "The service.",
|
|
@@ -85501,6 +85651,47 @@ var OPENAPI = {
|
|
|
85501
85651
|
},
|
|
85502
85652
|
"401": {
|
|
85503
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"
|
|
85504
85695
|
}
|
|
85505
85696
|
}
|
|
85506
85697
|
}
|
|
@@ -85674,6 +85865,9 @@ var OPENAPI = {
|
|
|
85674
85865
|
},
|
|
85675
85866
|
"404": {
|
|
85676
85867
|
"$ref": "#/components/responses/Error"
|
|
85868
|
+
},
|
|
85869
|
+
"409": {
|
|
85870
|
+
"$ref": "#/components/responses/Error"
|
|
85677
85871
|
}
|
|
85678
85872
|
}
|
|
85679
85873
|
}
|
|
@@ -85898,9 +86092,48 @@ var OPENAPI = {
|
|
|
85898
86092
|
"maxLength": 4096,
|
|
85899
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."
|
|
85900
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
|
+
},
|
|
85901
86100
|
"isolation": {
|
|
85902
86101
|
"$ref": "#/components/schemas/Isolation",
|
|
85903
|
-
"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."
|
|
85904
86137
|
},
|
|
85905
86138
|
"timeout": {
|
|
85906
86139
|
"$ref": "#/components/schemas/Timeout"
|
|
@@ -85916,7 +86149,7 @@ var OPENAPI = {
|
|
|
85916
86149
|
"none",
|
|
85917
86150
|
"container"
|
|
85918
86151
|
],
|
|
85919
|
-
"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."
|
|
85920
86153
|
},
|
|
85921
86154
|
"Endpoints": {
|
|
85922
86155
|
"type": "object",
|
|
@@ -85950,6 +86183,7 @@ var OPENAPI = {
|
|
|
85950
86183
|
"state",
|
|
85951
86184
|
"access",
|
|
85952
86185
|
"isolation",
|
|
86186
|
+
"attached",
|
|
85953
86187
|
"version",
|
|
85954
86188
|
"browser",
|
|
85955
86189
|
"workspace",
|
|
@@ -85975,12 +86209,16 @@ var OPENAPI = {
|
|
|
85975
86209
|
"$ref": "#/components/schemas/Isolation",
|
|
85976
86210
|
"description": "The isolation it was made in. It is never run in another."
|
|
85977
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
|
+
},
|
|
85978
86216
|
"version": {
|
|
85979
86217
|
"type": [
|
|
85980
86218
|
"string",
|
|
85981
86219
|
"null"
|
|
85982
86220
|
],
|
|
85983
|
-
"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."
|
|
85984
86222
|
},
|
|
85985
86223
|
"browser": {
|
|
85986
86224
|
"type": "boolean"
|
|
@@ -86764,7 +87002,7 @@ var OPENAPI = {
|
|
|
86764
87002
|
"computer",
|
|
86765
87003
|
"machine"
|
|
86766
87004
|
],
|
|
86767
|
-
"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."
|
|
86768
87006
|
},
|
|
86769
87007
|
"cpuUsedPct": {
|
|
86770
87008
|
"type": "number",
|
|
@@ -87136,27 +87374,143 @@ var OPENAPI = {
|
|
|
87136
87374
|
}
|
|
87137
87375
|
}
|
|
87138
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
|
+
},
|
|
87139
87493
|
"ServiceInfo": {
|
|
87140
87494
|
"type": "object",
|
|
87141
87495
|
"required": [
|
|
87142
87496
|
"version",
|
|
87143
|
-
"
|
|
87144
|
-
"
|
|
87497
|
+
"thisComputer",
|
|
87498
|
+
"made"
|
|
87145
87499
|
],
|
|
87146
87500
|
"properties": {
|
|
87147
87501
|
"version": {
|
|
87148
87502
|
"type": "string"
|
|
87149
87503
|
},
|
|
87150
|
-
"
|
|
87151
|
-
"$ref": "#/components/schemas/
|
|
87152
|
-
"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."
|
|
87153
87507
|
},
|
|
87154
|
-
"
|
|
87508
|
+
"made": {
|
|
87155
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.",
|
|
87156
87511
|
"items": {
|
|
87157
|
-
"$ref": "#/components/schemas/
|
|
87158
|
-
}
|
|
87159
|
-
"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
|
+
}
|
|
87160
87514
|
}
|
|
87161
87515
|
}
|
|
87162
87516
|
}
|
|
@@ -87169,7 +87523,7 @@ var OPERATIONS = [
|
|
|
87169
87523
|
"method": "GET",
|
|
87170
87524
|
"path": "/v1/info",
|
|
87171
87525
|
"tool": "service_info",
|
|
87172
|
-
"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.",
|
|
87173
87527
|
"status": 200,
|
|
87174
87528
|
"hasBody": false,
|
|
87175
87529
|
"pathParameters": [],
|
|
@@ -87184,32 +87538,251 @@ var OPERATIONS = [
|
|
|
87184
87538
|
"type": "object",
|
|
87185
87539
|
"required": [
|
|
87186
87540
|
"version",
|
|
87187
|
-
"
|
|
87188
|
-
"
|
|
87541
|
+
"thisComputer",
|
|
87542
|
+
"made"
|
|
87189
87543
|
],
|
|
87190
87544
|
"properties": {
|
|
87191
87545
|
"version": {
|
|
87192
87546
|
"type": "string"
|
|
87193
87547
|
},
|
|
87194
|
-
"
|
|
87195
|
-
"
|
|
87196
|
-
|
|
87197
|
-
|
|
87198
|
-
|
|
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
|
+
}
|
|
87199
87653
|
],
|
|
87200
|
-
"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."
|
|
87201
87655
|
},
|
|
87202
|
-
"
|
|
87656
|
+
"made": {
|
|
87203
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.",
|
|
87204
87659
|
"items": {
|
|
87205
|
-
"
|
|
87206
|
-
|
|
87207
|
-
|
|
87208
|
-
|
|
87209
|
-
|
|
87210
|
-
|
|
87211
|
-
|
|
87212
|
-
|
|
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
|
+
}
|
|
87213
87786
|
}
|
|
87214
87787
|
}
|
|
87215
87788
|
},
|
|
@@ -87253,6 +87826,7 @@ var OPERATIONS = [
|
|
|
87253
87826
|
"state",
|
|
87254
87827
|
"access",
|
|
87255
87828
|
"isolation",
|
|
87829
|
+
"attached",
|
|
87256
87830
|
"version",
|
|
87257
87831
|
"browser",
|
|
87258
87832
|
"workspace",
|
|
@@ -87295,12 +87869,16 @@ var OPERATIONS = [
|
|
|
87295
87869
|
],
|
|
87296
87870
|
"description": "The isolation it was made in. It is never run in another."
|
|
87297
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
|
+
},
|
|
87298
87876
|
"version": {
|
|
87299
87877
|
"type": [
|
|
87300
87878
|
"string",
|
|
87301
87879
|
"null"
|
|
87302
87880
|
],
|
|
87303
|
-
"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."
|
|
87304
87882
|
},
|
|
87305
87883
|
"browser": {
|
|
87306
87884
|
"type": "boolean"
|
|
@@ -87401,13 +87979,18 @@ var OPERATIONS = [
|
|
|
87401
87979
|
"maxLength": 4096,
|
|
87402
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."
|
|
87403
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
|
+
},
|
|
87404
87987
|
"isolation": {
|
|
87405
87988
|
"type": "string",
|
|
87406
87989
|
"enum": [
|
|
87407
87990
|
"none",
|
|
87408
87991
|
"container"
|
|
87409
87992
|
],
|
|
87410
|
-
"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."
|
|
87411
87994
|
},
|
|
87412
87995
|
"timeout": {
|
|
87413
87996
|
"type": "integer",
|
|
@@ -87438,6 +88021,203 @@ var OPERATIONS = [
|
|
|
87438
88021
|
"state",
|
|
87439
88022
|
"access",
|
|
87440
88023
|
"isolation",
|
|
88024
|
+
"attached",
|
|
88025
|
+
"version",
|
|
88026
|
+
"browser",
|
|
88027
|
+
"workspace",
|
|
88028
|
+
"startedAt",
|
|
88029
|
+
"endAt",
|
|
88030
|
+
"metadata",
|
|
88031
|
+
"endpoints"
|
|
88032
|
+
],
|
|
88033
|
+
"properties": {
|
|
88034
|
+
"computerID": {
|
|
88035
|
+
"type": "string"
|
|
88036
|
+
},
|
|
88037
|
+
"name": {
|
|
88038
|
+
"type": "string"
|
|
88039
|
+
},
|
|
88040
|
+
"state": {
|
|
88041
|
+
"type": "string",
|
|
88042
|
+
"enum": [
|
|
88043
|
+
"running",
|
|
88044
|
+
"stopped",
|
|
88045
|
+
"failed"
|
|
88046
|
+
],
|
|
88047
|
+
"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."
|
|
88048
|
+
},
|
|
88049
|
+
"access": {
|
|
88050
|
+
"type": "string",
|
|
88051
|
+
"enum": [
|
|
88052
|
+
"none",
|
|
88053
|
+
"read",
|
|
88054
|
+
"files",
|
|
88055
|
+
"terminal"
|
|
88056
|
+
],
|
|
88057
|
+
"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."
|
|
88058
|
+
},
|
|
88059
|
+
"isolation": {
|
|
88060
|
+
"type": "string",
|
|
88061
|
+
"enum": [
|
|
88062
|
+
"none",
|
|
88063
|
+
"container"
|
|
88064
|
+
],
|
|
88065
|
+
"description": "The isolation it was made in. It is never run in another."
|
|
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
|
+
},
|
|
88071
|
+
"version": {
|
|
88072
|
+
"type": [
|
|
88073
|
+
"string",
|
|
88074
|
+
"null"
|
|
88075
|
+
],
|
|
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",
|
|
87441
88221
|
"version",
|
|
87442
88222
|
"browser",
|
|
87443
88223
|
"workspace",
|
|
@@ -87480,12 +88260,16 @@ var OPERATIONS = [
|
|
|
87480
88260
|
],
|
|
87481
88261
|
"description": "The isolation it was made in. It is never run in another."
|
|
87482
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
|
+
},
|
|
87483
88267
|
"version": {
|
|
87484
88268
|
"type": [
|
|
87485
88269
|
"string",
|
|
87486
88270
|
"null"
|
|
87487
88271
|
],
|
|
87488
|
-
"description": "The version of the program it ran at its last start.
|
|
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."
|
|
87489
88273
|
},
|
|
87490
88274
|
"browser": {
|
|
87491
88275
|
"type": "boolean"
|
|
@@ -87596,6 +88380,7 @@ var OPERATIONS = [
|
|
|
87596
88380
|
"state",
|
|
87597
88381
|
"access",
|
|
87598
88382
|
"isolation",
|
|
88383
|
+
"attached",
|
|
87599
88384
|
"version",
|
|
87600
88385
|
"browser",
|
|
87601
88386
|
"workspace",
|
|
@@ -87638,12 +88423,16 @@ var OPERATIONS = [
|
|
|
87638
88423
|
],
|
|
87639
88424
|
"description": "The isolation it was made in. It is never run in another."
|
|
87640
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
|
+
},
|
|
87641
88430
|
"version": {
|
|
87642
88431
|
"type": [
|
|
87643
88432
|
"string",
|
|
87644
88433
|
"null"
|
|
87645
88434
|
],
|
|
87646
|
-
"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."
|
|
87647
88436
|
},
|
|
87648
88437
|
"browser": {
|
|
87649
88438
|
"type": "boolean"
|
|
@@ -87845,6 +88634,7 @@ var OPERATIONS = [
|
|
|
87845
88634
|
"state",
|
|
87846
88635
|
"access",
|
|
87847
88636
|
"isolation",
|
|
88637
|
+
"attached",
|
|
87848
88638
|
"version",
|
|
87849
88639
|
"browser",
|
|
87850
88640
|
"workspace",
|
|
@@ -87887,12 +88677,16 @@ var OPERATIONS = [
|
|
|
87887
88677
|
],
|
|
87888
88678
|
"description": "The isolation it was made in. It is never run in another."
|
|
87889
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
|
+
},
|
|
87890
88684
|
"version": {
|
|
87891
88685
|
"type": [
|
|
87892
88686
|
"string",
|
|
87893
88687
|
"null"
|
|
87894
88688
|
],
|
|
87895
|
-
"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."
|
|
87896
88690
|
},
|
|
87897
88691
|
"browser": {
|
|
87898
88692
|
"type": "boolean"
|
|
@@ -87987,6 +88781,7 @@ var OPERATIONS = [
|
|
|
87987
88781
|
"state",
|
|
87988
88782
|
"access",
|
|
87989
88783
|
"isolation",
|
|
88784
|
+
"attached",
|
|
87990
88785
|
"version",
|
|
87991
88786
|
"browser",
|
|
87992
88787
|
"workspace",
|
|
@@ -88029,12 +88824,16 @@ var OPERATIONS = [
|
|
|
88029
88824
|
],
|
|
88030
88825
|
"description": "The isolation it was made in. It is never run in another."
|
|
88031
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
|
+
},
|
|
88032
88831
|
"version": {
|
|
88033
88832
|
"type": [
|
|
88034
88833
|
"string",
|
|
88035
88834
|
"null"
|
|
88036
88835
|
],
|
|
88037
|
-
"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."
|
|
88038
88837
|
},
|
|
88039
88838
|
"browser": {
|
|
88040
88839
|
"type": "boolean"
|
|
@@ -88134,6 +88933,7 @@ var OPERATIONS = [
|
|
|
88134
88933
|
"state",
|
|
88135
88934
|
"access",
|
|
88136
88935
|
"isolation",
|
|
88936
|
+
"attached",
|
|
88137
88937
|
"version",
|
|
88138
88938
|
"browser",
|
|
88139
88939
|
"workspace",
|
|
@@ -88176,12 +88976,16 @@ var OPERATIONS = [
|
|
|
88176
88976
|
],
|
|
88177
88977
|
"description": "The isolation it was made in. It is never run in another."
|
|
88178
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
|
+
},
|
|
88179
88983
|
"version": {
|
|
88180
88984
|
"type": [
|
|
88181
88985
|
"string",
|
|
88182
88986
|
"null"
|
|
88183
88987
|
],
|
|
88184
|
-
"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."
|
|
88185
88989
|
},
|
|
88186
88990
|
"browser": {
|
|
88187
88991
|
"type": "boolean"
|
|
@@ -88425,6 +89229,8 @@ var OPERATIONS = [
|
|
|
88425
89229
|
var LOOPBACK = /* @__PURE__ */ new Set(["127.0.0.1", "localhost", "::1"]);
|
|
88426
89230
|
var WILDCARD = /* @__PURE__ */ new Set(["0.0.0.0", "::"]);
|
|
88427
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;
|
|
88428
89234
|
function checkExposure(host, options) {
|
|
88429
89235
|
const { tls, tlsProxy, publicUrl } = options;
|
|
88430
89236
|
if (tls && tlsProxy) throw new Error("--tls-cert and --tls-proxy are alternatives.");
|
|
@@ -88474,8 +89280,12 @@ async function serve(options) {
|
|
|
88474
89280
|
if (live)
|
|
88475
89281
|
throw new Error(`A service is already running with its data in ${data}, at ${live.url}.`);
|
|
88476
89282
|
let base = "";
|
|
88477
|
-
|
|
88478
|
-
|
|
89283
|
+
const computers = new Computers(
|
|
89284
|
+
data,
|
|
89285
|
+
() => base,
|
|
89286
|
+
options.runtimes,
|
|
89287
|
+
onlyThisMachine(host, options) ? void 0 : NOT_HERE
|
|
89288
|
+
);
|
|
88479
89289
|
const handlers = createHandlers(computers);
|
|
88480
89290
|
const routes = OPERATIONS.map((operation) => ({
|
|
88481
89291
|
operation,
|
|
@@ -88577,13 +89387,13 @@ Connection: close\r
|
|
|
88577
89387
|
${JSON.stringify({ code: status, message })}
|
|
88578
89388
|
`
|
|
88579
89389
|
);
|
|
88580
|
-
const
|
|
89390
|
+
const pathname = URL.parse(request.url ?? "/", "http://localhost")?.pathname ?? "";
|
|
88581
89391
|
const ticket = /^\/v1\/live\/([^/]+)$/.exec(pathname)?.[1];
|
|
88582
89392
|
if (!ticket) return refuse(404, "Not found.");
|
|
88583
89393
|
const origin = request.headers.origin;
|
|
88584
89394
|
if (origin !== void 0 && !allowed.has(origin))
|
|
88585
89395
|
return refuse(403, `A live session isn't opened from ${origin.slice(0, 200)}.`);
|
|
88586
|
-
computers.openLive(
|
|
89396
|
+
computers.openLive(ticket, request, socket, head).catch((error62) => {
|
|
88587
89397
|
if (error62 instanceof ApiError) refuse(error62.status, error62.message);
|
|
88588
89398
|
else socket.destroy();
|
|
88589
89399
|
});
|
|
@@ -88598,10 +89408,7 @@ ${JSON.stringify({ code: status, message })}
|
|
|
88598
89408
|
const record3 = recordOf(data);
|
|
88599
89409
|
rmSync6(record3, { force: true });
|
|
88600
89410
|
await computers.resume();
|
|
88601
|
-
writePrivate(
|
|
88602
|
-
record3,
|
|
88603
|
-
JSON.stringify({ url: base, pid: process.pid, isolation: options.isolation })
|
|
88604
|
-
);
|
|
89411
|
+
writePrivate(record3, JSON.stringify({ url: base, pid: process.pid }));
|
|
88605
89412
|
process.stdout.write(`AgentComputer on ${base}, data in ${data}
|
|
88606
89413
|
`);
|
|
88607
89414
|
let stopping = false;
|
|
@@ -88621,7 +89428,7 @@ ${JSON.stringify({ code: status, message })}
|
|
|
88621
89428
|
// src/main.ts
|
|
88622
89429
|
var USAGE = `Usage: agentcomputer <command> [--data DIR]
|
|
88623
89430
|
|
|
88624
|
-
serve [--listen HOST:PORT] [--
|
|
89431
|
+
serve [--listen HOST:PORT] [--image IMAGE]
|
|
88625
89432
|
[--tls-cert FILE --tls-key FILE | --tls-proxy] [--public-url URL] [--allow-origin ORIGIN]...
|
|
88626
89433
|
[--browser-name NAME] [--browser-path PATH]
|
|
88627
89434
|
run the service; 127.0.0.1:7878 by default, and
|
|
@@ -88630,11 +89437,16 @@ var USAGE = `Usage: agentcomputer <command> [--data DIR]
|
|
|
88630
89437
|
answers, printing where; one running is left as it is
|
|
88631
89438
|
down stop the service, and its computers with it
|
|
88632
89439
|
status where the service is running, if it is
|
|
88633
|
-
info the service's version
|
|
88634
|
-
|
|
88635
|
-
create --access none|read|files|terminal [--browser] [--workspace DIR
|
|
88636
|
-
[--isolation
|
|
88637
|
-
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
|
|
88638
89450
|
list [--state running|stopped|failed]
|
|
88639
89451
|
the computers
|
|
88640
89452
|
get <id> one computer
|
|
@@ -88644,7 +89456,8 @@ var USAGE = `Usage: agentcomputer <command> [--data DIR]
|
|
|
88644
89456
|
logs <id> what its servers wrote
|
|
88645
89457
|
live <id> --surface terminal|files|browser|load [--mode watch|operate]
|
|
88646
89458
|
a one-time ticket to open one live, as a WebSocket
|
|
88647
|
-
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
|
|
88648
89461
|
|
|
88649
89462
|
--version prints this program's version, with no service.
|
|
88650
89463
|
|
|
@@ -88657,7 +89470,7 @@ var UsageError = class extends Error {
|
|
|
88657
89470
|
function dataFolder(given) {
|
|
88658
89471
|
const xdg = process.env.XDG_DATA_HOME;
|
|
88659
89472
|
return resolve5(
|
|
88660
|
-
given ?? process.env.AGENTCOMPUTER_DATA ?? (xdg &&
|
|
89473
|
+
given ?? process.env.AGENTCOMPUTER_DATA ?? (xdg && isAbsolute3(xdg) ? join11(xdg, "agentcomputer") : join11(homedir2(), ".local", "share", "agentcomputer"))
|
|
88661
89474
|
);
|
|
88662
89475
|
}
|
|
88663
89476
|
var none = (data) => `No service is running with its data in ${data}. Start one: agentcomputer up`;
|
|
@@ -88694,6 +89507,7 @@ async function main() {
|
|
|
88694
89507
|
output: { type: "string" },
|
|
88695
89508
|
access: { type: "string" },
|
|
88696
89509
|
workspace: { type: "string" },
|
|
89510
|
+
"copy-from": { type: "string" },
|
|
88697
89511
|
name: { type: "string" },
|
|
88698
89512
|
timeout: { type: "string" },
|
|
88699
89513
|
state: { type: "string" },
|
|
@@ -88731,8 +89545,9 @@ async function main() {
|
|
|
88731
89545
|
};
|
|
88732
89546
|
const milliseconds = (seconds2) => Number(seconds2) * 1e3;
|
|
88733
89547
|
const { isolation } = values;
|
|
88734
|
-
|
|
88735
|
-
|
|
89548
|
+
for (const flag of ["isolation", "copy-from"])
|
|
89549
|
+
if (values[flag] !== void 0 && command !== "create")
|
|
89550
|
+
throw new UsageError(`Only create takes --${flag}.`);
|
|
88736
89551
|
if (command === "serve") {
|
|
88737
89552
|
const { "tls-cert": cert, "tls-key": key } = values;
|
|
88738
89553
|
if (Boolean(cert) !== Boolean(key))
|
|
@@ -88744,7 +89559,6 @@ async function main() {
|
|
|
88744
89559
|
tlsProxy: values["tls-proxy"],
|
|
88745
89560
|
publicUrl: values["public-url"],
|
|
88746
89561
|
allowOrigins: values["allow-origin"],
|
|
88747
|
-
isolation: isolation ?? "none",
|
|
88748
89562
|
runtimes: {
|
|
88749
89563
|
none: new ProcessRuntime({ browser: values["browser-name"], path: values["browser-path"] }),
|
|
88750
89564
|
container: new ContainerRuntime(values.image ?? `${IMAGE}:${VERSION2}`)
|
|
@@ -88769,31 +89583,43 @@ async function main() {
|
|
|
88769
89583
|
browser: values.browser === true
|
|
88770
89584
|
});
|
|
88771
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() });
|
|
88772
89606
|
switch (command) {
|
|
88773
89607
|
case "info":
|
|
88774
89608
|
return out(await Computer.serviceInfo(connection));
|
|
88775
|
-
case "create":
|
|
88776
|
-
|
|
88777
|
-
|
|
88778
|
-
|
|
88779
|
-
|
|
88780
|
-
|
|
88781
|
-
|
|
88782
|
-
|
|
88783
|
-
|
|
88784
|
-
|
|
88785
|
-
|
|
88786
|
-
|
|
88787
|
-
|
|
88788
|
-
|
|
88789
|
-
if (at < 1) throw new UsageError("--metadata takes KEY=VALUE.");
|
|
88790
|
-
return [pair.slice(0, at), pair.slice(at + 1)];
|
|
88791
|
-
})
|
|
88792
|
-
)
|
|
88793
|
-
} : {}
|
|
88794
|
-
});
|
|
88795
|
-
return out({ ...await computer.getInfo(), accessToken: computer.getMcpToken() });
|
|
88796
|
-
}
|
|
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
|
+
);
|
|
88797
89623
|
case "list":
|
|
88798
89624
|
return out(
|
|
88799
89625
|
await Computer.list({
|