@declaw/sdk 1.3.0 → 1.5.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.
- package/CHANGELOG.md +56 -0
- package/dist/index.cjs +253 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +110 -11
- package/dist/index.d.ts +110 -11
- package/dist/index.js +250 -55
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -33,13 +33,51 @@ var ConnectionConfig = class {
|
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
+
// src/api/idempotency.ts
|
|
37
|
+
var CODE_IDEMPOTENCY_IN_PROGRESS = "idempotency_in_progress";
|
|
38
|
+
var CODE_IDEMPOTENCY_KEY_REUSED = "idempotency_key_reused";
|
|
39
|
+
var CODE_TEMPLATE_NOT_READY = "template_not_ready";
|
|
40
|
+
var MAX_RETRY_AFTER_MS = 6e4;
|
|
41
|
+
function newIdempotencyKey() {
|
|
42
|
+
const c = globalThis.crypto;
|
|
43
|
+
if (c?.randomUUID) {
|
|
44
|
+
return c.randomUUID();
|
|
45
|
+
}
|
|
46
|
+
if (c?.getRandomValues) {
|
|
47
|
+
const b = c.getRandomValues(new Uint8Array(16));
|
|
48
|
+
b[6] = b[6] & 15 | 64;
|
|
49
|
+
b[8] = b[8] & 63 | 128;
|
|
50
|
+
const hex = Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
|
|
51
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
52
|
+
}
|
|
53
|
+
return "";
|
|
54
|
+
}
|
|
55
|
+
function retryAfterMs(response) {
|
|
56
|
+
const raw = response.headers.get("Retry-After");
|
|
57
|
+
if (raw === null) return void 0;
|
|
58
|
+
const secs = Number(raw);
|
|
59
|
+
if (!Number.isFinite(secs) || secs < 0) return void 0;
|
|
60
|
+
return Math.min(secs * 1e3, MAX_RETRY_AFTER_MS);
|
|
61
|
+
}
|
|
62
|
+
|
|
36
63
|
// src/errors.ts
|
|
37
64
|
var SandboxError = class extends Error {
|
|
38
65
|
sandboxId;
|
|
66
|
+
/**
|
|
67
|
+
* Machine-readable error code from the API's `code` field, when present.
|
|
68
|
+
*
|
|
69
|
+
* Branch on this, never on `message`. Messages are prose and change; codes are
|
|
70
|
+
* contract. It matters most where one status means several unrelated things:
|
|
71
|
+
* a 409 from `POST /sandboxes` is either `idempotency_in_progress` (the
|
|
72
|
+
* original create is still running — retry the identical request) or
|
|
73
|
+
* `template_not_ready` (rebuild the template; retrying cannot help).
|
|
74
|
+
*/
|
|
75
|
+
code;
|
|
39
76
|
constructor(message, opts) {
|
|
40
77
|
super(message);
|
|
41
78
|
this.name = "SandboxError";
|
|
42
79
|
this.sandboxId = opts?.sandboxId;
|
|
80
|
+
this.code = opts?.code;
|
|
43
81
|
}
|
|
44
82
|
};
|
|
45
83
|
var TimeoutError = class extends SandboxError {
|
|
@@ -85,9 +123,15 @@ var TemplateError = class extends SandboxError {
|
|
|
85
123
|
}
|
|
86
124
|
};
|
|
87
125
|
var BuildError = class extends TemplateError {
|
|
126
|
+
/** The failed build's ID, when the error comes from a build that ran (`Template.build`). */
|
|
127
|
+
buildId;
|
|
128
|
+
/** The failed build's full output, when the error comes from a build that ran. */
|
|
129
|
+
logs;
|
|
88
130
|
constructor(message, opts) {
|
|
89
131
|
super(message, opts);
|
|
90
132
|
this.name = "BuildError";
|
|
133
|
+
this.buildId = opts?.buildId;
|
|
134
|
+
this.logs = opts?.logs ?? [];
|
|
91
135
|
}
|
|
92
136
|
};
|
|
93
137
|
var FileUploadError = class extends SandboxError {
|
|
@@ -297,6 +341,15 @@ var ApiClient = class {
|
|
|
297
341
|
await this.delay(attempt);
|
|
298
342
|
continue;
|
|
299
343
|
}
|
|
344
|
+
if (response.status === 409 && attempt < this.maxRetries - 1) {
|
|
345
|
+
const parsed = await this.readErrorBody(response);
|
|
346
|
+
if (parsed.code === CODE_IDEMPOTENCY_IN_PROGRESS) {
|
|
347
|
+
const after = retryAfterMs(response);
|
|
348
|
+
await (after !== void 0 ? new Promise((r) => setTimeout(r, after)) : this.delay(attempt));
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
throw this.errorFrom(response, parsed);
|
|
352
|
+
}
|
|
300
353
|
if (!response.ok) {
|
|
301
354
|
throw await this.buildError(response);
|
|
302
355
|
}
|
|
@@ -322,20 +375,36 @@ var ApiClient = class {
|
|
|
322
375
|
`Request failed after ${this.maxRetries} retries: ${lastError?.message ?? "unknown error"}`
|
|
323
376
|
);
|
|
324
377
|
}
|
|
325
|
-
|
|
326
|
-
|
|
378
|
+
/**
|
|
379
|
+
* Read an error body ONCE.
|
|
380
|
+
*
|
|
381
|
+
* `Response` bodies are single-read streams, so the 409 path cannot inspect
|
|
382
|
+
* the code and then hand the response to a separate error builder — the
|
|
383
|
+
* second read yields nothing and the error loses its message. Everything that
|
|
384
|
+
* needs the body goes through here, and the parsed result is passed around
|
|
385
|
+
* instead of the response.
|
|
386
|
+
*/
|
|
387
|
+
async readErrorBody(response) {
|
|
327
388
|
try {
|
|
328
|
-
const body = await response.
|
|
389
|
+
const body = JSON.parse(await response.text());
|
|
329
390
|
const bodyMsg = body.message ?? body.error ?? response.statusText;
|
|
330
|
-
|
|
391
|
+
return {
|
|
392
|
+
message: `HTTP ${response.status}: ${bodyMsg}`,
|
|
393
|
+
code: typeof body.code === "string" ? body.code : void 0
|
|
394
|
+
};
|
|
331
395
|
} catch {
|
|
332
|
-
message
|
|
396
|
+
return { message: `HTTP ${response.status}: ${response.statusText}` };
|
|
333
397
|
}
|
|
398
|
+
}
|
|
399
|
+
errorFrom(response, parsed) {
|
|
334
400
|
const ErrorClass = STATUS_ERROR_MAP[response.status];
|
|
335
401
|
if (ErrorClass) {
|
|
336
|
-
return new ErrorClass(message);
|
|
402
|
+
return new ErrorClass(parsed.message, { code: parsed.code });
|
|
337
403
|
}
|
|
338
|
-
return new SandboxError(message);
|
|
404
|
+
return new SandboxError(parsed.message, { code: parsed.code });
|
|
405
|
+
}
|
|
406
|
+
async buildError(response) {
|
|
407
|
+
return this.errorFrom(response, await this.readErrorBody(response));
|
|
339
408
|
}
|
|
340
409
|
async parseResponseBody(response) {
|
|
341
410
|
const contentLength = response.headers.get("content-length");
|
|
@@ -2544,9 +2613,11 @@ var Sandbox = class _Sandbox {
|
|
|
2544
2613
|
if (opts?.volumes && opts.volumes.length > 0) {
|
|
2545
2614
|
body.volumes = opts.volumes.map(volumeAttachmentToJSON);
|
|
2546
2615
|
}
|
|
2616
|
+
const idempotencyKey = newIdempotencyKey();
|
|
2547
2617
|
const data = await client.post("/sandboxes", {
|
|
2548
2618
|
json: body,
|
|
2549
|
-
timeout: opts?.requestTimeout
|
|
2619
|
+
timeout: opts?.requestTimeout,
|
|
2620
|
+
...idempotencyKey ? { headers: { "Idempotency-Key": idempotencyKey } } : {}
|
|
2550
2621
|
});
|
|
2551
2622
|
const sandboxId = data.sandbox_id;
|
|
2552
2623
|
assertValidId(sandboxId, "sandbox ID (from server)");
|
|
@@ -3043,7 +3114,13 @@ var TemplateBase = class {
|
|
|
3043
3114
|
this._runCmds.push(cmds);
|
|
3044
3115
|
return this;
|
|
3045
3116
|
}
|
|
3046
|
-
/**
|
|
3117
|
+
/**
|
|
3118
|
+
* Copy a local file into the template.
|
|
3119
|
+
*
|
|
3120
|
+
* Not supported yet: a template build cannot upload local files, so
|
|
3121
|
+
* building a template that uses `copy()` throws `InvalidArgumentError`.
|
|
3122
|
+
* Fetch the file in a `runCmd` step, or use `fromDockerfile`.
|
|
3123
|
+
*/
|
|
3047
3124
|
copy(src, dst, mode) {
|
|
3048
3125
|
this._copies.push({ src, dst, mode });
|
|
3049
3126
|
return this;
|
|
@@ -3063,6 +3140,14 @@ var TemplateBase = class {
|
|
|
3063
3140
|
this._startCmd = cmd;
|
|
3064
3141
|
return this;
|
|
3065
3142
|
}
|
|
3143
|
+
/**
|
|
3144
|
+
* Whether `copy()` was used. Builds reject such a template until builds can
|
|
3145
|
+
* upload local files.
|
|
3146
|
+
* @internal
|
|
3147
|
+
*/
|
|
3148
|
+
hasCopies() {
|
|
3149
|
+
return this._copies.length > 0;
|
|
3150
|
+
}
|
|
3066
3151
|
/** Serialize the template to a JSON-friendly object. */
|
|
3067
3152
|
toJSON() {
|
|
3068
3153
|
if (this._dockerfile !== void 0) {
|
|
@@ -3074,14 +3159,11 @@ var TemplateBase = class {
|
|
|
3074
3159
|
if (this._runCmds.length > 0) {
|
|
3075
3160
|
result.run_cmds = this._runCmds.map((c) => c.join(" "));
|
|
3076
3161
|
}
|
|
3077
|
-
if (this._copies.length > 0) {
|
|
3078
|
-
result.copies = this._copies;
|
|
3079
|
-
}
|
|
3080
3162
|
if (Object.keys(this._envs).length > 0) {
|
|
3081
3163
|
result.envs = this._envs;
|
|
3082
3164
|
}
|
|
3083
3165
|
if (this._aptPackages.length > 0) {
|
|
3084
|
-
result.
|
|
3166
|
+
result.packages = this._aptPackages;
|
|
3085
3167
|
}
|
|
3086
3168
|
if (this._startCmd !== void 0) {
|
|
3087
3169
|
result.start_cmd = this._startCmd;
|
|
@@ -3093,19 +3175,70 @@ function parseBuildInfo(data) {
|
|
|
3093
3175
|
return {
|
|
3094
3176
|
buildId: data.build_id ?? data.buildId ?? "",
|
|
3095
3177
|
status: data.status ?? "",
|
|
3096
|
-
templateId: data.template_id ?? data.templateId ?? void 0
|
|
3178
|
+
templateId: data.template_id ?? data.templateId ?? void 0,
|
|
3179
|
+
logs: data.logs ?? []
|
|
3097
3180
|
};
|
|
3098
3181
|
}
|
|
3099
3182
|
function parseTemplateBuildStatus(data) {
|
|
3100
3183
|
return {
|
|
3101
3184
|
buildId: data.build_id ?? data.buildId ?? "",
|
|
3102
3185
|
status: data.status ?? "",
|
|
3103
|
-
|
|
3186
|
+
// A build with no output yet serializes its logs as null.
|
|
3187
|
+
logs: data.logs ?? [],
|
|
3188
|
+
templateId: data.template_id ?? data.templateId ?? void 0
|
|
3104
3189
|
};
|
|
3105
3190
|
}
|
|
3106
3191
|
|
|
3107
3192
|
// src/template/template.ts
|
|
3108
3193
|
var VALID_BUILD_ID_RE = /^[a-zA-Z0-9_-]+$/;
|
|
3194
|
+
var BUILD_STATUS_COMPLETED = "completed";
|
|
3195
|
+
var BUILD_STATUS_FAILED = "failed";
|
|
3196
|
+
var DEFAULT_BUILD_TIMEOUT_MS = 60 * 60 * 1e3;
|
|
3197
|
+
var FAILURE_LOG_LINES = 20;
|
|
3198
|
+
var buildPolling = {
|
|
3199
|
+
/** How often a waiting build is re-read. */
|
|
3200
|
+
intervalMs: 3e3,
|
|
3201
|
+
/**
|
|
3202
|
+
* How long status checks may keep failing temporarily (5xx, 408, 429, or no
|
|
3203
|
+
* response) before the wait gives up. It rides out a sandbox-manager
|
|
3204
|
+
* restart; the build itself keeps running.
|
|
3205
|
+
*/
|
|
3206
|
+
errorWindowMs: 2 * 60 * 1e3
|
|
3207
|
+
};
|
|
3208
|
+
var BUILD_LOG_TRUNCATION_NOTICE = "... [earlier build output truncated]";
|
|
3209
|
+
var LOG_ANCHOR_LINES = 64;
|
|
3210
|
+
var REJECTIONS = [
|
|
3211
|
+
AuthenticationError,
|
|
3212
|
+
ConflictError,
|
|
3213
|
+
InvalidArgumentError,
|
|
3214
|
+
NotEnoughSpaceError,
|
|
3215
|
+
NotFoundError
|
|
3216
|
+
];
|
|
3217
|
+
var LogCursor = class {
|
|
3218
|
+
seen = 0;
|
|
3219
|
+
tail = [];
|
|
3220
|
+
newLines(logs) {
|
|
3221
|
+
const fresh = logs.length === 0 || logs[0] !== BUILD_LOG_TRUNCATION_NOTICE ? logs.slice(this.seen) : this.afterTail(logs);
|
|
3222
|
+
this.seen = logs.length;
|
|
3223
|
+
this.tail = [...this.tail, ...fresh].slice(-LOG_ANCHOR_LINES);
|
|
3224
|
+
return fresh;
|
|
3225
|
+
}
|
|
3226
|
+
afterTail(logs) {
|
|
3227
|
+
const window = logs.slice(1);
|
|
3228
|
+
const n = this.tail.length;
|
|
3229
|
+
if (n > 0) {
|
|
3230
|
+
for (let end = window.length; end >= n; end--) {
|
|
3231
|
+
if (window[end - 1] === this.tail[n - 1] && this.tail.every((line, i) => window[end - n + i] === line)) {
|
|
3232
|
+
return window.slice(end);
|
|
3233
|
+
}
|
|
3234
|
+
}
|
|
3235
|
+
}
|
|
3236
|
+
return logs;
|
|
3237
|
+
}
|
|
3238
|
+
};
|
|
3239
|
+
function isTemporaryPollError(err) {
|
|
3240
|
+
return err instanceof SandboxError && !REJECTIONS.some((Rejection) => err instanceof Rejection);
|
|
3241
|
+
}
|
|
3109
3242
|
function assertValidBuildId(buildId) {
|
|
3110
3243
|
if (!buildId || !VALID_BUILD_ID_RE.test(buildId)) {
|
|
3111
3244
|
throw new InvalidArgumentError(
|
|
@@ -3113,72 +3246,131 @@ function assertValidBuildId(buildId) {
|
|
|
3113
3246
|
);
|
|
3114
3247
|
}
|
|
3115
3248
|
}
|
|
3249
|
+
function buildRequestBody(template, alias, opts) {
|
|
3250
|
+
if (template.hasCopies()) {
|
|
3251
|
+
throw new InvalidArgumentError(
|
|
3252
|
+
"TemplateBase.copy() is not supported yet: a template build cannot upload local files. Fetch them in a runCmd step, or use fromDockerfile()."
|
|
3253
|
+
);
|
|
3254
|
+
}
|
|
3255
|
+
const body = {
|
|
3256
|
+
template: template.toJSON(),
|
|
3257
|
+
alias
|
|
3258
|
+
};
|
|
3259
|
+
if (opts?.cpuCount !== void 0) {
|
|
3260
|
+
body.cpu_count = opts.cpuCount;
|
|
3261
|
+
}
|
|
3262
|
+
if (opts?.memoryMb !== void 0) {
|
|
3263
|
+
body.memory_mb = opts.memoryMb;
|
|
3264
|
+
}
|
|
3265
|
+
if (opts?.diskMb !== void 0) {
|
|
3266
|
+
body.disk_mb = opts.diskMb;
|
|
3267
|
+
}
|
|
3268
|
+
return body;
|
|
3269
|
+
}
|
|
3270
|
+
function buildFailedError(status) {
|
|
3271
|
+
let message = `template build ${status.buildId} failed`;
|
|
3272
|
+
const tail = status.logs.slice(-FAILURE_LOG_LINES);
|
|
3273
|
+
if (tail.length > 0) {
|
|
3274
|
+
message += ":\n" + tail.join("\n");
|
|
3275
|
+
}
|
|
3276
|
+
return new BuildError(message, { buildId: status.buildId, logs: status.logs });
|
|
3277
|
+
}
|
|
3116
3278
|
var Template = class {
|
|
3117
3279
|
/**
|
|
3118
|
-
* Build a template and wait for
|
|
3280
|
+
* Build a template and wait for the build to finish.
|
|
3119
3281
|
*
|
|
3120
|
-
*
|
|
3121
|
-
*
|
|
3282
|
+
* Builds usually take several minutes. While waiting, each new line of build
|
|
3283
|
+
* output is passed to `onBuildLogs`. Sandboxes are created from the finished
|
|
3284
|
+
* template by its alias: `Sandbox.create({ template: alias })`.
|
|
3285
|
+
*
|
|
3286
|
+
* @throws {BuildError} The build failed; the error carries its logs.
|
|
3287
|
+
* @throws {TimeoutError} The build was still running after `buildTimeout`.
|
|
3288
|
+
* It keeps running; follow it with `getBuildStatus()`.
|
|
3289
|
+
* @throws {InvalidArgumentError} The template uses `copy()`, which is not
|
|
3290
|
+
* supported yet.
|
|
3122
3291
|
*/
|
|
3123
3292
|
static async build(template, alias, opts) {
|
|
3293
|
+
const body = buildRequestBody(template, alias, opts);
|
|
3124
3294
|
const config = new ConnectionConfig({
|
|
3125
3295
|
apiKey: opts?.apiKey,
|
|
3126
3296
|
domain: opts?.domain,
|
|
3127
3297
|
requestTimeout: opts?.requestTimeout
|
|
3128
3298
|
});
|
|
3129
3299
|
const client = getSharedClient(config);
|
|
3130
|
-
const body = {
|
|
3131
|
-
template: template.toJSON(),
|
|
3132
|
-
alias
|
|
3133
|
-
};
|
|
3134
|
-
if (opts?.cpuCount !== void 0) {
|
|
3135
|
-
body.cpu_count = opts.cpuCount;
|
|
3136
|
-
}
|
|
3137
|
-
if (opts?.memoryMb !== void 0) {
|
|
3138
|
-
body.memory_mb = opts.memoryMb;
|
|
3139
|
-
}
|
|
3140
|
-
if (opts?.diskMb !== void 0) {
|
|
3141
|
-
body.disk_mb = opts.diskMb;
|
|
3142
|
-
}
|
|
3143
3300
|
const data = await client.post("/templates/build", {
|
|
3144
3301
|
json: body,
|
|
3145
3302
|
timeout: opts?.requestTimeout
|
|
3146
3303
|
});
|
|
3147
|
-
const
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3304
|
+
const info = parseBuildInfo(data);
|
|
3305
|
+
assertValidBuildId(info.buildId);
|
|
3306
|
+
let status = {
|
|
3307
|
+
buildId: info.buildId,
|
|
3308
|
+
status: info.status,
|
|
3309
|
+
logs: info.logs,
|
|
3310
|
+
templateId: info.templateId
|
|
3311
|
+
};
|
|
3312
|
+
const buildTimeout = opts?.buildTimeout ?? DEFAULT_BUILD_TIMEOUT_MS;
|
|
3313
|
+
const deadline = Date.now() + buildTimeout;
|
|
3314
|
+
const timedOut = (cause) => new TimeoutError(
|
|
3315
|
+
`template build ${info.buildId} was still running after ${buildTimeout}ms. It keeps running; follow it with Template.getBuildStatus('${info.buildId}').` + (cause instanceof Error ? ` Last status check: ${cause.message}` : "")
|
|
3316
|
+
);
|
|
3317
|
+
const cursor = new LogCursor();
|
|
3318
|
+
for (; ; ) {
|
|
3319
|
+
if (opts?.onBuildLogs) {
|
|
3320
|
+
for (const line of cursor.newLines(status.logs)) {
|
|
3321
|
+
opts.onBuildLogs(line);
|
|
3322
|
+
}
|
|
3323
|
+
}
|
|
3324
|
+
if (status.status === BUILD_STATUS_COMPLETED) {
|
|
3325
|
+
return {
|
|
3326
|
+
buildId: status.buildId,
|
|
3327
|
+
status: status.status,
|
|
3328
|
+
templateId: status.templateId ?? info.templateId,
|
|
3329
|
+
logs: status.logs
|
|
3330
|
+
};
|
|
3331
|
+
}
|
|
3332
|
+
if (status.status === BUILD_STATUS_FAILED) {
|
|
3333
|
+
throw buildFailedError(status);
|
|
3334
|
+
}
|
|
3335
|
+
if (Date.now() >= deadline) {
|
|
3336
|
+
throw timedOut();
|
|
3337
|
+
}
|
|
3338
|
+
let failingSince;
|
|
3339
|
+
for (; ; ) {
|
|
3340
|
+
await new Promise((resolve) => setTimeout(resolve, buildPolling.intervalMs));
|
|
3341
|
+
try {
|
|
3342
|
+
const next = await client.get(`/templates/builds/${info.buildId}`, {
|
|
3343
|
+
timeout: opts?.requestTimeout
|
|
3344
|
+
});
|
|
3345
|
+
status = parseTemplateBuildStatus(next);
|
|
3346
|
+
break;
|
|
3347
|
+
} catch (err) {
|
|
3348
|
+
if (!isTemporaryPollError(err)) {
|
|
3349
|
+
throw err;
|
|
3350
|
+
}
|
|
3351
|
+
failingSince ??= Date.now();
|
|
3352
|
+
if (Date.now() - failingSince >= buildPolling.errorWindowMs) {
|
|
3353
|
+
throw err;
|
|
3354
|
+
}
|
|
3355
|
+
if (Date.now() >= deadline) {
|
|
3356
|
+
throw timedOut(err);
|
|
3357
|
+
}
|
|
3358
|
+
}
|
|
3152
3359
|
}
|
|
3153
3360
|
}
|
|
3154
|
-
return result;
|
|
3155
3361
|
}
|
|
3156
3362
|
/**
|
|
3157
|
-
* Start a template build
|
|
3158
|
-
*
|
|
3159
|
-
* Sends POST /templates/build with `background: true`.
|
|
3363
|
+
* Start a template build and return as soon as the server has accepted it,
|
|
3364
|
+
* with status `building`. Follow the build with `getBuildStatus()`.
|
|
3160
3365
|
*/
|
|
3161
3366
|
static async buildInBackground(template, alias, opts) {
|
|
3367
|
+
const body = buildRequestBody(template, alias, opts);
|
|
3162
3368
|
const config = new ConnectionConfig({
|
|
3163
3369
|
apiKey: opts?.apiKey,
|
|
3164
3370
|
domain: opts?.domain,
|
|
3165
3371
|
requestTimeout: opts?.requestTimeout
|
|
3166
3372
|
});
|
|
3167
3373
|
const client = getSharedClient(config);
|
|
3168
|
-
const body = {
|
|
3169
|
-
template: template.toJSON(),
|
|
3170
|
-
alias,
|
|
3171
|
-
background: true
|
|
3172
|
-
};
|
|
3173
|
-
if (opts?.cpuCount !== void 0) {
|
|
3174
|
-
body.cpu_count = opts.cpuCount;
|
|
3175
|
-
}
|
|
3176
|
-
if (opts?.memoryMb !== void 0) {
|
|
3177
|
-
body.memory_mb = opts.memoryMb;
|
|
3178
|
-
}
|
|
3179
|
-
if (opts?.diskMb !== void 0) {
|
|
3180
|
-
body.disk_mb = opts.diskMb;
|
|
3181
|
-
}
|
|
3182
3374
|
const data = await client.post("/templates/build", {
|
|
3183
3375
|
json: body,
|
|
3184
3376
|
timeout: opts?.requestTimeout
|
|
@@ -3186,7 +3378,7 @@ var Template = class {
|
|
|
3186
3378
|
return parseBuildInfo(data);
|
|
3187
3379
|
}
|
|
3188
3380
|
/**
|
|
3189
|
-
* Get the status of a template build.
|
|
3381
|
+
* Get the status of a template build, including its logs so far.
|
|
3190
3382
|
*
|
|
3191
3383
|
* Sends GET /templates/builds/:buildId.
|
|
3192
3384
|
*/
|
|
@@ -3727,6 +3919,9 @@ export {
|
|
|
3727
3919
|
ApiClient,
|
|
3728
3920
|
AuthenticationError,
|
|
3729
3921
|
BuildError,
|
|
3922
|
+
CODE_IDEMPOTENCY_IN_PROGRESS,
|
|
3923
|
+
CODE_IDEMPOTENCY_KEY_REUSED,
|
|
3924
|
+
CODE_TEMPLATE_NOT_READY,
|
|
3730
3925
|
CommandExitError,
|
|
3731
3926
|
CommandHandle,
|
|
3732
3927
|
Commands,
|