@agentorg/computer 0.0.10 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -148,7 +148,7 @@ A computer at `--access terminal` has a surface you can open live, as a WebSocke
148
148
  A computer at `--access read` or above has another, and at `read` it is the only one:
149
149
 
150
150
  - **`files`** (protocol `files@1`): its workspace's files, for a file window. Text messages are JSON, and each request has an `id` of your choosing, which its answer repeats. `openapi.yaml` has each one's fields.
151
- - **`list`** is answered with `entries`: a folder's entries with their kind, size and date, folders first, the first thousand.
151
+ - **`list`** is answered with `entries`: a folder's entries with their kind, size and date, folders first, the first thousand. With them come `path`, the folder as it was asked for, and `workspace`, what the workspace is called: its folder's own name, and nothing of where it is. The two together name the folder, `Research/src`; a workspace the service made is called `workspace`, and one at the top of a disk has an empty name. A computer in a container made before `workspace` was added sends none, and then `path` alone names the folder.
152
152
  - **`read`** is answered with `data` and then one binary message, a range of a file's bytes. A file larger than one range is read by asking again from where the last ended.
153
153
  - **`changed`** is answered with `changes`: the files modified after a time, the newest thousand, the newest first. It skips what `.gitignore` files ignore, `.git`, `node_modules` and links, and a file that was removed isn't one of them. Each one asked walks the workspace once, a computer walks for one at a time, and nothing is walked that wasn't asked for.
154
154
  - **`write`**, on an `operate` socket, puts a file there a part at a time, each followed at once by one binary message, its bytes. Nothing is at the path until the part marked `last`, which puts the file there whole and is answered with `written`; the parts before it are answered only if one is refused. It makes no folders, and nothing removes or renames a file. A file not finished when the socket closes is given up.
