@boatdev/sdk 1.4.0 → 1.6.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.
Files changed (60) hide show
  1. package/.openapi-generator/FILES +4 -0
  2. package/dist/apis/BoatApi.d.ts +22 -0
  3. package/dist/apis/BoatApi.js +51 -0
  4. package/dist/boat-helpers.d.ts +6 -0
  5. package/dist/boat-helpers.js +28 -4
  6. package/dist/esm/apis/BoatApi.d.ts +22 -0
  7. package/dist/esm/apis/BoatApi.js +51 -0
  8. package/dist/esm/boat-helpers.d.ts +6 -0
  9. package/dist/esm/boat-helpers.js +28 -4
  10. package/dist/esm/models/NamedSnapshotAllowance.d.ts +74 -0
  11. package/dist/esm/models/NamedSnapshotAllowance.js +55 -0
  12. package/dist/esm/models/NamedSnapshotListResponse.d.ts +7 -0
  13. package/dist/esm/models/NamedSnapshotListResponse.js +3 -0
  14. package/dist/esm/models/PromptRequest.d.ts +6 -0
  15. package/dist/esm/models/PromptRequest.js +2 -0
  16. package/dist/esm/models/PromptResponse.d.ts +6 -0
  17. package/dist/esm/models/PromptResponse.js +2 -0
  18. package/dist/esm/models/PromptRun.d.ts +6 -0
  19. package/dist/esm/models/PromptRun.js +2 -0
  20. package/dist/esm/models/Sandbox.d.ts +39 -0
  21. package/dist/esm/models/Sandbox.js +18 -0
  22. package/dist/esm/models/Share200Response.d.ts +45 -0
  23. package/dist/esm/models/Share200Response.js +46 -0
  24. package/dist/esm/models/index.d.ts +2 -0
  25. package/dist/esm/models/index.js +2 -0
  26. package/dist/models/NamedSnapshotAllowance.d.ts +74 -0
  27. package/dist/models/NamedSnapshotAllowance.js +62 -0
  28. package/dist/models/NamedSnapshotListResponse.d.ts +7 -0
  29. package/dist/models/NamedSnapshotListResponse.js +3 -0
  30. package/dist/models/PromptRequest.d.ts +6 -0
  31. package/dist/models/PromptRequest.js +2 -0
  32. package/dist/models/PromptResponse.d.ts +6 -0
  33. package/dist/models/PromptResponse.js +2 -0
  34. package/dist/models/PromptRun.d.ts +6 -0
  35. package/dist/models/PromptRun.js +2 -0
  36. package/dist/models/Sandbox.d.ts +39 -0
  37. package/dist/models/Sandbox.js +19 -1
  38. package/dist/models/Share200Response.d.ts +45 -0
  39. package/dist/models/Share200Response.js +53 -0
  40. package/dist/models/index.d.ts +2 -0
  41. package/dist/models/index.js +2 -0
  42. package/docs/BoatApi.md +87 -2
  43. package/docs/NamedSnapshotAllowance.md +47 -0
  44. package/docs/NamedSnapshotListResponse.md +2 -0
  45. package/docs/PromptRequest.md +2 -0
  46. package/docs/PromptResponse.md +2 -0
  47. package/docs/PromptRun.md +2 -0
  48. package/docs/Sandbox.md +10 -0
  49. package/docs/Share200Response.md +36 -0
  50. package/package.json +1 -1
  51. package/src/apis/BoatApi.ts +76 -0
  52. package/src/boat-helpers.ts +27 -5
  53. package/src/models/NamedSnapshotAllowance.ts +121 -0
  54. package/src/models/NamedSnapshotListResponse.ts +15 -0
  55. package/src/models/PromptRequest.ts +8 -0
  56. package/src/models/PromptResponse.ts +8 -0
  57. package/src/models/PromptRun.ts +8 -0
  58. package/src/models/Sandbox.ts +50 -0
  59. package/src/models/Share200Response.ts +89 -0
  60. package/src/models/index.ts +2 -0
@@ -62,6 +62,7 @@ docs/LimitsResponse.md
62
62
  docs/MeResponse.md
63
63
  docs/MeResponseAllOfUser.md
64
64
  docs/NamedSnapshot.md
65
+ docs/NamedSnapshotAllowance.md
65
66
  docs/NamedSnapshotDeletedResponse.md
66
67
  docs/NamedSnapshotInfoResponse.md
67
68
  docs/NamedSnapshotListResponse.md
@@ -104,6 +105,7 @@ docs/SecretsUpdateRequest.md
104
105
  docs/SelectedRepository.md
105
106
  docs/SetEnvironmentSecretFileRequest.md
106
107
  docs/SetEnvironmentVarRequest.md
108
+ docs/Share200Response.md
107
109
  docs/SnapshotChunk.md
108
110
  docs/SnapshotDownloadResponse.md
109
111
  docs/SnapshotDownloadResponseAllOfInventory.md
@@ -201,6 +203,7 @@ src/models/LimitsResponse.ts
201
203
  src/models/MeResponse.ts
202
204
  src/models/MeResponseAllOfUser.ts
203
205
  src/models/NamedSnapshot.ts
206
+ src/models/NamedSnapshotAllowance.ts
204
207
  src/models/NamedSnapshotDeletedResponse.ts
205
208
  src/models/NamedSnapshotInfoResponse.ts
206
209
  src/models/NamedSnapshotListResponse.ts
