@coltonkirsten/a12s 0.5.0 → 0.7.0
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/src/client.d.ts +10 -16
- package/dist/src/client.js +11 -20
- package/dist/src/fleet.d.ts +20 -21
- package/dist/src/fleet.js +21 -18
- package/dist/src/index.d.ts +1 -10
- package/dist/src/index.js +1 -11
- package/dist/src/node.d.ts +13 -19
- package/dist/src/node.js +13 -22
- package/dist/src/types.d.ts +8 -56
- package/package.json +3 -3
package/dist/src/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { A12sEvent, ApiErrorBody, ComputerStatus,
|
|
2
|
-
export interface
|
|
1
|
+
import type { A12sEvent, ApiErrorBody, ComputerStatus, EnqueueResponse, GapData, InboxListOptions, InboxListResponse, Message, PutFleetRequest, PutFleetResponse, SendRequest, ServiceStatus, StatusResponse, Token, TokenRequest, Turn } from "./types.js";
|
|
2
|
+
export interface ConnectOptions {
|
|
3
3
|
/**
|
|
4
4
|
* The Controller's API, e.g. http://127.0.0.1:52011. Default "": the page's own origin, which is what a browser
|
|
5
5
|
* app served by `a12s gateway` uses.
|
|
@@ -58,18 +58,14 @@ export interface WaitOptions {
|
|
|
58
58
|
export interface Reply extends Turn {
|
|
59
59
|
message: EnqueueResponse;
|
|
60
60
|
}
|
|
61
|
-
/**
|
|
62
|
-
|
|
63
|
-
* methods. Kept for one release.
|
|
64
|
-
*/
|
|
65
|
-
export declare class A12sClient {
|
|
61
|
+
/** The HTTP transport behind {@link Fleet} and its handles; the package doesn't export it. */
|
|
62
|
+
export declare class Client {
|
|
66
63
|
readonly url: string;
|
|
67
64
|
private readonly token?;
|
|
68
65
|
private readonly fetchImpl;
|
|
69
66
|
private shared?;
|
|
70
|
-
constructor(opts?:
|
|
67
|
+
constructor(opts?: ConnectOptions);
|
|
71
68
|
private headers;
|
|
72
|
-
/** @internal */
|
|
73
69
|
request<T>(method: string, path: string, body?: unknown, opts?: {
|
|
74
70
|
headers?: Record<string, string>;
|
|
75
71
|
signal?: AbortSignal;
|
|
@@ -81,9 +77,9 @@ export declare class A12sClient {
|
|
|
81
77
|
* Puts a Message in a Computer's inbox and returns at once. It is delivered at the Computer's next idle moment,
|
|
82
78
|
* batched with anything else pending. Works while the Computer is busy or asleep.
|
|
83
79
|
*/
|
|
84
|
-
send(computer: string, msg:
|
|
80
|
+
send(computer: string, msg: SendRequest | string): Promise<EnqueueResponse>;
|
|
85
81
|
/** Sends a Message, waits for the Turn that delivers it and resolves when that Turn ends. */
|
|
86
|
-
prompt(computer: string, body: string, opts?: Omit<
|
|
82
|
+
prompt(computer: string, body: string, opts?: Omit<SendRequest, "body"> & WaitOptions): Promise<Reply>;
|
|
87
83
|
/**
|
|
88
84
|
* @internal Waits for the Turn that delivers the Message and resolves when it ends. Delivery is read from the
|
|
89
85
|
* Message's own snapshot and the Turn is replayed from its start, so it works however late it is called.
|
|
@@ -91,7 +87,7 @@ export declare class A12sClient {
|
|
|
91
87
|
reply(computer: string, message: EnqueueResponse, opts?: WaitOptions): Promise<Reply>;
|
|
92
88
|
/**
|
|
93
89
|
* Live events of one Computer, several, or (no argument) every Computer in the Fleet, merged. Each event carries
|
|
94
|
-
* its `
|
|
90
|
+
* its `agentComputer`. Reconnects after a network drop without losing or repeating events. Call `await stream.ready()`
|
|
95
91
|
* before sending work you want to see from the start; `close()` (or `break`) ends it.
|
|
96
92
|
*/
|
|
97
93
|
events(computers?: string | string[], opts?: EventsOptions): EventStream;
|
|
@@ -118,10 +114,8 @@ export declare class A12sClient {
|
|
|
118
114
|
sleep(computer: string, opts?: {
|
|
119
115
|
hold?: boolean;
|
|
120
116
|
}): Promise<void>;
|
|
121
|
-
/** Starts a sleeping agent computer; its session resumes on the next Turn.
|
|
122
|
-
wake(computer: string
|
|
123
|
-
clearInbox?: boolean;
|
|
124
|
-
}): Promise<void>;
|
|
117
|
+
/** Starts a sleeping agent computer; its session resumes on the next Turn. */
|
|
118
|
+
wake(computer: string): Promise<void>;
|
|
125
119
|
/** Holds the inbox: Messages still queue, none is delivered until resume(). */
|
|
126
120
|
hold(computer: string, opts?: {
|
|
127
121
|
reason?: string;
|
package/dist/src/client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Runs in Node, Deno, Bun and browsers: no node: imports here (`npm run
|
|
1
|
+
// Runs in Node, Deno, Bun and browsers: no node: imports here (`npm run browser` bundles it for the browser).
|
|
2
2
|
import { readSSE } from "./sse.js";
|
|
3
3
|
/** A refused call: the HTTP status and the Controller's error, including its fix line. */
|
|
4
4
|
export class A12sError extends Error {
|
|
@@ -45,11 +45,8 @@ export class A12sStreamError extends Error {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
const enc = encodeURIComponent;
|
|
48
|
-
/**
|
|
49
|
-
|
|
50
|
-
* methods. Kept for one release.
|
|
51
|
-
*/
|
|
52
|
-
export class A12sClient {
|
|
48
|
+
/** The HTTP transport behind {@link Fleet} and its handles; the package doesn't export it. */
|
|
49
|
+
export class Client {
|
|
53
50
|
url;
|
|
54
51
|
token;
|
|
55
52
|
fetchImpl;
|
|
@@ -62,7 +59,6 @@ export class A12sClient {
|
|
|
62
59
|
headers(extra = {}) {
|
|
63
60
|
return this.token ? { authorization: `Bearer ${this.token}`, ...extra } : extra;
|
|
64
61
|
}
|
|
65
|
-
/** @internal */
|
|
66
62
|
async request(method, path, body, opts = {}) {
|
|
67
63
|
const res = await this.fetchImpl(this.url + path, {
|
|
68
64
|
method,
|
|
@@ -90,8 +86,7 @@ export class A12sClient {
|
|
|
90
86
|
* batched with anything else pending. Works while the Computer is busy or asleep.
|
|
91
87
|
*/
|
|
92
88
|
send(computer, msg) {
|
|
93
|
-
const m = typeof msg === "string" ? { body: msg } :
|
|
94
|
-
m.idempotencyKey ??= globalThis.crypto.randomUUID();
|
|
89
|
+
const m = { ...(typeof msg === "string" ? { body: msg } : msg), idempotencyKey: globalThis.crypto.randomUUID() };
|
|
95
90
|
return this.request("POST", `/v1/agent-computers/${enc(computer)}/inbox`, m);
|
|
96
91
|
}
|
|
97
92
|
/** Sends a Message, waits for the Turn that delivers it and resolves when that Turn ends. */
|
|
@@ -118,7 +113,7 @@ export class A12sClient {
|
|
|
118
113
|
}
|
|
119
114
|
/**
|
|
120
115
|
* Live events of one Computer, several, or (no argument) every Computer in the Fleet, merged. Each event carries
|
|
121
|
-
* its `
|
|
116
|
+
* its `agentComputer`. Reconnects after a network drop without losing or repeating events. Call `await stream.ready()`
|
|
122
117
|
* before sending work you want to see from the start; `close()` (or `break`) ends it.
|
|
123
118
|
*/
|
|
124
119
|
events(computers, opts = {}) {
|
|
@@ -186,12 +181,9 @@ export class A12sClient {
|
|
|
186
181
|
...(opts.hold ? { hold: true } : {}),
|
|
187
182
|
});
|
|
188
183
|
}
|
|
189
|
-
/** Starts a sleeping agent computer; its session resumes on the next Turn.
|
|
190
|
-
async wake(computer
|
|
191
|
-
await this.request("POST", `/v1/agent-computers/${enc(computer)}/power`, {
|
|
192
|
-
state: "awake",
|
|
193
|
-
...(opts.clearInbox ? { clearInbox: true, requestId: crypto.randomUUID() } : {}),
|
|
194
|
-
});
|
|
184
|
+
/** Starts a sleeping agent computer; its session resumes on the next Turn. */
|
|
185
|
+
async wake(computer) {
|
|
186
|
+
await this.request("POST", `/v1/agent-computers/${enc(computer)}/power`, { state: "awake" });
|
|
195
187
|
}
|
|
196
188
|
/** Holds the inbox: Messages still queue, none is delivered until resume(). */
|
|
197
189
|
hold(computer, opts = {}) {
|
|
@@ -307,7 +299,7 @@ export class A12sClient {
|
|
|
307
299
|
cursor = undefined; // the stream goes live; a reconnect starts live too
|
|
308
300
|
if (opts.onGap === "throw")
|
|
309
301
|
throw new A12sGapError(data);
|
|
310
|
-
const gap = { v: 1, computer, session: "", turn: "", seq: 0, ts: new Date().toISOString(), type: "gap", data };
|
|
302
|
+
const gap = { v: 1, agentComputer: computer, session: "", turn: "", seq: 0, ts: new Date().toISOString(), type: "gap", data };
|
|
311
303
|
yield gap;
|
|
312
304
|
continue;
|
|
313
305
|
}
|
|
@@ -478,7 +470,7 @@ class SharedEvents {
|
|
|
478
470
|
}
|
|
479
471
|
if (f.event === "gap") {
|
|
480
472
|
const data = cursor !== undefined ? { lastEventId: cursor } : {};
|
|
481
|
-
const gap = { v: 1,
|
|
473
|
+
const gap = { v: 1, session: "", turn: "", seq: 0, ts: new Date().toISOString(), type: "gap", data };
|
|
482
474
|
for (const s of this.subs) {
|
|
483
475
|
if (s.onGap === "throw")
|
|
484
476
|
s.fail(new A12sGapError(data));
|
|
@@ -510,7 +502,7 @@ class SharedEvents {
|
|
|
510
502
|
}
|
|
511
503
|
}
|
|
512
504
|
function agentComputerOf(ev) {
|
|
513
|
-
return ev.agentComputer
|
|
505
|
+
return ev.agentComputer ?? "";
|
|
514
506
|
}
|
|
515
507
|
function wanted(names, ev) {
|
|
516
508
|
if (!names)
|
|
@@ -721,7 +713,6 @@ class TurnBuilder {
|
|
|
721
713
|
this.open.delete(key);
|
|
722
714
|
return {
|
|
723
715
|
agentComputer: name,
|
|
724
|
-
computer: name,
|
|
725
716
|
id: ev.turn,
|
|
726
717
|
session: ev.session,
|
|
727
718
|
status: ev.data.status,
|
package/dist/src/fleet.d.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { AgentComputerData, AgentComputerSpec,
|
|
1
|
+
import { Client, type ConnectOptions, type EventsOptions, TurnStream, type EventStream, type Reply, type SharedEventsOptions, type WaitOptions } from "./client.js";
|
|
2
|
+
import type { AgentComputerData, AgentComputerSpec, ComputerStatus, CredentialInfo, EnqueueResponse, FleetSpec, InboxListOptions, InboxListResponse, MergePatch, Message, SendRequest, ServiceStatus, StatusResponse, Token, TokenAction, Turn } from "./types.js";
|
|
3
3
|
/** The Fleet as written, and its version for a conditional write. */
|
|
4
4
|
export interface FleetState {
|
|
5
5
|
version: number;
|
|
6
6
|
spec: FleetSpec;
|
|
7
|
-
/** What changed through the API since the last whole-Fleet write. */
|
|
8
|
-
drift: Change[];
|
|
9
7
|
}
|
|
10
8
|
export interface CreateOptions {
|
|
11
9
|
/** Overwrite an existing one instead of failing with A12sError code `exists`. */
|
|
@@ -23,19 +21,21 @@ export interface CreateOptions {
|
|
|
23
21
|
* ```
|
|
24
22
|
*/
|
|
25
23
|
export declare class Fleet {
|
|
26
|
-
/**
|
|
27
|
-
readonly client:
|
|
24
|
+
/** For API calls that have no method here: `request(method, path, body?, { headers, signal })`. */
|
|
25
|
+
readonly client: Pick<Client, "url" | "request">;
|
|
28
26
|
readonly agentComputers: AgentComputers;
|
|
29
27
|
readonly services: Services;
|
|
30
28
|
readonly tokens: Tokens;
|
|
31
29
|
readonly credentials: Credentials;
|
|
30
|
+
private readonly transport;
|
|
32
31
|
/** No discovery: `url` and `token` as given, by default the page's own origin. */
|
|
33
|
-
constructor(opts?:
|
|
32
|
+
constructor(opts?: ConnectOptions);
|
|
34
33
|
/**
|
|
35
34
|
* 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
|
|
35
|
+
* needed). In Node: a running Fleet found from the files `a12s up` writes. Pass `url` and `token` to reach anything
|
|
36
|
+
* else.
|
|
37
37
|
*/
|
|
38
|
-
static connect(opts?:
|
|
38
|
+
static connect(opts?: ConnectOptions): Promise<Fleet>;
|
|
39
39
|
get url(): string;
|
|
40
40
|
get(): Promise<FleetState>;
|
|
41
41
|
/**
|
|
@@ -57,7 +57,7 @@ export declare class Fleet {
|
|
|
57
57
|
}
|
|
58
58
|
export declare class AgentComputers {
|
|
59
59
|
private readonly client;
|
|
60
|
-
constructor(client:
|
|
60
|
+
constructor(client: Client);
|
|
61
61
|
/**
|
|
62
62
|
* Adds an agent computer to the Fleet and starts it. One that names a credential with no value yet resolves at once,
|
|
63
63
|
* waiting in Provisioning (`status.waiting`, and a console warning); it starts when the value is set. Fails with
|
|
@@ -76,7 +76,7 @@ export declare class AgentComputer {
|
|
|
76
76
|
/** The spec with the Fleet's defaults merged in. */
|
|
77
77
|
effective: AgentComputerSpec;
|
|
78
78
|
status: ComputerStatus;
|
|
79
|
-
constructor(client:
|
|
79
|
+
constructor(client: Client, data: AgentComputerData);
|
|
80
80
|
private set;
|
|
81
81
|
private get path();
|
|
82
82
|
reload(): Promise<this>;
|
|
@@ -88,7 +88,7 @@ export declare class AgentComputer {
|
|
|
88
88
|
* Puts a Message in the inbox; it is delivered at the next idle moment. Await it for the queued Message, or call
|
|
89
89
|
* `wait()` on it (or on the awaited Message, at any time later) for the Turn that delivers it.
|
|
90
90
|
*/
|
|
91
|
-
send(text: string, opts?: Omit<
|
|
91
|
+
send(text: string, opts?: Omit<SendRequest, "body">): Sending;
|
|
92
92
|
/** Its events, live, from the Fleet's shared connection; `turn` replays one Turn from its start instead. */
|
|
93
93
|
events(opts?: EventsOptions): EventStream;
|
|
94
94
|
/** Its last `limit` finished Turns, newest first. */
|
|
@@ -104,10 +104,8 @@ export declare class AgentComputer {
|
|
|
104
104
|
sleep(opts?: {
|
|
105
105
|
hold?: boolean;
|
|
106
106
|
}): Promise<void>;
|
|
107
|
-
/** Wakes it;
|
|
108
|
-
wake(
|
|
109
|
-
clearInbox?: boolean;
|
|
110
|
-
}): Promise<void>;
|
|
107
|
+
/** Wakes it; its session resumes on the next Turn. */
|
|
108
|
+
wake(): Promise<void>;
|
|
111
109
|
/** Holds its inbox: Messages still queue, none is delivered until resume(). */
|
|
112
110
|
hold(opts?: {
|
|
113
111
|
reason?: string;
|
|
@@ -142,7 +140,7 @@ export declare class Sending implements Promise<SentMessage> {
|
|
|
142
140
|
}
|
|
143
141
|
export declare class Services {
|
|
144
142
|
private readonly client;
|
|
145
|
-
constructor(client:
|
|
143
|
+
constructor(client: Client);
|
|
146
144
|
/** Adds a Service to the Fleet. Fails with code `exists` if the name is taken. */
|
|
147
145
|
create(name: string, spec?: Record<string, unknown> & CreateOptions): Promise<Service>;
|
|
148
146
|
/** Throws {@link NotFound} if there is none. */
|
|
@@ -154,7 +152,7 @@ export declare class Service {
|
|
|
154
152
|
private readonly client;
|
|
155
153
|
readonly name: string;
|
|
156
154
|
status: ServiceStatus;
|
|
157
|
-
constructor(client:
|
|
155
|
+
constructor(client: Client, status: ServiceStatus);
|
|
158
156
|
/** As written in the Fleet. */
|
|
159
157
|
get spec(): Record<string, unknown>;
|
|
160
158
|
private get path();
|
|
@@ -169,10 +167,11 @@ export declare class Service {
|
|
|
169
167
|
}
|
|
170
168
|
export declare class Tokens {
|
|
171
169
|
private readonly client;
|
|
172
|
-
constructor(client:
|
|
170
|
+
constructor(client: Client);
|
|
173
171
|
/**
|
|
174
172
|
* A token for another program; owner only. The secret is in the result once. With `prefix` it may do everything
|
|
175
|
-
* the owner can for names that start with it
|
|
173
|
+
* the owner can for names that start with it except set `security.seccomp`, and nothing outside; otherwise
|
|
174
|
+
* `actions` on `agentComputers`.
|
|
176
175
|
*/
|
|
177
176
|
create(name: string, opts: {
|
|
178
177
|
prefix: string;
|
|
@@ -186,7 +185,7 @@ export declare class Tokens {
|
|
|
186
185
|
/** Credentials by name: set once, then name them in a spec's `credentials`. Values are never read back. */
|
|
187
186
|
export declare class Credentials {
|
|
188
187
|
private readonly client;
|
|
189
|
-
constructor(client:
|
|
188
|
+
constructor(client: Client);
|
|
190
189
|
/** Stores the value on the Controller; agent computers that use it get the new value at once. */
|
|
191
190
|
set(name: string, value: string): Promise<CredentialInfo>;
|
|
192
191
|
list(): Promise<CredentialInfo[]>;
|
package/dist/src/fleet.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// Runs in Node, Deno, Bun and browsers: no node: imports here (`npm run
|
|
2
|
-
import {
|
|
1
|
+
// Runs in Node, Deno, Bun and browsers: no node: imports here (`npm run browser` bundles it for the browser).
|
|
2
|
+
import { A12sError, Client, TurnStream, } from "./client.js";
|
|
3
3
|
const enc = encodeURIComponent;
|
|
4
4
|
const maxReplaceTries = 5;
|
|
5
5
|
/**
|
|
@@ -14,23 +14,25 @@ const maxReplaceTries = 5;
|
|
|
14
14
|
* ```
|
|
15
15
|
*/
|
|
16
16
|
export class Fleet {
|
|
17
|
-
/**
|
|
17
|
+
/** For API calls that have no method here: `request(method, path, body?, { headers, signal })`. */
|
|
18
18
|
client;
|
|
19
19
|
agentComputers;
|
|
20
20
|
services;
|
|
21
21
|
tokens;
|
|
22
22
|
credentials;
|
|
23
|
+
transport;
|
|
23
24
|
/** No discovery: `url` and `token` as given, by default the page's own origin. */
|
|
24
25
|
constructor(opts = {}) {
|
|
25
|
-
this.client = new
|
|
26
|
-
this.agentComputers = new AgentComputers(this.
|
|
27
|
-
this.services = new Services(this.
|
|
28
|
-
this.tokens = new Tokens(this.
|
|
29
|
-
this.credentials = new Credentials(this.
|
|
26
|
+
this.client = this.transport = new Client(opts);
|
|
27
|
+
this.agentComputers = new AgentComputers(this.transport);
|
|
28
|
+
this.services = new Services(this.transport);
|
|
29
|
+
this.tokens = new Tokens(this.transport);
|
|
30
|
+
this.credentials = new Credentials(this.transport);
|
|
30
31
|
}
|
|
31
32
|
/**
|
|
32
33
|
* In a browser: the Fleet behind the page's own origin, which is `a12s gateway` serving the page (no token
|
|
33
|
-
* needed). In Node: found
|
|
34
|
+
* needed). In Node: a running Fleet found from the files `a12s up` writes. Pass `url` and `token` to reach anything
|
|
35
|
+
* else.
|
|
34
36
|
*/
|
|
35
37
|
static async connect(opts = {}) {
|
|
36
38
|
return new Fleet(opts);
|
|
@@ -40,7 +42,7 @@ export class Fleet {
|
|
|
40
42
|
}
|
|
41
43
|
async get() {
|
|
42
44
|
const r = await this.client.request("GET", "/v1/fleet");
|
|
43
|
-
return { version: r.version, spec: r.fleet ?? emptySpec()
|
|
45
|
+
return { version: r.version, spec: r.fleet ?? emptySpec() };
|
|
44
46
|
}
|
|
45
47
|
/**
|
|
46
48
|
* Reads the Fleet, lets `fn` change it (in place, or by returning a new spec) and writes it back only if nobody
|
|
@@ -72,16 +74,16 @@ export class Fleet {
|
|
|
72
74
|
*/
|
|
73
75
|
events(agentComputers, opts = {}) {
|
|
74
76
|
if (opts.turn !== undefined || opts.after !== undefined)
|
|
75
|
-
return this.
|
|
76
|
-
return this.
|
|
77
|
+
return this.transport.events(agentComputers, opts);
|
|
78
|
+
return this.transport.sharedEvents(namesOf(agentComputers), opts);
|
|
77
79
|
}
|
|
78
80
|
/** Finished Turns of the named agent computers, or all of them, as they end. */
|
|
79
81
|
turns(agentComputers, opts = {}) {
|
|
80
|
-
return new TurnStream(this.
|
|
82
|
+
return new TurnStream(this.transport.sharedEvents(namesOf(agentComputers), opts));
|
|
81
83
|
}
|
|
82
84
|
/** Every agent computer and Service: phase, session, active Turn, inbox, power. */
|
|
83
85
|
status() {
|
|
84
|
-
return this.
|
|
86
|
+
return this.transport.status();
|
|
85
87
|
}
|
|
86
88
|
}
|
|
87
89
|
function namesOf(names) {
|
|
@@ -189,9 +191,9 @@ export class AgentComputer {
|
|
|
189
191
|
sleep(opts = {}) {
|
|
190
192
|
return this.client.sleep(this.name, opts);
|
|
191
193
|
}
|
|
192
|
-
/** Wakes it;
|
|
193
|
-
wake(
|
|
194
|
-
return this.client.wake(this.name
|
|
194
|
+
/** Wakes it; its session resumes on the next Turn. */
|
|
195
|
+
wake() {
|
|
196
|
+
return this.client.wake(this.name);
|
|
195
197
|
}
|
|
196
198
|
/** Holds its inbox: Messages still queue, none is delivered until resume(). */
|
|
197
199
|
hold(opts = {}) {
|
|
@@ -311,7 +313,8 @@ export class Tokens {
|
|
|
311
313
|
}
|
|
312
314
|
/**
|
|
313
315
|
* A token for another program; owner only. The secret is in the result once. With `prefix` it may do everything
|
|
314
|
-
* the owner can for names that start with it
|
|
316
|
+
* the owner can for names that start with it except set `security.seccomp`, and nothing outside; otherwise
|
|
317
|
+
* `actions` on `agentComputers`.
|
|
315
318
|
*/
|
|
316
319
|
create(name, opts) {
|
|
317
320
|
if ("prefix" in opts) {
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
export * from "./client.js";
|
|
1
|
+
export { A12sError, A12sGapError, A12sStreamError, EventStream, NotFound, TurnStream, type ConnectOptions, type EventsOptions, type Reply, type SharedEventsOptions, type WaitOptions, } from "./client.js";
|
|
3
2
|
export * from "./fleet.js";
|
|
4
3
|
export * from "./types.js";
|
|
5
|
-
export type ConnectOptions = A12sClientOptions;
|
|
6
|
-
/**
|
|
7
|
-
* @deprecated Use `Fleet.connect()`. Kept for one release.
|
|
8
|
-
*
|
|
9
|
-
* In a browser: a client for the page's own origin, which is `a12s gateway` serving the page (no token needed).
|
|
10
|
-
* Pass `url` and `token` to reach anything else.
|
|
11
|
-
*/
|
|
12
|
-
export declare function connect(opts?: ConnectOptions): Promise<A12sClient>;
|
package/dist/src/index.js
CHANGED
|
@@ -1,15 +1,5 @@
|
|
|
1
1
|
// The default entry (browsers, Deno, workers): no node: imports. Node resolves "@coltonkirsten/a12s" to ./node.ts instead, through
|
|
2
2
|
// the "node" export condition, so `import { Fleet } from "@coltonkirsten/a12s"` works everywhere.
|
|
3
|
-
|
|
4
|
-
export * from "./client.js";
|
|
3
|
+
export { A12sError, A12sGapError, A12sStreamError, EventStream, NotFound, TurnStream, } from "./client.js";
|
|
5
4
|
export * from "./fleet.js";
|
|
6
5
|
export * from "./types.js";
|
|
7
|
-
/**
|
|
8
|
-
* @deprecated Use `Fleet.connect()`. Kept for one release.
|
|
9
|
-
*
|
|
10
|
-
* In a browser: a client for the page's own origin, which is `a12s gateway` serving the page (no token needed).
|
|
11
|
-
* Pass `url` and `token` to reach anything else.
|
|
12
|
-
*/
|
|
13
|
-
export async function connect(opts = {}) {
|
|
14
|
-
return new A12sClient(opts);
|
|
15
|
-
}
|
package/dist/src/node.d.ts
CHANGED
|
@@ -1,31 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ConnectOptions as PageConnectOptions } from "./client.js";
|
|
2
2
|
import { Fleet as PageFleet } from "./fleet.js";
|
|
3
|
-
export * from "./
|
|
4
|
-
export * from "./fleet.js";
|
|
5
|
-
export * from "./types.js";
|
|
3
|
+
export * from "./index.js";
|
|
6
4
|
export declare class Fleet extends PageFleet {
|
|
7
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* A running Fleet, as its owner. It uses the first of:
|
|
7
|
+
* 1. `url` (and `token`), or `$A12S_URL` (and `$A12S_TOKEN`);
|
|
8
|
+
* 2. the Fleet named by `fleet`;
|
|
9
|
+
* 3. the Fleet file in `$A12S_FLEET`, else the nearest `fleet.yaml` in the current directory or a parent;
|
|
10
|
+
* 4. the only Fleet with a running Controller on this machine.
|
|
11
|
+
* For 2–4 it reads `~/.a12s/<fleet>/controller.json`, which `a12s up` writes: its URL always, and its owner token
|
|
12
|
+
* unless `token` is given (a prefix or narrow token on this machine).
|
|
13
|
+
*/
|
|
8
14
|
static connect(opts?: ConnectOptions): Promise<Fleet>;
|
|
9
15
|
}
|
|
10
|
-
export interface ConnectOptions extends
|
|
11
|
-
/** The Fleet's name (`metadata.name`). Default: found as described on {@link connect}. */
|
|
16
|
+
export interface ConnectOptions extends PageConnectOptions {
|
|
17
|
+
/** The Fleet's name (`metadata.name`). Default: found as described on {@link Fleet.connect}. */
|
|
12
18
|
fleet?: string;
|
|
13
19
|
/** Where `.a12s/` lives. Default: the home directory. */
|
|
14
20
|
home?: string;
|
|
15
21
|
/** Where to start looking for fleet.yaml. Default: the current directory. */
|
|
16
22
|
cwd?: string;
|
|
17
23
|
}
|
|
18
|
-
/**
|
|
19
|
-
* @deprecated Use `Fleet.connect()`, which finds the Fleet the same way. Kept for one release.
|
|
20
|
-
*
|
|
21
|
-
* A client for a running Fleet, as its owner. It uses the first of:
|
|
22
|
-
* 1. `url` (and `token`), or `$A12S_URL` (and `$A12S_TOKEN`);
|
|
23
|
-
* 2. the Fleet named by `fleet`;
|
|
24
|
-
* 3. the Fleet file in `$A12S_FLEET`, else the nearest `fleet.yaml` in the current directory or a parent;
|
|
25
|
-
* 4. the only Fleet with a running Controller on this machine.
|
|
26
|
-
* For 2–4 it reads `~/.a12s/<fleet>/controller.json`, which `a12s up` writes: its URL always, and its owner token
|
|
27
|
-
* unless `token` is given (a prefix or narrow token on this machine).
|
|
28
|
-
*/
|
|
29
|
-
export declare function connect(opts?: ConnectOptions): Promise<A12sClient>;
|
|
30
24
|
/** metadata.name from a Fleet file, in either `metadata: { name: x }` or block form. */
|
|
31
25
|
export declare function fleetName(yaml: string): string | undefined;
|
package/dist/src/node.js
CHANGED
|
@@ -1,32 +1,23 @@
|
|
|
1
|
-
// The Node entry ("node" export condition): connect() finds a running Fleet from the files `a12s up` writes.
|
|
1
|
+
// The Node entry ("node" export condition): Fleet.connect() finds a running Fleet from the files `a12s up` writes.
|
|
2
2
|
import { readdir, readFile } from "node:fs/promises";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { dirname, join, resolve } from "node:path";
|
|
5
|
-
import { A12sClient } from "./client.js";
|
|
6
5
|
import { Fleet as PageFleet } from "./fleet.js";
|
|
7
|
-
export * from "./
|
|
8
|
-
export * from "./fleet.js";
|
|
9
|
-
export * from "./types.js";
|
|
6
|
+
export * from "./index.js";
|
|
10
7
|
export class Fleet extends PageFleet {
|
|
11
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* A running Fleet, as its owner. It uses the first of:
|
|
10
|
+
* 1. `url` (and `token`), or `$A12S_URL` (and `$A12S_TOKEN`);
|
|
11
|
+
* 2. the Fleet named by `fleet`;
|
|
12
|
+
* 3. the Fleet file in `$A12S_FLEET`, else the nearest `fleet.yaml` in the current directory or a parent;
|
|
13
|
+
* 4. the only Fleet with a running Controller on this machine.
|
|
14
|
+
* For 2–4 it reads `~/.a12s/<fleet>/controller.json`, which `a12s up` writes: its URL always, and its owner token
|
|
15
|
+
* unless `token` is given (a prefix or narrow token on this machine).
|
|
16
|
+
*/
|
|
12
17
|
static async connect(opts = {}) {
|
|
13
18
|
return new Fleet(await discover(opts));
|
|
14
19
|
}
|
|
15
20
|
}
|
|
16
|
-
/**
|
|
17
|
-
* @deprecated Use `Fleet.connect()`, which finds the Fleet the same way. Kept for one release.
|
|
18
|
-
*
|
|
19
|
-
* A client for a running Fleet, as its owner. It uses the first of:
|
|
20
|
-
* 1. `url` (and `token`), or `$A12S_URL` (and `$A12S_TOKEN`);
|
|
21
|
-
* 2. the Fleet named by `fleet`;
|
|
22
|
-
* 3. the Fleet file in `$A12S_FLEET`, else the nearest `fleet.yaml` in the current directory or a parent;
|
|
23
|
-
* 4. the only Fleet with a running Controller on this machine.
|
|
24
|
-
* For 2–4 it reads `~/.a12s/<fleet>/controller.json`, which `a12s up` writes: its URL always, and its owner token
|
|
25
|
-
* unless `token` is given (a prefix or narrow token on this machine).
|
|
26
|
-
*/
|
|
27
|
-
export async function connect(opts = {}) {
|
|
28
|
-
return new A12sClient(await discover(opts));
|
|
29
|
-
}
|
|
30
21
|
async function discover(opts) {
|
|
31
22
|
const url = opts.url ?? process.env.A12S_URL;
|
|
32
23
|
if (url)
|
|
@@ -93,6 +84,6 @@ async function onlyRunningFleet(home) {
|
|
|
93
84
|
if (running.length === 1)
|
|
94
85
|
return running[0];
|
|
95
86
|
throw new Error(running.length === 0
|
|
96
|
-
? "no running Fleet found: run a12s up in your Fleet's directory, or pass connect({ url, token })"
|
|
97
|
-
: `several Fleets are running (${running.join(", ")}): pass connect({ fleet: "<name>" }) or run from the Fleet's directory`);
|
|
87
|
+
? "no running Fleet found: run a12s up in your Fleet's directory, or pass Fleet.connect({ url, token })"
|
|
88
|
+
: `several Fleets are running (${running.join(", ")}): pass Fleet.connect({ fleet: "<name>" }) or run from the Fleet's directory`);
|
|
98
89
|
}
|
package/dist/src/types.d.ts
CHANGED
|
@@ -28,18 +28,8 @@ export interface AgentComputerSpec {
|
|
|
28
28
|
cpu?: string | number;
|
|
29
29
|
memory?: string | number;
|
|
30
30
|
};
|
|
31
|
-
|
|
32
|
-
size?: string | number;
|
|
33
|
-
preset?: string;
|
|
34
|
-
};
|
|
35
|
-
autonomy?: "full" | "restricted";
|
|
36
|
-
/** Credential names; their values come from `a12s up` or the credentials API. */
|
|
31
|
+
/** Credential names, added to the defaults' list; their values come from `a12s creds set` or the credentials API. */
|
|
37
32
|
credentials?: string[];
|
|
38
|
-
drives?: Array<{
|
|
39
|
-
name: string;
|
|
40
|
-
at: string;
|
|
41
|
-
readOnly?: boolean;
|
|
42
|
-
}>;
|
|
43
33
|
egress?: {
|
|
44
34
|
allow?: string[];
|
|
45
35
|
};
|
|
@@ -50,7 +40,6 @@ export interface AgentComputerSpec {
|
|
|
50
40
|
inbox?: {
|
|
51
41
|
maxMessages?: number;
|
|
52
42
|
maxBytes?: string;
|
|
53
|
-
intro?: string;
|
|
54
43
|
};
|
|
55
44
|
power?: {
|
|
56
45
|
sleepAfterIdle?: string;
|
|
@@ -78,15 +67,7 @@ export interface FleetSpec {
|
|
|
78
67
|
metadata: {
|
|
79
68
|
name: string;
|
|
80
69
|
};
|
|
81
|
-
egress?: {
|
|
82
|
-
enforcement?: string;
|
|
83
|
-
allowPrivate?: string[];
|
|
84
|
-
};
|
|
85
70
|
defaults?: AgentComputerSpec;
|
|
86
|
-
drives?: Record<string, {
|
|
87
|
-
size?: string | number;
|
|
88
|
-
access: string;
|
|
89
|
-
}>;
|
|
90
71
|
agent_computers: Record<string, AgentComputerSpec>;
|
|
91
72
|
services?: Record<string, Record<string, unknown>>;
|
|
92
73
|
}
|
|
@@ -110,8 +91,6 @@ export interface FieldDiff {
|
|
|
110
91
|
export interface FleetResponse {
|
|
111
92
|
version: number;
|
|
112
93
|
fleet: FleetSpec | null;
|
|
113
|
-
/** What changed through the API since the last whole-Fleet write: `a12s up` from the file undoes it. */
|
|
114
|
-
drift: Change[];
|
|
115
94
|
}
|
|
116
95
|
export interface AgentComputerData {
|
|
117
96
|
name: string;
|
|
@@ -124,22 +103,10 @@ export interface AgentComputerData {
|
|
|
124
103
|
export interface AgentComputersResponse {
|
|
125
104
|
agentComputers: AgentComputerData[];
|
|
126
105
|
}
|
|
127
|
-
export interface Lock {
|
|
128
|
-
a12s?: string;
|
|
129
|
-
images: Record<string, string>;
|
|
130
|
-
bundles: Record<string, string>;
|
|
131
|
-
presets: Record<string, string>;
|
|
132
|
-
services?: Record<string, string>;
|
|
133
|
-
/** Each security.seccomp profile's digest, by its path in the Fleet file. */
|
|
134
|
-
seccomp?: Record<string, string>;
|
|
135
|
-
}
|
|
136
106
|
export interface PutFleetRequest {
|
|
137
107
|
fleet: FleetSpec;
|
|
138
|
-
|
|
139
|
-
/** Credential values by name, base64-encoded (Go []byte). Kept in the Controller's memory only. */
|
|
108
|
+
/** Credential values by name, base64-encoded (Go []byte). */
|
|
140
109
|
credentials?: Record<string, string>;
|
|
141
|
-
asleep?: boolean;
|
|
142
|
-
refresh?: string[];
|
|
143
110
|
}
|
|
144
111
|
export interface ServiceChanges {
|
|
145
112
|
created: string[] | null;
|
|
@@ -155,7 +122,6 @@ export interface PutFleetResponse {
|
|
|
155
122
|
updated: string[] | null;
|
|
156
123
|
staged: string[] | null;
|
|
157
124
|
removed: string[] | null;
|
|
158
|
-
lock: Lock | null;
|
|
159
125
|
errors?: Record<string, string>;
|
|
160
126
|
warnings?: string[];
|
|
161
127
|
services: ServiceChanges;
|
|
@@ -218,28 +184,21 @@ export interface ComputerStatus {
|
|
|
218
184
|
image: string;
|
|
219
185
|
/** The Fleet's security.seccomp path, when the Computer runs with a custom seccomp profile. */
|
|
220
186
|
seccomp?: string;
|
|
221
|
-
autonomy: string;
|
|
222
187
|
generation: number;
|
|
223
188
|
stagedGeneration?: number;
|
|
224
189
|
credentialGeneration?: number;
|
|
225
|
-
/** A quantity such as "10Gi". */
|
|
226
|
-
homeSize?: string;
|
|
227
|
-
drives?: string[];
|
|
228
190
|
egressMode?: string;
|
|
229
191
|
warnings?: string[];
|
|
230
192
|
inbox?: InboxSummary;
|
|
231
|
-
/** Set only on a wake --clear-inbox answer: how many Messages were discarded. */
|
|
232
|
-
inboxCleared?: number;
|
|
233
193
|
power?: PowerStatus;
|
|
234
194
|
}
|
|
235
195
|
export interface DriveRow {
|
|
236
196
|
name: string;
|
|
237
|
-
kind: "home" | "
|
|
197
|
+
kind: "home" | "state";
|
|
238
198
|
computer?: string;
|
|
239
199
|
service?: string;
|
|
240
200
|
/** A quantity such as "10Gi". */
|
|
241
201
|
size?: string;
|
|
242
|
-
access?: string;
|
|
243
202
|
attachedTo?: string[];
|
|
244
203
|
orphaned?: boolean;
|
|
245
204
|
}
|
|
@@ -257,7 +216,6 @@ export interface ServiceStatus {
|
|
|
257
216
|
send?: string[];
|
|
258
217
|
uses?: string[];
|
|
259
218
|
usedBy?: string[];
|
|
260
|
-
publish?: string[];
|
|
261
219
|
ports?: string[];
|
|
262
220
|
stateDrive?: string;
|
|
263
221
|
egressMode?: string;
|
|
@@ -267,12 +225,8 @@ export interface ServiceStatus {
|
|
|
267
225
|
}
|
|
268
226
|
export interface StatusResponse {
|
|
269
227
|
fleet: string;
|
|
270
|
-
egressEnforcement: string;
|
|
271
228
|
agentComputers: ComputerStatus[];
|
|
272
|
-
/** @deprecated `agentComputers` under its old name. */
|
|
273
|
-
computers: ComputerStatus[];
|
|
274
229
|
orphanedDrives?: DriveRow[];
|
|
275
|
-
credentialsLoaded: boolean;
|
|
276
230
|
warnings?: string[];
|
|
277
231
|
orphanedInboxes?: InboxSummary[];
|
|
278
232
|
services?: ServiceStatus[];
|
|
@@ -284,12 +238,14 @@ export interface EnqueueRequest {
|
|
|
284
238
|
sender?: string;
|
|
285
239
|
metadata?: Record<string, string>;
|
|
286
240
|
fresh?: boolean;
|
|
287
|
-
/**
|
|
241
|
+
/** Set by the client on every send: a request repeated with the same key returns the original Message. */
|
|
288
242
|
idempotencyKey?: string;
|
|
289
243
|
/** Seconds; 0 means now or never. */
|
|
290
244
|
expires?: number;
|
|
291
245
|
replaceKey?: string;
|
|
292
246
|
}
|
|
247
|
+
/** What send() takes: the client sets the idempotencyKey itself. */
|
|
248
|
+
export type SendRequest = Omit<EnqueueRequest, "idempotencyKey">;
|
|
293
249
|
export interface EnqueueResponse {
|
|
294
250
|
id: string;
|
|
295
251
|
seq: number;
|
|
@@ -336,10 +292,8 @@ export interface InboxListOptions {
|
|
|
336
292
|
/** The fields every event has. `seq` is the agent computer's journal position (0 for the Controller's own events). */
|
|
337
293
|
export interface EventEnvelope {
|
|
338
294
|
v: number;
|
|
339
|
-
/** The agent computer it is about; absent on `fleet.changed` and
|
|
295
|
+
/** The agent computer it is about; absent on `fleet.changed` and `service.phase`. */
|
|
340
296
|
agentComputer?: string;
|
|
341
|
-
/** `agentComputer` under its old name, for one release. */
|
|
342
|
-
computer: string;
|
|
343
297
|
session: string;
|
|
344
298
|
/** The Turn it belongs to; "" for events outside a Turn. */
|
|
345
299
|
turn: string;
|
|
@@ -515,8 +469,6 @@ export interface ToolCall {
|
|
|
515
469
|
/** A finished Turn: what `turns()` yields and `wait()` returns. */
|
|
516
470
|
export interface Turn {
|
|
517
471
|
agentComputer: string;
|
|
518
|
-
/** `agentComputer` under its old name, for one release. */
|
|
519
|
-
computer: string;
|
|
520
472
|
/** The Turn id. */
|
|
521
473
|
id: string;
|
|
522
474
|
session: string;
|
|
@@ -553,7 +505,7 @@ export interface TokenRequest {
|
|
|
553
505
|
name: string;
|
|
554
506
|
actions?: TokenAction[];
|
|
555
507
|
computers?: string[];
|
|
556
|
-
/** Every power over agent computers, Services and credentials whose names start with it; none outside. */
|
|
508
|
+
/** Every power over agent computers, Services and credentials whose names start with it but seccomp; none outside. */
|
|
557
509
|
prefix?: string;
|
|
558
510
|
}
|
|
559
511
|
/** A credential's name, whether it has a value, and who uses it. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coltonkirsten/a12s",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "TypeScript client for a12s: send work to agent Computers, stream their events and Turns, in Node or the browser",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
"provenance": true
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
|
-
"build": "rm -rf dist && tsc -p tsconfig.json && npm run
|
|
38
|
+
"build": "rm -rf dist && tsc -p tsconfig.json && npm run browser",
|
|
39
39
|
"lint": "tsc -p tsconfig.json --noEmit",
|
|
40
40
|
"test": "npm run build && node --test 'dist/test/*.test.js'",
|
|
41
|
-
"
|
|
41
|
+
"browser": "esbuild src/index.ts --bundle --platform=browser --format=esm --log-level=warning --outfile=dist/browser.js"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/node": "^24.19.1",
|