@coltonkirsten/a12s 0.7.0 → 0.8.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.
@@ -105,7 +105,10 @@ export declare class Client {
105
105
  message(computer: string, id: string): Promise<Message>;
106
106
  /** Withdraws a pending Message; a 409 A12sError names its state if it is too late. */
107
107
  withdraw(computer: string, id: string): Promise<Message>;
108
- /** Interrupts a Turn (default: the active one). The Turn ends `interrupted`; nothing is replayed. */
108
+ /**
109
+ * Interrupts a Turn (default: whatever runs) and ends the session's background work. The Turn ends `interrupted`;
110
+ * nothing is replayed.
111
+ */
109
112
  stop(computer: string, turn?: string): Promise<void>;
110
113
  /**
111
114
  * Stops the agent computer's processes and keeps its disks, session and inbox. A Message from a sender its power
@@ -165,11 +165,15 @@ export class Client {
165
165
  withdraw(computer, id) {
166
166
  return this.request("DELETE", `/v1/agent-computers/${enc(computer)}/inbox/${enc(id)}`);
167
167
  }
168
- /** Interrupts a Turn (default: the active one). The Turn ends `interrupted`; nothing is replayed. */
168
+ /**
169
+ * Interrupts a Turn (default: whatever runs) and ends the session's background work. The Turn ends `interrupted`;
170
+ * nothing is replayed.
171
+ */
169
172
  async stop(computer, turn) {
170
- const id = turn ?? (await this.computer(computer)).activeTurn;
171
- if (id)
172
- await this.request("POST", `/v1/agent-computers/${enc(computer)}/turns/${enc(id)}/stop`, {});
173
+ if (turn)
174
+ await this.request("POST", `/v1/agent-computers/${enc(computer)}/turns/${enc(turn)}/stop`, {});
175
+ else
176
+ await this.request("POST", `/v1/agent-computers/${enc(computer)}/stop`, {});
173
177
  }
174
178
  /**
175
179
  * Stops the agent computer's processes and keeps its disks, session and inbox. A Message from a sender its power
@@ -692,6 +696,7 @@ class TurnBuilder {
692
696
  case "turn.started":
693
697
  t.messages = ev.data.inbox?.messages ?? [];
694
698
  t.startedAt = ev.ts;
699
+ t.reason = ev.data.reason;
695
700
  return undefined;
696
701
  case "tool.started":
697
702
  t.afterTool = true;
@@ -716,6 +721,7 @@ class TurnBuilder {
716
721
  id: ev.turn,
717
722
  session: ev.session,
718
723
  status: ev.data.status,
724
+ ...(t.reason ? { reason: t.reason } : {}),
719
725
  text: t.text,
720
726
  ...(ev.data.error ? { error: ev.data.error } : {}),
721
727
  messages: t.messages,
@@ -112,7 +112,7 @@ export declare class AgentComputer {
112
112
  }): Promise<InboxListResponse>;
113
113
  /** Releases a hold on its inbox. */
114
114
  resume(): Promise<InboxListResponse>;
115
- /** Interrupts a Turn (default: the active one). */
115
+ /** Interrupts a Turn (default: whatever runs) and ends the session's background work. */
116
116
  stop(turn?: string): Promise<void>;
117
117
  inbox(opts?: InboxListOptions): Promise<InboxListResponse>;
118
118
  message(id: string): Promise<Message>;
@@ -170,8 +170,8 @@ export declare class Tokens {
170
170
  constructor(client: Client);
171
171
  /**
172
172
  * A token for another program; owner only. The secret is in the result once. With `prefix` it may do everything
173
- * the owner can for names that start with it except set `security.seccomp`, and nothing outside; otherwise
174
- * `actions` on `agentComputers`.
173
+ * the owner can for names that start with it except set `security.seccomp` or `attach`, and nothing outside;
174
+ * otherwise `actions` on `agentComputers`.
175
175
  */
176
176
  create(name: string, opts: {
177
177
  prefix: string;
package/dist/src/fleet.js CHANGED
@@ -203,7 +203,7 @@ export class AgentComputer {
203
203
  resume() {
204
204
  return this.client.resume(this.name);
205
205
  }
206
- /** Interrupts a Turn (default: the active one). */
206
+ /** Interrupts a Turn (default: whatever runs) and ends the session's background work. */
207
207
  stop(turn) {
208
208
  return this.client.stop(this.name, turn);
209
209
  }
@@ -313,8 +313,8 @@ export class Tokens {
313
313
  }
314
314
  /**
315
315
  * A token for another program; owner only. The secret is in the result once. With `prefix` it may do everything
316
- * the owner can for names that start with it except set `security.seccomp`, and nothing outside; otherwise
317
- * `actions` on `agentComputers`.
316
+ * the owner can for names that start with it except set `security.seccomp` or `attach`, and nothing outside;
317
+ * otherwise `actions` on `agentComputers`.
318
318
  */
319
319
  create(name, opts) {
320
320
  if ("prefix" in opts) {
@@ -37,6 +37,15 @@ export interface AgentComputerSpec {
37
37
  security?: {
38
38
  seccomp?: Record<string, unknown>;
39
39
  };
40
+ /**
41
+ * Host folders mounted at /home/agent/<name>, by name; owner only. `host` is an absolute path on the machine
42
+ * running a12s; `keep` paths (like node_modules) stay inside a12s, on a drive each, never in the host folder.
43
+ */
44
+ attach?: Record<string, {
45
+ host: string;
46
+ readOnly?: boolean;
47
+ keep?: string[];
48
+ }>;
40
49
  inbox?: {
41
50
  maxMessages?: number;
42
51
  maxBytes?: string;
@@ -191,11 +200,17 @@ export interface ComputerStatus {
191
200
  warnings?: string[];
192
201
  inbox?: InboxSummary;
193
202
  power?: PowerStatus;
203
+ /** Set while the harness session runs background work (sub-agents, shells) between Turns; it is not idle then. */
204
+ background?: {
205
+ tasks: number;
206
+ };
194
207
  }
195
208
  export interface DriveRow {
196
209
  name: string;
197
- kind: "home" | "state";
210
+ kind: "home" | "state" | "keep";
198
211
  computer?: string;
212
+ /** Where a keep drive is mounted, e.g. /home/agent/project/node_modules. */
213
+ path?: string;
199
214
  service?: string;
200
215
  /** A quantity such as "10Gi". */
201
216
  size?: string;
@@ -332,9 +347,25 @@ export interface TurnStartedData {
332
347
  prompt: string;
333
348
  cwd: string;
334
349
  requestId?: string;
335
- /** The Messages this Turn delivers. Absent for a continuation after `restart_harness`. */
350
+ /** The Messages this Turn delivers. Absent for a continuation after `restart_harness` and a background Turn. */
336
351
  inbox?: TurnInbox;
337
352
  continuation?: string;
353
+ /** "background": the harness started this Turn by itself when background work ended. */
354
+ reason?: string;
355
+ }
356
+ /** Background work (a sub-agent, a shell) the harness keeps running after the Turn that started it. */
357
+ export interface TaskData {
358
+ id: string;
359
+ /** The harness's own kind: local_agent, local_bash, shell, … */
360
+ kind: string;
361
+ description: string;
362
+ /** On task.finished. "killed": the session ended (stop, sleep, restart, a new session) while it ran. */
363
+ status?: "completed" | "failed" | "stopped" | "killed";
364
+ }
365
+ /** POST /v1/agent-computers/{name}/stop: the Turns it stopped and how many background tasks it ended. */
366
+ export interface StopResponse {
367
+ turns: string[];
368
+ background: number;
338
369
  }
339
370
  export interface TurnFinishedData {
340
371
  status: "completed" | "failed" | "interrupted";
@@ -445,6 +476,8 @@ export type TurnRefusedEvent = Ev<"turn.refused", {
445
476
  /** A Message that ended without delivery (cleared, withdrawn, expired, replaced), body included. */
446
477
  export type InboxDiscardedEvent = Ev<"inbox.discarded", Record<string, unknown>>;
447
478
  export type EgressDeniedEvent = Ev<"egress.denied", EgressDeniedData>;
479
+ export type TaskStartedEvent = Ev<"task.started", TaskData>;
480
+ export type TaskFinishedEvent = Ev<"task.finished", TaskData>;
448
481
  /** Made by the Controller, on the fleet-wide stream only. */
449
482
  export type FleetChangedEvent = Ev<"fleet.changed", FleetChangedData>;
450
483
  /** Made by the Controller, on the fleet-wide stream only. */
@@ -456,7 +489,7 @@ export type ServicePhaseEvent = Ev<"service.phase", ServicePhaseData>;
456
489
  /** Made by the SDK, never journaled: the stream could not resume from its cursor and events were lost. */
457
490
  export type GapEvent = Ev<"gap", GapData>;
458
491
  /** One event of an agent computer's journal, or the Controller's own on the fleet-wide stream. Narrow on `type` to get typed `data`. */
459
- export type A12sEvent = TurnStartedEvent | TurnDispatchedEvent | TextDeltaEvent | ToolStartedEvent | ToolFinishedEvent | PermissionEvent | DiagnosticEvent | TurnFinishedEvent | SessionChangedEvent | ResumeFailedEvent | LifecycleEvent | HarnessRestartedEvent | ContinuationAbandonedEvent | TurnRefusedEvent | InboxDiscardedEvent | EgressDeniedEvent | FleetChangedEvent | PhaseEvent | InboxChangedEvent | ServicePhaseEvent | GapEvent;
492
+ export type A12sEvent = TurnStartedEvent | TurnDispatchedEvent | TextDeltaEvent | ToolStartedEvent | ToolFinishedEvent | PermissionEvent | DiagnosticEvent | TurnFinishedEvent | SessionChangedEvent | ResumeFailedEvent | LifecycleEvent | HarnessRestartedEvent | ContinuationAbandonedEvent | TurnRefusedEvent | InboxDiscardedEvent | EgressDeniedEvent | TaskStartedEvent | TaskFinishedEvent | FleetChangedEvent | PhaseEvent | InboxChangedEvent | ServicePhaseEvent | GapEvent;
460
493
  export type EventType = A12sEvent["type"];
461
494
  /** One tool call in a Turn. A `send` to another Computer is `mcp__a12s__send` with `input.body`. */
462
495
  export interface ToolCall {
@@ -473,6 +506,8 @@ export interface Turn {
473
506
  id: string;
474
507
  session: string;
475
508
  status: TurnFinishedData["status"];
509
+ /** "background": the harness started this Turn by itself when background work ended; it delivered no Messages. */
510
+ reason?: string;
476
511
  /** Everything the agent said in the Turn, concatenated. */
477
512
  text: string;
478
513
  error?: string;
@@ -505,7 +540,10 @@ export interface TokenRequest {
505
540
  name: string;
506
541
  actions?: TokenAction[];
507
542
  computers?: string[];
508
- /** Every power over agent computers, Services and credentials whose names start with it but seccomp; none outside. */
543
+ /**
544
+ * Every power over agent computers, Services and credentials whose names start with it but seccomp and attach;
545
+ * none outside.
546
+ */
509
547
  prefix?: string;
510
548
  }
511
549
  /** 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.7.0",
3
+ "version": "0.8.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",