@declaw/sdk 1.3.0 → 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.d.cts CHANGED
@@ -88,6 +88,17 @@ declare class ApiClient {
88
88
  private buildUrl;
89
89
  private buildHeaders;
90
90
  private requestWithRetry;
91
+ /**
92
+ * Read an error body ONCE.
93
+ *
94
+ * `Response` bodies are single-read streams, so the 409 path cannot inspect
95
+ * the code and then hand the response to a separate error builder — the
96
+ * second read yields nothing and the error loses its message. Everything that
97
+ * needs the body goes through here, and the parsed result is passed around
98
+ * instead of the response.
99
+ */
100
+ private readErrorBody;
101
+ private errorFrom;
91
102
  private buildError;
92
103
  private parseResponseBody;
93
104
  /**
@@ -98,6 +109,37 @@ declare class ApiClient {
98
109
  declare function getSharedClient(config: ConnectionConfig): ApiClient;
99
110
  declare function resetSharedClients(): void;
100
111
 
112
+ /**
113
+ * Idempotency keys and retry pacing for `POST /sandboxes`.
114
+ *
115
+ * Note this SDK already jitters its backoff (see `ApiClient.delay` —
116
+ * exponential with an equal-jitter multiplier), unlike the Go and Python
117
+ * clients which used a deterministic `delay * attempt`. Only the key and the
118
+ * response-code handling are new here.
119
+ */
120
+ /**
121
+ * Machine-readable error codes returned by `POST /sandboxes`.
122
+ *
123
+ * Branch on these, never on the message. It matters most where one status means
124
+ * several unrelated things, and only one of them is retryable.
125
+ */
126
+ /**
127
+ * 409 — the original create carrying this key is still running. Retrying the
128
+ * IDENTICAL request is correct, and is how a caller recovers the sandbox ID
129
+ * after a lost response. `Retry-After` is set.
130
+ */
131
+ declare const CODE_IDEMPOTENCY_IN_PROGRESS = "idempotency_in_progress";
132
+ /**
133
+ * 422 — the key was already used with different parameters. Not retryable; the
134
+ * caller must generate a fresh key per logical create.
135
+ */
136
+ declare const CODE_IDEMPOTENCY_KEY_REUSED = "idempotency_key_reused";
137
+ /**
138
+ * 409 — unrelated to idempotency; the template needs a rebuild. Retrying the
139
+ * request unchanged cannot fix it.
140
+ */
141
+ declare const CODE_TEMPLATE_NOT_READY = "template_not_ready";
142
+
101
143
  /** CIDR for all traffic. */
102
144
  declare const ALL_TRAFFIC = "0.0.0.0/0";
103
145
  /** Network configuration options for a sandbox. */
@@ -1523,38 +1565,54 @@ declare class Sandbox {
1523
1565
  */
1524
1566
  declare class SandboxError extends Error {
1525
1567
  sandboxId?: string;
1568
+ /**
1569
+ * Machine-readable error code from the API's `code` field, when present.
1570
+ *
1571
+ * Branch on this, never on `message`. Messages are prose and change; codes are
1572
+ * contract. It matters most where one status means several unrelated things:
1573
+ * a 409 from `POST /sandboxes` is either `idempotency_in_progress` (the
1574
+ * original create is still running — retry the identical request) or
1575
+ * `template_not_ready` (rebuild the template; retrying cannot help).
1576
+ */
1577
+ code?: string;
1526
1578
  constructor(message: string, opts?: {
1527
1579
  sandboxId?: string;
1580
+ code?: string;
1528
1581
  });
1529
1582
  }
1530
1583
  /** Thrown when an operation exceeds its timeout. */
1531
1584
  declare class TimeoutError extends SandboxError {
1532
1585
  constructor(message: string, opts?: {
1533
1586
  sandboxId?: string;
1587
+ code?: string;
1534
1588
  });
1535
1589
  }
1536
1590
  /** Thrown when a sandbox or resource is not found. */
1537
1591
  declare class NotFoundError extends SandboxError {
1538
1592
  constructor(message: string, opts?: {
1539
1593
  sandboxId?: string;
1594
+ code?: string;
1540
1595
  });
1541
1596
  }
1542
1597
  /** Thrown when authentication fails. */
1543
1598
  declare class AuthenticationError extends SandboxError {
1544
1599
  constructor(message: string, opts?: {
1545
1600
  sandboxId?: string;
1601
+ code?: string;
1546
1602
  });
1547
1603
  }
1548
1604
  /** Thrown when an argument is invalid. */
1549
1605
  declare class InvalidArgumentError extends SandboxError {
1550
1606
  constructor(message: string, opts?: {
1551
1607
  sandboxId?: string;
1608
+ code?: string;
1552
1609
  });
1553
1610
  }
1554
1611
  /** Thrown when there is not enough disk space. */
1555
1612
  declare class NotEnoughSpaceError extends SandboxError {
1556
1613
  constructor(message: string, opts?: {
1557
1614
  sandboxId?: string;
1615
+ code?: string;
1558
1616
  });
1559
1617
  }
1560
1618
  /**
@@ -1569,36 +1627,42 @@ declare class NotEnoughSpaceError extends SandboxError {
1569
1627
  declare class ConflictError extends SandboxError {
1570
1628
  constructor(message: string, opts?: {
1571
1629
  sandboxId?: string;
1630
+ code?: string;
1572
1631
  });
1573
1632
  }
1574
1633
  /** Thrown for template-related errors. */
1575
1634
  declare class TemplateError extends SandboxError {
1576
1635
  constructor(message: string, opts?: {
1577
1636
  sandboxId?: string;
1637
+ code?: string;
1578
1638
  });
1579
1639
  }
1580
1640
  /** Thrown when a template build fails. */
1581
1641
  declare class BuildError extends TemplateError {
1582
1642
  constructor(message: string, opts?: {
1583
1643
  sandboxId?: string;
1644
+ code?: string;
1584
1645
  });
1585
1646
  }
1586
1647
  /** Thrown when a file upload fails. */
1587
1648
  declare class FileUploadError extends SandboxError {
1588
1649
  constructor(message: string, opts?: {
1589
1650
  sandboxId?: string;
1651
+ code?: string;
1590
1652
  });
1591
1653
  }
1592
1654
  /** Thrown when git authentication fails inside a sandbox. */
1593
1655
  declare class GitAuthError extends SandboxError {
1594
1656
  constructor(message: string, opts?: {
1595
1657
  sandboxId?: string;
1658
+ code?: string;
1596
1659
  });
1597
1660
  }
1598
1661
  /** Thrown when a git upstream operation fails. */
1599
1662
  declare class GitUpstreamError extends SandboxError {
1600
1663
  constructor(message: string, opts?: {
1601
1664
  sandboxId?: string;
1665
+ code?: string;
1602
1666
  });
1603
1667
  }
1604
1668
  /** Thrown when a command exits with a non-zero exit code. */
@@ -2150,4 +2214,4 @@ declare class Vault {
2150
2214
  private static _resolveSecretId;
2151
2215
  }
2152
2216
 
2153
- export { ALL_TRAFFIC, ApiClient, type AuditConfig, type AuditEntry, AuthenticationError, BuildError, type BuildInfo, type CodeSecurityConfig, CommandExitError, CommandHandle, type CommandResult, type CommandWaitOpts, Commands, ConflictError, ConnectionConfig, type ConnectionConfigOptions, type ContentGateConfig, type CopyItem, type CreateSecretInput, DEFAULT_MASK_PATTERNS, type EntryInfo, type EnvSecurityConfig, type FileEntry, type FileInfo, FileType, FileUploadError, Filesystem, type FilesystemEvent, FilesystemEventType, type FullInjectionDefenseOptions, type GetBuildStatusOpts, GitAuthError, GitUpstreamError, Governance, type GovernanceAdvisory, type GovernanceControl, type GovernancePack, type GovernanceRequestOpts, InjectionAction, type InjectionDefenseConfig, type InjectionJudgeConfig, InjectionSensitivity, InvalidArgumentError, type InvisibleTextConfig, type LockLease, type LockStatus, type NetworkPolicy, NotEnoughSpaceError, NotFoundError, type PIIConfig, PIIType, type ProcessInfo, Pty, type PtyConnectOpts, type PtyCreateOpts, PtyHandle, type PtyOutput, type PtyResult, type PtySize, RedactionAction, type RequestOpts, type RunOpts, type RunStreamOpts, Sandbox, SandboxError, type SandboxInfo, type SandboxLifecycle, type SandboxMetrics, type SandboxNetworkOpts, type SandboxOpts, SandboxPaginator, type SandboxQuery, SandboxState, type SecureEnvVar, type SecurityPolicy, type Snapshot, type SnapshotInfo, SnapshotPaginator, type SnapshotSource, type Stderr, Stdio, StdioProcess, type StdioResult, type StdioStartOpts, type Stdout, Template, TemplateBase, type TemplateBuildOpts, type TemplateBuildStatus, TemplateError, TimeoutError, type ToxicityConfig, TransformDirection, type TransformationRule, Vault, type VaultPreset, type VaultRequestOpts, type VaultScope, type VaultSecret, type VolumeAttachMode, type VolumeAttachment, type VolumeCreateOpts, VolumeFiles, type VolumeInfo, VolumeLocks, type VolumeRemoveOpts, type VolumeRequestOpts, type VolumeWriteOpts, Volumes, WatchHandle, type WriteEntry, type WriteInfo, applyTransformation, codeSecurityConfigToJSON, contentGateConfigToJSON, createAuditConfig, createCodeSecurityConfig, createContentGateConfig, createEnvSecurityConfig, createInjectionDefenseConfig, createInvisibleTextConfig, createNetworkPolicy, createPIIConfig, createSecurityPolicy, createToxicityConfig, createTransformationRule, domainMatches, fullInjectionDefensePolicy, getSharedClient, invisibleTextConfigToJSON, isSensitive, networkPolicyToOpts, parseAuditConfig, parseAuditEntry, parseBuildInfo, parseCodeSecurityConfig, parseCommandResult, parseContentGateConfig, parseEntryInfo, parseEnvSecurityConfig, parseFileEntry, parseFileInfo, parseFilesystemEvent, parseGovernancePack, parseInjectionDefenseConfig, parseInvisibleTextConfig, parseLockLease, parseLockStatus, parseNetworkPolicy, parsePIIConfig, parseProcessInfo, parseSandboxInfo, parseSandboxLifecycle, parseSandboxMetrics, parseSecurityPolicy, parseSnapshot, parseSnapshotInfo, parseTemplateBuildStatus, parseToxicityConfig, parseVaultPreset, parseVaultScope, parseVaultSecret, parseVolumeInfo, parseWriteInfo, requiresTlsInterception, resetSharedClients, securityPolicyToJSON, toxicityConfigToJSON, validateNetworkEntry, vaultScopeToJSON, volumeAttachmentToJSON };
2217
+ export { ALL_TRAFFIC, ApiClient, type AuditConfig, type AuditEntry, AuthenticationError, BuildError, type BuildInfo, CODE_IDEMPOTENCY_IN_PROGRESS, CODE_IDEMPOTENCY_KEY_REUSED, CODE_TEMPLATE_NOT_READY, type CodeSecurityConfig, CommandExitError, CommandHandle, type CommandResult, type CommandWaitOpts, Commands, ConflictError, ConnectionConfig, type ConnectionConfigOptions, type ContentGateConfig, type CopyItem, type CreateSecretInput, DEFAULT_MASK_PATTERNS, type EntryInfo, type EnvSecurityConfig, type FileEntry, type FileInfo, FileType, FileUploadError, Filesystem, type FilesystemEvent, FilesystemEventType, type FullInjectionDefenseOptions, type GetBuildStatusOpts, GitAuthError, GitUpstreamError, Governance, type GovernanceAdvisory, type GovernanceControl, type GovernancePack, type GovernanceRequestOpts, InjectionAction, type InjectionDefenseConfig, type InjectionJudgeConfig, InjectionSensitivity, InvalidArgumentError, type InvisibleTextConfig, type LockLease, type LockStatus, type NetworkPolicy, NotEnoughSpaceError, NotFoundError, type PIIConfig, PIIType, type ProcessInfo, Pty, type PtyConnectOpts, type PtyCreateOpts, PtyHandle, type PtyOutput, type PtyResult, type PtySize, RedactionAction, type RequestOpts, type RunOpts, type RunStreamOpts, Sandbox, SandboxError, type SandboxInfo, type SandboxLifecycle, type SandboxMetrics, type SandboxNetworkOpts, type SandboxOpts, SandboxPaginator, type SandboxQuery, SandboxState, type SecureEnvVar, type SecurityPolicy, type Snapshot, type SnapshotInfo, SnapshotPaginator, type SnapshotSource, type Stderr, Stdio, StdioProcess, type StdioResult, type StdioStartOpts, type Stdout, Template, TemplateBase, type TemplateBuildOpts, type TemplateBuildStatus, TemplateError, TimeoutError, type ToxicityConfig, TransformDirection, type TransformationRule, Vault, type VaultPreset, type VaultRequestOpts, type VaultScope, type VaultSecret, type VolumeAttachMode, type VolumeAttachment, type VolumeCreateOpts, VolumeFiles, type VolumeInfo, VolumeLocks, type VolumeRemoveOpts, type VolumeRequestOpts, type VolumeWriteOpts, Volumes, WatchHandle, type WriteEntry, type WriteInfo, applyTransformation, codeSecurityConfigToJSON, contentGateConfigToJSON, createAuditConfig, createCodeSecurityConfig, createContentGateConfig, createEnvSecurityConfig, createInjectionDefenseConfig, createInvisibleTextConfig, createNetworkPolicy, createPIIConfig, createSecurityPolicy, createToxicityConfig, createTransformationRule, domainMatches, fullInjectionDefensePolicy, getSharedClient, invisibleTextConfigToJSON, isSensitive, networkPolicyToOpts, parseAuditConfig, parseAuditEntry, parseBuildInfo, parseCodeSecurityConfig, parseCommandResult, parseContentGateConfig, parseEntryInfo, parseEnvSecurityConfig, parseFileEntry, parseFileInfo, parseFilesystemEvent, parseGovernancePack, parseInjectionDefenseConfig, parseInvisibleTextConfig, parseLockLease, parseLockStatus, parseNetworkPolicy, parsePIIConfig, parseProcessInfo, parseSandboxInfo, parseSandboxLifecycle, parseSandboxMetrics, parseSecurityPolicy, parseSnapshot, parseSnapshotInfo, parseTemplateBuildStatus, parseToxicityConfig, parseVaultPreset, parseVaultScope, parseVaultSecret, parseVolumeInfo, parseWriteInfo, requiresTlsInterception, resetSharedClients, securityPolicyToJSON, toxicityConfigToJSON, validateNetworkEntry, vaultScopeToJSON, volumeAttachmentToJSON };
package/dist/index.d.ts CHANGED
@@ -88,6 +88,17 @@ declare class ApiClient {
88
88
  private buildUrl;
89
89
  private buildHeaders;
90
90
  private requestWithRetry;
91
+ /**
92
+ * Read an error body ONCE.
93
+ *
94
+ * `Response` bodies are single-read streams, so the 409 path cannot inspect
95
+ * the code and then hand the response to a separate error builder — the
96
+ * second read yields nothing and the error loses its message. Everything that
97
+ * needs the body goes through here, and the parsed result is passed around
98
+ * instead of the response.
99
+ */
100
+ private readErrorBody;
101
+ private errorFrom;
91
102
  private buildError;
92
103
  private parseResponseBody;
93
104
  /**
@@ -98,6 +109,37 @@ declare class ApiClient {
98
109
  declare function getSharedClient(config: ConnectionConfig): ApiClient;
99
110
  declare function resetSharedClients(): void;
100
111
 
112
+ /**
113
+ * Idempotency keys and retry pacing for `POST /sandboxes`.
114
+ *
115
+ * Note this SDK already jitters its backoff (see `ApiClient.delay` —
116
+ * exponential with an equal-jitter multiplier), unlike the Go and Python
117
+ * clients which used a deterministic `delay * attempt`. Only the key and the
118
+ * response-code handling are new here.
119
+ */
120
+ /**
121
+ * Machine-readable error codes returned by `POST /sandboxes`.
122
+ *
123
+ * Branch on these, never on the message. It matters most where one status means
124
+ * several unrelated things, and only one of them is retryable.
125
+ */
126
+ /**
127
+ * 409 — the original create carrying this key is still running. Retrying the
128
+ * IDENTICAL request is correct, and is how a caller recovers the sandbox ID
129
+ * after a lost response. `Retry-After` is set.
130
+ */
131
+ declare const CODE_IDEMPOTENCY_IN_PROGRESS = "idempotency_in_progress";
132
+ /**
133
+ * 422 — the key was already used with different parameters. Not retryable; the
134
+ * caller must generate a fresh key per logical create.
135
+ */
136
+ declare const CODE_IDEMPOTENCY_KEY_REUSED = "idempotency_key_reused";
137
+ /**
138
+ * 409 — unrelated to idempotency; the template needs a rebuild. Retrying the
139
+ * request unchanged cannot fix it.
140
+ */
141
+ declare const CODE_TEMPLATE_NOT_READY = "template_not_ready";
142
+
101
143
  /** CIDR for all traffic. */
102
144
  declare const ALL_TRAFFIC = "0.0.0.0/0";
103
145
  /** Network configuration options for a sandbox. */
@@ -1523,38 +1565,54 @@ declare class Sandbox {
1523
1565
  */
1524
1566
  declare class SandboxError extends Error {
1525
1567
  sandboxId?: string;
1568
+ /**
1569
+ * Machine-readable error code from the API's `code` field, when present.
1570
+ *
1571
+ * Branch on this, never on `message`. Messages are prose and change; codes are
1572
+ * contract. It matters most where one status means several unrelated things:
1573
+ * a 409 from `POST /sandboxes` is either `idempotency_in_progress` (the
1574
+ * original create is still running — retry the identical request) or
1575
+ * `template_not_ready` (rebuild the template; retrying cannot help).
1576
+ */
1577
+ code?: string;
1526
1578
  constructor(message: string, opts?: {
1527
1579
  sandboxId?: string;
1580
+ code?: string;
1528
1581
  });
1529
1582
  }
1530
1583
  /** Thrown when an operation exceeds its timeout. */
1531
1584
  declare class TimeoutError extends SandboxError {
1532
1585
  constructor(message: string, opts?: {
1533
1586
  sandboxId?: string;
1587
+ code?: string;
1534
1588
  });
1535
1589
  }
1536
1590
  /** Thrown when a sandbox or resource is not found. */
1537
1591
  declare class NotFoundError extends SandboxError {
1538
1592
  constructor(message: string, opts?: {
1539
1593
  sandboxId?: string;
1594
+ code?: string;
1540
1595
  });
1541
1596
  }
1542
1597
  /** Thrown when authentication fails. */
1543
1598
  declare class AuthenticationError extends SandboxError {
1544
1599
  constructor(message: string, opts?: {
1545
1600
  sandboxId?: string;
1601
+ code?: string;
1546
1602
  });
1547
1603
  }
1548
1604
  /** Thrown when an argument is invalid. */
1549
1605
  declare class InvalidArgumentError extends SandboxError {
1550
1606
  constructor(message: string, opts?: {
1551
1607
  sandboxId?: string;
1608
+ code?: string;
1552
1609
  });
1553
1610
  }
1554
1611
  /** Thrown when there is not enough disk space. */
1555
1612
  declare class NotEnoughSpaceError extends SandboxError {
1556
1613
  constructor(message: string, opts?: {
1557
1614
  sandboxId?: string;
1615
+ code?: string;
1558
1616
  });
1559
1617
  }
1560
1618
  /**
@@ -1569,36 +1627,42 @@ declare class NotEnoughSpaceError extends SandboxError {
1569
1627
  declare class ConflictError extends SandboxError {
1570
1628
  constructor(message: string, opts?: {
1571
1629
  sandboxId?: string;
1630
+ code?: string;
1572
1631
  });
1573
1632
  }
1574
1633
  /** Thrown for template-related errors. */
1575
1634
  declare class TemplateError extends SandboxError {
1576
1635
  constructor(message: string, opts?: {
1577
1636
  sandboxId?: string;
1637
+ code?: string;
1578
1638
  });
1579
1639
  }
1580
1640
  /** Thrown when a template build fails. */
1581
1641
  declare class BuildError extends TemplateError {
1582
1642
  constructor(message: string, opts?: {
1583
1643
  sandboxId?: string;
1644
+ code?: string;
1584
1645
  });
1585
1646
  }
1586
1647
  /** Thrown when a file upload fails. */
1587
1648
  declare class FileUploadError extends SandboxError {
1588
1649
  constructor(message: string, opts?: {
1589
1650
  sandboxId?: string;
1651
+ code?: string;
1590
1652
  });
1591
1653
  }
1592
1654
  /** Thrown when git authentication fails inside a sandbox. */
1593
1655
  declare class GitAuthError extends SandboxError {
1594
1656
  constructor(message: string, opts?: {
1595
1657
  sandboxId?: string;
1658
+ code?: string;
1596
1659
  });
1597
1660
  }
1598
1661
  /** Thrown when a git upstream operation fails. */
1599
1662
  declare class GitUpstreamError extends SandboxError {
1600
1663
  constructor(message: string, opts?: {
1601
1664
  sandboxId?: string;
1665
+ code?: string;
1602
1666
  });
1603
1667
  }
1604
1668
  /** Thrown when a command exits with a non-zero exit code. */
@@ -2150,4 +2214,4 @@ declare class Vault {
2150
2214
  private static _resolveSecretId;
2151
2215
  }
2152
2216
 
2153
- export { ALL_TRAFFIC, ApiClient, type AuditConfig, type AuditEntry, AuthenticationError, BuildError, type BuildInfo, type CodeSecurityConfig, CommandExitError, CommandHandle, type CommandResult, type CommandWaitOpts, Commands, ConflictError, ConnectionConfig, type ConnectionConfigOptions, type ContentGateConfig, type CopyItem, type CreateSecretInput, DEFAULT_MASK_PATTERNS, type EntryInfo, type EnvSecurityConfig, type FileEntry, type FileInfo, FileType, FileUploadError, Filesystem, type FilesystemEvent, FilesystemEventType, type FullInjectionDefenseOptions, type GetBuildStatusOpts, GitAuthError, GitUpstreamError, Governance, type GovernanceAdvisory, type GovernanceControl, type GovernancePack, type GovernanceRequestOpts, InjectionAction, type InjectionDefenseConfig, type InjectionJudgeConfig, InjectionSensitivity, InvalidArgumentError, type InvisibleTextConfig, type LockLease, type LockStatus, type NetworkPolicy, NotEnoughSpaceError, NotFoundError, type PIIConfig, PIIType, type ProcessInfo, Pty, type PtyConnectOpts, type PtyCreateOpts, PtyHandle, type PtyOutput, type PtyResult, type PtySize, RedactionAction, type RequestOpts, type RunOpts, type RunStreamOpts, Sandbox, SandboxError, type SandboxInfo, type SandboxLifecycle, type SandboxMetrics, type SandboxNetworkOpts, type SandboxOpts, SandboxPaginator, type SandboxQuery, SandboxState, type SecureEnvVar, type SecurityPolicy, type Snapshot, type SnapshotInfo, SnapshotPaginator, type SnapshotSource, type Stderr, Stdio, StdioProcess, type StdioResult, type StdioStartOpts, type Stdout, Template, TemplateBase, type TemplateBuildOpts, type TemplateBuildStatus, TemplateError, TimeoutError, type ToxicityConfig, TransformDirection, type TransformationRule, Vault, type VaultPreset, type VaultRequestOpts, type VaultScope, type VaultSecret, type VolumeAttachMode, type VolumeAttachment, type VolumeCreateOpts, VolumeFiles, type VolumeInfo, VolumeLocks, type VolumeRemoveOpts, type VolumeRequestOpts, type VolumeWriteOpts, Volumes, WatchHandle, type WriteEntry, type WriteInfo, applyTransformation, codeSecurityConfigToJSON, contentGateConfigToJSON, createAuditConfig, createCodeSecurityConfig, createContentGateConfig, createEnvSecurityConfig, createInjectionDefenseConfig, createInvisibleTextConfig, createNetworkPolicy, createPIIConfig, createSecurityPolicy, createToxicityConfig, createTransformationRule, domainMatches, fullInjectionDefensePolicy, getSharedClient, invisibleTextConfigToJSON, isSensitive, networkPolicyToOpts, parseAuditConfig, parseAuditEntry, parseBuildInfo, parseCodeSecurityConfig, parseCommandResult, parseContentGateConfig, parseEntryInfo, parseEnvSecurityConfig, parseFileEntry, parseFileInfo, parseFilesystemEvent, parseGovernancePack, parseInjectionDefenseConfig, parseInvisibleTextConfig, parseLockLease, parseLockStatus, parseNetworkPolicy, parsePIIConfig, parseProcessInfo, parseSandboxInfo, parseSandboxLifecycle, parseSandboxMetrics, parseSecurityPolicy, parseSnapshot, parseSnapshotInfo, parseTemplateBuildStatus, parseToxicityConfig, parseVaultPreset, parseVaultScope, parseVaultSecret, parseVolumeInfo, parseWriteInfo, requiresTlsInterception, resetSharedClients, securityPolicyToJSON, toxicityConfigToJSON, validateNetworkEntry, vaultScopeToJSON, volumeAttachmentToJSON };
2217
+ export { ALL_TRAFFIC, ApiClient, type AuditConfig, type AuditEntry, AuthenticationError, BuildError, type BuildInfo, CODE_IDEMPOTENCY_IN_PROGRESS, CODE_IDEMPOTENCY_KEY_REUSED, CODE_TEMPLATE_NOT_READY, type CodeSecurityConfig, CommandExitError, CommandHandle, type CommandResult, type CommandWaitOpts, Commands, ConflictError, ConnectionConfig, type ConnectionConfigOptions, type ContentGateConfig, type CopyItem, type CreateSecretInput, DEFAULT_MASK_PATTERNS, type EntryInfo, type EnvSecurityConfig, type FileEntry, type FileInfo, FileType, FileUploadError, Filesystem, type FilesystemEvent, FilesystemEventType, type FullInjectionDefenseOptions, type GetBuildStatusOpts, GitAuthError, GitUpstreamError, Governance, type GovernanceAdvisory, type GovernanceControl, type GovernancePack, type GovernanceRequestOpts, InjectionAction, type InjectionDefenseConfig, type InjectionJudgeConfig, InjectionSensitivity, InvalidArgumentError, type InvisibleTextConfig, type LockLease, type LockStatus, type NetworkPolicy, NotEnoughSpaceError, NotFoundError, type PIIConfig, PIIType, type ProcessInfo, Pty, type PtyConnectOpts, type PtyCreateOpts, PtyHandle, type PtyOutput, type PtyResult, type PtySize, RedactionAction, type RequestOpts, type RunOpts, type RunStreamOpts, Sandbox, SandboxError, type SandboxInfo, type SandboxLifecycle, type SandboxMetrics, type SandboxNetworkOpts, type SandboxOpts, SandboxPaginator, type SandboxQuery, SandboxState, type SecureEnvVar, type SecurityPolicy, type Snapshot, type SnapshotInfo, SnapshotPaginator, type SnapshotSource, type Stderr, Stdio, StdioProcess, type StdioResult, type StdioStartOpts, type Stdout, Template, TemplateBase, type TemplateBuildOpts, type TemplateBuildStatus, TemplateError, TimeoutError, type ToxicityConfig, TransformDirection, type TransformationRule, Vault, type VaultPreset, type VaultRequestOpts, type VaultScope, type VaultSecret, type VolumeAttachMode, type VolumeAttachment, type VolumeCreateOpts, VolumeFiles, type VolumeInfo, VolumeLocks, type VolumeRemoveOpts, type VolumeRequestOpts, type VolumeWriteOpts, Volumes, WatchHandle, type WriteEntry, type WriteInfo, applyTransformation, codeSecurityConfigToJSON, contentGateConfigToJSON, createAuditConfig, createCodeSecurityConfig, createContentGateConfig, createEnvSecurityConfig, createInjectionDefenseConfig, createInvisibleTextConfig, createNetworkPolicy, createPIIConfig, createSecurityPolicy, createToxicityConfig, createTransformationRule, domainMatches, fullInjectionDefensePolicy, getSharedClient, invisibleTextConfigToJSON, isSensitive, networkPolicyToOpts, parseAuditConfig, parseAuditEntry, parseBuildInfo, parseCodeSecurityConfig, parseCommandResult, parseContentGateConfig, parseEntryInfo, parseEnvSecurityConfig, parseFileEntry, parseFileInfo, parseFilesystemEvent, parseGovernancePack, parseInjectionDefenseConfig, parseInvisibleTextConfig, parseLockLease, parseLockStatus, parseNetworkPolicy, parsePIIConfig, parseProcessInfo, parseSandboxInfo, parseSandboxLifecycle, parseSandboxMetrics, parseSecurityPolicy, parseSnapshot, parseSnapshotInfo, parseTemplateBuildStatus, parseToxicityConfig, parseVaultPreset, parseVaultScope, parseVaultSecret, parseVolumeInfo, parseWriteInfo, requiresTlsInterception, resetSharedClients, securityPolicyToJSON, toxicityConfigToJSON, validateNetworkEntry, vaultScopeToJSON, volumeAttachmentToJSON };
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");
@@ -2544,9 +2607,11 @@ var Sandbox = class _Sandbox {
2544
2607
  if (opts?.volumes && opts.volumes.length > 0) {
2545
2608
  body.volumes = opts.volumes.map(volumeAttachmentToJSON);
2546
2609
  }
2610
+ const idempotencyKey = newIdempotencyKey();
2547
2611
  const data = await client.post("/sandboxes", {
2548
2612
  json: body,
2549
- timeout: opts?.requestTimeout
2613
+ timeout: opts?.requestTimeout,
2614
+ ...idempotencyKey ? { headers: { "Idempotency-Key": idempotencyKey } } : {}
2550
2615
  });
2551
2616
  const sandboxId = data.sandbox_id;
2552
2617
  assertValidId(sandboxId, "sandbox ID (from server)");
@@ -3727,6 +3792,9 @@ export {
3727
3792
  ApiClient,
3728
3793
  AuthenticationError,
3729
3794
  BuildError,
3795
+ CODE_IDEMPOTENCY_IN_PROGRESS,
3796
+ CODE_IDEMPOTENCY_KEY_REUSED,
3797
+ CODE_TEMPLATE_NOT_READY,
3730
3798
  CommandExitError,
3731
3799
  CommandHandle,
3732
3800
  Commands,