@@ -3849,7 +3849,7 @@ async function serveBrowserMcp(options) {
3849
3849
  import { execFile as execFile2, spawn as spawn3 } from "node:child_process";
3850
3850
  import { readFileSync as readFileSync3 } from "node:fs";
3851
3851
  import { connect } from "node:net";
3852
- import { join as join8 } from "node:path";
3852
+ import { basename as basename3, join as join8 } from "node:path";
3853
3853
  import { createInterface as createInterface2 } from "node:readline";
3854
3854
  import { Readable as Readable3 } from "node:stream";
3855
3855
  import { promisify as promisify2 } from "node:util";
@@ -28158,7 +28158,7 @@ import { join as join7 } from "node:path";
28158
28158
  // src/runtime.ts
28159
28159
  import { chmodSync as chmodSync2, existsSync, statSync as statSync2 } from "node:fs";
28160
28160
  import { createRequire as createRequire3 } from "node:module";
28161
- import { dirname as dirname3, join as join6 } from "node:path";
28161
+ import { basename as basename2, dirname as dirname3, join as join6 } from "node:path";
28162
28162
 
28163
28163
  // node_modules/@agentorg/exec/dist/lib.js
28164
28164
  import { realpathSync } from "node:fs";
@@ -28915,11 +28915,11 @@ var require_ignore = __commonJS2({
28915
28915
  const rules = this._rules;
28916
28916
  const { length } = rules;
28917
28917
  const shortcut = this._basenameCount * 2 >= length;
28918
- const basename2 = shortcut ? basenameOf(path) : path;
28918
+ const basename22 = shortcut ? basenameOf(path) : path;
28919
28919
  for (let index = length - 1; index >= 0; index--) {
28920
28920
  const rule = rules[index];
28921
28921
  if (rule[mode].test(
28922
- shortcut && rule._basenameOnly ? basename2 : path
28922
+ shortcut && rule._basenameOnly ? basename22 : path
28923
28923
  )) {
28924
28924
  const { negative } = rule;
28925
28925
  const ret = {
@@ -67117,16 +67117,6 @@ var BrowserLive = class {
67117
67117
  }
67118
67118
  };
67119
67119
 
67120
- // node_modules/ws/wrapper.mjs
67121
- var import_stream2 = __toESM(require_stream(), 1);
67122
- var import_extension = __toESM(require_extension(), 1);
67123
- var import_permessage_deflate = __toESM(require_permessage_deflate(), 1);
67124
- var import_receiver = __toESM(require_receiver(), 1);
67125
- var import_sender = __toESM(require_sender(), 1);
67126
- var import_subprotocol = __toESM(require_subprotocol(), 1);
67127
- var import_websocket = __toESM(require_websocket(), 1);
67128
- var import_websocket_server = __toESM(require_websocket_server(), 1);
67129
-
67130
67120
  // src/files-live.ts
67131
67121
  var MAX_PART = 1024 * 1024;
67132
67122
  var MAX_BUFFERED2 = 4 * 1024 * 1024;
@@ -67137,13 +67127,16 @@ var whole = (value) => Number.isSafeInteger(value);
67137
67127
  var sleep4 = (ms) => new Promise((done) => setTimeout(done, ms));
67138
67128
  var FilesLive = class {
67139
67129
  #files;
67130
+ #workspace;
67140
67131
  #sockets = /* @__PURE__ */ new Set();
67141
67132
  /** One walk of the workspace at a time, however many ask. */
67142
67133
  #walking = Promise.resolve();
67143
67134
  /** How many files are part written, over every socket. */
67144
67135
  #uploads = 0;
67145
- constructor(files) {
67136
+ /** `workspace` is what the workspace is called: its folder's own name, not where it is. */
67137
+ constructor(files, workspace) {
67146
67138
  this.#files = files;
67139
+ this.#workspace = workspace;
67147
67140
  }
67148
67141
  close() {
67149
67142
  for (const ws of this.#sockets) ws.close(1001, "It stopped.");
@@ -67213,7 +67206,13 @@ var FilesLive = class {
67213
67206
  const path = request.path ?? ".";
67214
67207
  if (!text2(path)) throw new Error("A path is text.");
67215
67208
  return inTurn(
67216
- async () => send2({ type: "entries", id, path, ...await this.#files.list(path) })
67209
+ async () => send2({
67210
+ type: "entries",
67211
+ id,
67212
+ workspace: this.#workspace,
67213
+ path,
67214
+ ...await this.#files.list(path)
67215
+ })
67217
67216
  );
67218
67217
  }
67219
67218
  case "read": {
@@ -67294,6 +67293,16 @@ var FilesLive = class {
67294
67293
  }
67295
67294
  };
67296
67295
 
67296
+ // node_modules/ws/wrapper.mjs
67297
+ var import_stream2 = __toESM(require_stream(), 1);
67298
+ var import_extension = __toESM(require_extension(), 1);
67299
+ var import_permessage_deflate = __toESM(require_permessage_deflate(), 1);
67300
+ var import_receiver = __toESM(require_receiver(), 1);
67301
+ var import_sender = __toESM(require_sender(), 1);
67302
+ var import_subprotocol = __toESM(require_subprotocol(), 1);
67303
+ var import_websocket = __toESM(require_websocket(), 1);
67304
+ var import_websocket_server = __toESM(require_websocket_server(), 1);
67305
+
67297
67306
  // src/text.ts
67298
67307
  var MAX_TEXT = 1e4;
67299
67308
  function* pieces(text3, most = MAX_TEXT) {
@@ -67346,7 +67355,7 @@ var Live = class {
67346
67355
  /** Whether a person may write files here: not where the agent can only read them. */
67347
67356
  #writes;
67348
67357
  #load;
67349
- constructor(exec, access, load, browser) {
67358
+ constructor(exec, access, load, files, browser) {
67350
67359
  this.#load = load;
67351
67360
  if (exec && access === "terminal") {
67352
67361
  this.#terminals = exec.terminals;
@@ -67354,7 +67363,7 @@ var Live = class {
67354
67363
  for (const message of messages(event)) for (const ws of this.#viewers) deliver(ws, message);
67355
67364
  });
67356
67365
  }
67357
- this.#files = exec && new FilesLive(exec.files);
67366
+ this.#files = files;
67358
67367
  this.#writes = access !== "read";
67359
67368
  this.#browser = browser;
67360
67369
  }
@@ -67648,7 +67657,8 @@ var ProcessRuntime = class {
67648
67657
  browser.gate = browserLive;
67649
67658
  }
67650
67659
  const load = new LoadLive(spec.workspace ?? folder, this.#contained);
67651
- const live = new Live(exec, spec.access, load, browserLive);
67660
+ const files = exec && new FilesLive(exec.files, spec.workspaceName ?? basename2(spec.workspace));
67661
+ const live = new Live(exec, spec.access, load, files, browserLive);
67652
67662
  const surfaces = live.surfaces();
67653
67663
  return {
67654
67664
  browserTools: browser?.tools ?? [],
@@ -67678,6 +67688,7 @@ var ProcessRuntime = class {
67678
67688
  // src/inside.ts
67679
67689
  var INNER_PORT = 8e3;
67680
67690
  var INNER_TOKEN_VARIABLE = "AGENTCOMPUTER_INNER_TOKEN";
67691
+ var WORKSPACE_NAME_VARIABLE = "AGENTCOMPUTER_WORKSPACE_NAME";
67681
67692
  var BROWSER = "/opt/browsers/headless-shell";
67682
67693
  async function serveInside(options) {
67683
67694
  const token = process.env[INNER_TOKEN_VARIABLE];
@@ -67688,7 +67699,7 @@ async function serveInside(options) {
67688
67699
  {
67689
67700
  id: "inside",
67690
67701
  ...options,
67691
- ...options.access === "none" ? {} : { workspace: "/workspace" }
67702
+ ...options.access === "none" ? {} : { workspace: "/workspace", workspaceName: process.env[WORKSPACE_NAME_VARIABLE] }
67692
67703
  },
67693
67704
  privateFolder(join7(homedir(), ".agentcomputer")),
67694
67705
  {
@@ -67816,6 +67827,9 @@ var ContainerRuntime = class {
67816
67827
  // By name, so the value stays out of the command line other users can see.
67817
67828
  "--env",
67818
67829
  INNER_TOKEN_VARIABLE,
67830
+ // What its workspace is called, which in there is only /workspace. An image from before
67831
+ // this was told leaves it.
67832
+ ...spec.workspace ? ["--env", WORKSPACE_NAME_VARIABLE] : [],
67819
67833
  // Files it writes in the workspace belong to whoever runs the service.
67820
67834
  ...uid ? ["--user", `${uid}:${process.getgid?.()}`] : [],
67821
67835
  ...spec.workspace ? [
@@ -67828,7 +67842,11 @@ var ContainerRuntime = class {
67828
67842
  spec.access,
67829
67843
  ...spec.browser ? ["--browser"] : []
67830
67844
  ],
67831
- { ...process.env, [INNER_TOKEN_VARIABLE]: token }
67845
+ {
67846
+ ...process.env,
67847
+ [INNER_TOKEN_VARIABLE]: token,
67848
+ ...spec.workspace ? { [WORKSPACE_NAME_VARIABLE]: basename3(spec.workspace) } : {}
67849
+ }
67832
67850
  );
67833
67851
  }
67834
67852
  /** The token between the service and this container, which a restart has to find again. */
@@ -67972,7 +67990,7 @@ async function forward(url3, authorization, request, response) {
67972
67990
  }
67973
67991
 
67974
67992
  // src/handlers.ts
67975
- var VERSION2 = "0.0.10";
67993
+ var VERSION2 = "0.0.11";
67976
67994
  function createHandlers(computers) {
67977
67995
  return {
67978
67996
  getInfo: async () => ({ version: VERSION2, isolation: computers.isolation }),
@@ -84935,7 +84953,7 @@ var OPENAPI = {
84935
84953
  "openapi": "3.1.0",
84936
84954
  "info": {
84937
84955
  "title": "AgentComputer",
84938
- "version": "0.0.10",
84956
+ "version": "0.0.11",
84939
84957
  "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.",
84940
84958
  "license": {
84941
84959
  "name": "Apache-2.0",
@@ -86442,8 +86460,13 @@ var OPENAPI = {
86442
86460
  "id": {
86443
86461
  "type": "string"
86444
86462
  },
86463
+ "workspace": {
86464
+ "type": "string",
86465
+ "description": "What the workspace is called: its folder's own name, and nothing of where it is. It comes with every entries answer, whichever folder was asked for, so that with path it names the folder. A computer in a container made before `workspace` was added sends none, and there path alone names the folder. It is `workspace` for a workspace the service made, and empty for one at the top of a disk."
86466
+ },
86445
86467
  "path": {
86446
- "type": "string"
86468
+ "type": "string",
86469
+ "description": "The folder as it was asked for: `.` for the workspace itself."
86447
86470
  },
86448
86471
  "entries": {
86449
86472
  "type": "array",
@@ -487,6 +487,9 @@ export interface components {
487
487
  /** @constant */
488
488
  type: "entries";
489
489
  id: string;
490
+ /** @description What the workspace is called: its folder's own name, and nothing of where it is. It comes with every entries answer, whichever folder was asked for, so that with path it names the folder. A computer in a container made before `workspace` was added sends none, and there path alone names the folder. It is `workspace` for a workspace the service made, and empty for one at the top of a disk. */
491
+ workspace?: string;
492
+ /** @description The folder as it was asked for: `.` for the workspace itself. */
490
493
  path: string;
491
494
  entries: {
492
495
  name: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentorg/computer",
3
- "version": "0.0.10",
3
+ "version": "0.0.11",
4
4
  "description": "Computers for agents, as a service: a terminal, files and a browser over MCP",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {