@agentorg/computer 0.0.2 → 0.0.4
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 +59 -5
- package/dist/THIRD_PARTY_LICENSES.txt +26 -1
- package/dist/agentcomputer.js +71558 -66720
- package/dist/sdk.js +74 -2
- package/dist/types/generated/schema.d.ts +125 -0
- package/dist/types/sdk.d.ts +61 -1
- package/package.json +10 -2
package/dist/sdk.js
CHANGED
|
@@ -24640,10 +24640,67 @@ var Endpoint = class {
|
|
|
24640
24640
|
await client?.close();
|
|
24641
24641
|
}
|
|
24642
24642
|
};
|
|
24643
|
+
async function openLive(session, onMessage) {
|
|
24644
|
+
const ws = new WebSocket(session.url);
|
|
24645
|
+
ws.binaryType = "arraybuffer";
|
|
24646
|
+
const closed = new Promise((done) => {
|
|
24647
|
+
ws.addEventListener("close", (event) => done({ code: event.code, reason: event.reason }));
|
|
24648
|
+
});
|
|
24649
|
+
await new Promise((done, failed) => {
|
|
24650
|
+
ws.addEventListener("open", () => done(), { once: true });
|
|
24651
|
+
ws.addEventListener(
|
|
24652
|
+
"error",
|
|
24653
|
+
() => failed(new ComputerError(502, "The live session didn't open.")),
|
|
24654
|
+
{ once: true }
|
|
24655
|
+
);
|
|
24656
|
+
});
|
|
24657
|
+
ws.addEventListener("message", (event) => onMessage(event.data));
|
|
24658
|
+
return { ws, closed };
|
|
24659
|
+
}
|
|
24660
|
+
var INPUT = 48;
|
|
24661
|
+
var RESIZE = 49;
|
|
24662
|
+
var Pty = class {
|
|
24663
|
+
#open;
|
|
24664
|
+
constructor(open2) {
|
|
24665
|
+
this.#open = open2;
|
|
24666
|
+
}
|
|
24667
|
+
/** Attach to its shell, starting one if none is running. Every attachment shares it. */
|
|
24668
|
+
async connect(opts) {
|
|
24669
|
+
const mode = opts.mode ?? "operate";
|
|
24670
|
+
const decoder = new TextDecoder();
|
|
24671
|
+
const { ws, closed } = await openLive(await this.#open("terminal", mode), (data) => {
|
|
24672
|
+
if (typeof data === "string") return;
|
|
24673
|
+
const frame = new Uint8Array(data);
|
|
24674
|
+
if (frame[0] === INPUT) opts.onData(decoder.decode(frame.subarray(1), { stream: true }));
|
|
24675
|
+
});
|
|
24676
|
+
const send = (type, text) => {
|
|
24677
|
+
const body = new TextEncoder().encode(text);
|
|
24678
|
+
const frame = new Uint8Array(body.length + 1);
|
|
24679
|
+
frame[0] = type;
|
|
24680
|
+
frame.set(body, 1);
|
|
24681
|
+
ws.send(frame);
|
|
24682
|
+
};
|
|
24683
|
+
return {
|
|
24684
|
+
sendInput: (data) => send(INPUT, data),
|
|
24685
|
+
resize: (columns, rows) => send(RESIZE, JSON.stringify({ columns, rows })),
|
|
24686
|
+
close: () => ws.close(),
|
|
24687
|
+
closed
|
|
24688
|
+
};
|
|
24689
|
+
}
|
|
24690
|
+
};
|
|
24643
24691
|
var Commands = class {
|
|
24644
24692
|
#endpoint;
|
|
24645
|
-
|
|
24693
|
+
#open;
|
|
24694
|
+
constructor(endpoint, open2) {
|
|
24646
24695
|
this.#endpoint = endpoint;
|
|
24696
|
+
this.#open = open2;
|
|
24697
|
+
}
|
|
24698
|
+
/** Each of the agent's commands as it runs: the ones already heard first, then as they come. */
|
|
24699
|
+
async watch(onEvent) {
|
|
24700
|
+
const { ws, closed } = await openLive(await this.#open("commands", "watch"), (data) => {
|
|
24701
|
+
if (typeof data === "string") onEvent(JSON.parse(data));
|
|
24702
|
+
});
|
|
24703
|
+
return { close: () => ws.close(), closed };
|
|
24647
24704
|
}
|
|
24648
24705
|
async run(cmd, opts = {}) {
|
|
24649
24706
|
let answer = await this.#endpoint.command("exec_command", {
|
|
@@ -24720,6 +24777,7 @@ var Computer = class _Computer {
|
|
|
24720
24777
|
computerID;
|
|
24721
24778
|
commands;
|
|
24722
24779
|
files;
|
|
24780
|
+
pty;
|
|
24723
24781
|
#connection;
|
|
24724
24782
|
#token;
|
|
24725
24783
|
#computer;
|
|
@@ -24730,7 +24788,9 @@ var Computer = class _Computer {
|
|
|
24730
24788
|
this.#token = token;
|
|
24731
24789
|
this.#urls = info.endpoints;
|
|
24732
24790
|
this.#computer = new Endpoint(info.endpoints.computer, token);
|
|
24733
|
-
|
|
24791
|
+
const open2 = (surface, mode) => this.liveSession(surface, mode);
|
|
24792
|
+
this.commands = new Commands(this.#computer, open2);
|
|
24793
|
+
this.pty = new Pty(open2);
|
|
24734
24794
|
this.files = new Files(this.#computer);
|
|
24735
24795
|
}
|
|
24736
24796
|
static async create(opts) {
|
|
@@ -24790,6 +24850,15 @@ var Computer = class _Computer {
|
|
|
24790
24850
|
static async getLogs(computerID, opts = {}) {
|
|
24791
24851
|
return answered(await apiOf(opts).GET("/v1/computers/{computerID}/logs", pathOf(computerID))).logs;
|
|
24792
24852
|
}
|
|
24853
|
+
/** A one-time ticket to open one of its surfaces live, within a minute. */
|
|
24854
|
+
static async createLiveSession(computerID, session, opts = {}) {
|
|
24855
|
+
return answered(
|
|
24856
|
+
await apiOf(opts).POST("/v1/computers/{computerID}/live", {
|
|
24857
|
+
...pathOf(computerID),
|
|
24858
|
+
body: { surface: session.surface, mode: session.mode ?? "watch" }
|
|
24859
|
+
})
|
|
24860
|
+
);
|
|
24861
|
+
}
|
|
24793
24862
|
static async kill(computerID, opts = {}) {
|
|
24794
24863
|
answered(await apiOf(opts).DELETE("/v1/computers/{computerID}", pathOf(computerID)));
|
|
24795
24864
|
}
|
|
@@ -24819,6 +24888,9 @@ var Computer = class _Computer {
|
|
|
24819
24888
|
start(opts = {}) {
|
|
24820
24889
|
return _Computer.start(this.computerID, { ...this.#connection, ...opts });
|
|
24821
24890
|
}
|
|
24891
|
+
liveSession(surface, mode = "watch") {
|
|
24892
|
+
return _Computer.createLiveSession(this.computerID, { surface, mode }, this.#connection);
|
|
24893
|
+
}
|
|
24822
24894
|
getLogs() {
|
|
24823
24895
|
return _Computer.getLogs(this.computerID, this.#connection);
|
|
24824
24896
|
}
|
|
@@ -135,6 +135,44 @@ export interface paths {
|
|
|
135
135
|
patch?: never;
|
|
136
136
|
trace?: never;
|
|
137
137
|
};
|
|
138
|
+
"/v1/computers/{computerID}/live": {
|
|
139
|
+
parameters: {
|
|
140
|
+
query?: never;
|
|
141
|
+
header?: never;
|
|
142
|
+
path: {
|
|
143
|
+
computerID: components["parameters"]["computerID"];
|
|
144
|
+
};
|
|
145
|
+
cookie?: never;
|
|
146
|
+
};
|
|
147
|
+
get?: never;
|
|
148
|
+
put?: never;
|
|
149
|
+
/** A one-time ticket to watch or operate one of its surfaces live: the agent's commands as they run, or a shell of your own. Open its url as a WebSocket within 60 seconds. */
|
|
150
|
+
post: operations["createLiveSession"];
|
|
151
|
+
delete?: never;
|
|
152
|
+
options?: never;
|
|
153
|
+
head?: never;
|
|
154
|
+
patch?: never;
|
|
155
|
+
trace?: never;
|
|
156
|
+
};
|
|
157
|
+
"/v1/live/{liveID}": {
|
|
158
|
+
parameters: {
|
|
159
|
+
query?: never;
|
|
160
|
+
header?: never;
|
|
161
|
+
path: {
|
|
162
|
+
liveID: string;
|
|
163
|
+
};
|
|
164
|
+
cookie?: never;
|
|
165
|
+
};
|
|
166
|
+
/** Open a live session as a WebSocket. The ticket in its path is its authority and works once, so it takes no token. A request with an Origin header is refused unless the service was told to allow that origin. */
|
|
167
|
+
get: operations["openLiveSession"];
|
|
168
|
+
put?: never;
|
|
169
|
+
post?: never;
|
|
170
|
+
delete?: never;
|
|
171
|
+
options?: never;
|
|
172
|
+
head?: never;
|
|
173
|
+
patch?: never;
|
|
174
|
+
trace?: never;
|
|
175
|
+
};
|
|
138
176
|
}
|
|
139
177
|
export type webhooks = Record<string, never>;
|
|
140
178
|
export interface components {
|
|
@@ -202,11 +240,45 @@ export interface components {
|
|
|
202
240
|
};
|
|
203
241
|
ComputerDetail: components["schemas"]["Computer"] & {
|
|
204
242
|
uptimeSeconds: number;
|
|
243
|
+
/** @description What can be opened live while it runs. */
|
|
244
|
+
surfaces: components["schemas"]["SurfaceInfo"][];
|
|
205
245
|
tools: {
|
|
206
246
|
computer: string[];
|
|
207
247
|
browser: string[];
|
|
208
248
|
};
|
|
209
249
|
};
|
|
250
|
+
/**
|
|
251
|
+
* @description commands: the agent's commands as they run, read-only, in commands@1. terminal: a shell of your own in its workspace, as its user, in pty@1.
|
|
252
|
+
* @enum {string}
|
|
253
|
+
*/
|
|
254
|
+
Surface: "commands" | "terminal";
|
|
255
|
+
/**
|
|
256
|
+
* @description In watch, what you send is dropped.
|
|
257
|
+
* @enum {string}
|
|
258
|
+
*/
|
|
259
|
+
LiveMode: "watch" | "operate";
|
|
260
|
+
SurfaceInfo: {
|
|
261
|
+
surface: components["schemas"]["Surface"];
|
|
262
|
+
protocol: string;
|
|
263
|
+
/** @description Whether it can be operated */
|
|
264
|
+
operate: boolean;
|
|
265
|
+
/** @description Why it can't be opened here */
|
|
266
|
+
unavailable?: string;
|
|
267
|
+
};
|
|
268
|
+
NewLiveSession: {
|
|
269
|
+
surface: components["schemas"]["Surface"];
|
|
270
|
+
/** @default watch */
|
|
271
|
+
mode: components["schemas"]["LiveMode"];
|
|
272
|
+
};
|
|
273
|
+
LiveSession: {
|
|
274
|
+
/** @description The WebSocket to open */
|
|
275
|
+
url: string;
|
|
276
|
+
protocol: string;
|
|
277
|
+
surface: components["schemas"]["Surface"];
|
|
278
|
+
mode: components["schemas"]["LiveMode"];
|
|
279
|
+
/** Format: date-time */
|
|
280
|
+
expiresAt: string;
|
|
281
|
+
};
|
|
210
282
|
ComputerLogs: {
|
|
211
283
|
logs: {
|
|
212
284
|
/** Format: date-time */
|
|
@@ -476,4 +548,57 @@ export interface operations {
|
|
|
476
548
|
404: components["responses"]["Error"];
|
|
477
549
|
};
|
|
478
550
|
};
|
|
551
|
+
createLiveSession: {
|
|
552
|
+
parameters: {
|
|
553
|
+
query?: never;
|
|
554
|
+
header?: never;
|
|
555
|
+
path: {
|
|
556
|
+
computerID: components["parameters"]["computerID"];
|
|
557
|
+
};
|
|
558
|
+
cookie?: never;
|
|
559
|
+
};
|
|
560
|
+
requestBody: {
|
|
561
|
+
content: {
|
|
562
|
+
"application/json": components["schemas"]["NewLiveSession"];
|
|
563
|
+
};
|
|
564
|
+
};
|
|
565
|
+
responses: {
|
|
566
|
+
/** @description The ticket. */
|
|
567
|
+
201: {
|
|
568
|
+
headers: {
|
|
569
|
+
[name: string]: unknown;
|
|
570
|
+
};
|
|
571
|
+
content: {
|
|
572
|
+
"application/json": components["schemas"]["LiveSession"];
|
|
573
|
+
};
|
|
574
|
+
};
|
|
575
|
+
400: components["responses"]["Error"];
|
|
576
|
+
401: components["responses"]["Unauthorized"];
|
|
577
|
+
404: components["responses"]["Error"];
|
|
578
|
+
409: components["responses"]["Error"];
|
|
579
|
+
};
|
|
580
|
+
};
|
|
581
|
+
openLiveSession: {
|
|
582
|
+
parameters: {
|
|
583
|
+
query?: never;
|
|
584
|
+
header?: never;
|
|
585
|
+
path: {
|
|
586
|
+
liveID: string;
|
|
587
|
+
};
|
|
588
|
+
cookie?: never;
|
|
589
|
+
};
|
|
590
|
+
requestBody?: never;
|
|
591
|
+
responses: {
|
|
592
|
+
/** @description The socket */
|
|
593
|
+
101: {
|
|
594
|
+
headers: {
|
|
595
|
+
[name: string]: unknown;
|
|
596
|
+
};
|
|
597
|
+
content?: never;
|
|
598
|
+
};
|
|
599
|
+
403: components["responses"]["Error"];
|
|
600
|
+
404: components["responses"]["Error"];
|
|
601
|
+
426: components["responses"]["Error"];
|
|
602
|
+
};
|
|
603
|
+
};
|
|
479
604
|
}
|
package/dist/types/sdk.d.ts
CHANGED
|
@@ -4,6 +4,39 @@ export type ComputerInfo = Schemas["Computer"];
|
|
|
4
4
|
export type ComputerDetail = Schemas["ComputerDetail"];
|
|
5
5
|
export type ServiceInfo = Schemas["ServiceInfo"];
|
|
6
6
|
export type ComputerLog = Schemas["ComputerLogs"]["logs"][number];
|
|
7
|
+
export type LiveSurface = Schemas["Surface"];
|
|
8
|
+
export type LiveMode = Schemas["LiveMode"];
|
|
9
|
+
export type LiveSession = Schemas["LiveSession"];
|
|
10
|
+
/** What happens to one of the agent's commands, as it happens. */
|
|
11
|
+
export type CommandEvent = {
|
|
12
|
+
type: "start";
|
|
13
|
+
id: string;
|
|
14
|
+
cmd: string;
|
|
15
|
+
workdir: string;
|
|
16
|
+
at: string;
|
|
17
|
+
} | {
|
|
18
|
+
type: "output";
|
|
19
|
+
id: string;
|
|
20
|
+
stream: "stdout" | "stderr";
|
|
21
|
+
text: string;
|
|
22
|
+
} | {
|
|
23
|
+
type: "exit";
|
|
24
|
+
id: string;
|
|
25
|
+
exitCode: number;
|
|
26
|
+
at: string;
|
|
27
|
+
};
|
|
28
|
+
export interface LiveHandle {
|
|
29
|
+
close(): void;
|
|
30
|
+
/** Resolves when the socket closes, with why. */
|
|
31
|
+
closed: Promise<{
|
|
32
|
+
code: number;
|
|
33
|
+
reason: string;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
export interface PtyHandle extends LiveHandle {
|
|
37
|
+
sendInput(data: string): void;
|
|
38
|
+
resize(columns: number, rows: number): void;
|
|
39
|
+
}
|
|
7
40
|
export interface ConnectionOpts {
|
|
8
41
|
/** The control token; `AGENTCOMPUTER_API_KEY` by default. */
|
|
9
42
|
apiKey?: string;
|
|
@@ -48,10 +81,23 @@ declare class Endpoint {
|
|
|
48
81
|
command(name: string, args: Record<string, unknown>): Promise<CommandAnswer>;
|
|
49
82
|
close(): Promise<void>;
|
|
50
83
|
}
|
|
84
|
+
type Opener = (surface: LiveSurface, mode: LiveMode) => Promise<LiveSession>;
|
|
85
|
+
/** A shell of your own on the computer, beside the agent's commands. */
|
|
86
|
+
declare class Pty {
|
|
87
|
+
#private;
|
|
88
|
+
constructor(open: Opener);
|
|
89
|
+
/** Attach to its shell, starting one if none is running. Every attachment shares it. */
|
|
90
|
+
connect(opts: {
|
|
91
|
+
onData: (data: string) => void;
|
|
92
|
+
mode?: LiveMode;
|
|
93
|
+
}): Promise<PtyHandle>;
|
|
94
|
+
}
|
|
51
95
|
/** Commands on a computer with the terminal level. */
|
|
52
96
|
declare class Commands {
|
|
53
97
|
#private;
|
|
54
|
-
constructor(endpoint: Endpoint);
|
|
98
|
+
constructor(endpoint: Endpoint, open: Opener);
|
|
99
|
+
/** Each of the agent's commands as it runs: the ones already heard first, then as they come. */
|
|
100
|
+
watch(onEvent: (event: CommandEvent) => void): Promise<LiveHandle>;
|
|
55
101
|
/** Run a command to its end. */
|
|
56
102
|
run(cmd: string, opts?: {
|
|
57
103
|
cwd?: string;
|
|
@@ -98,6 +144,7 @@ export declare class Computer {
|
|
|
98
144
|
readonly computerID: string;
|
|
99
145
|
readonly commands: Commands;
|
|
100
146
|
readonly files: Files;
|
|
147
|
+
readonly pty: Pty;
|
|
101
148
|
private constructor();
|
|
102
149
|
static create(opts: CreateOpts): Promise<Computer>;
|
|
103
150
|
/** A computer made earlier. Its token was shown when it was made, and only then. */
|
|
@@ -116,6 +163,11 @@ export declare class Computer {
|
|
|
116
163
|
timeoutMs?: number;
|
|
117
164
|
}): Promise<ComputerInfo>;
|
|
118
165
|
static getLogs(computerID: string, opts?: ConnectionOpts): Promise<ComputerLog[]>;
|
|
166
|
+
/** A one-time ticket to open one of its surfaces live, within a minute. */
|
|
167
|
+
static createLiveSession(computerID: string, session: {
|
|
168
|
+
surface: LiveSurface;
|
|
169
|
+
mode?: LiveMode;
|
|
170
|
+
}, opts?: ConnectionOpts): Promise<LiveSession>;
|
|
119
171
|
static kill(computerID: string, opts?: ConnectionOpts): Promise<void>;
|
|
120
172
|
/** The endpoint to give an MCP client. */
|
|
121
173
|
getMcpUrl(endpoint?: "computer" | "browser"): string;
|
|
@@ -134,6 +186,7 @@ export declare class Computer {
|
|
|
134
186
|
endpoints: components["schemas"]["Endpoints"];
|
|
135
187
|
} & {
|
|
136
188
|
uptimeSeconds: number;
|
|
189
|
+
surfaces: components["schemas"]["SurfaceInfo"][];
|
|
137
190
|
tools: {
|
|
138
191
|
computer: string[];
|
|
139
192
|
browser: string[];
|
|
@@ -178,6 +231,13 @@ export declare class Computer {
|
|
|
178
231
|
metadata: components["schemas"]["Metadata"];
|
|
179
232
|
endpoints: components["schemas"]["Endpoints"];
|
|
180
233
|
}>;
|
|
234
|
+
liveSession(surface: LiveSurface, mode?: LiveMode): Promise<{
|
|
235
|
+
url: string;
|
|
236
|
+
protocol: string;
|
|
237
|
+
surface: components["schemas"]["Surface"];
|
|
238
|
+
mode: components["schemas"]["LiveMode"];
|
|
239
|
+
expiresAt: string;
|
|
240
|
+
}>;
|
|
181
241
|
getLogs(): Promise<{
|
|
182
242
|
timestamp: string;
|
|
183
243
|
line: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentorg/computer",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
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": {
|
|
@@ -31,16 +31,18 @@
|
|
|
31
31
|
"@playwright/mcp": "0.0.84"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@agentorg/exec": "0.0.
|
|
34
|
+
"@agentorg/exec": "0.0.3",
|
|
35
35
|
"@biomejs/biome": "2.6.5",
|
|
36
36
|
"@modelcontextprotocol/client": "2.4.0",
|
|
37
37
|
"@modelcontextprotocol/node": "2.1.2",
|
|
38
38
|
"@modelcontextprotocol/server": "2.4.0",
|
|
39
39
|
"@types/node": "^22.20.5",
|
|
40
|
+
"@types/ws": "8.18.2",
|
|
40
41
|
"ajv": "8.20.0",
|
|
41
42
|
"esbuild": "0.28.2",
|
|
42
43
|
"openapi-fetch": "0.17.0",
|
|
43
44
|
"typescript": "^7.0.2",
|
|
45
|
+
"ws": "8.22.2",
|
|
44
46
|
"yaml": "2.9.1",
|
|
45
47
|
"zod": "^4.6.7"
|
|
46
48
|
},
|
|
@@ -49,5 +51,11 @@
|
|
|
49
51
|
"types": "./dist/types/sdk.d.ts",
|
|
50
52
|
"default": "./dist/sdk.js"
|
|
51
53
|
}
|
|
54
|
+
},
|
|
55
|
+
"optionalDependencies": {
|
|
56
|
+
"node-pty": "1.1.0"
|
|
57
|
+
},
|
|
58
|
+
"allowScripts": {
|
|
59
|
+
"node-pty@1.1.0": true
|
|
52
60
|
}
|
|
53
61
|
}
|