@enclave-run/sdk 0.2.0 → 0.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.mts CHANGED
@@ -2834,8 +2834,6 @@ interface components {
2834
2834
  network?: components["schemas"]["SandboxNetworkConfig"];
2835
2835
  /** @description Optional region code for sandbox placement. When omitted, Enclave automatically selects a placement region. */
2836
2836
  region?: string;
2837
- /** @description Secure all system communication with sandbox */
2838
- secure?: boolean;
2839
2837
  /** @description Identifier of the required template */
2840
2838
  templateID: string;
2841
2839
  /**
@@ -4350,6 +4348,15 @@ type StartRequest = Message<"process.StartRequest"> & {
4350
4348
  * @generated from field: optional bool stdin = 4;
4351
4349
  */
4352
4350
  stdin?: boolean;
4351
+ /**
4352
+ * A retried Start with the same key attaches to the process the first
4353
+ * Start launched (replaying its retained output) instead of running the
4354
+ * command again. Keys are kept while the process runs and for a short
4355
+ * retention window after it exits.
4356
+ *
4357
+ * @generated from field: optional string idempotency_key = 5;
4358
+ */
4359
+ idempotencyKey?: string;
4353
4360
  };
4354
4361
  /**
4355
4362
  * Describes the message process.StartRequest.
@@ -4418,6 +4425,15 @@ type ProcessEvent = Message<"process.ProcessEvent"> & {
4418
4425
  case: undefined;
4419
4426
  value?: undefined;
4420
4427
  };
4428
+ /**
4429
+ * Per-process position of a data or end event, starting at 1. Start and
4430
+ * keepalive events carry 0. A client that reconnects with
4431
+ * ConnectRequest.after_sequence receives every retained event after it;
4432
+ * a jump in the sequence means older output was evicted.
4433
+ *
4434
+ * @generated from field: uint64 sequence = 5;
4435
+ */
4436
+ sequence: bigint;
4421
4437
  };
4422
4438
  /**
4423
4439
  * @generated from message process.ProcessEvent.StartEvent
@@ -4686,6 +4702,15 @@ type ConnectRequest = Message<"process.ConnectRequest"> & {
4686
4702
  * @generated from field: process.ProcessSelector process = 1;
4687
4703
  */
4688
4704
  process?: ProcessSelector;
4705
+ /**
4706
+ * Replay retained events with a greater sequence before streaming live
4707
+ * ones. Unset streams live events only. An exited process stays
4708
+ * connectable for a short retention window and always ends with its
4709
+ * end event (exit code).
4710
+ *
4711
+ * @generated from field: optional uint64 after_sequence = 2;
4712
+ */
4713
+ afterSequence?: bigint;
4689
4714
  };
4690
4715
  /**
4691
4716
  * Describes the message process.ConnectRequest.
@@ -7283,12 +7308,6 @@ interface SandboxOpts extends ConnectionOpts {
7283
7308
  * @default 300_000 // 5 minutes
7284
7309
  */
7285
7310
  timeoutMs?: number;
7286
- /**
7287
- * Secure all traffic coming to the sandbox controller with auth token
7288
- *
7289
- * @default true
7290
- */
7291
- secure?: boolean;
7292
7311
  /**
7293
7312
  * Allow sandbox to access the internet. If set to `False`, it works the same as setting network `denyOut` to `[0.0.0.0/0]`.
7294
7313
  *
@@ -7905,6 +7924,12 @@ declare class Commands {
7905
7924
  * @internal
7906
7925
  */
7907
7926
  get supportsStdinClose(): boolean;
7927
+ /**
7928
+ * sbxd 1.1.0+ numbers process output and accepts idempotent starts, so a
7929
+ * dropped command stream can be resumed without losing or repeating
7930
+ * output, and a retried start never runs the command twice.
7931
+ */
7932
+ private get supportsProcessResume();
7908
7933
  /**
7909
7934
  * List all running commands and PTY sessions.
7910
7935
  *
package/dist/index.d.ts CHANGED
@@ -2834,8 +2834,6 @@ interface components {
2834
2834
  network?: components["schemas"]["SandboxNetworkConfig"];
2835
2835
  /** @description Optional region code for sandbox placement. When omitted, Enclave automatically selects a placement region. */
2836
2836
  region?: string;
2837
- /** @description Secure all system communication with sandbox */
2838
- secure?: boolean;
2839
2837
  /** @description Identifier of the required template */
2840
2838
  templateID: string;
2841
2839
  /**
@@ -4350,6 +4348,15 @@ type StartRequest = Message<"process.StartRequest"> & {
4350
4348
  * @generated from field: optional bool stdin = 4;
4351
4349
  */
4352
4350
  stdin?: boolean;
4351
+ /**
4352
+ * A retried Start with the same key attaches to the process the first
4353
+ * Start launched (replaying its retained output) instead of running the
4354
+ * command again. Keys are kept while the process runs and for a short
4355
+ * retention window after it exits.
4356
+ *
4357
+ * @generated from field: optional string idempotency_key = 5;
4358
+ */
4359
+ idempotencyKey?: string;
4353
4360
  };
