@coltonkirsten/a12s 0.3.0 → 0.4.1
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/dist/a12s.js +492 -19
- package/dist/src/client.d.ts +20 -1
- package/dist/src/client.js +233 -19
- package/dist/src/fleet.d.ts +160 -0
- package/dist/src/fleet.js +306 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +4 -1
- package/dist/src/node.d.ts +8 -0
- package/dist/src/node.js +15 -2
- package/dist/src/types.d.ts +201 -14
- package/package.json +1 -1
package/dist/src/client.js
CHANGED
|
@@ -16,6 +16,16 @@ export class A12sError extends Error {
|
|
|
16
16
|
this.details = body.details;
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
+
/** A 404: the agent computer, Service, Message or token does not exist. */
|
|
20
|
+
export class NotFound extends A12sError {
|
|
21
|
+
constructor(status, body) {
|
|
22
|
+
super(status, body);
|
|
23
|
+
this.name = "NotFound";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function apiError(status, body) {
|
|
27
|
+
return status === 404 ? new NotFound(status, body) : new A12sError(status, body);
|
|
28
|
+
}
|
|
19
29
|
/** Thrown by an event stream with `onGap: "throw"` when events were lost. */
|
|
20
30
|
export class A12sGapError extends Error {
|
|
21
31
|
after;
|
|
@@ -35,10 +45,15 @@ export class A12sStreamError extends Error {
|
|
|
35
45
|
}
|
|
36
46
|
}
|
|
37
47
|
const enc = encodeURIComponent;
|
|
48
|
+
/**
|
|
49
|
+
* @deprecated Use {@link Fleet}: `fleet.agentComputers.get(name)` returns an {@link AgentComputer} with these
|
|
50
|
+
* methods. Kept for one release.
|
|
51
|
+
*/
|
|
38
52
|
export class A12sClient {
|
|
39
53
|
url;
|
|
40
54
|
token;
|
|
41
55
|
fetchImpl;
|
|
56
|
+
shared;
|
|
42
57
|
constructor(opts = {}) {
|
|
43
58
|
this.url = (opts.url ?? "").replace(/\/+$/, "");
|
|
44
59
|
this.token = opts.token;
|
|
@@ -47,16 +62,17 @@ export class A12sClient {
|
|
|
47
62
|
headers(extra = {}) {
|
|
48
63
|
return this.token ? { authorization: `Bearer ${this.token}`, ...extra } : extra;
|
|
49
64
|
}
|
|
50
|
-
|
|
65
|
+
/** @internal */
|
|
66
|
+
async request(method, path, body, opts = {}) {
|
|
51
67
|
const res = await this.fetchImpl(this.url + path, {
|
|
52
68
|
method,
|
|
53
|
-
headers: this.headers(body === undefined ? {} : { "content-type": "application/json" }),
|
|
69
|
+
headers: this.headers({ ...(body === undefined ? {} : { "content-type": "application/json" }), ...opts.headers }),
|
|
54
70
|
body: body === undefined ? undefined : JSON.stringify(body),
|
|
55
|
-
signal,
|
|
71
|
+
signal: opts.signal,
|
|
56
72
|
});
|
|
57
73
|
const text = await res.text();
|
|
58
74
|
if (!res.ok)
|
|
59
|
-
throw
|
|
75
|
+
throw apiError(res.status, parseError(res.status, text));
|
|
60
76
|
return (text ? JSON.parse(text) : undefined);
|
|
61
77
|
}
|
|
62
78
|
/** Every Computer and Service: phase, session, active Turn, inbox, power. */
|
|
@@ -64,9 +80,9 @@ export class A12sClient {
|
|
|
64
80
|
return this.request("GET", "/v1/status");
|
|
65
81
|
}
|
|
66
82
|
async computer(name) {
|
|
67
|
-
const c = (await this.status()).
|
|
83
|
+
const c = (await this.status()).agentComputers.find((x) => x.name === name);
|
|
68
84
|
if (!c)
|
|
69
|
-
throw new
|
|
85
|
+
throw new NotFound(404, { code: "not_found", message: `no Computer ${name}` });
|
|
70
86
|
return c;
|
|
71
87
|
}
|
|
72
88
|
/**
|
|
@@ -76,7 +92,7 @@ export class A12sClient {
|
|
|
76
92
|
send(computer, msg) {
|
|
77
93
|
const m = typeof msg === "string" ? { body: msg } : { ...msg };
|
|
78
94
|
m.idempotencyKey ??= globalThis.crypto.randomUUID();
|
|
79
|
-
return this.request("POST", `/v1/computers/${enc(computer)}/inbox`, m);
|
|
95
|
+
return this.request("POST", `/v1/agent-computers/${enc(computer)}/inbox`, m);
|
|
80
96
|
}
|
|
81
97
|
/** Sends a Message, waits for the Turn that delivers it and resolves when that Turn ends: what `a12s prompt` does. */
|
|
82
98
|
async prompt(computer, body, opts = {}) {
|
|
@@ -105,8 +121,21 @@ export class A12sClient {
|
|
|
105
121
|
}
|
|
106
122
|
return new EventStream((name, live, signal) => {
|
|
107
123
|
const q = opts.turn ? `?turn=${enc(opts.turn)}` : "";
|
|
108
|
-
return this.stream(name, `/v1/computers/${enc(name)}/events${q}`, opts.after, { ...opts, signal, live });
|
|
109
|
-
}, names ?? (async () => (await this.status()).
|
|
124
|
+
return this.stream(name, `/v1/agent-computers/${enc(name)}/events${q}`, opts.after, { ...opts, signal, live });
|
|
125
|
+
}, names ?? (async () => (await this.status()).agentComputers.map((c) => c.name)), opts.signal);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* @internal Events of the named agent computers (all if none), and the Controller's own about them, read from this
|
|
129
|
+
* client's one GET /v1/events connection.
|
|
130
|
+
*/
|
|
131
|
+
sharedEvents(names, opts = {}) {
|
|
132
|
+
this.shared ??= new SharedEvents((cursor, signal) => this.fetchImpl(this.url + "/v1/events", {
|
|
133
|
+
headers: this.headers({ accept: "text/event-stream", ...(cursor !== undefined ? { "last-event-id": cursor } : {}) }),
|
|
134
|
+
signal,
|
|
135
|
+
}));
|
|
136
|
+
const shared = this.shared;
|
|
137
|
+
const wanted = names && new Set(names);
|
|
138
|
+
return new EventStream((_name, live, signal) => shared.subscribe({ wanted, live, onGap: opts.onGap, reconnectMs: opts.reconnectMs }, signal), [""], opts.signal);
|
|
110
139
|
}
|
|
111
140
|
/**
|
|
112
141
|
* Finished Turns of one Computer, several or all, as they end: who sent the work (`messages`), what the agent said
|
|
@@ -124,28 +153,28 @@ export class A12sClient {
|
|
|
124
153
|
if (opts.after !== undefined)
|
|
125
154
|
q.set("after", String(opts.after));
|
|
126
155
|
const qs = q.toString();
|
|
127
|
-
return this.request("GET", `/v1/computers/${enc(computer)}/inbox${qs ? "?" + qs : ""}`);
|
|
156
|
+
return this.request("GET", `/v1/agent-computers/${enc(computer)}/inbox${qs ? "?" + qs : ""}`);
|
|
128
157
|
}
|
|
129
158
|
message(computer, id) {
|
|
130
|
-
return this.request("GET", `/v1/computers/${enc(computer)}/inbox/${enc(id)}`);
|
|
159
|
+
return this.request("GET", `/v1/agent-computers/${enc(computer)}/inbox/${enc(id)}`);
|
|
131
160
|
}
|
|
132
161
|
/** Withdraws a pending Message; a 409 A12sError names its state if it is too late. */
|
|
133
162
|
withdraw(computer, id) {
|
|
134
|
-
return this.request("DELETE", `/v1/computers/${enc(computer)}/inbox/${enc(id)}`);
|
|
163
|
+
return this.request("DELETE", `/v1/agent-computers/${enc(computer)}/inbox/${enc(id)}`);
|
|
135
164
|
}
|
|
136
165
|
/** Interrupts a Turn (default: the active one). The Turn ends `interrupted`; nothing is replayed. */
|
|
137
166
|
async stop(computer, turn) {
|
|
138
167
|
const id = turn ?? (await this.computer(computer)).activeTurn;
|
|
139
168
|
if (id)
|
|
140
|
-
await this.request("POST", `/v1/computers/${enc(computer)}/turns/${enc(id)}/stop`, {});
|
|
169
|
+
await this.request("POST", `/v1/agent-computers/${enc(computer)}/turns/${enc(id)}/stop`, {});
|
|
141
170
|
}
|
|
142
171
|
/** Stops the Computer's processes and keeps its disks, session and inbox. */
|
|
143
172
|
async sleep(computer) {
|
|
144
|
-
await this.request("POST", `/v1/computers/${enc(computer)}/power`, { state: "asleep" });
|
|
173
|
+
await this.request("POST", `/v1/agent-computers/${enc(computer)}/power`, { state: "asleep" });
|
|
145
174
|
}
|
|
146
175
|
/** Starts a sleeping Computer; its session resumes on the next Turn. */
|
|
147
176
|
async wake(computer) {
|
|
148
|
-
await this.request("POST", `/v1/computers/${enc(computer)}/power`, { state: "awake" });
|
|
177
|
+
await this.request("POST", `/v1/agent-computers/${enc(computer)}/power`, { state: "awake" });
|
|
149
178
|
}
|
|
150
179
|
async services() {
|
|
151
180
|
return (await this.request("GET", "/v1/services")).services ?? [];
|
|
@@ -165,7 +194,7 @@ export class A12sClient {
|
|
|
165
194
|
async deliveredIn(computer, id, signal) {
|
|
166
195
|
// Every subscription starts with a snapshot, so resubscribing after a drop never misses the delivery.
|
|
167
196
|
while (!signal?.aborted) {
|
|
168
|
-
for await (const ev of this.stream(computer, `/v1/computers/${enc(computer)}/inbox/${enc(id)}/events`, undefined, {
|
|
197
|
+
for await (const ev of this.stream(computer, `/v1/agent-computers/${enc(computer)}/inbox/${enc(id)}/events`, undefined, {
|
|
169
198
|
signal,
|
|
170
199
|
once: true,
|
|
171
200
|
})) {
|
|
@@ -214,7 +243,7 @@ export class A12sClient {
|
|
|
214
243
|
continue;
|
|
215
244
|
}
|
|
216
245
|
if (!res.ok) {
|
|
217
|
-
const err =
|
|
246
|
+
const err = apiError(res.status, parseError(res.status, await res.text()));
|
|
218
247
|
// Asleep or starting: the journal comes back with the Computer.
|
|
219
248
|
if (res.status !== 503 && res.status !== 502)
|
|
220
249
|
throw err;
|
|
@@ -285,6 +314,188 @@ export class A12sClient {
|
|
|
285
314
|
}
|
|
286
315
|
}
|
|
287
316
|
}
|
|
317
|
+
/** One GET /v1/events connection, open while anything subscribes: watching fifty agent computers takes one. */
|
|
318
|
+
class SharedEvents {
|
|
319
|
+
open;
|
|
320
|
+
subs = new Set();
|
|
321
|
+
conn;
|
|
322
|
+
live = false;
|
|
323
|
+
constructor(open) {
|
|
324
|
+
this.open = open;
|
|
325
|
+
}
|
|
326
|
+
async *subscribe(sub, signal) {
|
|
327
|
+
const queue = [];
|
|
328
|
+
let failure;
|
|
329
|
+
let wake;
|
|
330
|
+
const notify = () => {
|
|
331
|
+
const w = wake;
|
|
332
|
+
wake = undefined;
|
|
333
|
+
w?.();
|
|
334
|
+
};
|
|
335
|
+
const s = {
|
|
336
|
+
...sub,
|
|
337
|
+
push: (ev) => {
|
|
338
|
+
queue.push(ev);
|
|
339
|
+
notify();
|
|
340
|
+
},
|
|
341
|
+
fail: (error) => {
|
|
342
|
+
failure ??= { error };
|
|
343
|
+
notify();
|
|
344
|
+
},
|
|
345
|
+
};
|
|
346
|
+
signal.addEventListener("abort", notify, { once: true });
|
|
347
|
+
this.add(s);
|
|
348
|
+
try {
|
|
349
|
+
for (;;) {
|
|
350
|
+
if (queue.length) {
|
|
351
|
+
yield queue.shift();
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
if (failure)
|
|
355
|
+
throw failure.error;
|
|
356
|
+
if (signal.aborted)
|
|
357
|
+
return;
|
|
358
|
+
await new Promise((r) => (wake = r));
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
finally {
|
|
362
|
+
signal.removeEventListener("abort", notify);
|
|
363
|
+
this.remove(s);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
add(s) {
|
|
367
|
+
this.subs.add(s);
|
|
368
|
+
if (!this.conn) {
|
|
369
|
+
const conn = new AbortController();
|
|
370
|
+
this.conn = conn;
|
|
371
|
+
this.live = false;
|
|
372
|
+
void this.run(conn);
|
|
373
|
+
}
|
|
374
|
+
else if (this.live) {
|
|
375
|
+
s.live();
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
remove(s) {
|
|
379
|
+
this.subs.delete(s);
|
|
380
|
+
if (this.subs.size === 0)
|
|
381
|
+
this.stop();
|
|
382
|
+
}
|
|
383
|
+
stop() {
|
|
384
|
+
this.conn?.abort();
|
|
385
|
+
this.conn = undefined;
|
|
386
|
+
this.live = false;
|
|
387
|
+
}
|
|
388
|
+
async run(conn) {
|
|
389
|
+
const { signal } = conn;
|
|
390
|
+
let cursor;
|
|
391
|
+
try {
|
|
392
|
+
while (!signal.aborted) {
|
|
393
|
+
let res;
|
|
394
|
+
try {
|
|
395
|
+
res = await this.open(cursor, signal);
|
|
396
|
+
}
|
|
397
|
+
catch (err) {
|
|
398
|
+
if (signal.aborted)
|
|
399
|
+
return;
|
|
400
|
+
if (!isNetworkError(err))
|
|
401
|
+
throw err;
|
|
402
|
+
}
|
|
403
|
+
if (res && !res.ok) {
|
|
404
|
+
const err = apiError(res.status, parseError(res.status, await res.text()));
|
|
405
|
+
if (res.status !== 502 && res.status !== 503)
|
|
406
|
+
throw err;
|
|
407
|
+
res = undefined;
|
|
408
|
+
}
|
|
409
|
+
if (res) {
|
|
410
|
+
if (!res.body)
|
|
411
|
+
throw new A12sStreamError("GET /v1/events: response has no body");
|
|
412
|
+
const frames = readSSE(res.body);
|
|
413
|
+
try {
|
|
414
|
+
for (;;) {
|
|
415
|
+
let r;
|
|
416
|
+
try {
|
|
417
|
+
r = await frames.next();
|
|
418
|
+
}
|
|
419
|
+
catch {
|
|
420
|
+
break;
|
|
421
|
+
}
|
|
422
|
+
if (r.done)
|
|
423
|
+
break;
|
|
424
|
+
cursor = this.frame(r.value, cursor);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
finally {
|
|
428
|
+
await frames.return(undefined);
|
|
429
|
+
res.body.cancel().catch(() => { });
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
await sleep(this.reconnectMs(), signal);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
catch (err) {
|
|
436
|
+
if (signal.aborted)
|
|
437
|
+
return;
|
|
438
|
+
const subs = [...this.subs];
|
|
439
|
+
if (this.conn === conn)
|
|
440
|
+
this.stop();
|
|
441
|
+
for (const s of subs)
|
|
442
|
+
s.fail(err);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
/** Delivers one frame and returns the cursor to resume after. */
|
|
446
|
+
frame(f, cursor) {
|
|
447
|
+
if (f.event === "head") {
|
|
448
|
+
const id = parseJSON(f.data)?.id;
|
|
449
|
+
this.live = true;
|
|
450
|
+
for (const s of this.subs)
|
|
451
|
+
s.live();
|
|
452
|
+
return typeof id === "string" && id ? id : cursor;
|
|
453
|
+
}
|
|
454
|
+
if (f.event === "gap") {
|
|
455
|
+
const data = cursor !== undefined ? { lastEventId: cursor } : {};
|
|
456
|
+
const gap = { v: 1, computer: "", session: "", turn: "", seq: 0, ts: new Date().toISOString(), type: "gap", data };
|
|
457
|
+
for (const s of this.subs) {
|
|
458
|
+
if (s.onGap === "throw")
|
|
459
|
+
s.fail(new A12sGapError(data));
|
|
460
|
+
else
|
|
461
|
+
s.push(gap);
|
|
462
|
+
}
|
|
463
|
+
return cursor;
|
|
464
|
+
}
|
|
465
|
+
if (f.event || !f.data)
|
|
466
|
+
return cursor;
|
|
467
|
+
let ev;
|
|
468
|
+
try {
|
|
469
|
+
ev = JSON.parse(f.data);
|
|
470
|
+
}
|
|
471
|
+
catch (err) {
|
|
472
|
+
throw new A12sStreamError(`malformed event after ${cursor ?? "(start)"}: ${f.data.slice(0, 120)}`, { cause: err });
|
|
473
|
+
}
|
|
474
|
+
for (const s of this.subs)
|
|
475
|
+
if (wanted(s.wanted, ev))
|
|
476
|
+
s.push(ev);
|
|
477
|
+
return f.id ?? cursor;
|
|
478
|
+
}
|
|
479
|
+
reconnectMs() {
|
|
480
|
+
let ms = 1000;
|
|
481
|
+
for (const s of this.subs)
|
|
482
|
+
if (s.reconnectMs !== undefined)
|
|
483
|
+
ms = Math.min(ms, s.reconnectMs);
|
|
484
|
+
return ms;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
function agentComputerOf(ev) {
|
|
488
|
+
return ev.agentComputer || ev.computer;
|
|
489
|
+
}
|
|
490
|
+
function wanted(names, ev) {
|
|
491
|
+
if (!names)
|
|
492
|
+
return true;
|
|
493
|
+
if (ev.type === "fleet.changed")
|
|
494
|
+
return (ev.data?.names ?? []).some((n) => names.has(n));
|
|
495
|
+
if (ev.type === "service.phase")
|
|
496
|
+
return names.has(ev.data?.service);
|
|
497
|
+
return names.has(agentComputerOf(ev));
|
|
498
|
+
}
|
|
288
499
|
/** Events of one or more Computers, merged in arrival order. Iterate it with `for await`. */
|
|
289
500
|
export class EventStream {
|
|
290
501
|
source;
|
|
@@ -442,7 +653,8 @@ class TurnBuilder {
|
|
|
442
653
|
add(ev) {
|
|
443
654
|
if (!ev.turn)
|
|
444
655
|
return undefined;
|
|
445
|
-
const
|
|
656
|
+
const name = agentComputerOf(ev);
|
|
657
|
+
const key = `${name}\u0000${ev.turn}`;
|
|
446
658
|
let t = this.open.get(key);
|
|
447
659
|
if (!t)
|
|
448
660
|
this.open.set(key, (t = { text: "", afterTool: false, messages: [], tools: new Map() }));
|
|
@@ -470,7 +682,8 @@ class TurnBuilder {
|
|
|
470
682
|
case "turn.finished":
|
|
471
683
|
this.open.delete(key);
|
|
472
684
|
return {
|
|
473
|
-
|
|
685
|
+
agentComputer: name,
|
|
686
|
+
computer: name,
|
|
474
687
|
id: ev.turn,
|
|
475
688
|
session: ev.session,
|
|
476
689
|
status: ev.data.status,
|
|
@@ -479,6 +692,7 @@ class TurnBuilder {
|
|
|
479
692
|
messages: t.messages,
|
|
480
693
|
tools: [...t.tools.values()],
|
|
481
694
|
usage: ev.data.usage,
|
|
695
|
+
...(ev.data.tokens ? { tokens: ev.data.tokens } : {}),
|
|
482
696
|
...(t.startedAt ? { startedAt: t.startedAt } : {}),
|
|
483
697
|
finishedAt: ev.ts,
|
|
484
698
|
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { A12sClient, type A12sClientOptions, type EventsOptions, TurnStream, type EventStream, type PromptOptions, type PromptResult, type SharedEventsOptions } from "./client.js";
|
|
2
|
+
import type { AgentComputerData, AgentComputerSpec, Change, ComputerStatus, CredentialInfo, EnqueueRequest, EnqueueResponse, FleetSpec, InboxListOptions, InboxListResponse, MergePatch, Message, ServiceStatus, StatusResponse, Token, TokenAction, Turn } from "./types.js";
|
|
3
|
+
/** The Fleet as written, and its version for a conditional write. */
|
|
4
|
+
export interface FleetState {
|
|
5
|
+
version: number;
|
|
6
|
+
spec: FleetSpec;
|
|
7
|
+
/** What changed through the API since the last whole-Fleet write. */
|
|
8
|
+
drift: Change[];
|
|
9
|
+
}
|
|
10
|
+
export interface CreateOptions {
|
|
11
|
+
/** Overwrite an existing one instead of failing with A12sError code `exists`. */
|
|
12
|
+
replace?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A running Fleet. Its agent computers, Services and tokens are in {@link agentComputers}, {@link services} and
|
|
16
|
+
* {@link tokens}.
|
|
17
|
+
*
|
|
18
|
+
* ```ts
|
|
19
|
+
* const fleet = await Fleet.connect();
|
|
20
|
+
* const hello = await fleet.agentComputers.create("hello", { instructions: "Be helpful" });
|
|
21
|
+
* await hello.prompt("hi");
|
|
22
|
+
* await hello.remove();
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare class Fleet {
|
|
26
|
+
/** The lower-level client the handles use, for API calls that have no method here. */
|
|
27
|
+
readonly client: A12sClient;
|
|
28
|
+
readonly agentComputers: AgentComputers;
|
|
29
|
+
readonly services: Services;
|
|
30
|
+
readonly tokens: Tokens;
|
|
31
|
+
readonly credentials: Credentials;
|
|
32
|
+
/** No discovery: `url` and `token` as given, by default the page's own origin. */
|
|
33
|
+
constructor(opts?: A12sClientOptions);
|
|
34
|
+
/**
|
|
35
|
+
* In a browser: the Fleet behind the page's own origin, which is `a12s gateway` serving the page (no token
|
|
36
|
+
* needed). In Node: found like {@link connect} finds it. Pass `url` and `token` to reach anything else.
|
|
37
|
+
*/
|
|
38
|
+
static connect(opts?: A12sClientOptions): Promise<Fleet>;
|
|
39
|
+
get url(): string;
|
|
40
|
+
get(): Promise<FleetState>;
|
|
41
|
+
/**
|
|
42
|
+
* Reads the Fleet, lets `fn` change it (in place, or by returning a new spec) and writes it back only if nobody
|
|
43
|
+
* wrote in between; otherwise it reads again and retries, up to 5 times. `spec.defaults` is always present.
|
|
44
|
+
*/
|
|
45
|
+
replace(fn: (spec: FleetSpec) => FleetSpec | void | Promise<FleetSpec | void>): Promise<FleetState>;
|
|
46
|
+
/**
|
|
47
|
+
* Live events of the named agent computers, or (no argument) all of them, and the Fleet's own (`fleet.changed`,
|
|
48
|
+
* `agent_computer.phase`). Every stream of this Fleet shares one connection, which reconnects without losing
|
|
49
|
+
* events. `await stream.ready()` before sending work you want to see from the start; `close()` (or `break`) ends it.
|
|
50
|
+
* `turn` or `after` (one agent computer) replays from its journal instead.
|
|
51
|
+
*/
|
|
52
|
+
events(agentComputers?: string | string[], opts?: EventsOptions): EventStream;
|
|
53
|
+
/** Finished Turns of the named agent computers, or all of them, as they end. */
|
|
54
|
+
turns(agentComputers?: string | string[], opts?: SharedEventsOptions): TurnStream;
|
|
55
|
+
/** Every agent computer and Service: phase, session, active Turn, inbox, power. */
|
|
56
|
+
status(): Promise<StatusResponse>;
|
|
57
|
+
}
|
|
58
|
+
export declare class AgentComputers {
|
|
59
|
+
private readonly client;
|
|
60
|
+
constructor(client: A12sClient);
|
|
61
|
+
/** Adds an agent computer to the Fleet and starts it. Fails with code `exists` if the name is taken. */
|
|
62
|
+
create(name: string, spec?: AgentComputerSpec & CreateOptions): Promise<AgentComputer>;
|
|
63
|
+
/** Throws {@link NotFound} if there is none. */
|
|
64
|
+
get(name: string): Promise<AgentComputer>;
|
|
65
|
+
list(): Promise<AgentComputer[]>;
|
|
66
|
+
}
|
|
67
|
+
/** A handle on one agent computer. `spec`, `effective` and `status` are as of the last create, get, reload or update. */
|
|
68
|
+
export declare class AgentComputer {
|
|
69
|
+
private readonly client;
|
|
70
|
+
readonly name: string;
|
|
71
|
+
spec: AgentComputerSpec;
|
|
72
|
+
/** The spec with the Fleet's defaults merged in. */
|
|
73
|
+
effective: AgentComputerSpec;
|
|
74
|
+
status: ComputerStatus;
|
|
75
|
+
constructor(client: A12sClient, data: AgentComputerData);
|
|
76
|
+
private set;
|
|
77
|
+
private get path();
|
|
78
|
+
reload(): Promise<this>;
|
|
79
|
+
/** Changes the spec: a key set to null goes back to the Fleet's default. A busy one picks it up when idle. */
|
|
80
|
+
update(changes: MergePatch<AgentComputerSpec>): Promise<this>;
|
|
81
|
+
/** Removes it from the Fleet and stops it; its drives are kept. */
|
|
82
|
+
remove(): Promise<void>;
|
|
83
|
+
/** Sends a Message, waits for the Turn that delivers it and resolves when that Turn ends. */
|
|
84
|
+
prompt(text: string, opts?: PromptOptions): Promise<PromptResult>;
|
|
85
|
+
/** Puts a Message in the inbox and returns at once; it is delivered at the next idle moment. */
|
|
86
|
+
send(text: string, opts?: Omit<EnqueueRequest, "body">): Promise<EnqueueResponse>;
|
|
87
|
+
/** Its events, live, from the Fleet's shared connection; `turn` replays one Turn from its start instead. */
|
|
88
|
+
events(opts?: EventsOptions): EventStream;
|
|
89
|
+
/** Its last `limit` finished Turns, newest first. */
|
|
90
|
+
turns(opts: {
|
|
91
|
+
limit: number;
|
|
92
|
+
}): Promise<Turn[]>;
|
|
93
|
+
/** Its Turns as they end, from the Fleet's shared connection. */
|
|
94
|
+
turns(opts?: SharedEventsOptions & {
|
|
95
|
+
limit?: undefined;
|
|
96
|
+
}): TurnStream;
|
|
97
|
+
private pastTurns;
|
|
98
|
+
/** Stops its processes and keeps its disks, session and inbox. */
|
|
99
|
+
sleep(): Promise<void>;
|
|
100
|
+
wake(): Promise<void>;
|
|
101
|
+
/** Interrupts a Turn (default: the active one). */
|
|
102
|
+
stop(turn?: string): Promise<void>;
|
|
103
|
+
inbox(opts?: InboxListOptions): Promise<InboxListResponse>;
|
|
104
|
+
message(id: string): Promise<Message>;
|
|
105
|
+
/** Withdraws a pending Message; a 409 A12sError names its state if it is too late. */
|
|
106
|
+
withdraw(id: string): Promise<Message>;
|
|
107
|
+
}
|
|
108
|
+
export declare class Services {
|
|
109
|
+
private readonly client;
|
|
110
|
+
constructor(client: A12sClient);
|
|
111
|
+
/** Adds a Service to the Fleet. Fails with code `exists` if the name is taken. */
|
|
112
|
+
create(name: string, spec?: Record<string, unknown> & CreateOptions): Promise<Service>;
|
|
113
|
+
/** Throws {@link NotFound} if there is none. */
|
|
114
|
+
get(name: string): Promise<Service>;
|
|
115
|
+
list(): Promise<Service[]>;
|
|
116
|
+
}
|
|
117
|
+
/** A handle on one Service. `spec` and `status` are as of the last create, get, reload, update or power change. */
|
|
118
|
+
export declare class Service {
|
|
119
|
+
private readonly client;
|
|
120
|
+
readonly name: string;
|
|
121
|
+
status: ServiceStatus;
|
|
122
|
+
constructor(client: A12sClient, status: ServiceStatus);
|
|
123
|
+
/** As written in the Fleet. */
|
|
124
|
+
get spec(): Record<string, unknown>;
|
|
125
|
+
private get path();
|
|
126
|
+
reload(): Promise<this>;
|
|
127
|
+
/** Changes the spec as a JSON merge patch: a key set to null is removed. */
|
|
128
|
+
update(changes: Record<string, unknown>): Promise<this>;
|
|
129
|
+
/** Removes it from the Fleet and stops it; its state drive is kept. */
|
|
130
|
+
remove(): Promise<void>;
|
|
131
|
+
sleep(): Promise<this>;
|
|
132
|
+
wake(): Promise<this>;
|
|
133
|
+
private power;
|
|
134
|
+
}
|
|
135
|
+
export declare class Tokens {
|
|
136
|
+
private readonly client;
|
|
137
|
+
constructor(client: A12sClient);
|
|
138
|
+
/**
|
|
139
|
+
* A token for another program; owner only. The secret is in the result once. With `prefix` it may do everything
|
|
140
|
+
* the owner can for names that start with it, and nothing outside; otherwise `actions` on `agentComputers`.
|
|
141
|
+
*/
|
|
142
|
+
create(name: string, opts: {
|
|
143
|
+
prefix: string;
|
|
144
|
+
} | {
|
|
145
|
+
actions: TokenAction[];
|
|
146
|
+
agentComputers?: string[];
|
|
147
|
+
}): Promise<Token>;
|
|
148
|
+
list(): Promise<Token[]>;
|
|
149
|
+
remove(name: string): Promise<void>;
|
|
150
|
+
}
|
|
151
|
+
/** Credentials by name: set once, then name them in a spec's `credentials`. Values are never read back. */
|
|
152
|
+
export declare class Credentials {
|
|
153
|
+
private readonly client;
|
|
154
|
+
constructor(client: A12sClient);
|
|
155
|
+
/** Stores the value on the Controller; agent computers that use it get the new value at once. */
|
|
156
|
+
set(name: string, value: string): Promise<CredentialInfo>;
|
|
157
|
+
list(): Promise<CredentialInfo[]>;
|
|
158
|
+
/** Fails with A12sError code `in_use` while an agent computer or Service uses it. */
|
|
159
|
+
remove(name: string): Promise<void>;
|
|
160
|
+
}
|