@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.
@@ -1,5 +1,5 @@
1
- import type { A12sEvent, ApiErrorBody, ComputerStatus, EnqueueRequest, EnqueueResponse, GapData, InboxListOptions, InboxListResponse, Message, PutFleetRequest, PutFleetResponse, ServiceStatus, StatusResponse, Token, TokenRequest, Turn } from "./types.js";
2
- export interface A12sClientOptions {
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
- * @deprecated Use {@link Fleet}: `fleet.agentComputers.get(name)` returns an {@link AgentComputer} with these
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?: A12sClientOptions);
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: EnqueueRequest | string): Promise<EnqueueResponse>;
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<EnqueueRequest, "body"> & WaitOptions): Promise<Reply>;
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 `computer`. Reconnects after a network drop without losing or repeating events. Call `await stream.ready()`
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. `clearInbox` discards pending Messages. */
122
- wake(computer: string, opts?: {
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;
@@ -1,4 +1,4 @@
1
- // Runs in Node, Deno, Bun and browsers: no node: imports here (`npm run dashboard` bundles it for the browser).
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
- * @deprecated Use {@link Fleet}: `fleet.agentComputers.get(name)` returns an {@link AgentComputer} with these
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 } : { ...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 `computer`. Reconnects after a network drop without losing or repeating events. Call `await stream.ready()`
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. `clearInbox` discards pending Messages. */
190
- async wake(computer, opts = {}) {
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, computer: "", session: "", turn: "", seq: 0, ts: new Date().toISOString(), type: "gap", data };
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 || ev.computer;
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,
@@ -1,11 +1,9 @@
1
- import { A12sClient, type A12sClientOptions, type EventsOptions, TurnStream, type EventStream, type Reply, type SharedEventsOptions, type WaitOptions } 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";
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
- /** The lower-level client the handles use, for API calls that have no method here. */
27
- readonly client: A12sClient;
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?: A12sClientOptions);
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 like {@link connect} finds it. Pass `url` and `token` to reach anything else.
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?: A12sClientOptions): Promise<Fleet>;
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: A12sClient);
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: A12sClient, data: AgentComputerData);
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<EnqueueRequest, "body">): Sending;
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; `clearInbox` discards the pending Messages first. */
108
- wake(opts?: {
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: A12sClient);
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: A12sClient, status: ServiceStatus);
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: A12sClient);
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, and nothing outside; otherwise `actions` on `agentComputers`.
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: A12sClient);
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 dashboard` bundles it for the browser).
2
- import { A12sClient, A12sError, TurnStream, } from "./client.js";
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
- /** The lower-level client the handles use, for API calls that have no method here. */
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 A12sClient(opts);
26
- this.agentComputers = new AgentComputers(this.client);
27
- this.services = new Services(this.client);
28
- this.tokens = new Tokens(this.client);
29
- this.credentials = new Credentials(this.client);
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 like {@link connect} finds it. Pass `url` and `token` to reach anything else.
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(), drift: r.drift ?? [] };
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.client.events(agentComputers, opts);
76
- return this.client.sharedEvents(namesOf(agentComputers), opts);
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.client.sharedEvents(namesOf(agentComputers), opts));
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.client.status();
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; `clearInbox` discards the pending Messages first. */
193
- wake(opts = {}) {
194
- return this.client.wake(this.name, opts);
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, and nothing outside; otherwise `actions` on `agentComputers`.
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) {
@@ -1,12 +1,3 @@
1
- import { A12sClient, type A12sClientOptions } from "./client.js";
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
- import { A12sClient } from "./client.js";
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
- }
@@ -1,31 +1,25 @@
1
- import { A12sClient, type A12sClientOptions } from "./client.js";
1
+ import type { ConnectOptions as PageConnectOptions } from "./client.js";
2
2
  import { Fleet as PageFleet } from "./fleet.js";
3
- export * from "./client.js";
4
- export * from "./fleet.js";
5
- export * from "./types.js";
3
+ export * from "./index.js";
6
4
  export declare class Fleet extends PageFleet {
7
- /** A running Fleet, as its owner, found like {@link connect} finds it. */
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 A12sClientOptions {
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 "./client.js";
8
- export * from "./fleet.js";
9
- export * from "./types.js";
6
+ export * from "./index.js";
10
7
  export class Fleet extends PageFleet {
11
- /** A running Fleet, as its owner, found like {@link connect} finds it. */
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
  }
@@ -28,18 +28,8 @@ export interface AgentComputerSpec {
28
28
  cpu?: string | number;
29
29
  memory?: string | number;
30
30
  };
31
- home?: {
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
- lock?: Lock;
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" | "work" | "state";
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
- /** A retry with the same key returns the original Message. The client sends a random one if unset. */
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 in journals older than the field. */
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.5.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 dashboard",
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
- "dashboard": "esbuild ../../internal/gateway/dashboard/main.js --bundle --platform=browser --format=esm --alias:@coltonkirsten/a12s=./src/index.ts --log-level=warning --outfile=dist/dashboard.js"
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",