4354
4361
  /**
4355
4362
  * Describes the message process.StartRequest.
@@ -4418,6 +4425,15 @@ type ProcessEvent = Message<"process.ProcessEvent"> & {
4418
4425
  case: undefined;
4419
4426
  value?: undefined;
4420
4427
  };
4428
+ /**
4429
+ * Per-process position of a data or end event, starting at 1. Start and
4430
+ * keepalive events carry 0. A client that reconnects with
4431
+ * ConnectRequest.after_sequence receives every retained event after it;
4432
+ * a jump in the sequence means older output was evicted.
4433
+ *
4434
+ * @generated from field: uint64 sequence = 5;
4435
+ */
4436
+ sequence: bigint;
4421
4437
  };
4422
4438
  /**
4423
4439
  * @generated from message process.ProcessEvent.StartEvent
@@ -4686,6 +4702,15 @@ type ConnectRequest = Message<"process.ConnectRequest"> & {
4686
4702
  * @generated from field: process.ProcessSelector process = 1;
4687
4703
  */
4688
4704
  process?: ProcessSelector;
4705
+ /**
4706
+ * Replay retained events with a greater sequence before streaming live
4707
+ * ones. Unset streams live events only. An exited process stays
4708
+ * connectable for a short retention window and always ends with its
4709
+ * end event (exit code).
4710
+ *
4711
+ * @generated from field: optional uint64 after_sequence = 2;
4712
+ */
4713
+ afterSequence?: bigint;
4689
4714
  };
4690
4715
  /**
4691
4716
  * Describes the message process.ConnectRequest.
@@ -7283,12 +7308,6 @@ interface SandboxOpts extends ConnectionOpts {
7283
7308
  * @default 300_000 // 5 minutes
7284
7309
  */
7285
7310
  timeoutMs?: number;
7286
- /**
7287
- * Secure all traffic coming to the sandbox controller with auth token
7288
- *
7289
- * @default true
7290
- */
7291
- secure?: boolean;
7292
7311
  /**
7293
7312
  * Allow sandbox to access the internet. If set to `False`, it works the same as setting network `denyOut` to `[0.0.0.0/0]`.
7294
7313
  *
@@ -7905,6 +7924,12 @@ declare class Commands {
7905
7924
  * @internal
7906
7925
  */
7907
7926
  get supportsStdinClose(): boolean;