@@ -243,6 +246,7 @@ src/models/SecretsUpdateRequest.ts
243
246
  src/models/SelectedRepository.ts
244
247
  src/models/SetEnvironmentSecretFileRequest.ts
245
248
  src/models/SetEnvironmentVarRequest.ts
249
+ src/models/Share200Response.ts
246
250
  src/models/SnapshotChunk.ts
247
251
  src/models/SnapshotDownloadResponse.ts
248
252
  src/models/SnapshotDownloadResponseAllOfInventory.ts
@@ -64,6 +64,7 @@ import { type SecretsResponse } from '../models/SecretsResponse';
64
64
  import { type SecretsUpdateRequest } from '../models/SecretsUpdateRequest';
65
65
  import { type SetEnvironmentSecretFileRequest } from '../models/SetEnvironmentSecretFileRequest';
66
66
  import { type SetEnvironmentVarRequest } from '../models/SetEnvironmentVarRequest';
67
+ import { type Share200Response } from '../models/Share200Response';
67
68
  import { type SnapshotDownloadResponse } from '../models/SnapshotDownloadResponse';
68
69
  import { type SnapshotLatestResponse } from '../models/SnapshotLatestResponse';
69
70
  import { type SnapshotListResponse } from '../models/SnapshotListResponse';
@@ -257,6 +258,8 @@ export interface RotateWebhookSigningSecretRequest {
257
258
  webhookId: string;
258
259
  }
