@agentorg/computer 0.0.19 → 0.0.21
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 +114 -36
- package/dist/THIRD_PARTY_LICENSES.txt +109 -1
- package/dist/agentcomputer.js +81113 -64014
- package/dist/sdk.js +9 -2
- package/dist/types/generated/schema.d.ts +382 -11
- package/dist/types/sdk.d.ts +22 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -23,10 +23,10 @@ That gives an agent this computer instead: the machine the service runs on, whol
|
|
|
23
23
|
|
|
24
24
|
## This computer and containers
|
|
25
25
|
|
|
26
|
-
Each computer is this computer, attached with `attach`, or one made in a container of its own with `create`. A container needs Docker on the service's machine. The service follows your `DOCKER_HOST` or current context and never changes them, and comes up without Docker.
|
|
26
|
+
Each computer is this computer, attached with `attach`, or one made in a container of its own with `create`. A service started with `serve --lend` only lends this computer: it makes nothing, `info.made` is empty, and `create` is refused with 409. It listens only on loopback, as this computer is offered only there, and a container it finds in its data folder from before can't be started or removed until a service without `--lend` has the folder. A container needs Docker on the service's machine. The service follows your `DOCKER_HOST` or current context and never changes them, and comes up without Docker.
|
|
27
27
|
|
|
28
28
|
- **`info` says what the service offers**, each part ready or not and why, in a line a person reads:
|
|
29
|
-
- `thisComputer`: its capabilities (`about`, `terminal`, `files` and `screen`) and the browsers that can go with it.
|
|
29
|
+
- `thisComputer`: its capabilities (`about`, `terminal`, `files` and `screen`) and the browsers that can go with it. The screen is ready where Cua Driver is installed and granted.
|
|
30
30
|
- `made`, each kind it makes: today a container, ready while Docker answers, with its capabilities and browsers.
|
|
31
31
|
- **A container is refused with 409 where Docker doesn't answer:** `A container needs Docker, which isn't answering on this machine.` One already made isn't started there, and isn't killed there either, since its container couldn't be removed: both are refused with the same words, and it is kept.
|
|
32
32
|
- **A computer with no isolation is no longer made.** `create --isolation none` is refused with 400, and `attach` is what does that now.
|
|
@@ -36,8 +36,44 @@ This computer:
|
|
|
36
36
|
|
|
37
37
|
- **It is offered only by a service that no other machine reaches:** one that listens on loopback, with no `--tls-proxy` and no `--public-url`. A service that other machines can reach is a server, and doesn't offer its own machine. There `info` says why, attaching is refused with 409 in the same words, and a computer attached before is refused at start.
|
|
38
38
|
- **`--workspace`, which `attach` needs, is its work folder.** Commands and relative paths start there, and `about` names it. But its files reach the whole machine, as whoever started the service, and so do its commands at `--access terminal`.
|
|
39
|
+
- **Its commands, and a shell a person opens, get the environment the service was started with,** less every `AGENTCOMPUTER_` variable. That is no wall either: commands run in a login shell, so what the person's profile exports comes back, and with the terminal on an agent can read any of the person's processes' environment, the service's among them, with `ps -E`. So start the service from a shell holding nothing an agent shouldn't read.
|
|
39
40
|
- **`kill` detaches it.** What the service kept for it goes, and nothing of the machine's.
|
|
40
41
|
- **Its browser,** with `--browser`, is a headless one with a profile of its own. It runs the Chrome installed on the machine, or what `serve --browser-name` or `--browser-path` names. `info` says whether that program is there.
|
|
42
|
+
- **Or the person's own browser,** with `--own-browser` (`browser: "own"`): their Chrome or Edge, whichever has remote debugging on, Chrome where both do, as they use it, signed in. Its agent works in it with the same tools, and the person watches it in the same live view.
|
|
43
|
+
- **The agent has the person's sign-ins, not their open tabs.** It works only in tabs it opens, and in the pages those open: its first call opens a tab of its own, and its tools list and act on its tabs alone. The person's own tabs are left as they are: no dialog of theirs is answered and no file picker of theirs taken over, and nothing that changes the browser as a whole, such as its cookies or its network, is the agent's to do. A page opened with a modifier or middle click has no opener, so it isn't the agent's. Sharing one of their tabs with the agent can come later. The live view shows the person every tab, and takes over no file picker here, so theirs open as they always do.
|
|
44
|
+
- It is reached through the browser's own attach, from version 144, with nothing installed. The person switches on remote debugging once, on the machine, at `chrome://inspect/#remote-debugging` (`edge://inspect/#remote-debugging` in Edge), with the browser open. The browser then asks them to allow each connection: attaching waits up to 2 minutes for that, and is refused with 409 if it isn't allowed. That and Edge's switch are as their makers describe them; here they have been tried only against a browser started with its remote debugging on, which asks nobody.
|
|
45
|
+
- `info` says whether it is ready (`browsers`, `kind` `own`), and if not, which browser and what to do on that machine. Attaching with it is refused with 409 until then. `serve --own-browser-data DIR` names the browser's user data folder in place of looking for Chrome's and Edge's. It is connected to only where what listens on its port is the person's own: another user's process can't stand in for it.
|
|
46
|
+
- The connection changes nothing of the person's: their downloads, colours and focus stay as they have them. It is never closed: when the computer stops or is detached, the browser is only let go, with the tabs the agent opened. When the browser closes, or the person ends the connection, the computer is `failed`.
|
|
47
|
+
- **Its screen,** with `--screen` (`screen: true`), is the machine's own, through [Cua Driver](https://github.com/trycua/cua/tree/main/libs/cua-driver). It acts as the person, whatever `--access` says: its agent can type into any window, a terminal's too. Its agent gets a `screen` endpoint with three tools, and none of the driver's others:
|
|
48
|
+
- `see`: the whole screen as a picture (`apps` lists its windows), or one window's elements, each with a reference, and a picture of it;
|
|
49
|
+
- `act`: one thing on the screen (click, double or right click, drag, scroll, type, a key or keys together), aimed at an element's reference or at a point in the picture just seen. Click an element that can't be pressed, such as a text area, by its point; the driver's refusal to press it says so. It acts in the background by default, without moving the person's pointer or taking their focus. Where that can't be done it is refused, and `delivery_mode: "foreground"` brings the window forward and acts there.
|
|
50
|
+
- `apps`: the running apps and their windows, and bringing one forward. Each window's `app_name`, `title`, `pid`, `window_id`, `z_index` (higher in front) and `bounds` are also given as fields. The bounds are in the screen's points, not the pixels `act` aims in: to aim at a window, see it and use its picture.
|
|
51
|
+
- On a machine the service only lends (`serve --lend`), the agent acts only in the background: `act` takes no `delivery_mode`, and `apps` takes no window to bring forward, which would take the person's front app and their typing. Where the driver's answer to `act` advises the foreground, the agent is told in plain words instead. What `see` and `apps` say of the screen is never rewritten.
|
|
52
|
+
- The driver's hints and suggested next calls, which can name its own tools, aren't passed on with any of the three.
|
|
53
|
+
- **The person installs Cua Driver once,** the signed app from cua.ai/download, and on macOS grants it Screen Recording and Accessibility once. AgentComputer never installs or ships it, nor its optional perception extension, which is AGPL. `info` says whether the screen is ready, at Cua Driver 0.49.7 or later, and if not, what to do; attaching with it is refused with 409 until then. `serve --screen-driver PATH` names the program; otherwise it is `cua-driver` on the path, in `~/.local/bin`, or inside `/Applications/CuaDriver.app`.
|
|
54
|
+
- **An app can carry Cua Driver and host it,** as the driver's embedding guide describes, so that the grants are the app's.
|
|
55
|
+
- The app runs `cua-driver serve --embedded --socket PATH` itself. The service, started with `serve --screen-driver DRIVER --screen-socket PATH`, where DRIVER is the driver inside the app, reaches it there through `cua-driver mcp --embedded`.
|
|
56
|
+
- The grants are read from that driver, and listed under the outermost app the driver is inside.
|
|
57
|
+
- Asked for, they are asked for by the app: the service opens it through the system with `--args grant` and each grant to ask for, `screen-recording` or `accessibility`, which it asks for in turn.
|
|
58
|
+
- Once a grant changes, the app restarts its driver, which reads grants once. That ends the connections of computers using the screen, which then say Cua Driver has stopped.
|
|
59
|
+
- **What the service starts of Cua Driver sends no telemetry and checks for no updates,** so no update notice reaches a computer's log. The person's own Cua Driver app follows its own settings: `cua-driver telemetry disable` turns its telemetry off.
|
|
60
|
+
|
|
61
|
+
**Upgrading from 0.0.20:**
|
|
62
|
+
|
|
63
|
+
- **Commands on this computer no longer get the service's own `AGENTCOMPUTER_` variables,** such as `AGENTCOMPUTER_API_KEY` where the shell that started the service held it. A command that read one should be given what it needs another way.
|
|
64
|
+
|
|
65
|
+
**Upgrading from 0.0.19:**
|
|
66
|
+
|
|
67
|
+
- **A computer's `browser` can be `"own"`,** for this computer attached with the person's own browser, where it was only `true` or `false`. At run time this breaks only for such a computer, in a client that reads `browser` as a boolean: `browser === true` takes it for a computer with no browser, and a strict schema that expects a boolean refuses it. At build time it breaks TypeScript code that puts `browser` into a `boolean`, whatever the computer, as the SDK's type is now `boolean | "own"`. Test it as truthy to know whether a computer has a browser.
|
|
68
|
+
- **A computer has a new `state`, `starting`:** while it is made, started, or brought back as the service starts, until it is running. A client that knows only `running`, `stopped` and `failed` should take it as neither running nor stopped. `list --state running`, and the SDK's `isRunning()`, leave it out.
|
|
69
|
+
- **The service says it is up, with `AgentComputer on …` and its record, before what was running is back.** That is brought back after, all at once, each `starting` until it is running: `Its container is being started.`, or for this computer `It is being started.` A script that starts the service and then uses a computer should wait until its `state` isn't `starting`; meanwhile what needs it running is refused with 409 and its `reason`.
|
|
70
|
+
- **While `create` waits, `list` shows the computer as `starting`;** it showed `running`. `create` and `start` still answer once it is running, except `start` on one already starting, which answers at once, still `starting`.
|
|
71
|
+
- **Every computer has `reason` and `progress`.** `reason` says why a failed one failed, which only its logs said.
|
|
72
|
+
- **Computers carry other new fields,** which a client with a strict schema needs: `screen` and `endpoints.screen`, and in `get`, `tools.screen`. Every running computer's `surfaces` now lists `presence`, and `screen` where it was attached with it. `info` lists the person's own browser, `kind: "own"`, beside `headless`.
|
|
73
|
+
- **`about` has a new row, `Acting now`,** before `CPU`, so `CPU`, `Memory` and `Disk` each come one later.
|
|
74
|
+
- **A file a browser call names,** by `paths` or `filename`, has to be in the computer's workspace or its output folder. The MCP client's roots no longer move or widen that, so a path under a client's root elsewhere is refused.
|
|
75
|
+
- **An image that can't be fetched is refused with 409,** `Its image couldn't be fetched: ` and Docker's words; it was 500.
|
|
76
|
+
- **This computer's own endpoint takes one JSON-RPC request in each POST,** as the browser's does, and refuses a batch with 400. MCP clients send no batches.
|
|
41
77
|
|
|
42
78
|
**Upgrading from 0.0.18 or earlier:**
|
|
43
79
|
|
|
@@ -55,7 +91,11 @@ A computer in a container:
|
|
|
55
91
|
- Its image holds AgentExec, Playwright MCP and a headless Chromium. It is `ghcr.io/uniac-ai/agentcomputer/computer` at the service's version; `--image` names another.
|
|
56
92
|
- `--workspace` is mounted at `/workspace`, read-only at `--access read`, and nothing else of the machine is visible. The computer is told that folder's path on the machine and the machine's name, which `about` answers. Docker has to be able to share that folder, and the data folder, where its home is. Without `--workspace`, the service makes one, in the data folder.
|
|
57
93
|
- `--copy-from DIR` (`copyFrom`), used instead of `--workspace`, has the folder the service makes start with a copy of what is in `DIR`, taken once when the computer is made. `DIR` itself is never mounted or changed. Links are copied as they are, and sockets, pipes and devices are left out. It needs `--access` other than `none`.
|
|
58
|
-
- The image is fetched the first time it is needed
|
|
94
|
+
- **The image is fetched the first time it is needed,** which can take minutes: when the first computer in a container is made or started under this version, a call that then waits for it. `docker pull` it beforehand to spare that wait.
|
|
95
|
+
- Meanwhile the computer is listed with `state` `starting`. Its `reason` says what it waits on, in a line a person reads with no numbers, `Its image is being fetched.`, and its `progress` how far that has come: `{ "title": "Downloading its image", "done": …, "total": …, "moved": … }`, in bytes, with `total` as far as is known (Docker gives each layer's size as the layer begins, so it can grow) and `moved` the time it last moved: bytes came, or a layer was unpacked. A download that has stopped is still waited on: `moved` says since when. What needs the computer running is refused with 409 and its `reason`.
|
|
96
|
+
- `create` answers only once the computer is running, with its id and token. To show the download meanwhile, give the computer a name or metadata of your own and find it among the computers listed (`GET /v1/computers`, `Computer.list`): it is there once any `--copy-from` copy is done. One the service brings back when it starts keeps its id: `GET /v1/computers/{computerID}` shows it.
|
|
97
|
+
- Where Docker is on a socket here, as Docker Desktop and colima are, the image is fetched through Docker's API, which counts the bytes. Where it is elsewhere, or where that can't fetch the image, as from a registry that needs a sign-in, `docker pull` fetches it, which counts nothing: `progress` is null.
|
|
98
|
+
- When it can't be fetched, making the computer is refused with 409, `Its image couldn't be fetched: ` and Docker's words.
|
|
59
99
|
- It runs as the user who started the service, with no capabilities.
|
|
60
100
|
- Its home, `/home/computer`, is a folder of the machine's, in the computer's own folder in the data folder, mounted as the workspace is. What the agent keeps there stays, the browser's profile with its sign-ins among it. `stop` stops the container and keeps it, and `kill` removes it with the computer's folder.
|
|
61
101
|
- **After an update,** a computer in a container is made again at its first start under a new version of the service, or under another `--image`: its container is removed and made again from the service's image. It keeps its workspace, its home, and its id, token, endpoints and settings. It loses its running commands, as at any restart, and everything else in the container: software installed there, and files outside `/workspace` and `/home/computer`, such as `/tmp`. Keep what must last in those two folders, or in an image of your own. Every computer's answer says the `version` of the program it runs.
|
|
@@ -63,26 +103,27 @@ A computer in a container:
|
|
|
63
103
|
|
|
64
104
|
## Access
|
|
65
105
|
|
|
66
|
-
| `--access` | Tools at the `computer` endpoint
|
|
67
|
-
| ---------- |
|
|
68
|
-
| `read` | `about`, `read`, `list`, `search`
|
|
69
|
-
| `files` | Those, and `edit`
|
|
70
|
-
| `terminal` | Those, and `exec_command`, `write_stdin`, `list_sessions`
|
|
71
|
-
| `none` | No `computer` endpoint; needs `--
|
|
106
|
+
| `--access` | Tools at the `computer` endpoint |
|
|
107
|
+
| ---------- | ------------------------------------------------------------------ |
|
|
108
|
+
| `read` | `about`, `read`, `list`, `search` |
|
|
109
|
+
| `files` | Those, and `edit` |
|
|
110
|
+
| `terminal` | Those, and `exec_command`, `write_stdin`, `list_sessions` |
|
|
111
|
+
| `none` | No `computer` endpoint; needs a browser, or `--screen` on `attach` |
|
|
72
112
|
|
|
73
113
|
`read` answers a text file as numbered lines, and a PNG, JPEG, GIF or WebP of up to 3 MiB as the picture itself: an image an MCP client can pass on to a model. The browser's `browser_take_screenshot` answers an image too, but not one of more than 3 MiB, which a `fullPage` screenshot of a long page can be many times over: it answers an error that gives the size and says to take it again without `fullPage`, or of one element. The most counts bytes only: a model may still refuse a smaller picture for its height or width.
|
|
74
114
|
|
|
75
115
|
`about` tells the agent what a person looking at the computer reads. It takes nothing and answers JSON text, `{"rows": [...]}`, each row a `label` and a `value`, with `"path": true` on a value that is a path and `"caution": true` on one to be read as a caution; a row that is neither has neither. The rows come in this order:
|
|
76
116
|
|
|
77
|
-
| `label`
|
|
78
|
-
|
|
|
79
|
-
| `Where`
|
|
80
|
-
| `Folder`
|
|
81
|
-
| `Reaches`
|
|
82
|
-
| `Isolation`
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
117
|
+
| `label` | `value` |
|
|
118
|
+
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
119
|
+
| `Where` | The machine's own name |
|
|
120
|
+
| `Folder` | The workspace's path on that machine, as a path |
|
|
121
|
+
| `Reaches` | `Read-only files`, `Files`, or `Files and terminal`; with a browser, `, Browser` after it |
|
|
122
|
+
| `Isolation` | `None: it acts as you, on the whole machine`, as a caution, or `A container of its own` |
|
|
123
|
+
| `Acting now` | Who else acted on it in the last 10 s, and on what, the most recent first: `Scout: the files; The person: terminal s_…`, or `Nobody else` |
|
|
124
|
+
| `CPU` | Used, of all the machine's CPUs, as a whole percentage: `37%` |
|
|
125
|
+
| `Memory` | Used of the machine's total, counted in 1024s and written GB: `9.2 of 16 GB` |
|
|
126
|
+
| `Disk` | Used of total, of the volume the workspace is on, counted in 1000s: `212 of 494 GB` |
|
|
86
127
|
|
|
87
128
|
- **In a container** the agent's commands find the folder somewhere else, so `Folder` says both and is not marked as a path: `/home/me/Research on the machine, mounted at /workspace in it`. CPU and Memory there are the computer's own; on this computer they are the whole machine's.
|
|
88
129
|
- **The last three** are a reading of its load taken over half a second when it is asked, in the same way the `load` surface reads. They come together, or not at all where a reading can't be taken.
|
|
@@ -90,26 +131,26 @@ A computer in a container:
|
|
|
90
131
|
|
|
91
132
|
A client that calls a computer's tools can put the commands it starts in a group, and stop them together. At `--access terminal` it sends a word as `agentexec/group` in the `_meta` of an `exec_command` call, and the request `agentexec/group/stop` with `{"group": "<word>"}` on the `computer` endpoint, which ends every running command of that group and answers `{"stopped": <how many>}`. Giving up a call does not stop its command; only that request does. A shell a person opened is in no group. This is AgentExec's, described in [its README](https://github.com/uniac-ai/AgentExec#sessions), and the service passes both through, on this computer and in a container.
|
|
92
133
|
|
|
93
|
-
In a container the file tools stay inside the workspace, which is a check and not a boundary: the container is the boundary. On this computer they reach the whole machine. Below `terminal`, the browser's `browser_run_code_unsafe` tool is hidden and refused, because it would otherwise be a terminal. The browser's endpoint takes one JSON-RPC request in each POST, as a JSON object, and refuses anything else with 400, a batch among them: it checks each request before passing it on, and passes on only what it read. The service enforces all of this, whatever the client does.
|
|
134
|
+
In a container the file tools stay inside the workspace, which is a check and not a boundary: the container is the boundary. On this computer they reach the whole machine. Below `terminal`, the browser's `browser_run_code_unsafe` tool is hidden and refused, because it would otherwise be a terminal. The browser's endpoint takes one JSON-RPC request in each POST, as a JSON object, and refuses anything else with 400, a batch among them: it checks each request before passing it on, and passes on only what it read. A file a browser call names, such as a snapshot's `filename`, is in the computer's folder, whatever roots the client gives. The service enforces all of this, whatever the client does.
|
|
94
135
|
|
|
95
136
|
Before 0.0.14 the browser's endpoint passed on a body it couldn't read as one request, unchecked. So on a computer made with `--access none`, `read` or `files` and `--browser`, a caller holding that computer's token could run code in its browser by sending the call in a batch or behind a byte order mark. It needed the computer's own token and a client that sends such a body, which MCP clients don't. 0.0.14 fixes it; a computer in a container made by an earlier version keeps the fault until its container is made again.
|
|
96
137
|
|
|
97
|
-
|
|
138
|
+
A browser of the computer's own has no debug port: a small host process starts it and shares it on a Unix socket in a folder only its user can enter, which the agent's tools and the live view both use. The person's own browser has the port its own attach opens on loopback, which it asks the person about; the host connects to it once, and shares that connection the same way. Playwright MCP, which serves the tools, listens on a Unix socket in a second such folder, and no port either. Only the service's user can reach them; callers go through the computer's `browser` endpoint and its token. It lives as long as its computer does: a client that ends its session or goes away leaves the browser and its pages as they are, and the agent's `browser_close` is refused. Only an agent with `--access terminal` can stop it, with `browser_run_code_unsafe` or from its terminal.
|
|
98
139
|
|
|
99
140
|
## Commands
|
|
100
141
|
|
|
101
|
-
| |
|
|
102
|
-
| ----------------------------------------- |
|
|
103
|
-
| `serve` | Run the service: `--listen` (127.0.0.1:7878), `--data`
|
|
104
|
-
| `up`, `down`, `status` | Run the service in the background, stop it, say where it is running
|
|
105
|
-
| `info` | The service's version and what it offers: this computer, and the kinds it makes, each ready or not
|
|
106
|
-
| `create` | Make a computer: `--access`, `--browser`, `--isolation`, `--workspace` or `--copy-from`, `--name`, `--timeout`, `--metadata KEY=VALUE`
|
|
107
|
-
| `attach` | Attach this computer: `--access`, `--workspace`, `--browser`, `--name`, `--timeout`, `--metadata KEY=VALUE`
|
|
108
|
-
| `list [--state]`, `get <id>`, `logs <id>` | Look at them
|
|
109
|
-
| `timeout <id> <seconds>` | It now stops this long from now
|
|
110
|
-
| `stop <id>`, `start <id> [--timeout]` | Stop it, keeping its folder and token; start it again
|
|
111
|
-
| `live <id> --surface [--mode]` | A one-time ticket to open one of its surfaces live; see [Live sessions](#live-sessions)
|
|
112
|
-
| `kill <id>` | Stop it and remove what the service made; this computer, detach it
|
|
142
|
+
| | |
|
|
143
|
+
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
144
|
+
| `serve` | Run the service: `--listen` (127.0.0.1:7878), `--data` |
|
|
145
|
+
| `up`, `down`, `status` | Run the service in the background, stop it, say where it is running |
|
|
146
|
+
| `info` | The service's version and what it offers: this computer, and the kinds it makes, each ready or not |
|
|
147
|
+
| `create` | Make a computer: `--access`, `--browser`, `--isolation`, `--workspace` or `--copy-from`, `--name`, `--timeout`, `--metadata KEY=VALUE` |
|
|
148
|
+
| `attach` | Attach this computer: `--access`, `--workspace`, `--browser` or `--own-browser`, `--screen`, `--name`, `--timeout`, `--metadata KEY=VALUE` |
|
|
149
|
+
| `list [--state]`, `get <id>`, `logs <id>` | Look at them |
|
|
150
|
+
| `timeout <id> <seconds>` | It now stops this long from now |
|
|
151
|
+
| `stop <id>`, `start <id> [--timeout]` | Stop it, keeping its folder and token; start it again |
|
|
152
|
+
| `live <id> --surface [--mode]` | A one-time ticket to open one of its surfaces live; see [Live sessions](#live-sessions) |
|
|
153
|
+
| `kill <id>` | Stop it and remove what the service made; this computer, detach it |
|
|
113
154
|
|
|
114
155
|
**In the background.** `up` takes what `serve` takes, runs the service in the background for you, and returns once it answers, printing its `url`, `pid` and version. If one already answers for the data folder it prints that one and starts nothing. `status` prints the same, or exits 1 with none running. `down` ends it and says nothing; its computers stop with it, and start again when it next does. `serve` won't run beside a service that already answers for the same data folder. `--version` prints the program's version, with no service.
|
|
115
156
|
|
|
@@ -141,6 +182,11 @@ The data folder is `--data`, else `$AGENTCOMPUTER_DATA`, else `$XDG_DATA_HOME/ag
|
|
|
141
182
|
| `POST /v1/computers/{computerID}/start` | `computer_start` |
|
|
142
183
|
| `GET /v1/computers/{computerID}/logs` | `computer_logs` |
|
|
143
184
|
| `POST /v1/computers/{computerID}/live` | `computer_live` |
|
|
185
|
+
| `GET /v1/connection` | |
|
|
186
|
+
| `GET /v1/acting` | |
|
|
187
|
+
| `GET /v1/setup` | |
|
|
188
|
+
| `PUT /v1/setup/{capability}` | |
|
|
189
|
+
| `POST /v1/setup/{capability}/ask` | |
|
|
144
190
|
|
|
145
191
|
These take the control token, kept in the data folder. A computer's own endpoints take its `accessToken`, and neither token works for the other:
|
|
146
192
|
|
|
@@ -151,6 +197,27 @@ These take the control token, kept in the data folder. A computer's own endpoint
|
|
|
151
197
|
|
|
152
198
|
`POST /v1/computers` and `POST /v1/computers/attach` are the only places an `accessToken` is shown. Failures are `{ "code": 404, "message": "..." }`.
|
|
153
199
|
|
|
200
|
+
- **A client that relies on the service can hold a connection to it:** a WebSocket at `/v1/connection?name=NAME`, with the control token in its `Authorization` header. Nothing is sent either way; the service pings, and drops one that stops answering. `GET /v1/connection` says who holds one: `{ "connected": true, "clients": [{ "name", "since", "local" }] }`, where `name` is its first 100 characters and `local` is whether it connects from the service's machine, false behind `--tls-proxy`.
|
|
201
|
+
- **The person's switches.** Each part of this computer an agent can use (`terminal`, `files`, `screen`, and `browser`, the person's own) has the person's own switch.
|
|
202
|
+
- Off, agents' new calls to that part refuse with "The person turned off the screen for agents on this Mac" (or "this machine" off macOS), `info` says the same, and attaching with the screen or the person's browser is refused with 409. What an agent already started, such as a command, runs on.
|
|
203
|
+
- The terminal and the screen each reach the whole machine: with the terminal on, commands read and change any file, whatever the files' switch; with the screen on, the agent acts in any app.
|
|
204
|
+
- So the switches tell an agent what it may use; they don't stop it. With the terminal, the files or the screen on, an agent acts as the person and can read the service's control token in its data folder, like any file of theirs; with the terminal or the screen, it can use it to set the other switches.
|
|
205
|
+
- Any browser's calls that reach the machine answer to its switches too: `browser_run_code_unsafe` to the terminal's, and a call that names files, by `paths` or `filename`, to the files'.
|
|
206
|
+
- The computer's own endpoint on this machine reads each call whole and checks it as it arrives, so it takes one JSON-RPC request in each POST, as the browser's does, and refuses a batch.
|
|
207
|
+
- A service started with `--lend` starts with every switch off, for the person to turn on. Any other starts with every one on. They are kept in the data folder, so they last across a restart. A switches file that can't be read leaves every one off.
|
|
208
|
+
- **`GET /v1/setup`** gives `{ "capabilities": [...] }`, each part as `{ "capability", "on", "ready", "needs" }`, read afresh each time.
|
|
209
|
+
- `ready` is whether the part has all it needs, apart from its switch. `needs` lists each thing it needs, always, each with its state.
|
|
210
|
+
- The terminal and files need nothing, and are always ready; on macOS the Mac asks folder by folder.
|
|
211
|
+
- The screen needs Cua Driver, and on macOS its `screen-recording` and `accessibility` grants, each `granted`, `not-granted` or `unknown`; it is ready once both are granted. While Cua Driver isn't installed, the one item is `{ "need": "install", "state": "missing" }`. `holder` names whom System Settings lists the grants under: the outermost app Cua Driver is inside, CuaDriver for its own app, or an app that carries the driver.
|
|
212
|
+
- The browser lists Chrome, then Edge, each `on` (open, with remote debugging on), `off`, or `missing` (not installed); a service given one browser's folder, with `--own-browser-data`, lists just that one as `named`. It is ready with one on. With both on, the agent's is Chrome.
|
|
213
|
+
- **`POST /v1/setup/{capability}/ask`**, with `{ "need": "..." }` or no body, asks the person, on the service's machine, macOS only, for one thing the part needs, or for everything it is missing. It answers once the steps have started, with each part then:
|
|
214
|
+
- `screen-recording` or `accessibility`, while it is missing: Cua Driver's own grant, its app started first, through the system, so the Mac names that app. Cua Driver asks in its own order, Accessibility first. For a driver an app hosts, the app asks, for that grant alone. Then, missing or not, that grant's own pane in System Settings opens.
|
|
215
|
+
- `chrome` or `edge`: that browser opens at its inspect page, where remote debugging is switched on. One the service was given only the folder of, the person opens themselves.
|
|
216
|
+
- With none named: the screen's grant while either is missing; the first browser installed, Chrome before Edge, while none is on.
|
|
217
|
+
- What the part doesn't need, a browser that isn't installed, or steps that couldn't be started answer 409, saying why.
|
|
218
|
+
- **`PUT /v1/setup/{capability}`** with `{ "on": true }` or `{ "on": false }` sets a switch. Turning it on, or on again, also asks for everything the part is missing, as asking with no need does. Where that couldn't be started, it answers 409, saying why, and the switch stays on.
|
|
219
|
+
- **`GET /v1/acting`** is who is acting now on every computer attached to this machine, in one list, as each one's `presence` surface has it. A computer in a container isn't included: its own `presence` surface has it.
|
|
220
|
+
|
|
154
221
|
## SDK
|
|
155
222
|
|
|
156
223
|
```ts
|
|
@@ -166,7 +233,7 @@ await computer.kill();
|
|
|
166
233
|
|
|
167
234
|
It reads the control token from `AGENTCOMPUTER_API_KEY` and the address from `AGENTCOMPUTER_API_URL`, or takes `apiKey` and `apiUrl` as options. `computer.getMcpUrl("browser")` and `computer.getMcpToken()` give an MCP client what it needs, and `Computer.connect(id, { accessToken })` picks up a computer made earlier.
|
|
168
235
|
|
|
169
|
-
`files.write` makes a new file or fills an empty one; `files.edit` changes one that has content. `files.read` returns the whole text, or fails if a line is longer than the tool can return.
|
|
236
|
+
`files.write` makes a new file or fills an empty one; `files.edit` changes one that has content. `files.read` returns the whole text, or fails if a line is longer than the tool can return. The file calls return the tool's answer alone, without the line on who else just acted there. They count as the agent's calls, so that line isn't given again on the agent's next one.
|
|
170
237
|
|
|
171
238
|
## Across a network
|
|
172
239
|
|
|
@@ -232,12 +299,23 @@ A computer with `--browser` has another:
|
|
|
232
299
|
- **A dialog, a file chooser and a list belong to a page.** A dialog is told to the sockets shown its page until someone answers it, you or the agent. Nothing says when the agent answers a file chooser, so when it answers one every open chooser is taken as closed: press again if yours was.
|
|
233
300
|
- **A client written for the earlier `screencast@1` still connects.** Its `release` is ignored and no `driver` event comes: nobody holds the browser any more.
|
|
234
301
|
|
|
235
|
-
|
|
302
|
+
A computer attached with `--screen` has another:
|
|
303
|
+
|
|
304
|
+
- **`screen`** (protocol `screen@1`): the machine's screen, the one the agent sees and acts on. Binary messages are PNG frames of the whole screen, at most 1,280 pixels on their longest side. Text messages are JSON: the service sends `size` and `refused`, and an `operate` socket sends `mouse` (`click`, `double_click`, `right_click`, `drag` or `scroll`), `key` (`keys`: one, or several pressed together, by Cua Driver's names, such as `["enter"]` or `["ctrl", "c"]`) and `text`. `openapi.yaml` has each one's fields.
|
|
305
|
+
- **A frame is sent only when the picture changed.** The screen is taken twice a second while a socket is open, and not at all while nobody watches. A socket is sent the last frame when it opens, after a `size`, and another `size` comes before a frame of a different size. One more than 4 MiB behind is sent nothing until it catches up.
|
|
306
|
+
- **Your input is done as you,** through Cua Driver, in the order you sent it. A point is in pixels of the frames, scaled to the screen; keys and text go to the window in front, which the agent may just have changed. What isn't done is answered with `refused`, and why, only to the socket that sent it.
|
|
307
|
+
- No message is over 65,536 bytes: a larger one closes the socket. Binary messages, and whatever a `watch` socket sends, are dropped.
|
|
308
|
+
|
|
309
|
+
Every running computer has two more, to watch only:
|
|
236
310
|
|
|
237
311
|
- **`load`** (protocol `metrics@1`): how busy it is. The service sends a reading every two seconds while a socket is open, the first two seconds after the first socket opens, and the last one at once to a socket that opens later: `{"type":"reading","scope":"machine","cpuUsedPct":37.2,"memUsed":…,"memTotal":…,"diskUsed":…,"diskTotal":…}`, in bytes. `openapi.yaml` has each field, as `LoadReading`.
|
|
238
312
|
- **`scope` says whose numbers they are.** A computer in a container reads its own (`computer`), against the machine's totals, since a container has no limit of its own. This computer has no edge to measure at, so it reads the whole machine's (`machine`); so does a container that can't read its own.
|
|
239
313
|
- **The disk is the volume its workspace is on,** not the workspace's own size.
|
|
240
314
|
- **Nothing depends on it.** Nothing is read while nobody watches or asks, a reading that can't be taken is left out, and a socket that hasn't read the one before is not sent the next.
|
|
315
|
+
- **`presence`** (protocol `presence@1`): who is acting on it now, and on what: a terminal, the files, the browser or the screen. It sends the whole list, `{"type":"presence","acting":[…]}`, when it opens and each time someone starts or stops acting on something. Someone stops 10 seconds after they last acted there. `openapi.yaml` has each field, as `PresenceEvent` and `Acting`, with what counts as acting.
|
|
316
|
+
- **The agent is told too.** `about` names who else is acting. The answer to the agent's call on something someone else acted on since its last call there ends with a line naming each of them: `The person used this terminal 3 s ago.`, `The person wrote a file here 2 s ago.`, `The person used the browser 4 s ago.` or `The person used the screen 1 s ago.`
|
|
317
|
+
- **Computers attached to the same machine share its files and its screen.** Each is shown the person and the other computers' agents acting on them, by name, and its agent's line names each one since its last call: `The person wrote a file here 1 s ago. Helper used the files here 2 s ago.` A computer's terminals and browser stay its own; the person's own browser is shared by the computers attached with it, and each shows only its own agent acting there.
|
|
318
|
+
- **Nothing is refused by it,** for the person or the agent.
|
|
241
319
|
|
|
242
320
|
`POST /v1/computers/{computerID}/live` with `{ "surface": "terminal", "mode": "operate" }` gives a ticket: a `url` to open once within a minute, which needs no token. A request with an `Origin` header is refused unless `serve --allow-origin` names that origin, so a page can't open one. The SDK does the same with `computer.terminals.connect({ onEvent })`, or gives the ticket alone with `computer.liveSession("files")` or `computer.liveSession("browser", "operate")`, and the CLI with `agentcomputer live <id> --surface terminal --mode operate`.
|
|
243
321
|
|
|
@@ -247,12 +325,12 @@ A shell of your own needs [node-pty](https://github.com/microsoft/node-pty), an
|
|
|
247
325
|
|
|
248
326
|
- A container has no CPU or memory limit, and its network is Docker's default, so it reaches the internet and anything else Docker's network does.
|
|
249
327
|
- In a container the browser runs without its own sandbox, which needs privileges a computer doesn't have. The container is the boundary.
|
|
250
|
-
- A browser that stops, or a container that ends by itself, shows the computer as `failed`, and what can no longer be opened live says so in `surfaces`. So does a computer that couldn't be brought back when the service started, for one in a container because Docker didn't answer
|
|
328
|
+
- A browser that stops, or a container that ends by itself, shows the computer as `failed`, with why in its `reason`, and what can no longer be opened live says so in `surfaces`. So does a computer that couldn't be brought back when the service started, for one in a container because Docker didn't answer or its image couldn't be fetched. Its `logs` say more. Stop the computer and start it again.
|
|
251
329
|
- A file being written through the `files` surface sits beside its path as `.agentexec-…` until its last part, where a listing, and the agent, can see it. It stays if the service dies meanwhile.
|
|
252
330
|
|
|
253
331
|
## Tests
|
|
254
332
|
|
|
255
|
-
`npm test` runs the built service through the official MCP client, and one scenario through HTTP, MCP, the SDK and the CLI that fails if any operation in the schema isn't reached by each. Set `AGENTCOMPUTER_TEST_IMAGE` to a built image (`npm run build`, then `docker build .`) to run the same suite on containers, and `AGENTCOMPUTER_TEST_SERVICE_IMAGE` to one from `Dockerfile.service` to run the service itself as a container, with `AGENTCOMPUTER_TEST_ROOT` naming a folder Docker can mount if the temporary one isn't. After changing `openapi.yaml`, `npm run generate` writes what comes from it; CI fails if that changes anything. Set `AGENTCOMPUTER_BROWSER_PATH` to a Chromium program, such as Playwright's headless shell, to run the browser tests that are skipped without it.
|
|
333
|
+
`npm test` runs the built service through the official MCP client, and one scenario through HTTP, MCP, the SDK and the CLI that fails if any operation in the schema with an MCP tool isn't reached by each. Set `AGENTCOMPUTER_TEST_IMAGE` to a built image (`npm run build`, then `docker build .`) to run the same suite on containers, and `AGENTCOMPUTER_TEST_SERVICE_IMAGE` to one from `Dockerfile.service` to run the service itself as a container, with `AGENTCOMPUTER_TEST_ROOT` naming a folder Docker can mount if the temporary one isn't. After changing `openapi.yaml`, `npm run generate` writes what comes from it; CI fails if that changes anything. Set `AGENTCOMPUTER_BROWSER_PATH` to a Chromium program, such as Playwright's headless shell, to run the browser tests that are skipped without it.
|
|
256
334
|
|
|
257
335
|
## Licence
|
|
258
336
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
@agentorg/exec 0.0.
|
|
1
|
+
@agentorg/exec 0.0.10 (Apache-2.0)
|
|
2
2
|
|
|
3
3
|
Apache License
|
|
4
4
|
Version 2.0, January 2004
|
|
@@ -1114,6 +1114,32 @@ the full license text.
|
|
|
1114
1114
|
|
|
1115
1115
|
========================================================================
|
|
1116
1116
|
|
|
1117
|
+
cross-spawn 7.0.6 (MIT)
|
|
1118
|
+
|
|
1119
|
+
The MIT License (MIT)
|
|
1120
|
+
|
|
1121
|
+
Copyright (c) 2018 Made With MOXY Lda <hello@moxy.studio>
|
|
1122
|
+
|
|
1123
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
1124
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
1125
|
+
in the Software without restriction, including without limitation the rights
|
|
1126
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
1127
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
1128
|
+
furnished to do so, subject to the following conditions:
|
|
1129
|
+
|
|
1130
|
+
The above copyright notice and this permission notice shall be included in
|
|
1131
|
+
all copies or substantial portions of the Software.
|
|
1132
|
+
|
|
1133
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
1134
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
1135
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
1136
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
1137
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
1138
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
1139
|
+
THE SOFTWARE.
|
|
1140
|
+
|
|
1141
|
+
========================================================================
|
|
1142
|
+
|
|
1117
1143
|
eventsource 3.0.7 (MIT)
|
|
1118
1144
|
|
|
1119
1145
|
The MIT License
|
|
@@ -1193,6 +1219,26 @@ SOFTWARE.
|
|
|
1193
1219
|
|
|
1194
1220
|
========================================================================
|
|
1195
1221
|
|
|
1222
|
+
isexe 2.0.0 (ISC)
|
|
1223
|
+
|
|
1224
|
+
The ISC License
|
|
1225
|
+
|
|
1226
|
+
Copyright (c) Isaac Z. Schlueter and Contributors
|
|
1227
|
+
|
|
1228
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
1229
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
1230
|
+
copyright notice and this permission notice appear in all copies.
|
|
1231
|
+
|
|
1232
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
1233
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
1234
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
1235
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
1236
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
1237
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
|
1238
|
+
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
1239
|
+
|
|
1240
|
+
========================================================================
|
|
1241
|
+
|
|
1196
1242
|
jose 6.2.17 (MIT)
|
|
1197
1243
|
|
|
1198
1244
|
The MIT License (MIT)
|
|
@@ -1245,6 +1291,20 @@ SOFTWARE.
|
|
|
1245
1291
|
|
|
1246
1292
|
========================================================================
|
|
1247
1293
|
|
|
1294
|
+
path-key 3.1.1 (MIT)
|
|
1295
|
+
|
|
1296
|
+
MIT License
|
|
1297
|
+
|
|
1298
|
+
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
|
1299
|
+
|
|
1300
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
1301
|
+
|
|
1302
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
1303
|
+
|
|
1304
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
1305
|
+
|
|
1306
|
+
========================================================================
|
|
1307
|
+
|
|
1248
1308
|
pkce-challenge 5.0.1 (MIT)
|
|
1249
1309
|
|
|
1250
1310
|
MIT License
|
|
@@ -1271,6 +1331,54 @@ SOFTWARE.
|
|
|
1271
1331
|
|
|
1272
1332
|
========================================================================
|
|
1273
1333
|
|
|
1334
|
+
shebang-command 2.0.0 (MIT)
|
|
1335
|
+
|
|
1336
|
+
MIT License
|
|
1337
|
+
|
|
1338
|
+
Copyright (c) Kevin Mårtensson <kevinmartensson@gmail.com> (github.com/kevva)
|
|
1339
|
+
|
|
1340
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
1341
|
+
|
|
1342
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
1343
|
+
|
|
1344
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
1345
|
+
|
|
1346
|
+
========================================================================
|
|
1347
|
+
|
|
1348
|
+
shebang-regex 3.0.0 (MIT)
|
|
1349
|
+
|
|
1350
|
+
MIT License
|
|
1351
|
+
|
|
1352
|
+
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
|
1353
|
+
|
|
1354
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
1355
|
+
|
|
1356
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
1357
|
+
|
|
1358
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
1359
|
+
|
|
1360
|
+
========================================================================
|
|
1361
|
+
|
|
1362
|
+
which 2.0.2 (ISC)
|
|
1363
|
+
|
|
1364
|
+
The ISC License
|
|
1365
|
+
|
|
1366
|
+
Copyright (c) Isaac Z. Schlueter and Contributors
|
|
1367
|
+
|
|
1368
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
1369
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
1370
|
+
copyright notice and this permission notice appear in all copies.
|
|
1371
|
+
|
|
1372
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
1373
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
1374
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
1375
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
1376
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
1377
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
|
1378
|
+
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
1379
|
+
|
|
1380
|
+
========================================================================
|
|
1381
|
+
|
|
1274
1382
|
ws 8.22.2 (MIT)
|
|
1275
1383
|
|
|
1276
1384
|
Copyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com>
|