7927
+ /**
7928
+ * sbxd 1.1.0+ numbers process output and accepts idempotent starts, so a
7929
+ * dropped command stream can be resumed without losing or repeating
7930
+ * output, and a retried start never runs the command twice.
7931
+ */
7932
+ private get supportsProcessResume();
7908
7933
  /**
7909
7934
  * List all running commands and PTY sessions.
7910
7935
  *
package/dist/index.js CHANGED
@@ -128,7 +128,7 @@ var import_openapi_fetch = __toESM(require("openapi-fetch"));
128
128
  var import_platform2 = __toESM(require("platform"));
129
129
 
130
130
  // package.json
131
- var version = "0.2.0";
131
+ var version = "0.4.0";
132
132
 
133
133
  // src/utils.ts
134
134
  var import_platform = __toESM(require("platform"));
@@ -1000,6 +1000,7 @@ var ENVD_DEBUG_FALLBACK = "99.99.99";
1000
1000
  var ENVD_COMMANDS_STDIN = "0.3.0";
1001
1001
  var ENVD_DEFAULT_USER = "0.4.0";
1002
1002
  var ENVD_ENVD_CLOSE = "0.5.2";
1003
+ var ENVD_PROCESS_RESUME = "1.1.0";
1003
1004
 
1004
1005
  // src/envd/rpc.ts
1005
1006
  function handleRpcError(err) {
@@ -2673,23 +2674,121 @@ var Git = class {
2673
2674
  var import_connect_web = require("@connectrpc/connect-web");
2674
2675
 
2675
2676
  // src/sandbox/commands/index.ts
2676
- var import_connect5 = require("@connectrpc/connect");
2677
+ var import_connect6 = require("@connectrpc/connect");
2677
2678
  var import_compare_versions3 = require("compare-versions");
2678
2679
 
2679
2680
  // src/envd/process/process_pb.ts
2680
2681
  var import_codegenv22 = require("@bufbuild/protobuf/codegenv2");
2681
- var file_process_process = /* @__PURE__ */ (0, import_codegenv22.fileDesc)("ChVwcm9jZXNzL3Byb2Nlc3MucHJvdG8SB3Byb2Nlc3MiSgoDUFRZEh8KBHNpemUYASABKAsyES5wcm9jZXNzLlBUWS5TaXplGiIKBFNpemUSDAoEY29scxgBIAEoDRIMCgRyb3dzGAIgASgNIqEBCg1Qcm9jZXNzQ29uZmlnEgsKA2NtZBgBIAEoCRIMCgRhcmdzGAIgAygJEi4KBGVudnMYAyADKAsyIC5wcm9jZXNzLlByb2Nlc3NDb25maWcuRW52c0VudHJ5EhAKA2N3ZBgEIAEoCUgAiAEBGisKCUVudnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBQgYKBF9jd2QiDQoLTGlzdFJlcXVlc3QiXAoLUHJvY2Vzc0luZm8SJgoGY29uZmlnGAEgASgLMhYucHJvY2Vzcy5Qcm9jZXNzQ29uZmlnEgsKA3BpZBgCIAEoDRIQCgN0YWcYAyABKAlIAIgBAUIGCgRfdGFnIjcKDExpc3RSZXNwb25zZRInCglwcm9jZXNzZXMYASADKAsyFC5wcm9jZXNzLlByb2Nlc3NJbmZvIpcBCgxTdGFydFJlcXVlc3QSJwoHcHJvY2VzcxgBIAEoCzIWLnByb2Nlc3MuUHJvY2Vzc0NvbmZpZxIeCgNwdHkYAiABKAsyDC5wcm9jZXNzLlBUWUgAiAEBEhAKA3RhZxgDIAEoCUgBiAEBEhIKBXN0ZGluGAQgASgISAKIAQFCBgoEX3B0eUIGCgRfdGFnQggKBl9zdGRpbiJiCg1VcGRhdGVSZXF1ZXN0EikKB3Byb2Nlc3MYASABKAsyGC5wcm9jZXNzLlByb2Nlc3NTZWxlY3RvchIeCgNwdHkYAiABKAsyDC5wcm9jZXNzLlBUWUgAiAEBQgYKBF9wdHkiEAoOVXBkYXRlUmVzcG9uc2UirwMKDFByb2Nlc3NFdmVudBIxCgVzdGFydBgBIAEoCzIgLnByb2Nlc3MuUHJvY2Vzc0V2ZW50LlN0YXJ0RXZlbnRIABIvCgRkYXRhGAIgASgLMh8ucHJvY2Vzcy5Qcm9jZXNzRXZlbnQuRGF0YUV2ZW50SAASLQoDZW5kGAMgASgLMh4ucHJvY2Vzcy5Qcm9jZXNzRXZlbnQuRW5kRXZlbnRIABI0CglrZWVwYWxpdmUYBCABKAsyHy5wcm9jZXNzLlByb2Nlc3NFdmVudC5LZWVwQWxpdmVIABoZCgpTdGFydEV2ZW50EgsKA3BpZBgBIAEoDRpICglEYXRhRXZlbnQSEAoGc3Rkb3V0GAEgASgMSAASEAoGc3RkZXJyGAIgASgMSAASDQoDcHR5GAMgASgMSABCCAoGb3V0cHV0GlsKCEVuZEV2ZW50EhEKCWV4aXRfY29kZRgBIAEoERIOCgZleGl0ZWQYAiABKAgSDgoGc3RhdHVzGAMgASgJEhIKBWVycm9yGAQgASgJSACIAQFCCAoGX2Vycm9yGgsKCUtlZXBBbGl2ZUIHCgVldmVudCI1Cg1TdGFydFJlc3BvbnNlEiQKBWV2ZW50GAEgASgLMhUucHJvY2Vzcy5Qcm9jZXNzRXZlbnQiNwoPQ29ubmVjdFJlc3BvbnNlEiQKBWV2ZW50GAEgASgLMhUucHJvY2Vzcy5Qcm9jZXNzRXZlbnQiYwoQU2VuZElucHV0UmVxdWVzdBIpCgdwcm9jZXNzGAEgASgLMhgucHJvY2Vzcy5Qcm9jZXNzU2VsZWN0b3ISJAoFaW5wdXQYAiABKAsyFS5wcm9jZXNzLlByb2Nlc3NJbnB1dCITChFTZW5kSW5wdXRSZXNwb25zZSI3CgxQcm9jZXNzSW5wdXQSDwoFc3RkaW4YASABKAxIABINCgNwdHkYAiABKAxIAEIHCgVpbnB1dCLCAgoSU3RyZWFtSW5wdXRSZXF1ZXN0EjcKBXN0YXJ0GAEgASgLMiYucHJvY2Vzcy5TdHJlYW1JbnB1dFJlcXVlc3QuU3RhcnRFdmVudEgAEjUKBGRhdGEYAiABKAsyJS5wcm9jZXNzLlN0cmVhbUlucHV0UmVxdWVzdC5EYXRhRXZlbnRIABI6CglrZWVwYWxpdmUYAyABKAsyJS5wcm9jZXNzLlN0cmVhbUlucHV0UmVxdWVzdC5LZWVwQWxpdmVIABo3CgpTdGFydEV2ZW50EikKB3Byb2Nlc3MYASABKAsyGC5wcm9jZXNzLlByb2Nlc3NTZWxlY3RvchoxCglEYXRhRXZlbnQSJAoFaW5wdXQYAiABKAsyFS5wcm9jZXNzLlByb2Nlc3NJbnB1dBoLCglLZWVwQWxpdmVCBwoFZXZlbnQiFQoTU3RyZWFtSW5wdXRSZXNwb25zZSJfChFTZW5kU2lnbmFsUmVxdWVzdBIpCgdwcm9jZXNzGAEgASgLMhgucHJvY2Vzcy5Qcm9jZXNzU2VsZWN0b3ISHwoGc2lnbmFsGAIgASgOMg8ucHJvY2Vzcy5TaWduYWwiFAoSU2VuZFNpZ25hbFJlc3BvbnNlIj4KEUNsb3NlU3RkaW5SZXF1ZXN0EikKB3Byb2Nlc3MYASABKAsyGC5wcm9jZXNzLlByb2Nlc3NTZWxlY3RvciIUChJDbG9zZVN0ZGluUmVzcG9uc2UiOwoOQ29ubmVjdFJlcXVlc3QSKQoHcHJvY2VzcxgBIAEoCzIYLnByb2Nlc3MuUHJvY2Vzc1NlbGVjdG9yIjsKD1Byb2Nlc3NTZWxlY3RvchINCgNwaWQYASABKA1IABINCgN0YWcYAiABKAlIAEIKCghzZWxlY3RvcipICgZTaWduYWwSFgoSU0lHTkFMX1VOU1BFQ0lGSUVEEAASEgoOU0lHTkFMX1NJR1RFUk0QDxISCg5TSUdOQUxfU0lHS0lMTBAJMpEECgdQcm9jZXNzEjMKBExpc3QSFC5wcm9jZXNzLkxpc3RSZXF1ZXN0GhUucHJvY2Vzcy5MaXN0UmVzcG9uc2USPgoHQ29ubmVjdBIXLnByb2Nlc3MuQ29ubmVjdFJlcXVlc3QaGC5wcm9jZXNzLkNvbm5lY3RSZXNwb25zZTABEjgKBVN0YXJ0EhUucHJvY2Vzcy5TdGFydFJlcXVlc3QaFi5wcm9jZXNzLlN0YXJ0UmVzcG9uc2UwARI5CgZVcGRhdGUSFi5wcm9jZXNzLlVwZGF0ZVJlcXVlc3QaFy5wcm9jZXNzLlVwZGF0ZVJlc3BvbnNlEkoKC1N0cmVhbUlucHV0EhsucHJvY2Vzcy5TdHJlYW1JbnB1dFJlcXVlc3QaHC5wcm9jZXNzLlN0cmVhbUlucHV0UmVzcG9uc2UoARJCCglTZW5kSW5wdXQSGS5wcm9jZXNzLlNlbmRJbnB1dFJlcXVlc3QaGi5wcm9jZXNzLlNlbmRJbnB1dFJlc3BvbnNlEkUKClNlbmRTaWduYWwSGi5wcm9jZXNzLlNlbmRTaWduYWxSZXF1ZXN0GhsucHJvY2Vzcy5TZW5kU2lnbmFsUmVzcG9uc2USRQoKQ2xvc2VTdGRpbhIaLnByb2Nlc3MuQ2xvc2VTdGRpblJlcXVlc3QaGy5wcm9jZXNzLkNsb3NlU3RkaW5SZXNwb25zZUJXCgtjb20ucHJvY2Vzc0IMUHJvY2Vzc1Byb3RvUAGiAgNQWFiqAgdQcm9jZXNzygIHUHJvY2Vzc+ICE1Byb2Nlc3NcR1BCTWV0YWRhdGHqAgdQcm9jZXNzYgZwcm90bzM");
2682
+ var file_process_process = /* @__PURE__ */ (0, import_codegenv22.fileDesc)("ChVwcm9jZXNzL3Byb2Nlc3MucHJvdG8SB3Byb2Nlc3MiSgoDUFRZEh8KBHNpemUYASABKAsyES5wcm9jZXNzLlBUWS5TaXplGiIKBFNpemUSDAoEY29scxgBIAEoDRIMCgRyb3dzGAIgASgNIqEBCg1Qcm9jZXNzQ29uZmlnEgsKA2NtZBgBIAEoCRIMCgRhcmdzGAIgAygJEi4KBGVudnMYAyADKAsyIC5wcm9jZXNzLlByb2Nlc3NDb25maWcuRW52c0VudHJ5EhAKA2N3ZBgEIAEoCUgAiAEBGisKCUVudnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBQgYKBF9jd2QiDQoLTGlzdFJlcXVlc3QiXAoLUHJvY2Vzc0luZm8SJgoGY29uZmlnGAEgASgLMhYucHJvY2Vzcy5Qcm9jZXNzQ29uZmlnEgsKA3BpZBgCIAEoDRIQCgN0YWcYAyABKAlIAIgBAUIGCgRfdGFnIjcKDExpc3RSZXNwb25zZRInCglwcm9jZXNzZXMYASADKAsyFC5wcm9jZXNzLlByb2Nlc3NJbmZvIskBCgxTdGFydFJlcXVlc3QSJwoHcHJvY2VzcxgBIAEoCzIWLnByb2Nlc3MuUHJvY2Vzc0NvbmZpZxIeCgNwdHkYAiABKAsyDC5wcm9jZXNzLlBUWUgAiAEBEhAKA3RhZxgDIAEoCUgBiAEBEhIKBXN0ZGluGAQgASgISAKIAQESHAoPaWRlbXBvdGVuY3lfa2V5GAUgASgJSAOIAQFCBgoEX3B0eUIGCgRfdGFnQggKBl9zdGRpbkISChBfaWRlbXBvdGVuY3lfa2V5ImIKDVVwZGF0ZVJlcXVlc3QSKQoHcHJvY2VzcxgBIAEoCzIYLnByb2Nlc3MuUHJvY2Vzc1NlbGVjdG9yEh4KA3B0eRgCIAEoCzIMLnByb2Nlc3MuUFRZSACIAQFCBgoEX3B0eSIQCg5VcGRhdGVSZXNwb25zZSLBAwoMUHJvY2Vzc0V2ZW50EjEKBXN0YXJ0GAEgASgLMiAucHJvY2Vzcy5Qcm9jZXNzRXZlbnQuU3RhcnRFdmVudEgAEi8KBGRhdGEYAiABKAsyHy5wcm9jZXNzLlByb2Nlc3NFdmVudC5EYXRhRXZlbnRIABItCgNlbmQYAyABKAsyHi5wcm9jZXNzLlByb2Nlc3NFdmVudC5FbmRFdmVudEgAEjQKCWtlZXBhbGl2ZRgEIAEoCzIfLnByb2Nlc3MuUHJvY2Vzc0V2ZW50LktlZXBBbGl2ZUgAEhAKCHNlcXVlbmNlGAUgASgEGhkKClN0YXJ0RXZlbnQSCwoDcGlkGAEgASgNGkgKCURhdGFFdmVudBIQCgZzdGRvdXQYASABKAxIABIQCgZzdGRlcnIYAiABKAxIABINCgNwdHkYAyABKAxIAEIICgZvdXRwdXQaWwoIRW5kRXZlbnQSEQoJZXhpdF9jb2RlGAEgASgREg4KBmV4aXRlZBgCIAEoCBIOCgZzdGF0dXMYAyABKAkSEgoFZXJyb3IYBCABKAlIAIgBAUIICgZfZXJyb3IaCwoJS2VlcEFsaXZlQgcKBWV2ZW50IjUKDVN0YXJ0UmVzcG9uc2USJAoFZXZlbnQYASABKAsyFS5wcm9jZXNzLlByb2Nlc3NFdmVudCI3Cg9Db25uZWN0UmVzcG9uc2USJAoFZXZlbnQYASABKAsyFS5wcm9jZXNzLlByb2Nlc3NFdmVudCJjChBTZW5kSW5wdXRSZXF1ZXN0EikKB3Byb2Nlc3MYASABKAsyGC5wcm9jZXNzLlByb2Nlc3NTZWxlY3RvchIkCgVpbnB1dBgCIAEoCzIVLnByb2Nlc3MuUHJvY2Vzc0lucHV0IhMKEVNlbmRJbnB1dFJlc3BvbnNlIjcKDFByb2Nlc3NJbnB1dBIPCgVzdGRpbhgBIAEoDEgAEg0KA3B0eRgCIAEoDEgAQgcKBWlucHV0IsICChJTdHJlYW1JbnB1dFJlcXVlc3QSNwoFc3RhcnQYASABKAsyJi5wcm9jZXNzLlN0cmVhbUlucHV0UmVxdWVzdC5TdGFydEV2ZW50SAASNQoEZGF0YRgCIAEoCzIlLnByb2Nlc3MuU3RyZWFtSW5wdXRSZXF1ZXN0LkRhdGFFdmVudEgAEjoKCWtlZXBhbGl2ZRgDIAEoCzIlLnByb2Nlc3MuU3RyZWFtSW5wdXRSZXF1ZXN0LktlZXBBbGl2ZUgAGjcKClN0YXJ0RXZlbnQSKQoHcHJvY2VzcxgBIAEoCzIYLnByb2Nlc3MuUHJvY2Vzc1NlbGVjdG9yGjEKCURhdGFFdmVudBIkCgVpbnB1dBgCIAEoCzIVLnByb2Nlc3MuUHJvY2Vzc0lucHV0GgsKCUtlZXBBbGl2ZUIHCgVldmVudCIVChNTdHJlYW1JbnB1dFJlc3BvbnNlIl8KEVNlbmRTaWduYWxSZXF1ZXN0EikKB3Byb2Nlc3MYASABKAsyGC5wcm9jZXNzLlByb2Nlc3NTZWxlY3RvchIfCgZzaWduYWwYAiABKA4yDy5wcm9jZXNzLlNpZ25hbCIUChJTZW5kU2lnbmFsUmVzcG9uc2UiPgoRQ2xvc2VTdGRpblJlcXVlc3QSKQoHcHJvY2VzcxgBIAEoCzIYLnByb2Nlc3MuUHJvY2Vzc1NlbGVjdG9yIhQKEkNsb3NlU3RkaW5SZXNwb25zZSJrCg5Db25uZWN0UmVxdWVzdBIpCgdwcm9jZXNzGAEgASgLMhgucHJvY2Vzcy5Qcm9jZXNzU2VsZWN0b3ISGwoOYWZ0ZXJfc2VxdWVuY2UYAiABKARIAIgBAUIRCg9fYWZ0ZXJfc2VxdWVuY2UiOwoPUHJvY2Vzc1NlbGVjdG9yEg0KA3BpZBgBIAEoDUgAEg0KA3RhZxgCIAEoCUgAQgoKCHNlbGVjdG9yKkgKBlNpZ25hbBIWChJTSUdOQUxfVU5TUEVDSUZJRUQQABISCg5TSUdOQUxfU0lHVEVSTRAPEhIKDlNJR05BTF9TSUdLSUxMEAkykQQKB1Byb2Nlc3MSMwoETGlzdBIULnByb2Nlc3MuTGlzdFJlcXVlc3QaFS5wcm9jZXNzLkxpc3RSZXNwb25zZRI+CgdDb25uZWN0EhcucHJvY2Vzcy5Db25uZWN0UmVxdWVzdBoYLnByb2Nlc3MuQ29ubmVjdFJlc3BvbnNlMAESOAoFU3RhcnQSFS5wcm9jZXNzLlN0YXJ0UmVxdWVzdBoWLnByb2Nlc3MuU3RhcnRSZXNwb25zZTABEjkKBlVwZGF0ZRIWLnByb2Nlc3MuVXBkYXRlUmVxdWVzdBoXLnByb2Nlc3MuVXBkYXRlUmVzcG9uc2USSgoLU3RyZWFtSW5wdXQSGy5wcm9jZXNzLlN0cmVhbUlucHV0UmVxdWVzdBocLnByb2Nlc3MuU3RyZWFtSW5wdXRSZXNwb25zZSgBEkIKCVNlbmRJbnB1dBIZLnByb2Nlc3MuU2VuZElucHV0UmVxdWVzdBoaLnByb2Nlc3MuU2VuZElucHV0UmVzcG9uc2USRQoKU2VuZFNpZ25hbBIaLnByb2Nlc3MuU2VuZFNpZ25hbFJlcXVlc3QaGy5wcm9jZXNzLlNlbmRTaWduYWxSZXNwb25zZRJFCgpDbG9zZVN0ZGluEhoucHJvY2Vzcy5DbG9zZVN0ZGluUmVxdWVzdBobLnByb2Nlc3MuQ2xvc2VTdGRpblJlc3BvbnNlQlcKC2NvbS5wcm9jZXNzQgxQcm9jZXNzUHJvdG9QAaICA1BYWKoCB1Byb2Nlc3PKAgdQcm9jZXNz4gITUHJvY2Vzc1xHUEJNZXRhZGF0YeoCB1Byb2Nlc3NiBnByb3RvMw");
2682
2683
  var Process = /* @__PURE__ */ (0, import_codegenv22.serviceDesc)(file_process_process, 0);