259
260
  export interface SandboxesRequest {
261
+ org?: string;
262
+ xBoatOrg?: string;
260
263
  limit?: number;
261
264
  cursor?: string | null;
262
265
  sort?: SandboxesSortEnum;
@@ -280,6 +283,9 @@ export interface SetEnvironmentVarOperationRequest {
280
283
  key: string;
281
284
  setEnvironmentVarRequest: SetEnvironmentVarRequest;
282
285
  }
286
+ export interface ShareRequest {
287
+ sandboxId: string;
288
+ }
283
289
  export interface SshKeyOperationRequest {
284
290
  sandboxId: string;
285
291
  sshKeyRequest: SshKeyRequest;
@@ -1023,10 +1029,12 @@ export declare class BoatApi extends runtime.BaseAPI {
1023
1029
  */
1024
1030
  sandboxesRequestOpts(requestParameters: SandboxesRequest): Promise<runtime.RequestOpts>;
1025
1031
  /**
1032
+ * Your sandboxes. In an organization\'s scope (the active wallet, `org`, or `X-Boat-Org`) the list also holds every sandbox that organization pays for, whoever created it; `createdBy` and `access` say whose it is and what you may do with it.
1026
1033
  * List sandboxes
1027
1034
  */
1028
1035
  sandboxesRaw(requestParameters: SandboxesRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<SandboxListResponse>>;
1029
1036
  /**
1037
+ * Your sandboxes. In an organization\'s scope (the active wallet, `org`, or `X-Boat-Org`) the list also holds every sandbox that organization pays for, whoever created it; `createdBy` and `access` say whose it is and what you may do with it.
1030
1038
  * List sandboxes
1031
1039
  */
1032
1040
  sandboxes(requestParameters?: SandboxesRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SandboxListResponse>;
@@ -1114,6 +1122,20 @@ export declare class BoatApi extends runtime.BaseAPI {
1114
1122
  * Set one environment variable
1115
1123
  */
1116
1124
  setEnvironmentVar(requestParameters: SetEnvironmentVarOperationRequest | runtime.FlatBody<SetEnvironmentVarOperationRequest, 'setEnvironmentVarRequest'>, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<EnvironmentItemChangeResponse>;
1125
+ /**
1126
+ * Creates request options for share without sending the request
1127
+ */
1128
+ shareRequestOpts(requestParameters: ShareRequest): Promise<runtime.RequestOpts>;
1129
+ /**
1130
+ * Let every member of the organization that pays for this sandbox use it. Your personal logins (GitHub token, Claude and Codex logins, environment secrets, the sandbox\'s own CLI key) are never pushed to it again and are wiped off its disk at its next start, so a teammate never acts as you. Files you wrote stay. One-way: the sandbox stays like a `noEnv` sandbox from then on. A running sandbox stays `view` for the organization until you stop and resume it (`restartRequired`). Only the person who created the sandbox can share it, and only a sandbox billed to an organization. Sharing an already shared sandbox is a no-op.
1131
+ * Share sandbox with the organization
1132
+ */
1133
+ shareRaw(requestParameters: ShareRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Share200Response>>;
1134
+ /**
1135
+ * Let every member of the organization that pays for this sandbox use it. Your personal logins (GitHub token, Claude and Codex logins, environment secrets, the sandbox\'s own CLI key) are never pushed to it again and are wiped off its disk at its next start, so a teammate never acts as you. Files you wrote stay. One-way: the sandbox stays like a `noEnv` sandbox from then on. A running sandbox stays `view` for the organization until you stop and resume it (`restartRequired`). Only the person who created the sandbox can share it, and only a sandbox billed to an organization. Sharing an already shared sandbox is a no-op.
1136
+ * Share sandbox with the organization
1137
+ */
1138
+ share(requestParameters: ShareRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Share200Response>;
1117
1139
  /**
1118
1140
  * Creates request options for sshKey without sending the request
1119
1141
  */
@@ -102,6 +102,7 @@ const SecretsResponse_1 = require("../models/SecretsResponse");
102
102
  const SecretsUpdateRequest_1 = require("../models/SecretsUpdateRequest");
103
103
  const SetEnvironmentSecretFileRequest_1 = require("../models/SetEnvironmentSecretFileRequest");
104
104
  const SetEnvironmentVarRequest_1 = require("../models/SetEnvironmentVarRequest");
105
+ const Share200Response_1 = require("../models/Share200Response");
105
106
  const SnapshotDownloadResponse_1 = require("../models/SnapshotDownloadResponse");
106
107
  const SnapshotLatestResponse_1 = require("../models/SnapshotLatestResponse");
107
108
  const SnapshotListResponse_1 = require("../models/SnapshotListResponse");
@@ -2360,6 +2361,9 @@ class BoatApi extends runtime.BaseAPI {
2360
2361
  */
2361
2362
  async sandboxesRequestOpts(requestParameters) {
2362
2363
  const queryParameters = {};
2364
+ if (requestParameters['org'] != null) {
2365
+ queryParameters['org'] = requestParameters['org'];
2366
+ }
2363
2367
  if (requestParameters['limit'] != null) {
2364
2368
  queryParameters['limit'] = requestParameters['limit'];
2365
2369
  }
@@ -2373,6 +2377,9 @@ class BoatApi extends runtime.BaseAPI {
2373
2377
  queryParameters['state'] = requestParameters['state'];
2374
2378
  }
2375
2379
  const headerParameters = {};
2380
+ if (requestParameters['xBoatOrg'] != null) {
2381
+ headerParameters['X-Boat-Org'] = String(requestParameters['xBoatOrg']);
2382
+ }
2376
2383
  if (this.configuration && this.configuration.accessToken) {
2377
2384
  const token = this.configuration.accessToken;
2378
2385
  const tokenString = await token("BoatBearerAuth", []);
@@ -2389,6 +2396,7 @@ class BoatApi extends runtime.BaseAPI {
2389
2396
  };
2390
2397
  }
2391
2398
  /**
2399
+ * Your sandboxes. In an organization\'s scope (the active wallet, `org`, or `X-Boat-Org`) the list also holds every sandbox that organization pays for, whoever created it; `createdBy` and `access` say whose it is and what you may do with it.
2392
2400
  * List sandboxes
2393
2401
  */
2394
2402
  async sandboxesRaw(requestParameters, initOverrides) {
@@ -2397,6 +2405,7 @@ class BoatApi extends runtime.BaseAPI {
2397
2405
  return new runtime.JSONApiResponse(response, (jsonValue) => (0, SandboxListResponse_1.SandboxListResponseFromJSON)(jsonValue));
2398
2406
  }
2399
2407
  /**
2408
+ * Your sandboxes. In an organization\'s scope (the active wallet, `org`, or `X-Boat-Org`) the list also holds every sandbox that organization pays for, whoever created it; `createdBy` and `access` say whose it is and what you may do with it.
2400
2409
  * List sandboxes
2401
2410
  */
2402
2411
  async sandboxes(requestParameters = {}, initOverrides) {
@@ -2673,6 +2682,48 @@ class BoatApi extends runtime.BaseAPI {
2673
2682
  const response = await this.setEnvironmentVarRaw(requestParameters, initOverrides);
2674
2683
  return await response.value();
2675
2684
  }
2685
+ /**
2686
+ * Creates request options for share without sending the request
2687
+ */
2688
+ async shareRequestOpts(requestParameters) {
2689
+ if (requestParameters['sandboxId'] == null) {
2690
+ throw new runtime.RequiredError('sandboxId', 'Required parameter "sandboxId" was null or undefined when calling share().');
2691
+ }
2692
+ const queryParameters = {};
2693
+ const headerParameters = {};
2694
+ if (this.configuration && this.configuration.accessToken) {
2695
+ const token = this.configuration.accessToken;
2696
+ const tokenString = await token("BoatBearerAuth", []);
2697
+ if (tokenString) {
2698
+ headerParameters["Authorization"] = `Bearer ${tokenString}`;
2699
+ }
2700
+ }
2701
+ let urlPath = `/sandboxes/{sandboxId}/share`;
2702
+ urlPath = urlPath.replace('{sandboxId}', encodeURIComponent(String(requestParameters['sandboxId'])));
2703
+ return {
2704
+ path: urlPath,
2705
+ method: 'POST',
2706
+ headers: headerParameters,
2707
+ query: queryParameters,
2708
+ };
2709
+ }
2710
+ /**
2711
+ * Let every member of the organization that pays for this sandbox use it. Your personal logins (GitHub token, Claude and Codex logins, environment secrets, the sandbox\'s own CLI key) are never pushed to it again and are wiped off its disk at its next start, so a teammate never acts as you. Files you wrote stay. One-way: the sandbox stays like a `noEnv` sandbox from then on. A running sandbox stays `view` for the organization until you stop and resume it (`restartRequired`). Only the person who created the sandbox can share it, and only a sandbox billed to an organization. Sharing an already shared sandbox is a no-op.
2712
+ * Share sandbox with the organization
2713
+ */
2714
+ async shareRaw(requestParameters, initOverrides) {
2715
+ const requestOptions = await this.shareRequestOpts(requestParameters);
2716
+ const response = await this.request(requestOptions, initOverrides);
2717
+ return new runtime.JSONApiResponse(response, (jsonValue) => (0, Share200Response_1.Share200ResponseFromJSON)(jsonValue));
2718
+ }
2719
+ /**
2720
+ * Let every member of the organization that pays for this sandbox use it. Your personal logins (GitHub token, Claude and Codex logins, environment secrets, the sandbox\'s own CLI key) are never pushed to it again and are wiped off its disk at its next start, so a teammate never acts as you. Files you wrote stay. One-way: the sandbox stays like a `noEnv` sandbox from then on. A running sandbox stays `view` for the organization until you stop and resume it (`restartRequired`). Only the person who created the sandbox can share it, and only a sandbox billed to an organization. Sharing an already shared sandbox is a no-op.
2721
+ * Share sandbox with the organization
2722
+ */
2723
+ async share(requestParameters, initOverrides) {
2724
+ const response = await this.shareRaw(requestParameters, initOverrides);
2725
+ return await response.value();
2726
+ }
2676
2727
  /**
2677
2728
  * Creates request options for sshKey without sending the request
2678
2729
  */
@@ -53,6 +53,12 @@ export declare function stopAndRemove(api: BoatApi, sandboxId: string, options?:
53
53
  }): Promise<import("./models").DeletionOperationResponse | import("./models").SandboxActionResponse>;
54
54
  export declare function readText(api: BoatApi, sandboxId: string, path: string): Promise<string>;
55
55
  export declare function writeText(api: BoatApi, sandboxId: string, path: string, content: string): Promise<import("./models").FileWriteResponse>;
56
+ /**
57
+ * Run a command and return its result.
58
+ *
59
+ * Safe to call right after `resume()`: a refusal that never ran the command
60
+ * (`retryable: true`, the sandbox is still restoring) is resent for up to 60 s.
61
+ */
56
62
  export declare function execCommand(api: BoatApi, sandboxId: string, command: string, cwd?: string, timeoutSeconds?: number): Promise<import("./models").Command200Response>;
57
63
  /** One line of a streamed command, as sent (an `exit` frame also carries e.g. `signal`, `oomKilled`). */
58
64
  export type CommandFrame = CommandStreamFrame & Record<string, unknown>;
@@ -172,12 +172,36 @@ async function readText(api, sandboxId, path) {
172
172
  async function writeText(api, sandboxId, path, content) {
173
173
  return api.writeFile({ sandboxId, fileWriteRequest: { path, content, encoding: 'utf8' } });
174
174
  }
175
- async function execCommand(api, sandboxId, command, cwd, timeoutSeconds = 30) {
176
- return api.command({ sandboxId, commandRequest: { command, cwd, timeoutSeconds } });
177
- }
178
175
  // A refusal that provably never ran the command (the sandbox is still restoring
179
- // its disk, `retryable: true` before `started`) is retried for this long.
176
+ // its disk, `retryable: true`) is retried for this long.
180
177
  const STREAM_RETRY_MS = 60000;
178
+ async function isRetryable(e) {
179
+ const response = e === null || e === void 0 ? void 0 : e.response;
180
+ if (!response)
181
+ return false;
182
+ const body = await response.clone().json().catch(() => undefined);
183
+ return (body === null || body === void 0 ? void 0 : body.retryable) === true;
184
+ }
185
+ /**
186
+ * Run a command and return its result.
187
+ *
188
+ * Safe to call right after `resume()`: a refusal that never ran the command
189
+ * (`retryable: true`, the sandbox is still restoring) is resent for up to 60 s.
190
+ */
191
+ async function execCommand(api, sandboxId, command, cwd, timeoutSeconds = 30) {
192
+ const deadline = Date.now() + STREAM_RETRY_MS;
193
+ for (;;) {
194
+ try {
195
+ return await api.command({ sandboxId, commandRequest: { command, cwd, timeoutSeconds } });
196
+ }
197
+ catch (e) {
198
+ // The 1 s pause before the resend must also fit before the deadline.
199
+ if (Date.now() + 1000 >= deadline || !(await isRetryable(e)))
200
+ throw e;
201
+ }
202
+ await delay(1000);
203
+ }
204
+ }
181
205
  async function* ndjsonFrames(response) {
182
206
  if (!response.body)
183
207
  throw new Error('The command stream has no body');
@@ -64,6 +64,7 @@ import { type SecretsResponse } from '../models/SecretsResponse';
64
64
  import { type SecretsUpdateRequest } from '../models/SecretsUpdateRequest';
65
65
  import { type SetEnvironmentSecretFileRequest } from '../models/SetEnvironmentSecretFileRequest';
66
66
  import { type SetEnvironmentVarRequest } from '../models/SetEnvironmentVarRequest';
67
+ import { type Share200Response } from '../models/Share200Response';
67
68
  import { type SnapshotDownloadResponse } from '../models/SnapshotDownloadResponse';
68
69
  import { type SnapshotLatestResponse } from '../models/SnapshotLatestResponse';
69
70
  import { type SnapshotListResponse } from '../models/SnapshotListResponse';
@@ -257,6 +258,8 @@ export interface RotateWebhookSigningSecretRequest {
257
258
  webhookId: string;
258
259
  }
259
260
  export interface SandboxesRequest {
261
+ org?: string;
262
+ xBoatOrg?: string;
260
263
  limit?: number;
261
264
  cursor?: string | null;
262
265
  sort?: SandboxesSortEnum;
@@ -280,6 +283,9 @@ export interface SetEnvironmentVarOperationRequest {
280
283
  key: string;
281
284
  setEnvironmentVarRequest: SetEnvironmentVarRequest;
282
285
  }
286
+ export interface ShareRequest {
287
+ sandboxId: string;
288
+ }
283
289
  export interface SshKeyOperationRequest {
284
290
  sandboxId: string;
285
291
  sshKeyRequest: SshKeyRequest;
@@ -1023,10 +1029,12 @@ export declare class BoatApi extends runtime.BaseAPI {
1023
1029
  */
1024
1030
  sandboxesRequestOpts(requestParameters: SandboxesRequest): Promise<runtime.RequestOpts>;
1025
1031
  /**
1032
+ * Your sandboxes. In an organization\'s scope (the active wallet, `org`, or `X-Boat-Org`) the list also holds every sandbox that organization pays for, whoever created it; `createdBy` and `access` say whose it is and what you may do with it.
1026
1033
  * List sandboxes
1027
1034
  */
1028
1035
  sandboxesRaw(requestParameters: SandboxesRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<SandboxListResponse>>;
1029
1036
  /**
1037
+ * Your sandboxes. In an organization\'s scope (the active wallet, `org`, or `X-Boat-Org`) the list also holds every sandbox that organization pays for, whoever created it; `createdBy` and `access` say whose it is and what you may do with it.
1030
1038
  * List sandboxes
1031
1039
  */
1032
1040
  sandboxes(requestParameters?: SandboxesRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SandboxListResponse>;
@@ -1114,6 +1122,20 @@ export declare class BoatApi extends runtime.BaseAPI {
1114
1122
  * Set one environment variable
1115
1123
  */
1116
1124
  setEnvironmentVar(requestParameters: SetEnvironmentVarOperationRequest | runtime.FlatBody<SetEnvironmentVarOperationRequest, 'setEnvironmentVarRequest'>, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<EnvironmentItemChangeResponse>;
1125
+ /**
1126
+ * Creates request options for share without sending the request
1127
+ */
1128
+ shareRequestOpts(requestParameters: ShareRequest): Promise<runtime.RequestOpts>;
1129
+ /**
1130
+ * Let every member of the organization that pays for this sandbox use it. Your personal logins (GitHub token, Claude and Codex logins, environment secrets, the sandbox\'s own CLI key) are never pushed to it again and are wiped off its disk at its next start, so a teammate never acts as you. Files you wrote stay. One-way: the sandbox stays like a `noEnv` sandbox from then on. A running sandbox stays `view` for the organization until you stop and resume it (`restartRequired`). Only the person who created the sandbox can share it, and only a sandbox billed to an organization. Sharing an already shared sandbox is a no-op.
1131
+ * Share sandbox with the organization
1132
+ */
1133
+ shareRaw(requestParameters: ShareRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Share200Response>>;
1134
+ /**
1135
+ * Let every member of the organization that pays for this sandbox use it. Your personal logins (GitHub token, Claude and Codex logins, environment secrets, the sandbox\'s own CLI key) are never pushed to it again and are wiped off its disk at its next start, so a teammate never acts as you. Files you wrote stay. One-way: the sandbox stays like a `noEnv` sandbox from then on. A running sandbox stays `view` for the organization until you stop and resume it (`restartRequired`). Only the person who created the sandbox can share it, and only a sandbox billed to an organization. Sharing an already shared sandbox is a no-op.
1136
+ * Share sandbox with the organization
1137
+ */
1138
+ share(requestParameters: ShareRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Share200Response>;
1117
1139
  /**
1118
1140
  * Creates request options for sshKey without sending the request
1119
1141
  */
@@ -66,6 +66,7 @@ import { SecretsResponseFromJSON, } from '../models/SecretsResponse';
66
66
  import { SecretsUpdateRequestToJSON, } from '../models/SecretsUpdateRequest';
67
67
  import { SetEnvironmentSecretFileRequestToJSON, } from '../models/SetEnvironmentSecretFileRequest';
68
68
  import { SetEnvironmentVarRequestToJSON, } from '../models/SetEnvironmentVarRequest';
69
+ import { Share200ResponseFromJSON, } from '../models/Share200Response';
69
70
  import { SnapshotDownloadResponseFromJSON, } from '../models/SnapshotDownloadResponse';
70
71
  import { SnapshotLatestResponseFromJSON, } from '../models/SnapshotLatestResponse';
71
72
  import { SnapshotListResponseFromJSON, } from '../models/SnapshotListResponse';
@@ -2324,6 +2325,9 @@ export class BoatApi extends runtime.BaseAPI {
2324
2325
  */
2325
2326
  async sandboxesRequestOpts(requestParameters) {
2326
2327
  const queryParameters = {};
2328
+ if (requestParameters['org'] != null) {
2329
+ queryParameters['org'] = requestParameters['org'];
2330
+ }
2327
2331
  if (requestParameters['limit'] != null) {
2328
2332
  queryParameters['limit'] = requestParameters['limit'];
2329
2333
  }
@@ -2337,6 +2341,9 @@ export class BoatApi extends runtime.BaseAPI {
2337
2341
  queryParameters['state'] = requestParameters['state'];
2338
2342
  }
2339
2343
  const headerParameters = {};
2344
+ if (requestParameters['xBoatOrg'] != null) {
2345
+ headerParameters['X-Boat-Org'] = String(requestParameters['xBoatOrg']);
2346
+ }
2340
2347
  if (this.configuration && this.configuration.accessToken) {
2341
2348
  const token = this.configuration.accessToken;
2342
2349
  const tokenString = await token("BoatBearerAuth", []);
@@ -2353,6 +2360,7 @@ export class BoatApi extends runtime.BaseAPI {
2353
2360
  };
2354
2361
  }
2355
2362
  /**
2363
+ * Your sandboxes. In an organization\'s scope (the active wallet, `org`, or `X-Boat-Org`) the list also holds every sandbox that organization pays for, whoever created it; `createdBy` and `access` say whose it is and what you may do with it.
2356
2364
  * List sandboxes
2357
2365
  */
2358
2366
  async sandboxesRaw(requestParameters, initOverrides) {
@@ -2361,6 +2369,7 @@ export class BoatApi extends runtime.BaseAPI {
2361
2369
  return new runtime.JSONApiResponse(response, (jsonValue) => SandboxListResponseFromJSON(jsonValue));
2362
2370
  }
2363
2371
  /**
2372
+ * Your sandboxes. In an organization\'s scope (the active wallet, `org`, or `X-Boat-Org`) the list also holds every sandbox that organization pays for, whoever created it; `createdBy` and `access` say whose it is and what you may do with it.
2364
2373
  * List sandboxes
2365
2374
  */
2366
2375
  async sandboxes(requestParameters = {}, initOverrides) {
@@ -2637,6 +2646,48 @@ export class BoatApi extends runtime.BaseAPI {
2637
2646
  const response = await this.setEnvironmentVarRaw(requestParameters, initOverrides);
2638
2647
  return await response.value();
2639
2648
  }
2649
+ /**
2650
+ * Creates request options for share without sending the request
2651
+ */
2652
+ async shareRequestOpts(requestParameters) {
2653
+ if (requestParameters['sandboxId'] == null) {
2654
+ throw new runtime.RequiredError('sandboxId', 'Required parameter "sandboxId" was null or undefined when calling share().');
2655
+ }
2656
+ const queryParameters = {};
2657
+ const headerParameters = {};
2658
+ if (this.configuration && this.configuration.accessToken) {
2659
+ const token = this.configuration.accessToken;
2660
+ const tokenString = await token("BoatBearerAuth", []);
2661
+ if (tokenString) {
2662
+ headerParameters["Authorization"] = `Bearer ${tokenString}`;
2663
+ }
2664
+ }
2665
+ let urlPath = `/sandboxes/{sandboxId}/share`;
2666
+ urlPath = urlPath.replace('{sandboxId}', encodeURIComponent(String(requestParameters['sandboxId'])));
2667
+ return {
2668
+ path: urlPath,
2669
+ method: 'POST',
2670
+ headers: headerParameters,
2671
+ query: queryParameters,
2672
+ };
2673
+ }
2674
+ /**
2675
+ * Let every member of the organization that pays for this sandbox use it. Your personal logins (GitHub token, Claude and Codex logins, environment secrets, the sandbox\'s own CLI key) are never pushed to it again and are wiped off its disk at its next start, so a teammate never acts as you. Files you wrote stay. One-way: the sandbox stays like a `noEnv` sandbox from then on. A running sandbox stays `view` for the organization until you stop and resume it (`restartRequired`). Only the person who created the sandbox can share it, and only a sandbox billed to an organization. Sharing an already shared sandbox is a no-op.
2676
+ * Share sandbox with the organization
2677
+ */
2678
+ async shareRaw(requestParameters, initOverrides) {
2679
+ const requestOptions = await this.shareRequestOpts(requestParameters);
2680
+ const response = await this.request(requestOptions, initOverrides);
2681
+ return new runtime.JSONApiResponse(response, (jsonValue) => Share200ResponseFromJSON(jsonValue));
2682
+ }
2683
+ /**
2684
+ * Let every member of the organization that pays for this sandbox use it. Your personal logins (GitHub token, Claude and Codex logins, environment secrets, the sandbox\'s own CLI key) are never pushed to it again and are wiped off its disk at its next start, so a teammate never acts as you. Files you wrote stay. One-way: the sandbox stays like a `noEnv` sandbox from then on. A running sandbox stays `view` for the organization until you stop and resume it (`restartRequired`). Only the person who created the sandbox can share it, and only a sandbox billed to an organization. Sharing an already shared sandbox is a no-op.
2685
+ * Share sandbox with the organization
2686
+ */
2687
+ async share(requestParameters, initOverrides) {
2688
+ const response = await this.shareRaw(requestParameters, initOverrides);
2689
+ return await response.value();
2690
+ }
2640
2691
  /**
2641
2692
  * Creates request options for sshKey without sending the request
2642
2693
  */
@@ -53,6 +53,12 @@ export declare function stopAndRemove(api: BoatApi, sandboxId: string, options?:
53
53
  }): Promise<import("./models").DeletionOperationResponse | import("./models").SandboxActionResponse>;
54
54
  export declare function readText(api: BoatApi, sandboxId: string, path: string): Promise<string>;
55
55
  export declare function writeText(api: BoatApi, sandboxId: string, path: string, content: string): Promise<import("./models").FileWriteResponse>;
56
+ /**
57
+ * Run a command and return its result.
58
+ *
59
+ * Safe to call right after `resume()`: a refusal that never ran the command
60
+ * (`retryable: true`, the sandbox is still restoring) is resent for up to 60 s.
61
+ */
56
62
  export declare function execCommand(api: BoatApi, sandboxId: string, command: string, cwd?: string, timeoutSeconds?: number): Promise<import("./models").Command200Response>;
57
63
  /** One line of a streamed command, as sent (an `exit` frame also carries e.g. `signal`, `oomKilled`). */
58
64
  export type CommandFrame = CommandStreamFrame & Record<string, unknown>;
@@ -158,12 +158,36 @@ export async function readText(api, sandboxId, path) {
158
158
  export async function writeText(api, sandboxId, path, content) {
159
159
  return api.writeFile({ sandboxId, fileWriteRequest: { path, content, encoding: 'utf8' } });
160
160
  }
161
- export async function execCommand(api, sandboxId, command, cwd, timeoutSeconds = 30) {
162
- return api.command({ sandboxId, commandRequest: { command, cwd, timeoutSeconds } });
163
- }
164
161
  // A refusal that provably never ran the command (the sandbox is still restoring
165
- // its disk, `retryable: true` before `started`) is retried for this long.
162
+ // its disk, `retryable: true`) is retried for this long.
166
163
  const STREAM_RETRY_MS = 60000;
164
+ async function isRetryable(e) {
165
+ const response = e === null || e === void 0 ? void 0 : e.response;
166
+ if (!response)
167
+ return false;
168
+ const body = await response.clone().json().catch(() => undefined);
169
+ return (body === null || body === void 0 ? void 0 : body.retryable) === true;
170
+ }
171
+ /**
172
+ * Run a command and return its result.
173
+ *
174
+ * Safe to call right after `resume()`: a refusal that never ran the command
175
+ * (`retryable: true`, the sandbox is still restoring) is resent for up to 60 s.
176
+ */
177
+ export async function execCommand(api, sandboxId, command, cwd, timeoutSeconds = 30) {
178
+ const deadline = Date.now() + STREAM_RETRY_MS;
179
+ for (;;) {
180
+ try {
181
+ return await api.command({ sandboxId, commandRequest: { command, cwd, timeoutSeconds } });
182
+ }
183
+ catch (e) {
184
+ // The 1 s pause before the resend must also fit before the deadline.
185
+ if (Date.now() + 1000 >= deadline || !(await isRetryable(e)))
186
+ throw e;
187
+ }
188
+ await delay(1000);
189
+ }
190
+ }
167
191
  async function* ndjsonFrames(response) {
168
192
  if (!response.body)
169
193
  throw new Error('The command stream has no body');
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Boat Public API v1
3
+ * 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.
4
+ *
5
+ * The version of the OpenAPI document: 1.0.0
6
+ *
7
+ *
8
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
9
+ * https://openapi-generator.tech
10
+ * Do not edit the class manually.
11
+ */
12
+ /**
13
+ * What the request's wallet (your active organization, `?org=`, or personal) pays for named snapshots. 10 are free per wallet; each one above costs $1.70 a month, charged daily from usage. An organization's count includes every member's names billed to it.
14
+ * @export
15
+ * @interface NamedSnapshotAllowance
16
+ */
17
+ export interface NamedSnapshotAllowance {
18
+ /**
19
+ * Organization the numbers are for. null = personal.
20
+ * @type {string}
21
+ * @memberof NamedSnapshotAllowance
22
+ */
23
+ org?: string | null;
24
+ /**
25
+ * That organization's name.
26
+ * @type {string}
27
+ * @memberof NamedSnapshotAllowance
28
+ */
29
+ orgName?: string | null;
30
+ /**
31
+ * Named snapshots kept for free.
32
+ * @type {number}
33
+ * @memberof NamedSnapshotAllowance
34
+ */
35
+ free?: number;
36
+ /**
37
+ * Named snapshots this wallet keeps.
38
+ * @type {number}
39
+ * @memberof NamedSnapshotAllowance
40
+ */
41
+ used?: number;
42
+ /**
43
+ * Named snapshots above the free ones.
44
+ * @type {number}
45
+ * @memberof NamedSnapshotAllowance
46
+ */
47
+ extra?: number;
48
+ /**
49
+ * What the extra ones cost per month.
50
+ * @type {number}
51
+ * @memberof NamedSnapshotAllowance
52
+ */
53
+ extraMonthlyDollars?: number;
54
+ /**
55
+ * Boat time the extra ones take per day, in dollars (the daily charge).
56
+ * @type {number}
57
+ * @memberof NamedSnapshotAllowance
58
+ */
59
+ extraDailyDollars?: number;
60
+ /**
61
+ * Monthly price of one extra named snapshot.
62
+ * @type {number}
63
+ * @memberof NamedSnapshotAllowance
64
+ */
65
+ pricePerExtraMonthlyDollars?: number;
66
+ }
67
+ /**
68
+ * Check if a given object implements the NamedSnapshotAllowance interface.
69
+ */
70
+ export declare function instanceOfNamedSnapshotAllowance(value: object): value is NamedSnapshotAllowance;
71
+ export declare function NamedSnapshotAllowanceFromJSON(json: any): NamedSnapshotAllowance;
72
+ export declare function NamedSnapshotAllowanceFromJSONTyped(json: any, ignoreDiscriminator: boolean): NamedSnapshotAllowance;
73
+ export declare function NamedSnapshotAllowanceToJSON(json: any): NamedSnapshotAllowance;
74
+ export declare function NamedSnapshotAllowanceToJSONTyped(value?: NamedSnapshotAllowance | null, ignoreDiscriminator?: boolean): any;
@@ -0,0 +1,55 @@
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
+ * Check if a given object implements the NamedSnapshotAllowance interface.
16
+ */
17
+ export function instanceOfNamedSnapshotAllowance(value) {
18
+ return true;
19
+ }
20
+ export function NamedSnapshotAllowanceFromJSON(json) {
21
+ return NamedSnapshotAllowanceFromJSONTyped(json, false);
22
+ }
23
+ export function NamedSnapshotAllowanceFromJSONTyped(json, ignoreDiscriminator) {
24
+ if (json == null) {
25
+ return json;
26
+ }
27
+ return {
28
+ 'org': json['org'] == null ? undefined : json['org'],
29
+ 'orgName': json['orgName'] == null ? undefined : json['orgName'],
30
+ 'free': json['free'] == null ? undefined : json['free'],
31
+ 'used': json['used'] == null ? undefined : json['used'],
32
+ 'extra': json['extra'] == null ? undefined : json['extra'],
33
+ 'extraMonthlyDollars': json['extraMonthlyDollars'] == null ? undefined : json['extraMonthlyDollars'],
34
+ 'extraDailyDollars': json['extraDailyDollars'] == null ? undefined : json['extraDailyDollars'],
35
+ 'pricePerExtraMonthlyDollars': json['pricePerExtraMonthlyDollars'] == null ? undefined : json['pricePerExtraMonthlyDollars'],
36
+ };
37
+ }
38
+ export function NamedSnapshotAllowanceToJSON(json) {
39
+ return NamedSnapshotAllowanceToJSONTyped(json, false);
40
+ }
41
+ export function NamedSnapshotAllowanceToJSONTyped(value, ignoreDiscriminator = false) {
42
+ if (value == null) {
43
+ return value;
44
+ }
45
+ return {
46
+ 'org': value['org'],
47
+ 'orgName': value['orgName'],
48
+ 'free': value['free'],
49
+ 'used': value['used'],
50
+ 'extra': value['extra'],
51
+ 'extraMonthlyDollars': value['extraMonthlyDollars'],
52
+ 'extraDailyDollars': value['extraDailyDollars'],
53
+ 'pricePerExtraMonthlyDollars': value['pricePerExtraMonthlyDollars'],
54
+ };
55
+ }
@@ -9,6 +9,7 @@
9
9
  * https://openapi-generator.tech
10
10
  * Do not edit the class manually.
11
11
  */
12
+ import type { NamedSnapshotAllowance } from './NamedSnapshotAllowance';
12
13
  import type { NamedSnapshot } from './NamedSnapshot';
13
14
  /**
14
15
  *
@@ -34,6 +35,12 @@ export interface NamedSnapshotListResponse {
34
35
  * @memberof NamedSnapshotListResponse
35
36
  */
36
37
  snapshots: Array<NamedSnapshot>;
38
+ /**
39
+ *
40
+ * @type {NamedSnapshotAllowance}
41
+ * @memberof NamedSnapshotListResponse
42
+ */
43
+ allowance?: NamedSnapshotAllowance;
37
44
  }
38
45
  /**
39
46
  * @export
@@ -11,6 +11,7 @@
11
11
  * https://openapi-generator.tech
12
12
  * Do not edit the class manually.
13
13
  */
14
+ import { NamedSnapshotAllowanceFromJSON, NamedSnapshotAllowanceToJSON, } from './NamedSnapshotAllowance';
14
15
  import { NamedSnapshotFromJSON, NamedSnapshotToJSON, } from './NamedSnapshot';
15
16
  /**
16
17
  * @export
@@ -41,6 +42,7 @@ export function NamedSnapshotListResponseFromJSONTyped(json, ignoreDiscriminator
41
42
  'ok': json['ok'],
42
43
  'type': json['type'],
43
44
  'snapshots': (json['snapshots'].map(NamedSnapshotFromJSON)),
45
+ 'allowance': json['allowance'] == null ? undefined : NamedSnapshotAllowanceFromJSON(json['allowance']),
44
46
  };
45
47
  }
46
48
  export function NamedSnapshotListResponseToJSON(json) {
@@ -54,5 +56,6 @@ export function NamedSnapshotListResponseToJSONTyped(value, ignoreDiscriminator
54
56
  'ok': value['ok'],
55
57
  'type': value['type'],
56
58
  'snapshots': (value['snapshots'].map(NamedSnapshotToJSON)),
59
+ 'allowance': NamedSnapshotAllowanceToJSON(value['allowance']),
57
60
  };
58
61
  }
@@ -40,6 +40,12 @@ export interface PromptRequest {
40
40
  * @memberof PromptRequest
41
41
  */
42
42
  reasoningEffort?: string | null;
43
+ /**
44
+ * Optional. `true` runs this prompt in fast mode. The model stays the same and gives output faster. The provider bills fast mode at its higher fast rate. Omit to use the choice saved on the Agents dashboard for that model. `false` forces standard speed. Only models with `fastMode` set to `true` in `GET /provider-models` accept `true`. Other models return 400 `fast_mode_not_supported`.
45
+ * @type {boolean}
46
+ * @memberof PromptRequest
47
+ */
48
+ fast?: boolean | null;
43
49
  /**
44
50
  * Start a NEW conversation on the sandbox (runs in parallel with any existing ones) instead of continuing the most-recently-active one. Mutually exclusive with `conversationId`.
45
51
  * @type {boolean}