@runblackcat/sdk 0.1.0-alpha.88 → 0.1.0-alpha.90
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 +7 -1
- package/package.json +1 -1
- package/sdk/dist/index.d.ts +20 -4
- package/sdk/dist/index.js +44 -41
package/README.md
CHANGED
|
@@ -168,6 +168,12 @@ GET /v1/sandboxes/acquisitions/{id} -> 202 pending … -> 200 {"state":"p
|
|
|
168
168
|
POST /v1/sandboxes/{id}/renew {ttl_secs} -> 200 {"expires_at":…, "renewable_until":…}
|
|
169
169
|
```
|
|
170
170
|
|
|
171
|
+
Add `?wait_secs=N` (held at most 55 s) to the create or the lookup to have the gateway
|
|
172
|
+
hold a still-pending claim and answer as soon as it is placed or fails; the
|
|
173
|
+
placed receipt carries `ports`, so there is nothing to poll and no second call.
|
|
174
|
+
A claim still pending when the hold ends is answered `pending`; ask again. It
|
|
175
|
+
does not apply to a `count` batch: wait on each member by `request_id`.
|
|
176
|
+
|
|
171
177
|
To start many identical sandboxes, add `"count": N` (1 to 1000) to the create.
|
|
172
178
|
`request_id` then names the batch and member `i` is `request_id.i`. The whole batch
|
|
173
179
|
is recorded in one durable transaction and answered `202` at once, with no
|
|
@@ -187,7 +193,7 @@ sandbox.
|
|
|
187
193
|
Backpressure is fleet capacity and the durable queue; there are no per-tenant
|
|
188
194
|
quotas. A queued acquisition that waits past the queue deadline is torn down by
|
|
189
195
|
the ordinary expiry reconciler. Request-rate limits are operator-set fleet state
|
|
190
|
-
(`blackcat admin rate-limits get|set`): token
|
|
196
|
+
(`blackcat admin rate-limits get|set`): session token-mint and OIDC limits are on by
|
|
191
197
|
default, every workload limit is unlimited until set.
|
|
192
198
|
|
|
193
199
|
The placer sizes the fleet from that backlog through the `CapacityProvider`
|
package/package.json
CHANGED
package/sdk/dist/index.d.ts
CHANGED
|
@@ -33,7 +33,14 @@ export type FetchFunction = (input: RequestInfo | URL, init?: RequestInit & {
|
|
|
33
33
|
}) => Promise<Response>;
|
|
34
34
|
export interface BlackcatClientOptions {
|
|
35
35
|
baseUrl: string;
|
|
36
|
+
/**
|
|
37
|
+
* A tenant API key. The gateway accepts it directly on every resource route
|
|
38
|
+
* for the tenant's own resources (limited to the key's operation set), so a
|
|
39
|
+
* trusted server-side caller needs no `tokens.mint` per call. Keep it
|
|
40
|
+
* server-side; hand less-trusted holders a minted `token` instead.
|
|
41
|
+
*/
|
|
36
42
|
apiKey?: string;
|
|
43
|
+
/** A capability token; preferred over `apiKey` when both are set. */
|
|
37
44
|
token?: string;
|
|
38
45
|
/** Capability identity and expiry, using idiomatic TypeScript names. */
|
|
39
46
|
tokenId?: string;
|
|
@@ -369,8 +376,8 @@ export type CreateCapacityReservationInput = ({
|
|
|
369
376
|
* ordinary work; a sandbox create naming it waits for one of its slots. */
|
|
370
377
|
placement?: "shared" | "dedicated";
|
|
371
378
|
/** With `placement: "dedicated"`, the provider shape to launch: an exact
|
|
372
|
-
* shape or a family (`c7i`)
|
|
373
|
-
* planner chooses. */
|
|
379
|
+
* shape or a family (`c7i`) the fleet can launch (direct EC2: the config's
|
|
380
|
+
* instance_types). Absent: the planner chooses. */
|
|
374
381
|
shape?: string;
|
|
375
382
|
/** Stable retry key, at most 107 ASCII letters, digits, `_` or `-`. */
|
|
376
383
|
idempotency_key?: string;
|
|
@@ -406,6 +413,15 @@ export interface CapacityReservation {
|
|
|
406
413
|
/** When the capacity must be ready (epoch milliseconds), or null. */
|
|
407
414
|
needed_by: number | null;
|
|
408
415
|
}
|
|
416
|
+
export interface WaitOptions {
|
|
417
|
+
/**
|
|
418
|
+
* Have the gateway hold a still-pending claim for up to this many seconds
|
|
419
|
+
* and answer as soon as it is placed or fails, with its ports, instead of
|
|
420
|
+
* answering `pending` at once. The gateway holds at most 55 seconds. A claim
|
|
421
|
+
* still pending after the hold is returned as `pending`; ask again.
|
|
422
|
+
*/
|
|
423
|
+
wait_secs?: number;
|
|
424
|
+
}
|
|
409
425
|
/**
|
|
410
426
|
* Response returned by POST /v1/sandboxes (the gateway has no template field).
|
|
411
427
|
* The gateway sends a `failed` receipt with HTTP 409, so `create` and
|
|
@@ -872,7 +888,7 @@ declare class SandboxesResource {
|
|
|
872
888
|
* recover a lost response. A pending receipt is not an executable sandbox;
|
|
873
889
|
* no automatic retry, new ID, or replacement allocation is synthesized here.
|
|
874
890
|
*/
|
|
875
|
-
create(input: CreateSandboxInput): Promise<CreateSandboxResponse>;
|
|
891
|
+
create(input: CreateSandboxInput, options?: WaitOptions): Promise<CreateSandboxResponse>;
|
|
876
892
|
/**
|
|
877
893
|
* Create `count` identical sandboxes under one request ID. Resolves as soon
|
|
878
894
|
* as the whole batch is durably recorded; nothing waits on a restore.
|
|
@@ -882,7 +898,7 @@ declare class SandboxesResource {
|
|
|
882
898
|
createBatch(input: CreateSandboxBatchInput): Promise<SandboxBatchResponse>;
|
|
883
899
|
/** Counts by state and every member of a batch created with `createBatch`. */
|
|
884
900
|
batch(requestId: string): Promise<SandboxBatchResponse>;
|
|
885
|
-
acquisition(requestId: string): Promise<CreateSandboxResponse>;
|
|
901
|
+
acquisition(requestId: string, options?: WaitOptions): Promise<CreateSandboxResponse>;
|
|
886
902
|
/**
|
|
887
903
|
* Fence an acquisition request ID before its create is recorded, or destroy
|
|
888
904
|
* the allocation when the create has already won.
|
package/sdk/dist/index.js
CHANGED
|
@@ -21,6 +21,9 @@ var BLACKCAT_ERROR_CODES = {
|
|
|
21
21
|
function withTemplate(input) {
|
|
22
22
|
return { ...input, template: input.template ?? "default" };
|
|
23
23
|
}
|
|
24
|
+
function waitQuery({ wait_secs }) {
|
|
25
|
+
return wait_secs === undefined ? "" : `?wait_secs=${wait_secs}`;
|
|
26
|
+
}
|
|
24
27
|
|
|
25
28
|
class BlackcatApiError extends Error {
|
|
26
29
|
status;
|
|
@@ -351,17 +354,17 @@ class TemplatesResource {
|
|
|
351
354
|
this.client = client;
|
|
352
355
|
}
|
|
353
356
|
create(input) {
|
|
354
|
-
return this.client.json("POST", "/v1/templates", input, "
|
|
357
|
+
return this.client.json("POST", "/v1/templates", input, "either");
|
|
355
358
|
}
|
|
356
359
|
list() {
|
|
357
|
-
return this.client.json("GET", "/v1/templates", undefined, "
|
|
360
|
+
return this.client.json("GET", "/v1/templates", undefined, "either");
|
|
358
361
|
}
|
|
359
362
|
async uploadImage(archive, options) {
|
|
360
363
|
const response = await this.client.raw("POST", "/v1/template-images", archive, "either", "application/octet-stream", false, options?.signal);
|
|
361
364
|
return await response.json();
|
|
362
365
|
}
|
|
363
366
|
activate(id) {
|
|
364
|
-
return this.client.json("POST", `/v1/templates/${pathSegment(id)}/activate`, undefined, "
|
|
367
|
+
return this.client.json("POST", `/v1/templates/${pathSegment(id)}/activate`, undefined, "either");
|
|
365
368
|
}
|
|
366
369
|
}
|
|
367
370
|
|
|
@@ -371,13 +374,13 @@ class TemplateResourcesResource {
|
|
|
371
374
|
this.client = client;
|
|
372
375
|
}
|
|
373
376
|
get(name) {
|
|
374
|
-
return this.client.json("GET", `/v1/template-resources/${pathSegment(name)}`, undefined, "
|
|
377
|
+
return this.client.json("GET", `/v1/template-resources/${pathSegment(name)}`, undefined, "either");
|
|
375
378
|
}
|
|
376
379
|
configure(name, input) {
|
|
377
|
-
return this.client.json("PUT", `/v1/template-resources/${pathSegment(name)}`, input, "
|
|
380
|
+
return this.client.json("PUT", `/v1/template-resources/${pathSegment(name)}`, input, "either");
|
|
378
381
|
}
|
|
379
382
|
delete(name) {
|
|
380
|
-
return this.client.json("DELETE", `/v1/template-resources/${pathSegment(name)}`, undefined, "
|
|
383
|
+
return this.client.json("DELETE", `/v1/template-resources/${pathSegment(name)}`, undefined, "either");
|
|
381
384
|
}
|
|
382
385
|
}
|
|
383
386
|
|
|
@@ -387,13 +390,13 @@ class TemplateBuildsResource {
|
|
|
387
390
|
this.client = client;
|
|
388
391
|
}
|
|
389
392
|
create(input) {
|
|
390
|
-
return this.client.json("POST", "/v1/template-builds", input, "
|
|
393
|
+
return this.client.json("POST", "/v1/template-builds", input, "either");
|
|
391
394
|
}
|
|
392
395
|
get(id) {
|
|
393
|
-
return this.client.json("GET", `/v1/template-builds/${pathSegment(id)}`, undefined, "
|
|
396
|
+
return this.client.json("GET", `/v1/template-builds/${pathSegment(id)}`, undefined, "either");
|
|
394
397
|
}
|
|
395
398
|
retry(id) {
|
|
396
|
-
return this.client.json("POST", `/v1/template-builds/${pathSegment(id)}/retry`, undefined, "
|
|
399
|
+
return this.client.json("POST", `/v1/template-builds/${pathSegment(id)}/retry`, undefined, "either");
|
|
397
400
|
}
|
|
398
401
|
}
|
|
399
402
|
|
|
@@ -424,7 +427,7 @@ class FleetResource {
|
|
|
424
427
|
this.client = client;
|
|
425
428
|
}
|
|
426
429
|
list() {
|
|
427
|
-
return this.client.json("GET", "/v1/fleet", undefined, "
|
|
430
|
+
return this.client.json("GET", "/v1/fleet", undefined, "either");
|
|
428
431
|
}
|
|
429
432
|
}
|
|
430
433
|
|
|
@@ -434,16 +437,16 @@ class ReservationsResource {
|
|
|
434
437
|
this.client = client;
|
|
435
438
|
}
|
|
436
439
|
create(input) {
|
|
437
|
-
return this.client.json("POST", "/v1/capacity-reservations", input, "
|
|
440
|
+
return this.client.json("POST", "/v1/capacity-reservations", input, "either");
|
|
438
441
|
}
|
|
439
442
|
get(id) {
|
|
440
|
-
return this.client.json("GET", `/v1/capacity-reservations/${pathSegment(id)}`, undefined, "
|
|
443
|
+
return this.client.json("GET", `/v1/capacity-reservations/${pathSegment(id)}`, undefined, "either");
|
|
441
444
|
}
|
|
442
445
|
release(id) {
|
|
443
|
-
return this.client.json("DELETE", `/v1/capacity-reservations/${pathSegment(id)}`, undefined, "
|
|
446
|
+
return this.client.json("DELETE", `/v1/capacity-reservations/${pathSegment(id)}`, undefined, "either");
|
|
444
447
|
}
|
|
445
448
|
renew(id, input) {
|
|
446
|
-
return this.client.json("POST", `/v1/capacity-reservations/${pathSegment(id)}/renew`, input, "
|
|
449
|
+
return this.client.json("POST", `/v1/capacity-reservations/${pathSegment(id)}/renew`, input, "either");
|
|
447
450
|
}
|
|
448
451
|
}
|
|
449
452
|
|
|
@@ -453,34 +456,34 @@ class SandboxesResource {
|
|
|
453
456
|
this.client = client;
|
|
454
457
|
}
|
|
455
458
|
list() {
|
|
456
|
-
return this.client.json("GET", "/v1/sandboxes", undefined, "
|
|
459
|
+
return this.client.json("GET", "/v1/sandboxes", undefined, "either");
|
|
457
460
|
}
|
|
458
|
-
async create(input) {
|
|
459
|
-
return parseCreateSandboxResponse(await this.client.json("POST",
|
|
461
|
+
async create(input, options = {}) {
|
|
462
|
+
return parseCreateSandboxResponse(await this.client.json("POST", `/v1/sandboxes${waitQuery(options)}`, withTemplate(input), "either", false), input.request_id);
|
|
460
463
|
}
|
|
461
464
|
async createBatch(input) {
|
|
462
|
-
return parseSandboxBatch(await this.client.json("POST", "/v1/sandboxes", withTemplate(input), "
|
|
465
|
+
return parseSandboxBatch(await this.client.json("POST", "/v1/sandboxes", withTemplate(input), "either", false), input.request_id);
|
|
463
466
|
}
|
|
464
467
|
async batch(requestId) {
|
|
465
|
-
return parseSandboxBatch(await this.client.json("GET", `/v1/sandboxes/batches/${pathSegment(requestId)}`, undefined, "
|
|
468
|
+
return parseSandboxBatch(await this.client.json("GET", `/v1/sandboxes/batches/${pathSegment(requestId)}`, undefined, "either"), requestId);
|
|
466
469
|
}
|
|
467
|
-
async acquisition(requestId) {
|
|
468
|
-
return parseCreateSandboxResponse(await this.client.json("GET", `/v1/sandboxes/acquisitions/${pathSegment(requestId)}`, undefined, "
|
|
470
|
+
async acquisition(requestId, options = {}) {
|
|
471
|
+
return parseCreateSandboxResponse(await this.client.json("GET", `/v1/sandboxes/acquisitions/${pathSegment(requestId)}${waitQuery(options)}`, undefined, "either", options.wait_secs === undefined ? undefined : false), requestId);
|
|
469
472
|
}
|
|
470
473
|
async cancelAcquisition(requestId) {
|
|
471
|
-
return parseCreateSandboxResponse(await this.client.json("DELETE", `/v1/sandboxes/acquisitions/${pathSegment(requestId)}`, undefined, "
|
|
474
|
+
return parseCreateSandboxResponse(await this.client.json("DELETE", `/v1/sandboxes/acquisitions/${pathSegment(requestId)}`, undefined, "either"), requestId);
|
|
472
475
|
}
|
|
473
476
|
get(id) {
|
|
474
|
-
return this.client.json("GET", `/v1/sandboxes/${pathSegment(id)}`, undefined, "
|
|
477
|
+
return this.client.json("GET", `/v1/sandboxes/${pathSegment(id)}`, undefined, "either");
|
|
475
478
|
}
|
|
476
479
|
renew(id, ttl_secs) {
|
|
477
|
-
return this.client.json("POST", `/v1/sandboxes/${pathSegment(id)}/renew`, { ttl_secs }, "
|
|
480
|
+
return this.client.json("POST", `/v1/sandboxes/${pathSegment(id)}/renew`, { ttl_secs }, "either");
|
|
478
481
|
}
|
|
479
482
|
grantSshKey(id, input) {
|
|
480
|
-
return this.client.json("POST", `/v1/sandboxes/${pathSegment(id)}/ssh-keys`, input, "
|
|
483
|
+
return this.client.json("POST", `/v1/sandboxes/${pathSegment(id)}/ssh-keys`, input, "either");
|
|
481
484
|
}
|
|
482
485
|
async exec(id, input) {
|
|
483
|
-
return this.client.json("POST", `/v1/sandboxes/${pathSegment(id)}/exec`, input, "
|
|
486
|
+
return this.client.json("POST", `/v1/sandboxes/${pathSegment(id)}/exec`, input, "either", false, execDeadline(input)).then(execResult);
|
|
484
487
|
}
|
|
485
488
|
async* execStream(id, input) {
|
|
486
489
|
if (input.stdin !== undefined && input.stdin.length > MAX_EXEC_STDIN) {
|
|
@@ -496,7 +499,7 @@ class SandboxesResource {
|
|
|
496
499
|
return chunk;
|
|
497
500
|
};
|
|
498
501
|
const decoder = new TextDecoder;
|
|
499
|
-
for await (const chunk of this.client.stream("POST", `/v1/sandboxes/${pathSegment(id)}/exec/stream`, JSON.stringify(input), "
|
|
502
|
+
for await (const chunk of this.client.stream("POST", `/v1/sandboxes/${pathSegment(id)}/exec/stream`, JSON.stringify(input), "either", "application/json", true, execDeadline(input))) {
|
|
500
503
|
lineBuffer += decoder.decode(chunk, { stream: true });
|
|
501
504
|
const lines = lineBuffer.split(`
|
|
502
505
|
`);
|
|
@@ -519,10 +522,10 @@ class SandboxesResource {
|
|
|
519
522
|
return this.client.json("POST", `/v1/sandboxes/${pathSegment(id)}/processes`, {
|
|
520
523
|
...input,
|
|
521
524
|
...input.stdin === undefined ? {} : { stdin: Array.from(input.stdin) }
|
|
522
|
-
}, "
|
|
525
|
+
}, "either", false, undefined, { "idempotency-key": requestId });
|
|
523
526
|
}
|
|
524
527
|
getProcess(id, processId) {
|
|
525
|
-
return this.client.json("GET", `/v1/sandboxes/${pathSegment(id)}/processes/${pathSegment(processId)}`, undefined, "
|
|
528
|
+
return this.client.json("GET", `/v1/sandboxes/${pathSegment(id)}/processes/${pathSegment(processId)}`, undefined, "either");
|
|
526
529
|
}
|
|
527
530
|
async processLogs(id, processId, input = {}) {
|
|
528
531
|
const options = typeof input === "number" ? { stdout_offset: 0, stderr_offset: 0, max_bytes: input } : input;
|
|
@@ -534,7 +537,7 @@ class SandboxesResource {
|
|
|
534
537
|
if (options.max_bytes !== undefined)
|
|
535
538
|
query.set("max_bytes", String(options.max_bytes));
|
|
536
539
|
const suffix = query.size === 0 ? "" : `?${query.toString()}`;
|
|
537
|
-
const response = await this.client.json("GET", `/v1/sandboxes/${pathSegment(id)}/processes/${pathSegment(processId)}/logs${suffix}`, undefined, "
|
|
540
|
+
const response = await this.client.json("GET", `/v1/sandboxes/${pathSegment(id)}/processes/${pathSegment(processId)}/logs${suffix}`, undefined, "either");
|
|
538
541
|
return {
|
|
539
542
|
...response,
|
|
540
543
|
logs: {
|
|
@@ -545,13 +548,13 @@ class SandboxesResource {
|
|
|
545
548
|
};
|
|
546
549
|
}
|
|
547
550
|
cancelProcess(id, processId) {
|
|
548
|
-
return this.client.json("DELETE", `/v1/sandboxes/${pathSegment(id)}/processes/${pathSegment(processId)}`, undefined, "
|
|
551
|
+
return this.client.json("DELETE", `/v1/sandboxes/${pathSegment(id)}/processes/${pathSegment(processId)}`, undefined, "either");
|
|
549
552
|
}
|
|
550
553
|
prepare(id, input, idempotencyKey) {
|
|
551
|
-
return this.client.json("POST", `/v1/sandboxes/${pathSegment(id)}/prepare`, input, "
|
|
554
|
+
return this.client.json("POST", `/v1/sandboxes/${pathSegment(id)}/prepare`, input, "either", undefined, undefined, { "idempotency-key": idempotencyKey });
|
|
552
555
|
}
|
|
553
556
|
logs(id) {
|
|
554
|
-
return this.client.stream("GET", `/v1/sandboxes/${pathSegment(id)}/logs`, undefined, "
|
|
557
|
+
return this.client.stream("GET", `/v1/sandboxes/${pathSegment(id)}/logs`, undefined, "either", undefined, true);
|
|
555
558
|
}
|
|
556
559
|
async readFileChunk(id, input) {
|
|
557
560
|
if (input.offset < 0 || input.length <= 0 || input.length > MAX_FILE_READ_CHUNK) {
|
|
@@ -562,7 +565,7 @@ class SandboxesResource {
|
|
|
562
565
|
offset: String(input.offset),
|
|
563
566
|
length: String(input.length)
|
|
564
567
|
});
|
|
565
|
-
const response = await this.client.raw("GET", `/v1/sandboxes/${pathSegment(id)}/files/read?${query.toString()}`, undefined, "
|
|
568
|
+
const response = await this.client.raw("GET", `/v1/sandboxes/${pathSegment(id)}/files/read?${query.toString()}`, undefined, "either");
|
|
566
569
|
const data = new Uint8Array(await response.arrayBuffer());
|
|
567
570
|
const offset = Number(response.headers.get("x-blackcat-offset") ?? input.offset);
|
|
568
571
|
const eof = response.headers.get("x-blackcat-eof") === "true";
|
|
@@ -613,7 +616,7 @@ class SandboxesResource {
|
|
|
613
616
|
offset: String(input.offset),
|
|
614
617
|
truncate: String(input.truncate)
|
|
615
618
|
});
|
|
616
|
-
await this.client.raw("POST", `/v1/sandboxes/${pathSegment(id)}/files/write?${query.toString()}`, requestBody(input.data), "
|
|
619
|
+
await this.client.raw("POST", `/v1/sandboxes/${pathSegment(id)}/files/write?${query.toString()}`, requestBody(input.data), "either", "application/octet-stream");
|
|
617
620
|
}
|
|
618
621
|
async writeFileStream(id, input) {
|
|
619
622
|
const start = input.offset ?? 0;
|
|
@@ -658,28 +661,28 @@ class SandboxesResource {
|
|
|
658
661
|
});
|
|
659
662
|
}
|
|
660
663
|
snapshot(id) {
|
|
661
|
-
return this.client.json("POST", `/v1/sandboxes/${pathSegment(id)}/snapshot`, undefined, "
|
|
664
|
+
return this.client.json("POST", `/v1/sandboxes/${pathSegment(id)}/snapshot`, undefined, "either");
|
|
662
665
|
}
|
|
663
666
|
pause(id) {
|
|
664
|
-
return this.client.raw("POST", `/v1/sandboxes/${pathSegment(id)}/pause`, undefined, "
|
|
667
|
+
return this.client.raw("POST", `/v1/sandboxes/${pathSegment(id)}/pause`, undefined, "either").then(() => {
|
|
665
668
|
return;
|
|
666
669
|
});
|
|
667
670
|
}
|
|
668
671
|
hibernate(id, input) {
|
|
669
|
-
return this.client.raw("POST", `/v1/sandboxes/${pathSegment(id)}/hibernate`, input === undefined ? undefined : JSON.stringify(input), "
|
|
672
|
+
return this.client.raw("POST", `/v1/sandboxes/${pathSegment(id)}/hibernate`, input === undefined ? undefined : JSON.stringify(input), "either", input === undefined ? undefined : "application/json", false).then(() => {
|
|
670
673
|
return;
|
|
671
674
|
});
|
|
672
675
|
}
|
|
673
676
|
resize(id, input) {
|
|
674
|
-
return this.client.json("POST", `/v1/sandboxes/${pathSegment(id)}/resize`, { ...input, request_id: input.request_id ?? `resize-${crypto.randomUUID()}` }, "
|
|
677
|
+
return this.client.json("POST", `/v1/sandboxes/${pathSegment(id)}/resize`, { ...input, request_id: input.request_id ?? `resize-${crypto.randomUUID()}` }, "either", false);
|
|
675
678
|
}
|
|
676
679
|
resume(id) {
|
|
677
|
-
return this.client.raw("POST", `/v1/sandboxes/${pathSegment(id)}/resume`, undefined, "
|
|
680
|
+
return this.client.raw("POST", `/v1/sandboxes/${pathSegment(id)}/resume`, undefined, "either").then(() => {
|
|
678
681
|
return;
|
|
679
682
|
});
|
|
680
683
|
}
|
|
681
684
|
destroy(id) {
|
|
682
|
-
return this.client.json("DELETE", `/v1/sandboxes/${pathSegment(id)}`, undefined, "
|
|
685
|
+
return this.client.json("DELETE", `/v1/sandboxes/${pathSegment(id)}`, undefined, "either");
|
|
683
686
|
}
|
|
684
687
|
}
|
|
685
688
|
|