2683
2684
 
2684
- // src/sandbox/commands/pty.ts
2685
+ // src/sandbox/commands/resumable.ts
2685
2686
  var import_connect4 = require("@connectrpc/connect");
2687
+ var DEFAULT_ATTEMPTS = 3;
2688
+ var defaultBackoff = (attempt) => 250 * 2 ** (attempt - 1);
2689
+ var ZERO = BigInt(0);
2690
+ var ONE = BigInt(1);
2691
+ function isResumableError(err) {
2692
+ const code = import_connect4.ConnectError.from(err).code;
2693
+ return code === import_connect4.Code.Unavailable || code === import_connect4.Code.Unknown || code === import_connect4.Code.Aborted || // sbxd drops a subscriber that stopped reading and asks it to reconnect.
2694
+ code === import_connect4.Code.ResourceExhausted;
2695
+ }
2696
+ function resumableProcessEvents(initial, reopen, opts) {
2697
+ return __asyncGenerator(this, null, function* () {
2698
+ var _a3, _b, _c, _d, _e, _f, _g;
2699
+ const maxAttempts = (_a3 = opts.maxAttempts) != null ? _a3 : DEFAULT_ATTEMPTS;
2700
+ const backoffMs = (_b = opts.backoffMs) != null ? _b : defaultBackoff;
2701
+ let stream2 = initial;
2702
+ let pid;
2703
+ let last = ZERO;
2704
+ let attempts = 0;
2705
+ let resumed = false;
2706
+ for (; ; ) {
2707
+ try {
2708
+ try {
2709
+ for (var iter = __forAwait(stream2), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
2710
+ const response = temp.value;
2711
+ const event = response.event;
2712
+ const kind = event == null ? void 0 : event.event.case;
2713
+ if (kind === "start") {
2714
+ if (resumed && pid !== void 0) {
2715
+ continue;
2716
+ }
2717
+ pid = event == null ? void 0 : event.event.value.pid;
2718
+ }
2719
+ const sequence = (_c = event == null ? void 0 : event.sequence) != null ? _c : ZERO;
2720
+ if (sequence > ZERO) {
2721
+ if (sequence <= last) {
2722
+ continue;
2723
+ }
2724
+ if (resumed && sequence > last + ONE) {
2725
+ (_e = (_d = opts.logger) == null ? void 0 : _d.warn) == null ? void 0 : _e.call(
2726
+ _d,
2727
+ `Process ${pid} output between events ${last} and ${sequence} was evicted before the reconnect`
2728
+ );
2729
+ }
2730
+ last = sequence;
2731
+ }
2732
+ attempts = 0;
2733
+ yield response;
2734
+ if (kind === "end") {
2735
+ return;
2736
+ }
2737
+ }
2738
+ } catch (temp) {
2739
+ error = [temp];
2740
+ } finally {
2741
+ try {
2742
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
2743
+ } finally {
2744
+ if (error)
2745
+ throw error[0];
2746
+ }
2747
+ }
2748
+ return;
2749
+ } catch (err) {
2750
+ if (opts.signal.aborted || !isResumableError(err) || attempts >= maxAttempts) {
2751
+ throw err;
2752
+ }
2753
+ attempts += 1;
2754
+ (_g = (_f = opts.logger) == null ? void 0 : _f.debug) == null ? void 0 : _g.call(
2755
+ _f,
2756
+ `Process stream dropped (${import_connect4.ConnectError.from(err).code}); reconnecting, attempt ${attempts}`
2757
+ );
2758
+ yield new __await(sleep(backoffMs(attempts), opts.signal));
2759
+ stream2 = reopen(pid, last);
2760
+ resumed = true;
2761
+ }
2762
+ }
2763
+ });
2764
+ }
2765
+ function sleep(ms, signal) {
2766
+ return new Promise((resolve, reject) => {
2767
+ if (signal.aborted) {
2768
+ reject(new import_connect4.ConnectError("operation was aborted", import_connect4.Code.Canceled));
2769
+ return;
2770
+ }
2771
+ const timer = setTimeout(() => {
2772
+ signal.removeEventListener("abort", onAbort);
2773
+ resolve();
2774
+ }, ms);
2775
+ const onAbort = () => {
2776
+ clearTimeout(timer);
2777
+ reject(new import_connect4.ConnectError("operation was aborted", import_connect4.Code.Canceled));
2778
+ };
2779
+ signal.addEventListener("abort", onAbort, { once: true });
2780
+ });
2781
+ }
2782
+
2783
+ // src/sandbox/commands/pty.ts
2784
+ var import_connect5 = require("@connectrpc/connect");
2686
2785
  var Pty = class {
2687
2786
  // 60 seconds
2688
2787
  constructor(transport, connectionConfig, metadata) {
2689
2788
  this.transport = transport;
2690
2789
  this.connectionConfig = connectionConfig;
2691
2790
  this.defaultPtyConnectionTimeout = 6e4;
2692
- this.rpc = (0, import_connect4.createClient)(Process, this.transport);
2791
+ this.rpc = (0, import_connect5.createClient)(Process, this.transport);
2693
2792
  this.envdVersion = metadata.version;
2694
2793
  }
2695
2794
  /**
@@ -2886,8 +2985,8 @@ var Pty = class {
2886
2985
  );
2887
2986
  return true;
2888
2987
  } catch (err) {
2889
- if (err instanceof import_connect4.ConnectError) {
2890
- if (err.code === import_connect4.Code.NotFound) {
2988
+ if (err instanceof import_connect5.ConnectError) {
2989
+ if (err.code === import_connect5.Code.NotFound) {
2891
2990
  return false;
2892
2991
  }
2893
2992
  }
@@ -2897,11 +2996,24 @@ var Pty = class {
2897
2996
  };
2898
2997
 
2899
2998
  // src/sandbox/commands/index.ts
2999
+ function remainingMs(deadline) {
3000
+ if (deadline === void 0) {
3001
+ return void 0;
3002
+ }
3003
+ const remaining = deadline - Date.now();
3004
+ if (remaining <= 0) {
3005
+ throw new import_connect6.ConnectError(
3006
+ "process stream deadline exceeded",
3007
+ import_connect6.Code.DeadlineExceeded
3008
+ );
3009
+ }
3010
+ return remaining;
3011
+ }
2900
3012
  var Commands = class {
2901
3013
  constructor(transport, connectionConfig, metadata) {
2902
3014
  this.connectionConfig = connectionConfig;
2903
3015
  this.defaultProcessConnectionTimeout = 6e4;
2904
- this.rpc = (0, import_connect5.createClient)(Process, transport);
3016
+ this.rpc = (0, import_connect6.createClient)(Process, transport);
2905
3017
  this.envdVersion = metadata.version;
2906
3018
  }
2907
3019
  /**
@@ -2911,6 +3023,14 @@ var Commands = class {
2911
3023
  get supportsStdinClose() {
2912
3024
  return (0, import_compare_versions3.compareVersions)(this.envdVersion, ENVD_ENVD_CLOSE) >= 0;
2913
3025
  }
3026
+ /**
3027
+ * sbxd 1.1.0+ numbers process output and accepts idempotent starts, so a
3028
+ * dropped command stream can be resumed without losing or repeating
3029
+ * output, and a retried start never runs the command twice.
3030
+ */
3031
+ get supportsProcessResume() {
3032
+ return (0, import_compare_versions3.compareVersions)(this.envdVersion, ENVD_PROCESS_RESUME) >= 0;
3033
+ }
2914
3034
  /**
2915
3035
  * List all running commands and PTY sessions.
2916
3036
  *
@@ -3025,8 +3145,8 @@ var Commands = class {
3025
3145
  );
3026
3146
  return true;
3027
3147
  } catch (err) {
3028
- if (err instanceof import_connect5.ConnectError) {
3029
- if (err.code === import_connect5.Code.NotFound) {
3148
+ if (err instanceof import_connect6.ConnectError) {
3149
+ if (err.code === import_connect6.Code.NotFound) {
3030
3150
  return false;
3031
3151
  }
3032
3152
  }
@@ -3049,23 +3169,31 @@ var Commands = class {
3049
3169
  const reqTimeout = requestTimeoutMs ? setTimeout(() => {
3050
3170
  controller.abort();
3051
3171
  }, requestTimeoutMs) : void 0;
3052
- const events = this.rpc.connect(
3172
+ const timeoutMs = (_b = opts == null ? void 0 : opts.timeoutMs) != null ? _b : this.defaultProcessConnectionTimeout;
3173
+ const deadline = timeoutMs ? Date.now() + timeoutMs : void 0;
3174
+ const connectTo = (afterSequence, remaining = timeoutMs) => this.rpc.connect(
3053
3175
  {
3054
3176
  process: {
3055
3177
  selector: {
3056
3178
  case: "pid",
3057
3179
  value: pid
3058
3180
  }
3059
- }
3181
+ },
3182
+ afterSequence
3060
3183
  },
3061
3184
  {
3062
3185
  signal: controller.signal,
3063
3186
  headers: {
3064
3187
  [KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString()
3065
3188
  },
3066
- timeoutMs: (_b = opts == null ? void 0 : opts.timeoutMs) != null ? _b : this.defaultProcessConnectionTimeout
3189
+ timeoutMs: remaining
3067
3190
  }
3068
3191
  );
3192
+ const events = this.supportsProcessResume ? resumableProcessEvents(
3193
+ connectTo(),
3194
+ (_, afterSequence) => connectTo(afterSequence, remainingMs(deadline)),
3195
+ { signal: controller.signal, logger: this.connectionConfig.logger }
3196
+ ) : connectTo();
3069
3197
  try {
3070
3198
  const pid2 = await handleProcessStartEvent(events);
3071
3199
  clearTimeout(reqTimeout);
@@ -3098,24 +3226,39 @@ var Commands = class {
3098
3226
  `Sandbox envd version ${this.envdVersion} can't specify stdin, it's always turned on. Please rebuild your template if you need this feature.`
3099
3227
  );
3100
3228
  }
3101
- const events = this.rpc.start(
3102
- {
3103
- process: {
3104
- cmd: "/bin/bash",
3105
- cwd: opts == null ? void 0 : opts.cwd,
3106
- envs: opts == null ? void 0 : opts.envs,
3107
- args: ["-l", "-c", cmd]
3108
- },
3109
- stdin: (opts == null ? void 0 : opts.stdin) || false
3229
+ const resume = this.supportsProcessResume;
3230
+ const request = {
3231
+ process: {
3232
+ cmd: "/bin/bash",
3233
+ cwd: opts == null ? void 0 : opts.cwd,
3234
+ envs: opts == null ? void 0 : opts.envs,
3235
+ args: ["-l", "-c", cmd]
3110
3236
  },
3111
- {
3112
- headers: __spreadProps(__spreadValues({}, authenticationHeader(this.envdVersion, opts == null ? void 0 : opts.user)), {
3113
- [KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString()
3114
- }),
3115
- signal: controller.signal,
3116
- timeoutMs: (_b = opts == null ? void 0 : opts.timeoutMs) != null ? _b : this.defaultProcessConnectionTimeout
3117
- }
3118
- );
3237
+ stdin: (opts == null ? void 0 : opts.stdin) || false,
3238
+ // A retried start with the same key attaches to the first one.
3239
+ idempotencyKey: resume ? crypto.randomUUID() : void 0
3240
+ };
3241
+ const timeoutMs = (_b = opts == null ? void 0 : opts.timeoutMs) != null ? _b : this.defaultProcessConnectionTimeout;
3242
+ const deadline = timeoutMs ? Date.now() + timeoutMs : void 0;
3243
+ const callOptions = (remaining) => ({
3244
+ headers: __spreadProps(__spreadValues({}, authenticationHeader(this.envdVersion, opts == null ? void 0 : opts.user)), {
3245
+ [KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString()
3246
+ }),
3247
+ signal: controller.signal,
3248
+ timeoutMs: remaining
3249
+ });
3250
+ const started = this.rpc.start(request, callOptions(timeoutMs));
3251
+ const events = resume ? resumableProcessEvents(
3252
+ started,
3253
+ (pid, afterSequence) => pid === void 0 ? this.rpc.start(request, callOptions(remainingMs(deadline))) : this.rpc.connect(
3254
+ {
3255
+ process: { selector: { case: "pid", value: pid } },
3256
+ afterSequence
3257
+ },
3258
+ callOptions(remainingMs(deadline))
3259
+ ),
3260
+ { signal: controller.signal, logger: this.connectionConfig.logger }
3261
+ ) : started;
3119
3262
  try {
3120
3263
  const pid = await handleProcessStartEvent(events);
3121
3264
  clearTimeout(reqTimeout);
@@ -3429,7 +3572,7 @@ var SandboxApi = class {
3429
3572
  return true;
3430
3573
  }
3431
3574
  static async createSandbox(template, timeoutMs, opts) {
3432
- var _a3, _b, _c;
3575
+ var _a3, _b;
3433
3576
  const config = ConnectionConfig.forSandbox(opts);
3434
3577
  const client = new ApiClient(config);
3435
3578
  const idempotencyKey = (_a3 = opts == null ? void 0 : opts.idempotencyKey) != null ? _a3 : crypto.randomUUID();
@@ -3448,8 +3591,7 @@ var SandboxApi = class {
3448
3591
  mcp: opts == null ? void 0 : opts.mcp,
3449
3592
  envVars: opts == null ? void 0 : opts.envs,
3450
3593
  timeout: timeoutToSeconds(timeoutMs),
3451
- secure: (_b = opts == null ? void 0 : opts.secure) != null ? _b : true,
3452
- allow_internet_access: (_c = opts == null ? void 0 : opts.allowInternetAccess) != null ? _c : true,
3594
+ allow_internet_access: (_b = opts == null ? void 0 : opts.allowInternetAccess) != null ? _b : true,
3453
3595
  network: opts == null ? void 0 : opts.network,
3454
3596
  autoPause: pauseOnTimeout
3455
3597
  }, pauseOnTimeout ? { autoResume: { policy: lifecycle.autoResume ? "any" : "off" } } : {}), config.region ? { region: config.region } : {});