@onesi/genesis 0.2.7 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  The TypeScript SDK for OneOS. One typed client for every Genesis service, through the Genesis API at `https://os.one.ml/api`.
4
4
 
5
5
  ```sh
6
- npm install @onesi/genesis@0.2.7
6
+ npm install @onesi/genesis@0.2.8
7
7
  ```
8
8
 
9
9
  ```ts
package/dist/client.js CHANGED
@@ -266,7 +266,7 @@ export class GenesisClient {
266
266
  const url = this.url(operationId, input);
267
267
  const headers = {
268
268
  accept: 'application/json',
269
- 'user-agent': this.opts.userAgent ?? '@onesi/genesis/0.2.7',
269
+ 'user-agent': this.opts.userAgent ?? '@onesi/genesis/0.2.8',
270
270
  ...this.opts.headers, ...init.headers,
271
271
  };
272
272
  if (op.service === 'blinds' && !['GET', 'HEAD', 'OPTIONS'].includes(op.method))
package/dist/context.d.ts CHANGED
@@ -6,7 +6,7 @@ export type GenesisContextSelection = {
6
6
  platformId: 'pf_console';
7
7
  workspaceId: string;
8
8
  fleetId: null;
9
- environmentId: 'sandbox';
9
+ environmentId: 'sandbox' | 'live';
10
10
  };
11
11
  export interface GenesisContextSession {
12
12
  principal: {
package/dist/context.js CHANGED
@@ -78,7 +78,7 @@ export async function selectGenesisContext(selection, options) {
78
78
  const requested = { ...selection };
79
79
  const keys = Object.keys(requested), full = 'projectId' in requested;
80
80
  if (!id(requested.organizationId, 'o') || keys.some(k => !(full ? ['organizationId', 'projectId', 'platformId', 'workspaceId', 'fleetId', 'environmentId'] : ['organizationId']).includes(k))
81
- || (full && (!id(requested.projectId, 'pr') || !id(requested.workspaceId, 'w') || requested.platformId !== 'pf_console' || requested.fleetId !== null || requested.environmentId !== 'sandbox')))
81
+ || (full && (!id(requested.projectId, 'pr') || !id(requested.workspaceId, 'w') || requested.platformId !== 'pf_console' || requested.fleetId !== null || (requested.environmentId !== 'sandbox' && requested.environmentId !== 'live'))))
82
82
  return fail(400);
83
83
  const controller = new AbortController(), cancel = () => controller.abort();
84
84
  options.signal?.addEventListener('abort', cancel, { once: true });
package/dist/fleets.d.ts CHANGED
@@ -10,6 +10,11 @@ export interface FleetsInstanceOptions {
10
10
  idempotencyKey?: string;
11
11
  signal?: AbortSignal;
12
12
  }
13
+ type SeatHireInput = NonNullable<OperationInput<'fleets_hireSeat'>['body']>;
14
+ type SeatUpdateInput = NonNullable<OperationInput<'fleets_updateSeat'>['body']>;
15
+ type SeatTaskInput = NonNullable<OperationInput<'fleets_submitSeatTask'>['body']>;
16
+ type PoolCreateInput = NonNullable<OperationInput<'fleets_createPool'>['body']>;
17
+ type PoolTopUpInput = NonNullable<OperationInput<'fleets_topUpPool'>['body']>;
13
18
  /** Managed Henry instances and tasks scoped to the credential's verified org. */
14
19
  export declare function fleetsModule(client: GenesisClient): {
15
20
  agents: {
@@ -155,6 +160,309 @@ export declare function fleetsModule(client: GenesisClient): {
155
160
  updated_at?: number;
156
161
  }>;
157
162
  };
163
+ /** Agent seats: a persistent Henry agent with a credit purse and a computer entitlement. Plan prices are display data. */
164
+ seats: {
165
+ plans: () => Promise<{
166
+ plans: import("./index.js").components["schemas"]["Fleets.SeatPlan"][];
167
+ credit?: {
168
+ unit?: string;
169
+ value_usd?: number;
170
+ meaning?: string;
171
+ };
172
+ }>;
173
+ list: () => Promise<{
174
+ seats: import("./index.js").components["schemas"]["Fleets.Seat"][];
175
+ }>;
176
+ /** Hire a seat. idempotency_key is required; reuse it on retry. fund: false opens an empty purse for top-up. */
177
+ hire: (body: SeatHireInput) => Promise<{
178
+ id: string;
179
+ object: "fleets.seat";
180
+ type: import("./index.js").components["schemas"]["Fleets.SeatType"];
181
+ name?: string;
182
+ state: "active" | "paused" | "held" | "killed" | "releasing" | "released";
183
+ pause_reason?: string;
184
+ agent_id?: string | null;
185
+ pool_id?: string | null;
186
+ purse: import("./index.js").components["schemas"]["Fleets.Purse"];
187
+ computer: import("./index.js").components["schemas"]["Fleets.Computer"];
188
+ release?: import("./index.js").components["schemas"]["Fleets.SeatRelease"];
189
+ created_at?: string;
190
+ updated_at?: string;
191
+ }>;
192
+ get: (seat_id: string) => Promise<{
193
+ id: string;
194
+ object: "fleets.seat";
195
+ type: import("./index.js").components["schemas"]["Fleets.SeatType"];
196
+ name?: string;
197
+ state: "active" | "paused" | "held" | "killed" | "releasing" | "released";
198
+ pause_reason?: string;
199
+ agent_id?: string | null;
200
+ pool_id?: string | null;
201
+ purse: import("./index.js").components["schemas"]["Fleets.Purse"];
202
+ computer: import("./index.js").components["schemas"]["Fleets.Computer"];
203
+ release?: import("./index.js").components["schemas"]["Fleets.SeatRelease"];
204
+ created_at?: string;
205
+ updated_at?: string;
206
+ }>;
207
+ update: (seat_id: string, body: SeatUpdateInput) => Promise<{
208
+ id: string;
209
+ object: "fleets.seat";
210
+ type: import("./index.js").components["schemas"]["Fleets.SeatType"];
211
+ name?: string;
212
+ state: "active" | "paused" | "held" | "killed" | "releasing" | "released";
213
+ pause_reason?: string;
214
+ agent_id?: string | null;
215
+ pool_id?: string | null;
216
+ purse: import("./index.js").components["schemas"]["Fleets.Purse"];
217
+ computer: import("./index.js").components["schemas"]["Fleets.Computer"];
218
+ release?: import("./index.js").components["schemas"]["Fleets.SeatRelease"];
219
+ created_at?: string;
220
+ updated_at?: string;
221
+ }>;
222
+ /** Add credits; overdraft is repaid first. Computer minutes come from the plan (upgrade, or use a pool). A pooled seat answers 409 pooled_seat: top up the pool. */
223
+ topUp: (seat_id: string, credits: number, idempotency_key: string) => Promise<{
224
+ id: string;
225
+ object: "fleets.seat";
226
+ type: import("./index.js").components["schemas"]["Fleets.SeatType"];
227
+ name?: string;
228
+ state: "active" | "paused" | "held" | "killed" | "releasing" | "released";
229
+ pause_reason?: string;
230
+ agent_id?: string | null;
231
+ pool_id?: string | null;
232
+ purse: import("./index.js").components["schemas"]["Fleets.Purse"];
233
+ computer: import("./index.js").components["schemas"]["Fleets.Computer"];
234
+ release?: import("./index.js").components["schemas"]["Fleets.SeatRelease"];
235
+ created_at?: string;
236
+ updated_at?: string;
237
+ }>;
238
+ /** Move to a larger plan; there is no downgrade. */
239
+ upgrade: (seat_id: string, type: "helper" | "operator" | "always_on") => Promise<{
240
+ id: string;
241
+ object: "fleets.seat";
242
+ type: import("./index.js").components["schemas"]["Fleets.SeatType"];
243
+ name?: string;
244
+ state: "active" | "paused" | "held" | "killed" | "releasing" | "released";
245
+ pause_reason?: string;
246
+ agent_id?: string | null;
247
+ pool_id?: string | null;
248
+ purse: import("./index.js").components["schemas"]["Fleets.Purse"];
249
+ computer: import("./index.js").components["schemas"]["Fleets.Computer"];
250
+ release?: import("./index.js").components["schemas"]["Fleets.SeatRelease"];
251
+ created_at?: string;
252
+ updated_at?: string;
253
+ }>;
254
+ hold: (seat_id: string) => Promise<{
255
+ id: string;
256
+ object: "fleets.seat";
257
+ type: import("./index.js").components["schemas"]["Fleets.SeatType"];
258
+ name?: string;
259
+ state: "active" | "paused" | "held" | "killed" | "releasing" | "released";
260
+ pause_reason?: string;
261
+ agent_id?: string | null;
262
+ pool_id?: string | null;
263
+ purse: import("./index.js").components["schemas"]["Fleets.Purse"];
264
+ computer: import("./index.js").components["schemas"]["Fleets.Computer"];
265
+ release?: import("./index.js").components["schemas"]["Fleets.SeatRelease"];
266
+ created_at?: string;
267
+ updated_at?: string;
268
+ } & {
269
+ cancelled_tasks: string[];
270
+ agent_state?: string;
271
+ }>;
272
+ resume: (seat_id: string) => Promise<{
273
+ id: string;
274
+ object: "fleets.seat";
275
+ type: import("./index.js").components["schemas"]["Fleets.SeatType"];
276
+ name?: string;
277
+ state: "active" | "paused" | "held" | "killed" | "releasing" | "released";
278
+ pause_reason?: string;
279
+ agent_id?: string | null;
280
+ pool_id?: string | null;
281
+ purse: import("./index.js").components["schemas"]["Fleets.Purse"];
282
+ computer: import("./index.js").components["schemas"]["Fleets.Computer"];
283
+ release?: import("./index.js").components["schemas"]["Fleets.SeatRelease"];
284
+ created_at?: string;
285
+ updated_at?: string;
286
+ }>;
287
+ kill: (seat_id: string) => Promise<{
288
+ id: string;
289
+ object: "fleets.seat";
290
+ type: import("./index.js").components["schemas"]["Fleets.SeatType"];
291
+ name?: string;
292
+ state: "active" | "paused" | "held" | "killed" | "releasing" | "released";
293
+ pause_reason?: string;
294
+ agent_id?: string | null;
295
+ pool_id?: string | null;
296
+ purse: import("./index.js").components["schemas"]["Fleets.Purse"];
297
+ computer: import("./index.js").components["schemas"]["Fleets.Computer"];
298
+ release?: import("./index.js").components["schemas"]["Fleets.SeatRelease"];
299
+ created_at?: string;
300
+ updated_at?: string;
301
+ } & {
302
+ cancelled_tasks: string[];
303
+ agent_state?: string;
304
+ }>;
305
+ /** Settle the purse and delete the agent (terminal); answers returned_credits, returned_computer_minutes, unpaid_overdraft_credits, spent_credits. */
306
+ release: (seat_id: string) => Promise<{
307
+ id: string;
308
+ object: "fleets.seat.release";
309
+ seat_id?: string;
310
+ state: "released";
311
+ returned_credits: number;
312
+ returned_computer_minutes: number;
313
+ unpaid_overdraft_credits?: number;
314
+ spent_credits?: number;
315
+ pool_id?: string | null;
316
+ agent_deleted?: boolean;
317
+ released_at?: string;
318
+ }>;
319
+ ledger: (seat_id: string) => Promise<{
320
+ id?: string;
321
+ entries: import("./index.js").components["schemas"]["Fleets.SeatLedgerEntry"][];
322
+ }>;
323
+ tasks: {
324
+ list: (seat_id: string) => Promise<{
325
+ tasks: import("./index.js").components["schemas"]["Fleets.SeatTask"][];
326
+ }>;
327
+ /** 402 purse_empty when parked, 403 computer_not_entitled for a helper's computer task, 409 when held, killed or released. */
328
+ submit: (seat_id: string, body: SeatTaskInput) => Promise<{
329
+ task_id: string;
330
+ object?: "fleets.seat.task";
331
+ seat_id: string;
332
+ kind: "research" | "computer";
333
+ state: "pending" | "running" | "awaiting_approval" | "completed" | "failed" | "cancelled" | "timed_out";
334
+ output?: string | null;
335
+ error?: string | null;
336
+ approvals?: import("./index.js").components["schemas"]["Fleets.SeatApproval"][];
337
+ credits?: {
338
+ reserved?: number;
339
+ charged?: number | null;
340
+ borrowed?: number;
341
+ };
342
+ computer_minutes?: number;
343
+ computer_minutes_allowed?: number;
344
+ settled?: boolean;
345
+ receipt_url?: string;
346
+ submitted_at?: string;
347
+ completed_at?: string | null;
348
+ }>;
349
+ get: (seat_id: string, task_id: string) => Promise<{
350
+ task_id: string;
351
+ object?: "fleets.seat.task";
352
+ seat_id: string;
353
+ kind: "research" | "computer";
354
+ state: "pending" | "running" | "awaiting_approval" | "completed" | "failed" | "cancelled" | "timed_out";
355
+ output?: string | null;
356
+ error?: string | null;
357
+ approvals?: import("./index.js").components["schemas"]["Fleets.SeatApproval"][];
358
+ credits?: {
359
+ reserved?: number;
360
+ charged?: number | null;
361
+ borrowed?: number;
362
+ };
363
+ computer_minutes?: number;
364
+ computer_minutes_allowed?: number;
365
+ settled?: boolean;
366
+ receipt_url?: string;
367
+ submitted_at?: string;
368
+ completed_at?: string | null;
369
+ }>;
370
+ decide: (seat_id: string, task_id: string, approval_id: string, decision: "approve" | "deny") => Promise<{
371
+ task_id: string;
372
+ object?: "fleets.seat.task";
373
+ seat_id: string;
374
+ kind: "research" | "computer";
375
+ state: "pending" | "running" | "awaiting_approval" | "completed" | "failed" | "cancelled" | "timed_out";
376
+ output?: string | null;
377
+ error?: string | null;
378
+ approvals?: import("./index.js").components["schemas"]["Fleets.SeatApproval"][];
379
+ credits?: {
380
+ reserved?: number;
381
+ charged?: number | null;
382
+ borrowed?: number;
383
+ };
384
+ computer_minutes?: number;
385
+ computer_minutes_allowed?: number;
386
+ settled?: boolean;
387
+ receipt_url?: string;
388
+ submitted_at?: string;
389
+ completed_at?: string | null;
390
+ }>;
391
+ };
392
+ };
393
+ /** Seat pools: a shared purse and computer minutes that seats hired with pool_id draw on. */
394
+ pools: {
395
+ list: () => Promise<{
396
+ pools: import("./index.js").components["schemas"]["Fleets.Pool"][];
397
+ }>;
398
+ create: (body: PoolCreateInput) => Promise<{
399
+ id: string;
400
+ object: "fleets.pool";
401
+ name?: string;
402
+ state?: string;
403
+ purse: import("./index.js").components["schemas"]["Fleets.Purse"];
404
+ computer: import("./index.js").components["schemas"]["Fleets.Computer"];
405
+ seats?: string[];
406
+ release?: import("./index.js").components["schemas"]["Fleets.PoolRelease"];
407
+ created_at?: string;
408
+ updated_at?: string;
409
+ }>;
410
+ get: (pool_id: string) => Promise<{
411
+ id: string;
412
+ object: "fleets.pool";
413
+ name?: string;
414
+ state?: string;
415
+ purse: import("./index.js").components["schemas"]["Fleets.Purse"];
416
+ computer: import("./index.js").components["schemas"]["Fleets.Computer"];
417
+ seats?: string[];
418
+ release?: import("./index.js").components["schemas"]["Fleets.PoolRelease"];
419
+ created_at?: string;
420
+ updated_at?: string;
421
+ }>;
422
+ topUp: (pool_id: string, body: PoolTopUpInput) => Promise<{
423
+ id: string;
424
+ object: "fleets.pool";
425
+ name?: string;
426
+ state?: string;
427
+ purse: import("./index.js").components["schemas"]["Fleets.Purse"];
428
+ computer: import("./index.js").components["schemas"]["Fleets.Computer"];
429
+ seats?: string[];
430
+ release?: import("./index.js").components["schemas"]["Fleets.PoolRelease"];
431
+ created_at?: string;
432
+ updated_at?: string;
433
+ }>;
434
+ ledger: (pool_id: string) => Promise<{
435
+ id?: string;
436
+ entries: import("./index.js").components["schemas"]["Fleets.SeatLedgerEntry"][];
437
+ }>;
438
+ /** Settle the pool (terminal); answers returned_credits and returned_computer_minutes. 409 pool_has_seats while seats remain. */
439
+ release: (pool_id: string) => Promise<{
440
+ id: string;
441
+ object: "fleets.pool.release";
442
+ pool_id?: string;
443
+ state: "released";
444
+ returned_credits: number;
445
+ returned_computer_minutes: number;
446
+ unpaid_overdraft_credits?: number;
447
+ spent_credits?: number;
448
+ released_at?: string;
449
+ }>;
450
+ };
451
+ /** The organization key seat computer tasks use for Panes and Shells; KMS-encrypted, never returned. */
452
+ computerConnection: {
453
+ get: () => Promise<{
454
+ connected: boolean;
455
+ updated_at?: number;
456
+ }>;
457
+ set: (api_key: string) => Promise<{
458
+ connected: boolean;
459
+ updated_at?: number;
460
+ }>;
461
+ delete: () => Promise<{
462
+ connected: boolean;
463
+ updated_at?: number;
464
+ }>;
465
+ };
158
466
  usage: {
159
467
  /** Task lifecycle and execution-time usage events, paged by task like tasks.list. */
160
468
  events: (query?: OperationInput<"fleets_listUsageEvents">) => Promise<{
package/dist/fleets.js CHANGED
@@ -94,6 +94,92 @@ const cursor = (value, operation, max) => {
94
94
  throw invalid(operation, 'after must be a non-negative integer cursor (next_after).');
95
95
  }
96
96
  };
97
+ const SEAT_TYPES = ['helper', 'operator', 'always_on'];
98
+ const MAX_CREDITS = 100_000_000;
99
+ /** Seat, pool, task and approval IDs: one path segment of Fleets' own ID characters. */
100
+ const seatPathId = (value, operation, what) => {
101
+ if (typeof value !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$/.test(value))
102
+ throw invalid(operation, `Invalid ${what} ID.`);
103
+ };
104
+ const bodyKey = (value, operation) => {
105
+ if (typeof value !== 'string' || !/^[!-~]{1,128}$/.test(value))
106
+ throw invalid(operation, 'idempotency_key is required: 1–128 visible ASCII characters, reused on retry.');
107
+ };
108
+ const whole = (value, operation, field, min) => {
109
+ if (!Number.isSafeInteger(value) || value < min || value > MAX_CREDITS) {
110
+ throw invalid(operation, `${field} must be a whole number of at least ${min}.`);
111
+ }
112
+ };
113
+ const seatName = (value, operation) => {
114
+ if (typeof value !== 'string' || !value.trim() || byteLength(value) > 128)
115
+ throw invalid(operation, 'Seat name must contain 1–128 UTF-8 bytes.');
116
+ };
117
+ const seatType = (value, operation) => {
118
+ if (typeof value !== 'string' || !SEAT_TYPES.includes(value))
119
+ throw invalid(operation, 'Seat type must be helper, operator or always_on.');
120
+ };
121
+ const plainBody = (body, operation, allowed) => {
122
+ if (!body || typeof body !== 'object' || Array.isArray(body))
123
+ throw invalid(operation, 'Provide a JSON object body.');
124
+ const extra = Object.keys(body).find(key => !allowed.includes(key));
125
+ if (extra)
126
+ throw invalid(operation, `Unknown field ${extra}.`);
127
+ };
128
+ function validateSeatHire(body) {
129
+ const op = 'fleets_hireSeat';
130
+ plainBody(body, op, ['type', 'name', 'borrow_ceiling_credits', 'pool_id', 'fund', 'idempotency_key']);
131
+ seatType(body.type, op);
132
+ if (body.name !== undefined)
133
+ seatName(body.name, op);
134
+ if (body.borrow_ceiling_credits !== undefined)
135
+ whole(body.borrow_ceiling_credits, op, 'borrow_ceiling_credits', 0);
136
+ if (body.pool_id !== undefined)
137
+ seatPathId(body.pool_id, op, 'pool');
138
+ if (body.fund !== undefined && typeof body.fund !== 'boolean')
139
+ throw invalid(op, 'fund must be true or false.');
140
+ bodyKey(body.idempotency_key, op);
141
+ }
142
+ function validateSeatUpdate(body) {
143
+ const op = 'fleets_updateSeat';
144
+ plainBody(body, op, ['name', 'borrow_ceiling_credits']);
145
+ if (!Object.keys(body).length)
146
+ throw invalid(op, 'Provide name or borrow_ceiling_credits.');
147
+ if (body.name !== undefined)
148
+ seatName(body.name, op);
149
+ if (body.borrow_ceiling_credits !== undefined)
150
+ whole(body.borrow_ceiling_credits, op, 'borrow_ceiling_credits', 0);
151
+ }
152
+ function validateSeatTask(body) {
153
+ const op = 'fleets_submitSeatTask';
154
+ plainBody(body, op, ['input', 'kind', 'timeout_seconds', 'approve_computer', 'idempotency_key']);
155
+ if (typeof body.input !== 'string' || !body.input || byteLength(body.input) > 65536 || body.input.includes('\0')) {
156
+ throw invalid(op, 'Task input must contain 1–65536 UTF-8 bytes without NUL.');
157
+ }
158
+ if (body.kind !== undefined && body.kind !== 'research' && body.kind !== 'computer')
159
+ throw invalid(op, 'Task kind must be research or computer (default research).');
160
+ if (body.timeout_seconds !== undefined && (!Number.isInteger(body.timeout_seconds) || body.timeout_seconds < 1 || body.timeout_seconds > 3600)) {
161
+ throw invalid(op, 'Timeout must be 1–3600 seconds.');
162
+ }
163
+ if (body.approve_computer !== undefined && typeof body.approve_computer !== 'boolean')
164
+ throw invalid(op, 'approve_computer must be true or false.');
165
+ bodyKey(body.idempotency_key, op);
166
+ }
167
+ function validatePool(body, op) {
168
+ plainBody(body, op, op === 'fleets_createPool' ? ['name', 'credits', 'computer_minutes', 'idempotency_key'] : ['credits', 'computer_minutes', 'idempotency_key']);
169
+ if (op === 'fleets_topUpPool' && body.credits === 0 && !body.computer_minutes)
170
+ throw invalid(op, 'Add credits or computer_minutes.');
171
+ if (op === 'fleets_createPool' && body.name !== undefined)
172
+ seatName(body.name, op);
173
+ whole(body.credits, op, 'credits', 0);
174
+ if (body.computer_minutes !== undefined)
175
+ whole(body.computer_minutes, op, 'computer_minutes', 0);
176
+ bodyKey(body.idempotency_key, op);
177
+ }
178
+ function validateComputerKey(apiKey) {
179
+ if (typeof apiKey !== 'string' || !apiKey || byteLength(apiKey) > 4096 || /[\r\n\0]/.test(apiKey)) {
180
+ throw invalid('fleets_putComputerConnection', 'Computer key must contain 1–4096 UTF-8 bytes without CR, LF or NUL.');
181
+ }
182
+ }
97
183
  /** Managed Henry instances and tasks scoped to the credential's verified org. */
98
184
  export function fleetsModule(client) {
99
185
  return {
@@ -174,6 +260,120 @@ export function fleetsModule(client) {
174
260
  },
175
261
  delete: () => client.request('fleets_deleteConnection', {}),
176
262
  },
263
+ /** Agent seats: a persistent Henry agent with a credit purse and a computer entitlement. Plan prices are display data. */
264
+ seats: {
265
+ plans: () => client.request('fleets_listSeatPlans', {}),
266
+ list: () => client.request('fleets_listSeats', {}),
267
+ /** Hire a seat. idempotency_key is required; reuse it on retry. fund: false opens an empty purse for top-up. */
268
+ hire: async (body) => {
269
+ validateSeatHire(body);
270
+ return client.request('fleets_hireSeat', { body });
271
+ },
272
+ get: async (seat_id) => {
273
+ seatPathId(seat_id, 'fleets_getSeat', 'seat');
274
+ return client.request('fleets_getSeat', { seat_id });
275
+ },
276
+ update: async (seat_id, body) => {
277
+ seatPathId(seat_id, 'fleets_updateSeat', 'seat');
278
+ validateSeatUpdate(body);
279
+ return client.request('fleets_updateSeat', { seat_id, body });
280
+ },
281
+ /** Add credits; overdraft is repaid first. Computer minutes come from the plan (upgrade, or use a pool). A pooled seat answers 409 pooled_seat: top up the pool. */
282
+ topUp: async (seat_id, credits, idempotency_key) => {
283
+ seatPathId(seat_id, 'fleets_topUpSeat', 'seat');
284
+ whole(credits, 'fleets_topUpSeat', 'credits', 1);
285
+ bodyKey(idempotency_key, 'fleets_topUpSeat');
286
+ return client.request('fleets_topUpSeat', { seat_id, body: { credits, idempotency_key } });
287
+ },
288
+ /** Move to a larger plan; there is no downgrade. */
289
+ upgrade: async (seat_id, type) => {
290
+ seatPathId(seat_id, 'fleets_upgradeSeat', 'seat');
291
+ seatType(type, 'fleets_upgradeSeat');
292
+ return client.request('fleets_upgradeSeat', { seat_id, body: { type } });
293
+ },
294
+ hold: async (seat_id) => {
295
+ seatPathId(seat_id, 'fleets_holdSeat', 'seat');
296
+ return client.request('fleets_holdSeat', { seat_id });
297
+ },
298
+ resume: async (seat_id) => {
299
+ seatPathId(seat_id, 'fleets_resumeSeat', 'seat');
300
+ return client.request('fleets_resumeSeat', { seat_id });
301
+ },
302
+ kill: async (seat_id) => {
303
+ seatPathId(seat_id, 'fleets_killSeat', 'seat');
304
+ return client.request('fleets_killSeat', { seat_id });
305
+ },
306
+ /** Settle the purse and delete the agent (terminal); answers returned_credits, returned_computer_minutes, unpaid_overdraft_credits, spent_credits. */
307
+ release: async (seat_id) => {
308
+ seatPathId(seat_id, 'fleets_releaseSeat', 'seat');
309
+ return client.request('fleets_releaseSeat', { seat_id });
310
+ },
311
+ ledger: async (seat_id) => {
312
+ seatPathId(seat_id, 'fleets_getSeatLedger', 'seat');
313
+ return client.request('fleets_getSeatLedger', { seat_id });
314
+ },
315
+ tasks: {
316
+ list: async (seat_id) => {
317
+ seatPathId(seat_id, 'fleets_listSeatTasks', 'seat');
318
+ return client.request('fleets_listSeatTasks', { seat_id });
319
+ },
320
+ /** 402 purse_empty when parked, 403 computer_not_entitled for a helper's computer task, 409 when held, killed or released. */
321
+ submit: async (seat_id, body) => {
322
+ seatPathId(seat_id, 'fleets_submitSeatTask', 'seat');
323
+ validateSeatTask(body);
324
+ return client.request('fleets_submitSeatTask', { seat_id, body });
325
+ },
326
+ get: async (seat_id, task_id) => {
327
+ seatPathId(seat_id, 'fleets_getSeatTask', 'seat');
328
+ seatPathId(task_id, 'fleets_getSeatTask', 'task');
329
+ return client.request('fleets_getSeatTask', { seat_id, task_id });
330
+ },
331
+ decide: async (seat_id, task_id, approval_id, decision) => {
332
+ const op = 'fleets_decideSeatTaskApproval';
333
+ seatPathId(seat_id, op, 'seat');
334
+ seatPathId(task_id, op, 'task');
335
+ seatPathId(approval_id, op, 'approval');
336
+ if (decision !== 'approve' && decision !== 'deny')
337
+ throw invalid(op, 'Decision must be approve or deny.');
338
+ return client.request(op, { seat_id, task_id, approval_id, body: { decision } });
339
+ },
340
+ },
341
+ },
342
+ /** Seat pools: a shared purse and computer minutes that seats hired with pool_id draw on. */
343
+ pools: {
344
+ list: () => client.request('fleets_listPools', {}),
345
+ create: async (body) => {
346
+ validatePool(body, 'fleets_createPool');
347
+ return client.request('fleets_createPool', { body });
348
+ },
349
+ get: async (pool_id) => {
350
+ seatPathId(pool_id, 'fleets_getPool', 'pool');
351
+ return client.request('fleets_getPool', { pool_id });
352
+ },
353
+ topUp: async (pool_id, body) => {
354
+ seatPathId(pool_id, 'fleets_topUpPool', 'pool');
355
+ validatePool(body, 'fleets_topUpPool');
356
+ return client.request('fleets_topUpPool', { pool_id, body });
357
+ },
358
+ ledger: async (pool_id) => {
359
+ seatPathId(pool_id, 'fleets_getPoolLedger', 'pool');
360
+ return client.request('fleets_getPoolLedger', { pool_id });
361
+ },
362
+ /** Settle the pool (terminal); answers returned_credits and returned_computer_minutes. 409 pool_has_seats while seats remain. */
363
+ release: async (pool_id) => {
364
+ seatPathId(pool_id, 'fleets_releasePool', 'pool');
365
+ return client.request('fleets_releasePool', { pool_id });
366
+ },
367
+ },
368
+ /** The organization key seat computer tasks use for Panes and Shells; KMS-encrypted, never returned. */
369
+ computerConnection: {
370
+ get: () => client.request('fleets_getComputerConnection', {}),
371
+ set: async (api_key) => {
372
+ validateComputerKey(api_key);
373
+ return client.request('fleets_putComputerConnection', { body: { api_key } });
374
+ },
375
+ delete: () => client.request('fleets_deleteComputerConnection', {}),
376
+ },
177
377
  usage: {
178
378
  /** Task lifecycle and execution-time usage events, paged by task like tasks.list. */
179
379
  events: (query = {}) => client.request('fleets_listUsageEvents', query),