@boatdev/sdk 1.9.7 → 1.9.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/.openapi-generator/FILES +4 -0
- package/README.md +2 -2
- package/dist/apis/BoatApi.d.ts +2 -2
- package/dist/apis/BoatApi.js +2 -2
- package/dist/boat-helpers.d.ts +23 -0
- package/dist/boat-helpers.js +97 -0
- package/dist/esm/apis/BoatApi.d.ts +2 -2
- package/dist/esm/apis/BoatApi.js +2 -2
- package/dist/esm/boat-helpers.d.ts +23 -0
- package/dist/esm/boat-helpers.js +95 -0
- package/dist/esm/models/CredentialProfile.d.ts +1 -1
- package/dist/esm/models/DeletionOperation.d.ts +1 -3
- package/dist/esm/models/DeletionOperation.js +0 -2
- package/dist/esm/models/LimitsFields.d.ts +7 -0
- package/dist/esm/models/LimitsFields.js +3 -0
- package/dist/esm/models/LimitsFieldsMachineTypesInner.d.ts +54 -0
- package/dist/esm/models/LimitsFieldsMachineTypesInner.js +60 -0
- package/dist/esm/models/LimitsResponse.d.ts +7 -0
- package/dist/esm/models/LimitsResponse.js +3 -0
- package/dist/esm/models/Sandbox.d.ts +15 -2
- package/dist/esm/models/Sandbox.js +5 -0
- package/dist/esm/models/SandboxHydration.d.ts +50 -0
- package/dist/esm/models/SandboxHydration.js +55 -0
- package/dist/esm/models/index.d.ts +2 -0
- package/dist/esm/models/index.js +2 -0
- package/dist/models/CredentialProfile.d.ts +1 -1
- package/dist/models/DeletionOperation.d.ts +1 -3
- package/dist/models/DeletionOperation.js +0 -2
- package/dist/models/LimitsFields.d.ts +7 -0
- package/dist/models/LimitsFields.js +3 -0
- package/dist/models/LimitsFieldsMachineTypesInner.d.ts +54 -0
- package/dist/models/LimitsFieldsMachineTypesInner.js +68 -0
- package/dist/models/LimitsResponse.d.ts +7 -0
- package/dist/models/LimitsResponse.js +3 -0
- package/dist/models/Sandbox.d.ts +15 -2
- package/dist/models/Sandbox.js +5 -0
- package/dist/models/SandboxHydration.d.ts +50 -0
- package/dist/models/SandboxHydration.js +62 -0
- package/dist/models/index.d.ts +2 -0
- package/dist/models/index.js +2 -0
- package/docs/BoatApi.md +1 -1
- package/docs/LimitsFields.md +2 -0
- package/docs/LimitsFieldsMachineTypesInner.md +36 -0
- package/docs/LimitsResponse.md +2 -0
- package/docs/Sandbox.md +4 -0
- package/docs/SandboxHydration.md +39 -0
- package/package.json +2 -2
- package/src/apis/BoatApi.ts +2 -2
- package/src/boat-helpers.ts +109 -0
- package/src/models/CredentialProfile.ts +1 -1
- package/src/models/DeletionOperation.ts +1 -3
- package/src/models/LimitsFields.ts +15 -0
- package/src/models/LimitsFieldsMachineTypesInner.ts +97 -0
- package/src/models/LimitsResponse.ts +15 -0
- package/src/models/Sandbox.ts +25 -2
- package/src/models/SandboxHydration.ts +93 -0
- package/src/models/index.ts +2 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* tslint:disable */
|
|
3
|
+
/* eslint-disable */
|
|
4
|
+
/**
|
|
5
|
+
* Boat Public API v1
|
|
6
|
+
* Public JSON API for creating, operating, prompting, observing, and exposing sandboxes from backend services, CI jobs, hosted workers, and Boat automation products. The v1 reference intentionally documents the developer integration surface only. Dashboard billing actions are not part of v1.
|
|
7
|
+
*
|
|
8
|
+
* The version of the OpenAPI document: 1.0.0
|
|
9
|
+
*
|
|
10
|
+
*
|
|
11
|
+
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
12
|
+
* https://openapi-generator.tech
|
|
13
|
+
* Do not edit the class manually.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.instanceOfSandboxHydration = instanceOfSandboxHydration;
|
|
17
|
+
exports.SandboxHydrationFromJSON = SandboxHydrationFromJSON;
|
|
18
|
+
exports.SandboxHydrationFromJSONTyped = SandboxHydrationFromJSONTyped;
|
|
19
|
+
exports.SandboxHydrationToJSON = SandboxHydrationToJSON;
|
|
20
|
+
exports.SandboxHydrationToJSONTyped = SandboxHydrationToJSONTyped;
|
|
21
|
+
/**
|
|
22
|
+
* Check if a given object implements the SandboxHydration interface.
|
|
23
|
+
*/
|
|
24
|
+
function instanceOfSandboxHydration(value) {
|
|
25
|
+
if (!('phase' in value) || value['phase'] === undefined)
|
|
26
|
+
return false;
|
|
27
|
+
if (!('entriesDone' in value) || value['entriesDone'] === undefined)
|
|
28
|
+
return false;
|
|
29
|
+
if (!('entriesTotal' in value) || value['entriesTotal'] === undefined)
|
|
30
|
+
return false;
|
|
31
|
+
if (!('percent' in value) || value['percent'] === undefined)
|
|
32
|
+
return false;
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
function SandboxHydrationFromJSON(json) {
|
|
36
|
+
return SandboxHydrationFromJSONTyped(json, false);
|
|
37
|
+
}
|
|
38
|
+
function SandboxHydrationFromJSONTyped(json, ignoreDiscriminator) {
|
|
39
|
+
if (json == null) {
|
|
40
|
+
return json;
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
'phase': json['phase'],
|
|
44
|
+
'entriesDone': json['entriesDone'],
|
|
45
|
+
'entriesTotal': json['entriesTotal'],
|
|
46
|
+
'percent': json['percent'],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function SandboxHydrationToJSON(json) {
|
|
50
|
+
return SandboxHydrationToJSONTyped(json, false);
|
|
51
|
+
}
|
|
52
|
+
function SandboxHydrationToJSONTyped(value, ignoreDiscriminator = false) {
|
|
53
|
+
if (value == null) {
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
'phase': value['phase'],
|
|
58
|
+
'entriesDone': value['entriesDone'],
|
|
59
|
+
'entriesTotal': value['entriesTotal'],
|
|
60
|
+
'percent': value['percent'],
|
|
61
|
+
};
|
|
62
|
+
}
|
package/dist/models/index.d.ts
CHANGED
|
@@ -72,6 +72,7 @@ export * from './HostPortResponse';
|
|
|
72
72
|
export * from './LimitsFields';
|
|
73
73
|
export * from './LimitsFieldsCurrentLimits';
|
|
74
74
|
export * from './LimitsFieldsGiftLimit';
|
|
75
|
+
export * from './LimitsFieldsMachineTypesInner';
|
|
75
76
|
export * from './LimitsFieldsSandboxPlanTiersInner';
|
|
76
77
|
export * from './LimitsFieldsStartLimits';
|
|
77
78
|
export * from './LimitsFieldsStarts';
|
|
@@ -121,6 +122,7 @@ export * from './SandboxEnvironmentListResponse';
|
|
|
121
122
|
export * from './SandboxEnvironmentResponse';
|
|
122
123
|
export * from './SandboxEnvironmentVersionSummary';
|
|
123
124
|
export * from './SandboxEvent';
|
|
125
|
+
export * from './SandboxHydration';
|
|
124
126
|
export * from './SandboxInfoResponse';
|
|
125
127
|
export * from './SandboxListResponse';
|
|
126
128
|
export * from './SandboxProcess';
|
package/dist/models/index.js
CHANGED
|
@@ -90,6 +90,7 @@ __exportStar(require("./HostPortResponse"), exports);
|
|
|
90
90
|
__exportStar(require("./LimitsFields"), exports);
|
|
91
91
|
__exportStar(require("./LimitsFieldsCurrentLimits"), exports);
|
|
92
92
|
__exportStar(require("./LimitsFieldsGiftLimit"), exports);
|
|
93
|
+
__exportStar(require("./LimitsFieldsMachineTypesInner"), exports);
|
|
93
94
|
__exportStar(require("./LimitsFieldsSandboxPlanTiersInner"), exports);
|
|
94
95
|
__exportStar(require("./LimitsFieldsStartLimits"), exports);
|
|
95
96
|
__exportStar(require("./LimitsFieldsStarts"), exports);
|
|
@@ -139,6 +140,7 @@ __exportStar(require("./SandboxEnvironmentListResponse"), exports);
|
|
|
139
140
|
__exportStar(require("./SandboxEnvironmentResponse"), exports);
|
|
140
141
|
__exportStar(require("./SandboxEnvironmentVersionSummary"), exports);
|
|
141
142
|
__exportStar(require("./SandboxEvent"), exports);
|
|
143
|
+
__exportStar(require("./SandboxHydration"), exports);
|
|
142
144
|
__exportStar(require("./SandboxInfoResponse"), exports);
|
|
143
145
|
__exportStar(require("./SandboxListResponse"), exports);
|
|
144
146
|
__exportStar(require("./SandboxProcess"), exports);
|
package/docs/BoatApi.md
CHANGED
|
@@ -4331,7 +4331,7 @@ example().catch(console.error);
|
|
|
4331
4331
|
|
|
4332
4332
|
List the accounts of a credential
|
|
4333
4333
|
|
|
4334
|
-
Every account of one credential (several ChatGPT sign-ins, several OpenAI keys), in the order they were added, the one in use marked. Labels only, never a secret. Needs an API key with `account.admin`.
|
|
4334
|
+
Every account of one credential (several ChatGPT sign-ins, several OpenAI keys), in the order they were added, the one in use marked. Labels only, never a secret. Needs an API key with `account.admin`, on a profile you manage: an org member who only uses an org profile gets `403`.
|
|
4335
4335
|
|
|
4336
4336
|
### Example
|
|
4337
4337
|
|
package/docs/LimitsFields.md
CHANGED
|
@@ -47,6 +47,7 @@ Name | Type
|
|
|
47
47
|
`last24hUsageSeconds` | number
|
|
48
48
|
`trialComputeCapSeconds` | number
|
|
49
49
|
`trialLine` | string
|
|
50
|
+
`machineTypes` | [Array<LimitsFieldsMachineTypesInner>](LimitsFieldsMachineTypesInner.md)
|
|
50
51
|
`giftLimit` | [LimitsFieldsGiftLimit](LimitsFieldsGiftLimit.md)
|
|
51
52
|
`billingStatus` | string
|
|
52
53
|
`subscriptionStatus` | string
|
|
@@ -106,6 +107,7 @@ const example = {
|
|
|
106
107
|
"last24hUsageSeconds": null,
|
|
107
108
|
"trialComputeCapSeconds": null,
|
|
108
109
|
"trialLine": null,
|
|
110
|
+
"machineTypes": null,
|
|
109
111
|
"giftLimit": null,
|
|
110
112
|
"billingStatus": null,
|
|
111
113
|
"subscriptionStatus": null,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
# LimitsFieldsMachineTypesInner
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
## Properties
|
|
6
|
+
|
|
7
|
+
Name | Type
|
|
8
|
+
------------ | -------------
|
|
9
|
+
`type` | string
|
|
10
|
+
`available` | boolean
|
|
11
|
+
`reason` | string
|
|
12
|
+
|
|
13
|
+
## Example
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import type { LimitsFieldsMachineTypesInner } from '@boatdev/sdk'
|
|
17
|
+
|
|
18
|
+
// TODO: Update the object below with actual values
|
|
19
|
+
const example = {
|
|
20
|
+
"type": null,
|
|
21
|
+
"available": null,
|
|
22
|
+
"reason": null,
|
|
23
|
+
} satisfies LimitsFieldsMachineTypesInner
|
|
24
|
+
|
|
25
|
+
console.log(example)
|
|
26
|
+
|
|
27
|
+
// Convert the instance to a JSON string
|
|
28
|
+
const exampleJSON: string = JSON.stringify(example)
|
|
29
|
+
console.log(exampleJSON)
|
|
30
|
+
|
|
31
|
+
// Parse the JSON string back to an object
|
|
32
|
+
const exampleParsed = JSON.parse(exampleJSON) as LimitsFieldsMachineTypesInner
|
|
33
|
+
console.log(exampleParsed)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
|
package/docs/LimitsResponse.md
CHANGED
|
@@ -49,6 +49,7 @@ Name | Type
|
|
|
49
49
|
`last24hUsageSeconds` | number
|
|
50
50
|
`trialComputeCapSeconds` | number
|
|
51
51
|
`trialLine` | string
|
|
52
|
+
`machineTypes` | [Array<LimitsFieldsMachineTypesInner>](LimitsFieldsMachineTypesInner.md)
|
|
52
53
|
`giftLimit` | [LimitsFieldsGiftLimit](LimitsFieldsGiftLimit.md)
|
|
53
54
|
`billingStatus` | string
|
|
54
55
|
`subscriptionStatus` | string
|
|
@@ -110,6 +111,7 @@ const example = {
|
|
|
110
111
|
"last24hUsageSeconds": null,
|
|
111
112
|
"trialComputeCapSeconds": null,
|
|
112
113
|
"trialLine": null,
|
|
114
|
+
"machineTypes": null,
|
|
113
115
|
"giftLimit": null,
|
|
114
116
|
"billingStatus": null,
|
|
115
117
|
"subscriptionStatus": null,
|
package/docs/Sandbox.md
CHANGED
|
@@ -15,6 +15,7 @@ Name | Type
|
|
|
15
15
|
`degradedSince` | Date
|
|
16
16
|
`hydrated` | boolean
|
|
17
17
|
`hydratedAt` | Date
|
|
18
|
+
`hydration` | [SandboxHydration](SandboxHydration.md)
|
|
18
19
|
`type` | string
|
|
19
20
|
`vcpu` | number
|
|
20
21
|
`memoryGB` | number
|
|
@@ -26,6 +27,7 @@ Name | Type
|
|
|
26
27
|
`createdAt` | Date
|
|
27
28
|
`updatedAt` | Date
|
|
28
29
|
`archiveAfter` | Date
|
|
30
|
+
`ttlSeconds` | number
|
|
29
31
|
`desktopAvailable` | boolean
|
|
30
32
|
`desktopUrl` | string
|
|
31
33
|
`snapshots` | boolean
|
|
@@ -64,6 +66,7 @@ const example = {
|
|
|
64
66
|
"degradedSince": null,
|
|
65
67
|
"hydrated": null,
|
|
66
68
|
"hydratedAt": null,
|
|
69
|
+
"hydration": null,
|
|
67
70
|
"type": null,
|
|
68
71
|
"vcpu": null,
|
|
69
72
|
"memoryGB": null,
|
|
@@ -75,6 +78,7 @@ const example = {
|
|
|
75
78
|
"createdAt": null,
|
|
76
79
|
"updatedAt": null,
|
|
77
80
|
"archiveAfter": null,
|
|
81
|
+
"ttlSeconds": null,
|
|
78
82
|
"desktopAvailable": null,
|
|
79
83
|
"desktopUrl": null,
|
|
80
84
|
"snapshots": null,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
|
|
2
|
+
# SandboxHydration
|
|
3
|
+
|
|
4
|
+
Restore progress while `hydrated` is false, on GET /sandboxes/{id} only. Null in lists, after hydration, or when the sandbox does not answer within 1.5 s.
|
|
5
|
+
|
|
6
|
+
## Properties
|
|
7
|
+
|
|
8
|
+
Name | Type
|
|
9
|
+
------------ | -------------
|
|
10
|
+
`phase` | string
|
|
11
|
+
`entriesDone` | number
|
|
12
|
+
`entriesTotal` | number
|
|
13
|
+
`percent` | number
|
|
14
|
+
|
|
15
|
+
## Example
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import type { SandboxHydration } from '@boatdev/sdk'
|
|
19
|
+
|
|
20
|
+
// TODO: Update the object below with actual values
|
|
21
|
+
const example = {
|
|
22
|
+
"phase": null,
|
|
23
|
+
"entriesDone": null,
|
|
24
|
+
"entriesTotal": null,
|
|
25
|
+
"percent": null,
|
|
26
|
+
} satisfies SandboxHydration
|
|
27
|
+
|
|
28
|
+
console.log(example)
|
|
29
|
+
|
|
30
|
+
// Convert the instance to a JSON string
|
|
31
|
+
const exampleJSON: string = JSON.stringify(example)
|
|
32
|
+
console.log(exampleJSON)
|
|
33
|
+
|
|
34
|
+
// Parse the JSON string back to an object
|
|
35
|
+
const exampleParsed = JSON.parse(exampleJSON) as SandboxHydration
|
|
36
|
+
console.log(exampleParsed)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@boatdev/sdk",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.8",
|
|
4
4
|
"description": "OpenAPI client for @boatdev/sdk",
|
|
5
5
|
"author": "OpenAPI-Generator",
|
|
6
6
|
"license": "MIT",
|
|
@@ -15,5 +15,5 @@
|
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"typescript": "7.0.2"
|
|
17
17
|
},
|
|
18
|
-
"homepage": "https://docs.boat.dev/sdks"
|
|
18
|
+
"homepage": "https://docs.boat.dev/sdks/overview"
|
|
19
19
|
}
|
package/src/apis/BoatApi.ts
CHANGED
|
@@ -4453,7 +4453,7 @@ export class BoatApi extends runtime.BaseAPI {
|
|
|
4453
4453
|
}
|
|
4454
4454
|
|
|
4455
4455
|
/**
|
|
4456
|
-
* Every account of one credential (several ChatGPT sign-ins, several OpenAI keys), in the order they were added, the one in use marked. Labels only, never a secret. Needs an API key with `account.admin`.
|
|
4456
|
+
* Every account of one credential (several ChatGPT sign-ins, several OpenAI keys), in the order they were added, the one in use marked. Labels only, never a secret. Needs an API key with `account.admin`, on a profile you manage: an org member who only uses an org profile gets `403`.
|
|
4457
4457
|
* List the accounts of a credential
|
|
4458
4458
|
*/
|
|
4459
4459
|
async listCredentialAccountsRaw(requestParameters: ListCredentialAccountsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<CredentialAccountsResponse>> {
|
|
@@ -4464,7 +4464,7 @@ export class BoatApi extends runtime.BaseAPI {
|
|
|
4464
4464
|
}
|
|
4465
4465
|
|
|
4466
4466
|
/**
|
|
4467
|
-
* Every account of one credential (several ChatGPT sign-ins, several OpenAI keys), in the order they were added, the one in use marked. Labels only, never a secret. Needs an API key with `account.admin`.
|
|
4467
|
+
* Every account of one credential (several ChatGPT sign-ins, several OpenAI keys), in the order they were added, the one in use marked. Labels only, never a secret. Needs an API key with `account.admin`, on a profile you manage: an org member who only uses an org profile gets `403`.
|
|
4468
4468
|
* List the accounts of a credential
|
|
4469
4469
|
*/
|
|
4470
4470
|
async listCredentialAccounts(requestParameters: ListCredentialAccountsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<CredentialAccountsResponse> {
|
package/src/boat-helpers.ts
CHANGED
|
@@ -281,3 +281,112 @@ export async function* streamCommand(
|
|
|
281
281
|
await delay(1_000);
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
|
+
|
|
285
|
+
// The server sends a heartbeat every 15 s, so 60 s of silence is a dead connection.
|
|
286
|
+
const ATTACH_IDLE_MS = 60_000;
|
|
287
|
+
// After the first connection, a failed reconnect is tried again for this long.
|
|
288
|
+
const ATTACH_RETRY_MS = 60_000;
|
|
289
|
+
|
|
290
|
+
export type FollowCommandOptions = {
|
|
291
|
+
signal?: AbortSignal;
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
function isNetworkError(e: unknown, signal?: AbortSignal): boolean {
|
|
295
|
+
if (signal?.aborted || e instanceof SyntaxError) return false;
|
|
296
|
+
return !(e as { response?: Response })?.response;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Yield a detached command's output from its start until it ends: `stdout`/`stderr`
|
|
301
|
+
* chunks (`frame.data`), then exactly one `exit` (`exitCode`, ...) or `error`
|
|
302
|
+
* (`message`). The server ends each connection after 10 minutes; this reconnects
|
|
303
|
+
* from the same offsets, with no gap and no repeat. A network cut is reconnected
|
|
304
|
+
* the same way for up to 60 s.
|
|
305
|
+
*/
|
|
306
|
+
export async function* followCommand(
|
|
307
|
+
api: BoatApi,
|
|
308
|
+
sandboxId: string,
|
|
309
|
+
processId: number,
|
|
310
|
+
options?: FollowCommandOptions,
|
|
311
|
+
): AsyncGenerator<CommandFrame> {
|
|
312
|
+
const offsets = { stdout: 0, stderr: 0 };
|
|
313
|
+
let connected = false;
|
|
314
|
+
// Set at the first failure after a good connection; any good connection clears it.
|
|
315
|
+
let failingSince: number | undefined;
|
|
316
|
+
for (;;) {
|
|
317
|
+
if (options?.signal?.aborted) throw options.signal.reason ?? new Error('followCommand aborted');
|
|
318
|
+
// One controller per connection: the caller's signal, or 60 s with no line.
|
|
319
|
+
const connection = new AbortController();
|
|
320
|
+
const abort = () => connection.abort();
|
|
321
|
+
options?.signal?.addEventListener('abort', abort);
|
|
322
|
+
let idle: ReturnType<typeof setTimeout> | undefined;
|
|
323
|
+
const touch = () => {
|
|
324
|
+
clearTimeout(idle);
|
|
325
|
+
idle = setTimeout(abort, ATTACH_IDLE_MS);
|
|
326
|
+
};
|
|
327
|
+
try {
|
|
328
|
+
touch();
|
|
329
|
+
const response = await api.attachCommandRaw(
|
|
330
|
+
{ sandboxId, processId, stdoutOffset: offsets.stdout, stderrOffset: offsets.stderr },
|
|
331
|
+
{ signal: connection.signal },
|
|
332
|
+
);
|
|
333
|
+
connected = true;
|
|
334
|
+
failingSince = undefined;
|
|
335
|
+
for await (const frame of ndjsonFrames(response.raw)) {
|
|
336
|
+
touch();
|
|
337
|
+
if (frame.type === 'stdout' || frame.type === 'stderr') {
|
|
338
|
+
offsets[frame.type] = (frame.nextOffset as number | undefined) ?? offsets[frame.type];
|
|
339
|
+
yield frame;
|
|
340
|
+
} else if (frame.type === 'exit' || frame.type === 'error') {
|
|
341
|
+
yield frame;
|
|
342
|
+
return;
|
|
343
|
+
} else {
|
|
344
|
+
// attached, heartbeat, reconnect: ours to handle, never the caller's.
|
|
345
|
+
offsets.stdout = (frame.stdoutOffset as number | undefined) ?? offsets.stdout;
|
|
346
|
+
offsets.stderr = (frame.stderrOffset as number | undefined) ?? offsets.stderr;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
} catch (e) {
|
|
350
|
+
failingSince ??= Date.now();
|
|
351
|
+
if (!isNetworkError(e, options?.signal) || !connected || Date.now() - failingSince >= ATTACH_RETRY_MS) throw e;
|
|
352
|
+
await delay(1_000);
|
|
353
|
+
} finally {
|
|
354
|
+
clearTimeout(idle);
|
|
355
|
+
options?.signal?.removeEventListener('abort', abort);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
export type RunCommandOptions = FollowCommandOptions & {
|
|
361
|
+
cwd?: string;
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Run a command with no time limit and yield its output until it ends.
|
|
366
|
+
*
|
|
367
|
+
* The command runs detached, so it has no 600 s cap and survives a dropped
|
|
368
|
+
* connection. Frames: `{ type: 'started', processId }`, then the frames of
|
|
369
|
+
* `followCommand`. Stopping early leaves the command running: call
|
|
370
|
+
* `stopCommand({ sandboxId, processId })` to stop it.
|
|
371
|
+
*/
|
|
372
|
+
export async function* runCommand(
|
|
373
|
+
api: BoatApi,
|
|
374
|
+
sandboxId: string,
|
|
375
|
+
command: string,
|
|
376
|
+
options?: RunCommandOptions,
|
|
377
|
+
): AsyncGenerator<CommandFrame> {
|
|
378
|
+
const deadline = Date.now() + STREAM_RETRY_MS;
|
|
379
|
+
let processId: number;
|
|
380
|
+
for (;;) {
|
|
381
|
+
try {
|
|
382
|
+
const started = await api.command({ sandboxId, commandRequest: { command, cwd: options?.cwd, detached: true } });
|
|
383
|
+
processId = (started as { processId: number }).processId;
|
|
384
|
+
break;
|
|
385
|
+
} catch (e) {
|
|
386
|
+
if (Date.now() + 1_000 >= deadline || !(await isRetryable(e))) throw e;
|
|
387
|
+
}
|
|
388
|
+
await delay(1_000);
|
|
389
|
+
}
|
|
390
|
+
yield { type: 'started', processId } as CommandFrame;
|
|
391
|
+
yield* followCommand(api, sandboxId, processId, options);
|
|
392
|
+
}
|
|
@@ -78,7 +78,7 @@ export interface CredentialProfile {
|
|
|
78
78
|
*/
|
|
79
79
|
connected: Array<CredentialId>;
|
|
80
80
|
/**
|
|
81
|
-
* Credentials with several accounts, keyed by credential id. Each lists every account (labels only), the one in use marked `active`.
|
|
81
|
+
* Credentials with several accounts, keyed by credential id. Each lists every account (labels only), the one in use marked `active`. Empty when you cannot manage the profile.
|
|
82
82
|
* @type {{ [key: string]: Array<CredentialAccount>; }}
|
|
83
83
|
* @memberof CredentialProfile
|
|
84
84
|
*/
|
|
@@ -50,7 +50,7 @@ export interface DeletionOperation {
|
|
|
50
50
|
*/
|
|
51
51
|
status: DeletionOperationStatusEnum;
|
|
52
52
|
/**
|
|
53
|
-
* What the background purge is doing. The target is already gone from every list, restore and fork once the operation exists. `waiting_for_uploads`: stored data is erased once the last upload URL issued for it expires (`expectedBy`). `
|
|
53
|
+
* What the background purge is doing. The target is already gone from every list, restore and fork once the operation exists. `waiting_for_uploads`: stored data is erased once the last upload URL issued for it expires (`expectedBy`). `retrying`: a transient fault, retried automatically. `completed`: a newer snapshot, a fork or a named snapshot made from it keeps the data it reads, until that is deleted too.
|
|
54
54
|
* @type {DeletionOperationStageEnum}
|
|
55
55
|
* @memberof DeletionOperation
|
|
56
56
|
*/
|
|
@@ -118,8 +118,6 @@ export type DeletionOperationStatusEnum = typeof DeletionOperationStatusEnum[key
|
|
|
118
118
|
export const DeletionOperationStageEnum = {
|
|
119
119
|
Removing: 'removing',
|
|
120
120
|
WaitingForUploads: 'waiting_for_uploads',
|
|
121
|
-
KeptForNewerSnapshots: 'kept_for_newer_snapshots',
|
|
122
|
-
WaitingForRestore: 'waiting_for_restore',
|
|
123
121
|
Retrying: 'retrying',
|
|
124
122
|
Completed: 'completed'
|
|
125
123
|
} as const;
|
|
@@ -27,6 +27,13 @@ import {
|
|
|
27
27
|
LimitsFieldsCurrentLimitsToJSON,
|
|
28
28
|
LimitsFieldsCurrentLimitsToJSONTyped,
|
|
29
29
|
} from './LimitsFieldsCurrentLimits';
|
|
30
|
+
import type { LimitsFieldsMachineTypesInner } from './LimitsFieldsMachineTypesInner';
|
|
31
|
+
import {
|
|
32
|
+
LimitsFieldsMachineTypesInnerFromJSON,
|
|
33
|
+
LimitsFieldsMachineTypesInnerFromJSONTyped,
|
|
34
|
+
LimitsFieldsMachineTypesInnerToJSON,
|
|
35
|
+
LimitsFieldsMachineTypesInnerToJSONTyped,
|
|
36
|
+
} from './LimitsFieldsMachineTypesInner';
|
|
30
37
|
import type { LimitsFieldsStartLimits } from './LimitsFieldsStartLimits';
|
|
31
38
|
import {
|
|
32
39
|
LimitsFieldsStartLimitsFromJSON,
|
|
@@ -302,6 +309,12 @@ export interface LimitsFields {
|
|
|
302
309
|
* @memberof LimitsFields
|
|
303
310
|
*/
|
|
304
311
|
trialLine?: string | null;
|
|
312
|
+
/**
|
|
313
|
+
* Each sandbox type, and whether this account can create it now. A blocked type carries the reason.
|
|
314
|
+
* @type {Array<LimitsFieldsMachineTypesInner>}
|
|
315
|
+
* @memberof LimitsFields
|
|
316
|
+
*/
|
|
317
|
+
machineTypes?: Array<LimitsFieldsMachineTypesInner>;
|
|
305
318
|
/**
|
|
306
319
|
*
|
|
307
320
|
* @type {LimitsFieldsGiftLimit}
|
|
@@ -427,6 +440,7 @@ export function LimitsFieldsFromJSONTyped(json: any, ignoreDiscriminator: boolea
|
|
|
427
440
|
'last24hUsageSeconds': json['last24hUsageSeconds'] == null ? undefined : json['last24hUsageSeconds'],
|
|
428
441
|
'trialComputeCapSeconds': json['trialComputeCapSeconds'] == null ? undefined : json['trialComputeCapSeconds'],
|
|
429
442
|
'trialLine': json['trialLine'] == null ? undefined : json['trialLine'],
|
|
443
|
+
'machineTypes': json['machineTypes'] == null ? undefined : ((json['machineTypes'] as Array<any>).map(LimitsFieldsMachineTypesInnerFromJSON)),
|
|
430
444
|
'giftLimit': json['giftLimit'] == null ? undefined : LimitsFieldsGiftLimitFromJSON(json['giftLimit']),
|
|
431
445
|
'billingStatus': json['billingStatus'],
|
|
432
446
|
'subscriptionStatus': json['subscriptionStatus'] == null ? undefined : json['subscriptionStatus'],
|
|
@@ -493,6 +507,7 @@ export function LimitsFieldsToJSONTyped(value?: LimitsFields | null, ignoreDiscr
|
|
|
493
507
|
'last24hUsageSeconds': value['last24hUsageSeconds'],
|
|
494
508
|
'trialComputeCapSeconds': value['trialComputeCapSeconds'],
|
|
495
509
|
'trialLine': value['trialLine'],
|
|
510
|
+
'machineTypes': value['machineTypes'] == null ? undefined : ((value['machineTypes'] as Array<any>).map(LimitsFieldsMachineTypesInnerToJSON)),
|
|
496
511
|
'giftLimit': LimitsFieldsGiftLimitToJSON(value['giftLimit']),
|
|
497
512
|
'billingStatus': value['billingStatus'],
|
|
498
513
|
'subscriptionStatus': value['subscriptionStatus'],
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
/**
|
|
4
|
+
* Boat Public API v1
|
|
5
|
+
* Public JSON API for creating, operating, prompting, observing, and exposing sandboxes from backend services, CI jobs, hosted workers, and Boat automation products. The v1 reference intentionally documents the developer integration surface only. Dashboard billing actions are not part of v1.
|
|
6
|
+
*
|
|
7
|
+
* The version of the OpenAPI document: 1.0.0
|
|
8
|
+
*
|
|
9
|
+
*
|
|
10
|
+
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
11
|
+
* https://openapi-generator.tech
|
|
12
|
+
* Do not edit the class manually.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { mapValues } from '../runtime';
|
|
16
|
+
/**
|
|
17
|
+
*
|
|
18
|
+
* @export
|
|
19
|
+
* @interface LimitsFieldsMachineTypesInner
|
|
20
|
+
*/
|
|
21
|
+
export interface LimitsFieldsMachineTypesInner {
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @type {LimitsFieldsMachineTypesInnerTypeEnum}
|
|
25
|
+
* @memberof LimitsFieldsMachineTypesInner
|
|
26
|
+
*/
|
|
27
|
+
type: LimitsFieldsMachineTypesInnerTypeEnum;
|
|
28
|
+
/**
|
|
29
|
+
*
|
|
30
|
+
* @type {boolean}
|
|
31
|
+
* @memberof LimitsFieldsMachineTypesInner
|
|
32
|
+
*/
|
|
33
|
+
available: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Why the type is blocked, for example `not during the free trial; the first payment unlocks it`. Null when available.
|
|
36
|
+
* @type {string}
|
|
37
|
+
* @memberof LimitsFieldsMachineTypesInner
|
|
38
|
+
*/
|
|
39
|
+
reason: string | null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @export
|
|
45
|
+
*/
|
|
46
|
+
export const LimitsFieldsMachineTypesInnerTypeEnum = {
|
|
47
|
+
Small: 'small',
|
|
48
|
+
Default: 'default',
|
|
49
|
+
Large: 'large',
|
|
50
|
+
Xlarge: 'xlarge'
|
|
51
|
+
} as const;
|
|
52
|
+
export type LimitsFieldsMachineTypesInnerTypeEnum = typeof LimitsFieldsMachineTypesInnerTypeEnum[keyof typeof LimitsFieldsMachineTypesInnerTypeEnum];
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Check if a given object implements the LimitsFieldsMachineTypesInner interface.
|
|
57
|
+
*/
|
|
58
|
+
export function instanceOfLimitsFieldsMachineTypesInner(value: object): value is LimitsFieldsMachineTypesInner {
|
|
59
|
+
if (!('type' in value) || value['type'] === undefined) return false;
|
|
60
|
+
if (!('available' in value) || value['available'] === undefined) return false;
|
|
61
|
+
if (!('reason' in value) || value['reason'] === undefined) return false;
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function LimitsFieldsMachineTypesInnerFromJSON(json: any): LimitsFieldsMachineTypesInner {
|
|
66
|
+
return LimitsFieldsMachineTypesInnerFromJSONTyped(json, false);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function LimitsFieldsMachineTypesInnerFromJSONTyped(json: any, ignoreDiscriminator: boolean): LimitsFieldsMachineTypesInner {
|
|
70
|
+
if (json == null) {
|
|
71
|
+
return json;
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
|
|
75
|
+
'type': json['type'],
|
|
76
|
+
'available': json['available'],
|
|
77
|
+
'reason': json['reason'],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function LimitsFieldsMachineTypesInnerToJSON(json: any): LimitsFieldsMachineTypesInner {
|
|
82
|
+
return LimitsFieldsMachineTypesInnerToJSONTyped(json, false);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function LimitsFieldsMachineTypesInnerToJSONTyped(value?: LimitsFieldsMachineTypesInner | null, ignoreDiscriminator: boolean = false): any {
|
|
86
|
+
if (value == null) {
|
|
87
|
+
return value;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
|
|
92
|
+
'type': value['type'],
|
|
93
|
+
'available': value['available'],
|
|
94
|
+
'reason': value['reason'],
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
@@ -27,6 +27,13 @@ import {
|
|
|
27
27
|
LimitsFieldsCurrentLimitsToJSON,
|
|
28
28
|
LimitsFieldsCurrentLimitsToJSONTyped,
|
|
29
29
|
} from './LimitsFieldsCurrentLimits';
|
|
30
|
+
import type { LimitsFieldsMachineTypesInner } from './LimitsFieldsMachineTypesInner';
|
|
31
|
+
import {
|
|
32
|
+
LimitsFieldsMachineTypesInnerFromJSON,
|
|
33
|
+
LimitsFieldsMachineTypesInnerFromJSONTyped,
|
|
34
|
+
LimitsFieldsMachineTypesInnerToJSON,
|
|
35
|
+
LimitsFieldsMachineTypesInnerToJSONTyped,
|
|
36
|
+
} from './LimitsFieldsMachineTypesInner';
|
|
30
37
|
import type { LimitsFieldsStartLimits } from './LimitsFieldsStartLimits';
|
|
31
38
|
import {
|
|
32
39
|
LimitsFieldsStartLimitsFromJSON,
|
|
@@ -313,6 +320,12 @@ export interface LimitsResponse {
|
|
|
313
320
|
* @memberof LimitsResponse
|
|
314
321
|
*/
|
|
315
322
|
trialLine?: string;
|
|
323
|
+
/**
|
|
324
|
+
* Each sandbox type, and whether this account can create it now. A blocked type carries the reason.
|
|
325
|
+
* @type {Array<LimitsFieldsMachineTypesInner>}
|
|
326
|
+
* @memberof LimitsResponse
|
|
327
|
+
*/
|
|
328
|
+
machineTypes?: Array<LimitsFieldsMachineTypesInner>;
|
|
316
329
|
/**
|
|
317
330
|
*
|
|
318
331
|
* @type {LimitsFieldsGiftLimit}
|
|
@@ -441,6 +454,7 @@ export function LimitsResponseFromJSONTyped(json: any, ignoreDiscriminator: bool
|
|
|
441
454
|
'last24hUsageSeconds': json['last24hUsageSeconds'] == null ? undefined : json['last24hUsageSeconds'],
|
|
442
455
|
'trialComputeCapSeconds': json['trialComputeCapSeconds'] == null ? undefined : json['trialComputeCapSeconds'],
|
|
443
456
|
'trialLine': json['trialLine'] == null ? undefined : json['trialLine'],
|
|
457
|
+
'machineTypes': json['machineTypes'] == null ? undefined : ((json['machineTypes'] as Array<any>).map(LimitsFieldsMachineTypesInnerFromJSON)),
|
|
444
458
|
'giftLimit': json['giftLimit'] == null ? undefined : LimitsFieldsGiftLimitFromJSON(json['giftLimit']),
|
|
445
459
|
'billingStatus': json['billingStatus'],
|
|
446
460
|
'subscriptionStatus': json['subscriptionStatus'] == null ? undefined : json['subscriptionStatus'],
|
|
@@ -508,6 +522,7 @@ export function LimitsResponseToJSONTyped(value?: LimitsResponse | null, ignoreD
|
|
|
508
522
|
'last24hUsageSeconds': value['last24hUsageSeconds'],
|
|
509
523
|
'trialComputeCapSeconds': value['trialComputeCapSeconds'],
|
|
510
524
|
'trialLine': value['trialLine'],
|
|
525
|
+
'machineTypes': value['machineTypes'] == null ? undefined : ((value['machineTypes'] as Array<any>).map(LimitsFieldsMachineTypesInnerToJSON)),
|
|
511
526
|
'giftLimit': LimitsFieldsGiftLimitToJSON(value['giftLimit']),
|
|
512
527
|
'billingStatus': value['billingStatus'],
|
|
513
528
|
'subscriptionStatus': value['subscriptionStatus'],
|