@declaw/sdk 1.2.3 → 1.4.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/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 {
@@ -297,6 +335,15 @@ var ApiClient = class {
297
335
  await this.delay(attempt);
298
336
  continue;
299
337
  }
338
+ if (response.status === 409 && attempt < this.maxRetries - 1) {
339
+ const parsed = await this.readErrorBody(response);
340
+ if (parsed.code === CODE_IDEMPOTENCY_IN_PROGRESS) {
341
+ const after = retryAfterMs(response);
342
+ await (after !== void 0 ? new Promise((r) => setTimeout(r, after)) : this.delay(attempt));
343
+ continue;
344
+ }
345
+ throw this.errorFrom(response, parsed);
346
+ }
300
347
  if (!response.ok) {
301
348
  throw await this.buildError(response);
302
349
  }
@@ -322,20 +369,36 @@ var ApiClient = class {
322
369
  `Request failed after ${this.maxRetries} retries: ${lastError?.message ?? "unknown error"}`
323
370
  );
324
371
  }
325
- async buildError(response) {
326
- let message;
372
+ /**
373
+ * Read an error body ONCE.
374
+ *
375
+ * `Response` bodies are single-read streams, so the 409 path cannot inspect
376
+ * the code and then hand the response to a separate error builder — the
377
+ * second read yields nothing and the error loses its message. Everything that
378
+ * needs the body goes through here, and the parsed result is passed around
379
+ * instead of the response.
380
+ */
381
+ async readErrorBody(response) {
327
382
  try {
328
- const body = await response.json();
383
+ const body = JSON.parse(await response.text());
329
384
  const bodyMsg = body.message ?? body.error ?? response.statusText;
330
- message = `HTTP ${response.status}: ${bodyMsg}`;
385
+ return {
386
+ message: `HTTP ${response.status}: ${bodyMsg}`,
387
+ code: typeof body.code === "string" ? body.code : void 0
388
+ };
331
389
  } catch {
332
- message = `HTTP ${response.status}: ${response.statusText}`;
390
+ return { message: `HTTP ${response.status}: ${response.statusText}` };
333
391
  }
392
+ }
393
+ errorFrom(response, parsed) {
334
394
  const ErrorClass = STATUS_ERROR_MAP[response.status];
335
395
  if (ErrorClass) {
336
- return new ErrorClass(message);
396
+ return new ErrorClass(parsed.message, { code: parsed.code });
337
397
  }
338
- return new SandboxError(message);
398
+ return new SandboxError(parsed.message, { code: parsed.code });
399
+ }
400
+ async buildError(response) {
401
+ return this.errorFrom(response, await this.readErrorBody(response));
339
402
  }
340
403
  async parseResponseBody(response) {
341
404
  const contentLength = response.headers.get("content-length");
@@ -509,7 +572,7 @@ function createInjectionDefenseConfig(opts) {
509
572
  enabled: opts?.enabled ?? false,
510
573
  sensitivity: opts?.sensitivity ?? "medium" /* Medium */,
511
574
  action: opts?.action ?? "log_only" /* LogOnly */,
512
- threshold: opts?.threshold ?? 0.8,
575
+ threshold: opts?.threshold ?? 0.95,
513
576
  domains: opts?.domains,
514
577
  judge: opts?.judge,
515
578
  injectionMode: opts?.injectionMode
@@ -536,7 +599,7 @@ function parseInjectionDefenseConfig(data) {
536
599
  enabled: data.enabled ?? false,
537
600
  sensitivity: data.sensitivity ?? "medium" /* Medium */,
538
601
  action: data.action ?? "log_only" /* LogOnly */,
539
- threshold: data.threshold ?? 0.8,
602
+ threshold: data.threshold ?? 0.95,
540
603
  domains: data.domains,
541
604
  judge: data.judge ? { enabled: data.judge.enabled ?? false, always: data.judge.always, policy: data.judge.policy } : void 0,
542
605
  injectionMode: data.injection_mode ?? data.injectionMode
@@ -914,14 +977,14 @@ function fullInjectionDefensePolicy(opts) {
914
977
  injectionDefense: createInjectionDefenseConfig({
915
978
  enabled: true,
916
979
  action: opts?.action ?? "block",
917
- threshold: opts?.threshold ?? 0.8,
980
+ threshold: opts?.threshold ?? 0.95,
918
981
  domains: opts?.domains,
919
982
  injectionMode: opts?.mode ?? "balanced",
920
983
  judge: { enabled: true, always: opts?.alwaysJudge ?? false, policy: opts?.agentPolicy ?? "" }
921
984
  }),
922
985
  customPolicy: createCustomPolicyConfig({
923
986
  enabled: true,
924
- policyRef: "prompt-injection@v2",
987
+ policyRef: "prompt-injection@v3",
925
988
  defaultDeny: false
926
989
  })
927
990
  });
@@ -962,7 +1025,7 @@ function securityPolicyToJSON(policy) {
962
1025
  action: injDefConfig.action,
963
1026
  threshold: injDefConfig.threshold
964
1027
  };
965
- if (injDefConfig.domains !== void 0) {
1028
+ if (injDefConfig.domains !== void 0 && injDefConfig.domains.length > 0) {
966
1029
  injDef.domains = injDefConfig.domains;
967
1030
  }
968
1031
  if (injDefConfig.injectionMode !== void 0) {
@@ -2074,6 +2137,311 @@ function volumeAttachmentToJSON(att) {
2074
2137
  return out;
2075
2138
  }
2076
2139
 
2140
+ // src/vault/models.ts
2141
+ function parseVaultScope(data) {
2142
+ const scope = {
2143
+ domainRegex: String(data.domain_regex ?? "")
2144
+ };
2145
+ if (data.injection_type !== void 0 && data.injection_type !== null) {
2146
+ scope.injectionType = String(data.injection_type);
2147
+ }
2148
+ if (data.header_name !== void 0 && data.header_name !== null) {
2149
+ scope.headerName = String(data.header_name);
2150
+ }
2151
+ if (data.value_prefix !== void 0 && data.value_prefix !== null) {
2152
+ scope.valuePrefix = String(data.value_prefix);
2153
+ }
2154
+ if (data.basic_username !== void 0 && data.basic_username !== null) {
2155
+ scope.basicUsername = String(data.basic_username);
2156
+ }
2157
+ if (data.extra_headers !== void 0 && data.extra_headers !== null) {
2158
+ scope.extraHeaders = data.extra_headers;
2159
+ }
2160
+ if (data.query_params !== void 0 && data.query_params !== null) {
2161
+ scope.queryParams = data.query_params;
2162
+ }
2163
+ return scope;
2164
+ }
2165
+ function parseVaultSecret(data) {
2166
+ const secret = {
2167
+ secretId: String(data.secret_id ?? ""),
2168
+ name: String(data.name ?? ""),
2169
+ createdAt: String(data.created_at ?? ""),
2170
+ updatedAt: String(data.updated_at ?? "")
2171
+ };
2172
+ const rawScopes = data.scopes;
2173
+ if (rawScopes && rawScopes.length > 0) {
2174
+ secret.scopes = rawScopes.map(parseVaultScope);
2175
+ }
2176
+ if (data.rotated_at !== void 0 && data.rotated_at !== null) {
2177
+ secret.rotatedAt = String(data.rotated_at);
2178
+ }
2179
+ if (data.rotation_interval_days !== void 0 && data.rotation_interval_days !== null) {
2180
+ secret.rotationIntervalDays = Number(data.rotation_interval_days);
2181
+ }
2182
+ if (data.rotation_due !== void 0 && data.rotation_due !== null) {
2183
+ secret.rotationDue = Boolean(data.rotation_due);
2184
+ }
2185
+ return secret;
2186
+ }
2187
+ function parseVaultPreset(data) {
2188
+ const rawScopes = data.scopes ?? [];
2189
+ const preset = {
2190
+ key: String(data.key ?? ""),
2191
+ name: String(data.name ?? ""),
2192
+ category: String(data.category ?? ""),
2193
+ keyHint: String(data.key_hint ?? ""),
2194
+ scopes: rawScopes.map(parseVaultScope)
2195
+ };
2196
+ if (data.docs_url !== void 0 && data.docs_url !== null) {
2197
+ preset.docsUrl = String(data.docs_url);
2198
+ }
2199
+ return preset;
2200
+ }
2201
+ function vaultScopeToJSON(scope) {
2202
+ const out = {
2203
+ domain_regex: scope.domainRegex
2204
+ };
2205
+ if (scope.injectionType !== void 0) {
2206
+ out.injection_type = scope.injectionType;
2207
+ }
2208
+ if (scope.headerName !== void 0) {
2209
+ out.header_name = scope.headerName;
2210
+ }
2211
+ if (scope.valuePrefix !== void 0) {
2212
+ out.value_prefix = scope.valuePrefix;
2213
+ }
2214
+ if (scope.basicUsername !== void 0) {
2215
+ out.basic_username = scope.basicUsername;
2216
+ }
2217
+ if (scope.extraHeaders !== void 0) {
2218
+ out.extra_headers = scope.extraHeaders;
2219
+ }
2220
+ if (scope.queryParams !== void 0) {
2221
+ out.query_params = scope.queryParams;
2222
+ }
2223
+ return out;
2224
+ }
2225
+
2226
+ // src/vault/vault.ts
2227
+ var DEFAULT_TEAM_NAME = "default";
2228
+ var DEFAULT_ENV_NAME = "prod";
2229
+ var defaultTeamCache = /* @__PURE__ */ new Map();
2230
+ function cacheKey(config) {
2231
+ return `${config.apiUrl}\0${config.apiKey}`;
2232
+ }
2233
+ async function resolveDefaultTeamId(config, create, timeout) {
2234
+ const key = cacheKey(config);
2235
+ const cached = defaultTeamCache.get(key);
2236
+ if (cached !== void 0) return cached;
2237
+ const client = getSharedClient(config);
2238
+ const resp = await client.get("/teams", { timeout });
2239
+ const rows = resp.teams ?? [];
2240
+ let best = null;
2241
+ for (const t of rows) {
2242
+ if (t.name === DEFAULT_TEAM_NAME) {
2243
+ if (best === null || t.created_at < best.created_at) {
2244
+ best = t;
2245
+ }
2246
+ }
2247
+ }
2248
+ if (best !== null) {
2249
+ defaultTeamCache.set(key, best.team_id);
2250
+ return best.team_id;
2251
+ }
2252
+ if (!create) return null;
2253
+ const created = await client.post("/teams", {
2254
+ json: { name: DEFAULT_TEAM_NAME },
2255
+ timeout
2256
+ });
2257
+ defaultTeamCache.set(key, created.team_id);
2258
+ return created.team_id;
2259
+ }
2260
+ async function ensureDefaultEnv(config, teamId, timeout) {
2261
+ const client = getSharedClient(config);
2262
+ const resp = await client.get(
2263
+ `/teams/${encodeURIComponent(teamId)}/environments`,
2264
+ { timeout }
2265
+ );
2266
+ const rows = resp.environments ?? [];
2267
+ if (rows.some((e) => e.name === DEFAULT_ENV_NAME)) return;
2268
+ try {
2269
+ await client.post(`/teams/${encodeURIComponent(teamId)}/environments`, {
2270
+ json: { name: DEFAULT_ENV_NAME },
2271
+ timeout
2272
+ });
2273
+ } catch {
2274
+ const resp2 = await client.get(
2275
+ `/teams/${encodeURIComponent(teamId)}/environments`,
2276
+ { timeout }
2277
+ );
2278
+ const rows2 = resp2.environments ?? [];
2279
+ if (rows2.some((e) => e.name === DEFAULT_ENV_NAME)) return;
2280
+ throw new Error(`Failed to ensure default environment "${DEFAULT_ENV_NAME}" on team ${teamId}`);
2281
+ }
2282
+ }
2283
+ async function expandVaultRefs(config, refs, timeout) {
2284
+ if (Object.keys(refs).length === 0) return refs;
2285
+ const needsTeam = Object.values(refs).some((v) => !v.startsWith("vault://"));
2286
+ if (!needsTeam) return refs;
2287
+ const teamId = await resolveDefaultTeamId(config, false, timeout);
2288
+ if (teamId === null) {
2289
+ throw new Error("vault_refs given but no vault secrets exist for this account");
2290
+ }
2291
+ const out = {};
2292
+ for (const [envVar, ref] of Object.entries(refs)) {
2293
+ out[envVar] = ref.startsWith("vault://") ? ref : `vault://${teamId}/${DEFAULT_ENV_NAME}/${ref}`;
2294
+ }
2295
+ return out;
2296
+ }
2297
+ function buildConfig(opts) {
2298
+ return new ConnectionConfig({
2299
+ apiKey: opts?.apiKey,
2300
+ domain: opts?.domain,
2301
+ apiUrl: opts?.apiUrl,
2302
+ requestTimeout: opts?.requestTimeout
2303
+ });
2304
+ }
2305
+ var Vault = class _Vault {
2306
+ // -------------------------------------------------------------------------
2307
+ // Secrets
2308
+ // -------------------------------------------------------------------------
2309
+ /**
2310
+ * Store a secret's value (server-side, in OpenBao) plus its injection
2311
+ * scopes, under the auto-provisioned default team + "prod" environment.
2312
+ * Returns metadata only — the value is never echoed.
2313
+ *
2314
+ * POST /teams/{teamId}/vault/secrets
2315
+ */
2316
+ static async createSecret(input, opts) {
2317
+ const config = buildConfig(opts);
2318
+ const teamId = await resolveDefaultTeamId(config, true, opts?.requestTimeout);
2319
+ if (teamId === null) throw new Error("Failed to resolve or create default team");
2320
+ await ensureDefaultEnv(config, teamId, opts?.requestTimeout);
2321
+ const body = {
2322
+ environment: DEFAULT_ENV_NAME,
2323
+ value: input.value
2324
+ };
2325
+ if (input.name) body.name = input.name;
2326
+ if (input.provider) body.provider = input.provider;
2327
+ if (input.scopes && input.scopes.length > 0) {
2328
+ body.scopes = input.scopes.map(vaultScopeToJSON);
2329
+ }
2330
+ if (input.rotationIntervalDays && input.rotationIntervalDays > 0) {
2331
+ body.rotation_interval_days = input.rotationIntervalDays;
2332
+ }
2333
+ const client = getSharedClient(config);
2334
+ const resp = await client.post(
2335
+ `/teams/${encodeURIComponent(teamId)}/vault/secrets`,
2336
+ { json: body, timeout: opts?.requestTimeout }
2337
+ );
2338
+ return parseVaultSecret(resp);
2339
+ }
2340
+ /**
2341
+ * List secret metadata for the default team. Returns an empty array if no
2342
+ * default team has been provisioned yet.
2343
+ *
2344
+ * GET /teams/{teamId}/vault/secrets -> {secrets}
2345
+ */
2346
+ static async listSecrets(opts) {
2347
+ const config = buildConfig(opts);
2348
+ const teamId = await resolveDefaultTeamId(config, false, opts?.requestTimeout);
2349
+ if (teamId === null) return [];
2350
+ const client = getSharedClient(config);
2351
+ const resp = await client.get(
2352
+ `/teams/${encodeURIComponent(teamId)}/vault/secrets`,
2353
+ { timeout: opts?.requestTimeout }
2354
+ );
2355
+ const rows = resp.secrets ?? [];
2356
+ return rows.map(parseVaultSecret);
2357
+ }
2358
+ /**
2359
+ * Replace a secret's value by name (server-side); scopes are unchanged.
2360
+ *
2361
+ * POST /teams/{teamId}/vault/secrets/{secretId}/rotate {value}
2362
+ */
2363
+ static async rotateSecret(name, value, opts) {
2364
+ const config = buildConfig(opts);
2365
+ const teamId = await resolveDefaultTeamId(config, false, opts?.requestTimeout);
2366
+ if (teamId === null) throw new Error(`vault secret "${name}" not found`);
2367
+ const secretId = await _Vault._resolveSecretId(config, teamId, name, opts?.requestTimeout);
2368
+ const client = getSharedClient(config);
2369
+ await client.post(
2370
+ `/teams/${encodeURIComponent(teamId)}/vault/secrets/${encodeURIComponent(secretId)}/rotate`,
2371
+ { json: { value }, timeout: opts?.requestTimeout }
2372
+ );
2373
+ }
2374
+ /**
2375
+ * Delete a secret by name — metadata and stored value.
2376
+ *
2377
+ * DELETE /teams/{teamId}/vault/secrets/{secretId}
2378
+ */
2379
+ static async deleteSecret(name, opts) {
2380
+ const config = buildConfig(opts);
2381
+ const teamId = await resolveDefaultTeamId(config, false, opts?.requestTimeout);
2382
+ if (teamId === null) throw new Error(`vault secret "${name}" not found`);
2383
+ const secretId = await _Vault._resolveSecretId(config, teamId, name, opts?.requestTimeout);
2384
+ const client = getSharedClient(config);
2385
+ await client.delete(
2386
+ `/teams/${encodeURIComponent(teamId)}/vault/secrets/${encodeURIComponent(secretId)}`,
2387
+ { timeout: opts?.requestTimeout }
2388
+ );
2389
+ }
2390
+ /**
2391
+ * Replace a secret's injection scopes by name; the value is unchanged. Use
2392
+ * this to change a secret's destination(s) or injection format in place
2393
+ * instead of delete + recreate. At least one scope is required.
2394
+ *
2395
+ * POST /teams/{teamId}/vault/secrets/{secretId}/scopes
2396
+ */
2397
+ static async updateScopes(name, scopes, opts) {
2398
+ if (!scopes || scopes.length === 0) {
2399
+ throw new Error("at least one scope is required");
2400
+ }
2401
+ const config = buildConfig(opts);
2402
+ const teamId = await resolveDefaultTeamId(config, false, opts?.requestTimeout);
2403
+ if (teamId === null) throw new Error(`vault secret "${name}" not found`);
2404
+ const secretId = await _Vault._resolveSecretId(config, teamId, name, opts?.requestTimeout);
2405
+ const client = getSharedClient(config);
2406
+ await client.post(
2407
+ `/teams/${encodeURIComponent(teamId)}/vault/secrets/${encodeURIComponent(secretId)}/scopes`,
2408
+ { json: { scopes: scopes.map(vaultScopeToJSON) }, timeout: opts?.requestTimeout }
2409
+ );
2410
+ }
2411
+ // -------------------------------------------------------------------------
2412
+ // Presets
2413
+ // -------------------------------------------------------------------------
2414
+ /**
2415
+ * List built-in provider preset catalog (templates only, no secret material).
2416
+ *
2417
+ * GET /vault/presets -> {presets}
2418
+ */
2419
+ static async listPresets(opts) {
2420
+ const client = getSharedClient(buildConfig(opts));
2421
+ const resp = await client.get("/vault/presets", {
2422
+ timeout: opts?.requestTimeout
2423
+ });
2424
+ const rows = resp.presets ?? [];
2425
+ return rows.map(parseVaultPreset);
2426
+ }
2427
+ // -------------------------------------------------------------------------
2428
+ // Internal helpers
2429
+ // -------------------------------------------------------------------------
2430
+ /** Maps a secret name to its id within the given team. */
2431
+ static async _resolveSecretId(config, teamId, name, timeout) {
2432
+ const client = getSharedClient(config);
2433
+ const resp = await client.get(
2434
+ `/teams/${encodeURIComponent(teamId)}/vault/secrets`,
2435
+ { timeout }
2436
+ );
2437
+ const rows = resp.secrets ?? [];
2438
+ for (const s of rows) {
2439
+ if (s.name === name) return String(s.secret_id ?? "");
2440
+ }
2441
+ throw new Error(`vault secret "${name}" not found`);
2442
+ }
2443
+ };
2444
+
2077
2445
  // src/sandbox/sandbox.ts
2078
2446
  var DEFAULT_TEMPLATE = "base";
2079
2447
  var DEFAULT_TIMEOUT = 300;
@@ -2219,6 +2587,9 @@ var Sandbox = class _Sandbox {
2219
2587
  if (opts?.envs) {
2220
2588
  body.envs = opts.envs;
2221
2589
  }
2590
+ if (opts?.vaultRefs) {
2591
+ body.vault_refs = await expandVaultRefs(config, opts.vaultRefs, opts.requestTimeout);
2592
+ }
2222
2593
  if (opts?.network) {
2223
2594
  body.network = networkOptsToJSON(opts.network);
2224
2595
  } else if (opts?.allowInternetAccess === false) {
@@ -2236,9 +2607,11 @@ var Sandbox = class _Sandbox {
2236
2607
  if (opts?.volumes && opts.volumes.length > 0) {
2237
2608
  body.volumes = opts.volumes.map(volumeAttachmentToJSON);
2238
2609
  }
2610
+ const idempotencyKey = newIdempotencyKey();
2239
2611
  const data = await client.post("/sandboxes", {
2240
2612
  json: body,
2241
- timeout: opts?.requestTimeout
2613
+ timeout: opts?.requestTimeout,
2614
+ ...idempotencyKey ? { headers: { "Idempotency-Key": idempotencyKey } } : {}
2242
2615
  });
2243
2616
  const sandboxId = data.sandbox_id;
2244
2617
  assertValidId(sandboxId, "sandbox ID (from server)");
@@ -3122,7 +3495,16 @@ function assertValidVolumeId3(id) {
3122
3495
  }
3123
3496
  }
3124
3497
  var Volumes = class {
3125
- /** Create a volume by streaming a tarball (gzip tar.gz) to the server. */
3498
+ /**
3499
+ * Create a volume named `name`, optionally populated with `data`.
3500
+ *
3501
+ * `POST /volumes` is the canonical create endpoint. With `data` (a gzip tar.gz)
3502
+ * the body is ingested into a new file-granular volume (or a legacy tarball
3503
+ * blob if no file-granular backend is configured). Creating an empty volume
3504
+ * (no `data`, or an empty buffer) requires a file-granular backend.
3505
+ * `empty(name)` / `ingest(name, data)` remain available for explicit,
3506
+ * backend-specific control.
3507
+ */
3126
3508
  static async create(name, data, opts) {
3127
3509
  if (!name) {
3128
3510
  throw new InvalidArgumentError("volume name is required");
@@ -3134,6 +3516,13 @@ var Volumes = class {
3134
3516
  requestTimeout: opts?.requestTimeout
3135
3517
  });
3136
3518
  const client = getSharedClient(config);
3519
+ if (data === void 0 || data.byteLength === 0) {
3520
+ const resp2 = await client.post("/volumes", {
3521
+ params: { name },
3522
+ timeout: opts?.requestTimeout
3523
+ });
3524
+ return parseVolumeInfo(resp2);
3525
+ }
3137
3526
  const body = data instanceof Uint8Array ? data : new Uint8Array(data);
3138
3527
  const resp = await client.post("/volumes", {
3139
3528
  params: { name },
@@ -3403,6 +3792,9 @@ export {
3403
3792
  ApiClient,
3404
3793
  AuthenticationError,
3405
3794
  BuildError,
3795
+ CODE_IDEMPOTENCY_IN_PROGRESS,
3796
+ CODE_IDEMPOTENCY_KEY_REUSED,
3797
+ CODE_TEMPLATE_NOT_READY,
3406
3798
  CommandExitError,
3407
3799
  CommandHandle,
3408
3800
  Commands,
@@ -3437,6 +3829,7 @@ export {
3437
3829
  TemplateError,
3438
3830
  TimeoutError,
3439
3831
  TransformDirection,
3832
+ Vault,
3440
3833
  VolumeFiles,
3441
3834
  VolumeLocks,
3442
3835
  Volumes,
@@ -3488,6 +3881,9 @@ export {
3488
3881
  parseSnapshotInfo,
3489
3882
  parseTemplateBuildStatus,
3490
3883
  parseToxicityConfig,
3884
+ parseVaultPreset,
3885
+ parseVaultScope,
3886
+ parseVaultSecret,
3491
3887
  parseVolumeInfo,
3492
3888
  parseWriteInfo,
3493
3889
  requiresTlsInterception,
@@ -3495,6 +3891,7 @@ export {
3495
3891
  securityPolicyToJSON,
3496
3892
  toxicityConfigToJSON,
3497
3893
  validateNetworkEntry,
3894
+ vaultScopeToJSON,
3498
3895
  volumeAttachmentToJSON
3499
3896
  };
3500
3897
  //# sourceMappingURL=index.js.map