modal 0.6.3 → 0.7.1

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.cjs CHANGED
@@ -33,6 +33,7 @@ __export(index_exports, {
33
33
  AlreadyExistsError: () => AlreadyExistsError,
34
34
  App: () => App2,
35
35
  AppService: () => AppService,
36
+ ClientClosedError: () => ClientClosedError,
36
37
  CloudBucketMount: () => CloudBucketMount2,
37
38
  CloudBucketMountService: () => CloudBucketMountService,
38
39
  Cls: () => Cls,
@@ -73,7 +74,7 @@ __export(index_exports, {
73
74
  module.exports = __toCommonJS(index_exports);
74
75
 
75
76
  // src/app.ts
76
- var import_nice_grpc11 = require("nice-grpc");
77
+ var import_nice_grpc12 = require("nice-grpc");
77
78
 
78
79
  // node_modules/@bufbuild/protobuf/dist/esm/wire/varint.js
79
80
  function varint64read() {
@@ -44280,8 +44281,8 @@ function isSet4(value) {
44280
44281
  }
44281
44282
 
44282
44283
  // src/client.ts
44283
- var import_uuid = require("uuid");
44284
- var import_nice_grpc10 = require("nice-grpc");
44284
+ var import_uuid2 = require("uuid");
44285
+ var import_nice_grpc11 = require("nice-grpc");
44285
44286
 
44286
44287
  // src/cloud_bucket_mount.ts
44287
44288
  var CloudBucketMountService = class {
@@ -44430,6 +44431,12 @@ var SandboxTimeoutError = class extends Error {
44430
44431
  this.name = "SandboxTimeoutError";
44431
44432
  }
44432
44433
  };
44434
+ var ClientClosedError = class extends Error {
44435
+ constructor(message = "Unable to perform operation on a detached sandbox") {
44436
+ super(message);
44437
+ this.name = "ClientClosedError";
44438
+ }
44439
+ };
44433
44440
 
44434
44441
  // src/function.ts
44435
44442
  var import_node_crypto = require("crypto");
@@ -46485,230 +46492,1874 @@ var Queue = class _Queue {
46485
46492
  };
46486
46493
 
46487
46494
  // src/sandbox.ts
46488
- var import_nice_grpc8 = require("nice-grpc");
46489
- var import_promises = require("timers/promises");
46495
+ var import_nice_grpc9 = require("nice-grpc");
46496
+ var import_promises2 = require("timers/promises");
46490
46497
 
46491
- // src/sandbox_filesystem.ts
46492
- var SandboxFile = class {
46493
- #client;
46494
- #fileDescriptor;
46495
- #taskId;
46496
- /** @ignore */
46497
- constructor(client2, fileDescriptor, taskId) {
46498
- this.#client = client2;
46499
- this.#fileDescriptor = fileDescriptor;
46500
- this.#taskId = taskId;
46498
+ // proto/modal_proto/task_command_router.ts
46499
+ function taskExecStderrConfigFromJSON(object) {
46500
+ switch (object) {
46501
+ case 0:
46502
+ case "TASK_EXEC_STDERR_CONFIG_DEVNULL":
46503
+ return 0 /* TASK_EXEC_STDERR_CONFIG_DEVNULL */;
46504
+ case 1:
46505
+ case "TASK_EXEC_STDERR_CONFIG_PIPE":
46506
+ return 1 /* TASK_EXEC_STDERR_CONFIG_PIPE */;
46507
+ case 2:
46508
+ case "TASK_EXEC_STDERR_CONFIG_STDOUT":
46509
+ return 2 /* TASK_EXEC_STDERR_CONFIG_STDOUT */;
46510
+ case -1:
46511
+ case "UNRECOGNIZED":
46512
+ default:
46513
+ return -1 /* UNRECOGNIZED */;
46501
46514
  }
46502
- /**
46503
- * Read data from the file.
46504
- * @returns Promise that resolves to the read data as Uint8Array
46505
- */
46506
- async read() {
46507
- const resp = await runFilesystemExec(this.#client.cpClient, {
46508
- fileReadRequest: {
46509
- fileDescriptor: this.#fileDescriptor
46510
- },
46511
- taskId: this.#taskId
46512
- });
46513
- const chunks = resp.chunks;
46514
- const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
46515
- const result = new Uint8Array(totalLength);
46516
- let offset = 0;
46517
- for (const chunk of chunks) {
46518
- result.set(chunk, offset);
46519
- offset += chunk.length;
46520
- }
46521
- return result;
46515
+ }
46516
+ function taskExecStderrConfigToJSON(object) {
46517
+ switch (object) {
46518
+ case 0 /* TASK_EXEC_STDERR_CONFIG_DEVNULL */:
46519
+ return "TASK_EXEC_STDERR_CONFIG_DEVNULL";
46520
+ case 1 /* TASK_EXEC_STDERR_CONFIG_PIPE */:
46521
+ return "TASK_EXEC_STDERR_CONFIG_PIPE";
46522
+ case 2 /* TASK_EXEC_STDERR_CONFIG_STDOUT */:
46523
+ return "TASK_EXEC_STDERR_CONFIG_STDOUT";
46524
+ case -1 /* UNRECOGNIZED */:
46525
+ default:
46526
+ return "UNRECOGNIZED";
46522
46527
  }
46523
- /**
46524
- * Write data to the file.
46525
- * @param data - Data to write (string or Uint8Array)
46526
- */
46527
- async write(data) {
46528
- await runFilesystemExec(this.#client.cpClient, {
46529
- fileWriteRequest: {
46530
- fileDescriptor: this.#fileDescriptor,
46531
- data
46532
- },
46533
- taskId: this.#taskId
46534
- });
46528
+ }
46529
+ function taskExecStdioFileDescriptorFromJSON(object) {
46530
+ switch (object) {
46531
+ case 0:
46532
+ case "TASK_EXEC_STDIO_FILE_DESCRIPTOR_STDOUT":
46533
+ return 0 /* TASK_EXEC_STDIO_FILE_DESCRIPTOR_STDOUT */;
46534
+ case 1:
46535
+ case "TASK_EXEC_STDIO_FILE_DESCRIPTOR_STDERR":
46536
+ return 1 /* TASK_EXEC_STDIO_FILE_DESCRIPTOR_STDERR */;
46537
+ case -1:
46538
+ case "UNRECOGNIZED":
46539
+ default:
46540
+ return -1 /* UNRECOGNIZED */;
46535
46541
  }
46536
- /**
46537
- * Flush any buffered data to the file.
46538
- */
46539
- async flush() {
46540
- await runFilesystemExec(this.#client.cpClient, {
46541
- fileFlushRequest: {
46542
- fileDescriptor: this.#fileDescriptor
46543
- },
46544
- taskId: this.#taskId
46545
- });
46542
+ }
46543
+ function taskExecStdioFileDescriptorToJSON(object) {
46544
+ switch (object) {
46545
+ case 0 /* TASK_EXEC_STDIO_FILE_DESCRIPTOR_STDOUT */:
46546
+ return "TASK_EXEC_STDIO_FILE_DESCRIPTOR_STDOUT";
46547
+ case 1 /* TASK_EXEC_STDIO_FILE_DESCRIPTOR_STDERR */:
46548
+ return "TASK_EXEC_STDIO_FILE_DESCRIPTOR_STDERR";
46549
+ case -1 /* UNRECOGNIZED */:
46550
+ default:
46551
+ return "UNRECOGNIZED";
46546
46552
  }
46547
- /**
46548
- * Close the file handle.
46549
- */
46550
- async close() {
46551
- await runFilesystemExec(this.#client.cpClient, {
46552
- fileCloseRequest: {
46553
- fileDescriptor: this.#fileDescriptor
46554
- },
46555
- taskId: this.#taskId
46556
- });
46553
+ }
46554
+ function taskExecStdoutConfigFromJSON(object) {
46555
+ switch (object) {
46556
+ case 0:
46557
+ case "TASK_EXEC_STDOUT_CONFIG_DEVNULL":
46558
+ return 0 /* TASK_EXEC_STDOUT_CONFIG_DEVNULL */;
46559
+ case 1:
46560
+ case "TASK_EXEC_STDOUT_CONFIG_PIPE":
46561
+ return 1 /* TASK_EXEC_STDOUT_CONFIG_PIPE */;
46562
+ case -1:
46563
+ case "UNRECOGNIZED":
46564
+ default:
46565
+ return -1 /* UNRECOGNIZED */;
46557
46566
  }
46558
- };
46559
- async function runFilesystemExec(cpClient, request) {
46560
- const response = await cpClient.containerFilesystemExec(request);
46561
- const chunks = [];
46562
- let retries = 10;
46563
- let completed = false;
46564
- while (!completed) {
46565
- try {
46566
- const outputIterator = cpClient.containerFilesystemExecGetOutput({
46567
- execId: response.execId,
46568
- timeout: 55
46569
- });
46570
- for await (const batch of outputIterator) {
46571
- chunks.push(...batch.output);
46572
- if (batch.eof) {
46573
- completed = true;
46574
- break;
46567
+ }
46568
+ function taskExecStdoutConfigToJSON(object) {
46569
+ switch (object) {
46570
+ case 0 /* TASK_EXEC_STDOUT_CONFIG_DEVNULL */:
46571
+ return "TASK_EXEC_STDOUT_CONFIG_DEVNULL";
46572
+ case 1 /* TASK_EXEC_STDOUT_CONFIG_PIPE */:
46573
+ return "TASK_EXEC_STDOUT_CONFIG_PIPE";
46574
+ case -1 /* UNRECOGNIZED */:
46575
+ default:
46576
+ return "UNRECOGNIZED";
46577
+ }
46578
+ }
46579
+ function createBaseTaskExecPollRequest() {
46580
+ return { taskId: "", execId: "" };
46581
+ }
46582
+ var TaskExecPollRequest = {
46583
+ encode(message, writer = new BinaryWriter()) {
46584
+ if (message.taskId !== "") {
46585
+ writer.uint32(10).string(message.taskId);
46586
+ }
46587
+ if (message.execId !== "") {
46588
+ writer.uint32(18).string(message.execId);
46589
+ }
46590
+ return writer;
46591
+ },
46592
+ decode(input, length) {
46593
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
46594
+ let end = length === void 0 ? reader.len : reader.pos + length;
46595
+ const message = createBaseTaskExecPollRequest();
46596
+ while (reader.pos < end) {
46597
+ const tag = reader.uint32();
46598
+ switch (tag >>> 3) {
46599
+ case 1: {
46600
+ if (tag !== 10) {
46601
+ break;
46602
+ }
46603
+ message.taskId = reader.string();
46604
+ continue;
46575
46605
  }
46576
- if (batch.error !== void 0) {
46577
- if (retries > 0) {
46578
- retries--;
46606
+ case 2: {
46607
+ if (tag !== 18) {
46579
46608
  break;
46580
46609
  }
46581
- throw new SandboxFilesystemError(batch.error.errorMessage);
46610
+ message.execId = reader.string();
46611
+ continue;
46582
46612
  }
46583
46613
  }
46584
- } catch (err) {
46585
- if (isRetryableGrpc(err) && retries > 0) {
46586
- retries--;
46587
- } else throw err;
46614
+ if ((tag & 7) === 4 || tag === 0) {
46615
+ break;
46616
+ }
46617
+ reader.skip(tag & 7);
46618
+ }
46619
+ return message;
46620
+ },
46621
+ fromJSON(object) {
46622
+ return {
46623
+ taskId: isSet5(object.taskId) ? globalThis.String(object.taskId) : "",
46624
+ execId: isSet5(object.execId) ? globalThis.String(object.execId) : ""
46625
+ };
46626
+ },
46627
+ toJSON(message) {
46628
+ const obj = {};
46629
+ if (message.taskId !== "") {
46630
+ obj.taskId = message.taskId;
46631
+ }
46632
+ if (message.execId !== "") {
46633
+ obj.execId = message.execId;
46588
46634
  }
46635
+ return obj;
46636
+ },
46637
+ create(base) {
46638
+ return TaskExecPollRequest.fromPartial(base ?? {});
46639
+ },
46640
+ fromPartial(object) {
46641
+ const message = createBaseTaskExecPollRequest();
46642
+ message.taskId = object.taskId ?? "";
46643
+ message.execId = object.execId ?? "";
46644
+ return message;
46589
46645
  }
46590
- return { chunks, response };
46591
- }
46592
-
46593
- // src/streams.ts
46594
- function toModalReadStream(stream) {
46595
- return Object.assign(stream, readMixin);
46596
- }
46597
- function toModalWriteStream(stream) {
46598
- return Object.assign(stream, writeMixin);
46646
+ };
46647
+ function createBaseTaskExecPollResponse() {
46648
+ return { code: void 0, signal: void 0 };
46599
46649
  }
46600
- var readMixin = {
46601
- async readText() {
46602
- const reader = this.getReader();
46603
- try {
46604
- const decoder2 = new TextDecoder("utf-8");
46605
- const chunks = [];
46606
- while (true) {
46607
- const { value, done } = await reader.read();
46608
- if (value) {
46609
- if (typeof value === "string") chunks.push(value);
46610
- else {
46611
- chunks.push(decoder2.decode(value.buffer, { stream: true }));
46650
+ var TaskExecPollResponse = {
46651
+ encode(message, writer = new BinaryWriter()) {
46652
+ if (message.code !== void 0) {
46653
+ writer.uint32(8).int32(message.code);
46654
+ }
46655
+ if (message.signal !== void 0) {
46656
+ writer.uint32(16).int32(message.signal);
46657
+ }
46658
+ return writer;
46659
+ },
46660
+ decode(input, length) {
46661
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
46662
+ let end = length === void 0 ? reader.len : reader.pos + length;
46663
+ const message = createBaseTaskExecPollResponse();
46664
+ while (reader.pos < end) {
46665
+ const tag = reader.uint32();
46666
+ switch (tag >>> 3) {
46667
+ case 1: {
46668
+ if (tag !== 8) {
46669
+ break;
46612
46670
  }
46671
+ message.code = reader.int32();
46672
+ continue;
46613
46673
  }
46614
- if (done) {
46615
- chunks.push(decoder2.decode(void 0, { stream: false }));
46616
- break;
46674
+ case 2: {
46675
+ if (tag !== 16) {
46676
+ break;
46677
+ }
46678
+ message.signal = reader.int32();
46679
+ continue;
46617
46680
  }
46618
46681
  }
46619
- return chunks.join("");
46620
- } finally {
46621
- reader.releaseLock();
46682
+ if ((tag & 7) === 4 || tag === 0) {
46683
+ break;
46684
+ }
46685
+ reader.skip(tag & 7);
46622
46686
  }
46687
+ return message;
46623
46688
  },
46624
- async readBytes() {
46625
- const chunks = [];
46626
- const reader = this.getReader();
46627
- try {
46628
- while (true) {
46629
- const { value, done } = await reader.read();
46630
- if (value) {
46631
- if (typeof value === "string") {
46632
- chunks.push(new TextEncoder().encode(value));
46633
- } else {
46634
- chunks.push(value);
46689
+ fromJSON(object) {
46690
+ return {
46691
+ code: isSet5(object.code) ? globalThis.Number(object.code) : void 0,
46692
+ signal: isSet5(object.signal) ? globalThis.Number(object.signal) : void 0
46693
+ };
46694
+ },
46695
+ toJSON(message) {
46696
+ const obj = {};
46697
+ if (message.code !== void 0) {
46698
+ obj.code = Math.round(message.code);
46699
+ }
46700
+ if (message.signal !== void 0) {
46701
+ obj.signal = Math.round(message.signal);
46702
+ }
46703
+ return obj;
46704
+ },
46705
+ create(base) {
46706
+ return TaskExecPollResponse.fromPartial(base ?? {});
46707
+ },
46708
+ fromPartial(object) {
46709
+ const message = createBaseTaskExecPollResponse();
46710
+ message.code = object.code ?? void 0;
46711
+ message.signal = object.signal ?? void 0;
46712
+ return message;
46713
+ }
46714
+ };
46715
+ function createBaseTaskExecStartRequest() {
46716
+ return {
46717
+ taskId: "",
46718
+ execId: "",
46719
+ commandArgs: [],
46720
+ stdoutConfig: 0,
46721
+ stderrConfig: 0,
46722
+ timeoutSecs: void 0,
46723
+ workdir: void 0,
46724
+ secretIds: [],
46725
+ ptyInfo: void 0,
46726
+ runtimeDebug: false
46727
+ };
46728
+ }
46729
+ var TaskExecStartRequest = {
46730
+ encode(message, writer = new BinaryWriter()) {
46731
+ if (message.taskId !== "") {
46732
+ writer.uint32(10).string(message.taskId);
46733
+ }
46734
+ if (message.execId !== "") {
46735
+ writer.uint32(18).string(message.execId);
46736
+ }
46737
+ for (const v of message.commandArgs) {
46738
+ writer.uint32(26).string(v);
46739
+ }
46740
+ if (message.stdoutConfig !== 0) {
46741
+ writer.uint32(32).int32(message.stdoutConfig);
46742
+ }
46743
+ if (message.stderrConfig !== 0) {
46744
+ writer.uint32(40).int32(message.stderrConfig);
46745
+ }
46746
+ if (message.timeoutSecs !== void 0) {
46747
+ writer.uint32(48).uint32(message.timeoutSecs);
46748
+ }
46749
+ if (message.workdir !== void 0) {
46750
+ writer.uint32(58).string(message.workdir);
46751
+ }
46752
+ for (const v of message.secretIds) {
46753
+ writer.uint32(66).string(v);
46754
+ }
46755
+ if (message.ptyInfo !== void 0) {
46756
+ PTYInfo.encode(message.ptyInfo, writer.uint32(74).fork()).join();
46757
+ }
46758
+ if (message.runtimeDebug !== false) {
46759
+ writer.uint32(80).bool(message.runtimeDebug);
46760
+ }
46761
+ return writer;
46762
+ },
46763
+ decode(input, length) {
46764
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
46765
+ let end = length === void 0 ? reader.len : reader.pos + length;
46766
+ const message = createBaseTaskExecStartRequest();
46767
+ while (reader.pos < end) {
46768
+ const tag = reader.uint32();
46769
+ switch (tag >>> 3) {
46770
+ case 1: {
46771
+ if (tag !== 10) {
46772
+ break;
46773
+ }
46774
+ message.taskId = reader.string();
46775
+ continue;
46776
+ }
46777
+ case 2: {
46778
+ if (tag !== 18) {
46779
+ break;
46635
46780
  }
46781
+ message.execId = reader.string();
46782
+ continue;
46783
+ }
46784
+ case 3: {
46785
+ if (tag !== 26) {
46786
+ break;
46787
+ }
46788
+ message.commandArgs.push(reader.string());
46789
+ continue;
46790
+ }
46791
+ case 4: {
46792
+ if (tag !== 32) {
46793
+ break;
46794
+ }
46795
+ message.stdoutConfig = reader.int32();
46796
+ continue;
46797
+ }
46798
+ case 5: {
46799
+ if (tag !== 40) {
46800
+ break;
46801
+ }
46802
+ message.stderrConfig = reader.int32();
46803
+ continue;
46804
+ }
46805
+ case 6: {
46806
+ if (tag !== 48) {
46807
+ break;
46808
+ }
46809
+ message.timeoutSecs = reader.uint32();
46810
+ continue;
46811
+ }
46812
+ case 7: {
46813
+ if (tag !== 58) {
46814
+ break;
46815
+ }
46816
+ message.workdir = reader.string();
46817
+ continue;
46818
+ }
46819
+ case 8: {
46820
+ if (tag !== 66) {
46821
+ break;
46822
+ }
46823
+ message.secretIds.push(reader.string());
46824
+ continue;
46825
+ }
46826
+ case 9: {
46827
+ if (tag !== 74) {
46828
+ break;
46829
+ }
46830
+ message.ptyInfo = PTYInfo.decode(reader, reader.uint32());
46831
+ continue;
46832
+ }
46833
+ case 10: {
46834
+ if (tag !== 80) {
46835
+ break;
46836
+ }
46837
+ message.runtimeDebug = reader.bool();
46838
+ continue;
46636
46839
  }
46637
- if (done) break;
46638
46840
  }
46639
- } finally {
46640
- reader.releaseLock();
46841
+ if ((tag & 7) === 4 || tag === 0) {
46842
+ break;
46843
+ }
46844
+ reader.skip(tag & 7);
46641
46845
  }
46642
- let totalLength = 0;
46643
- for (const chunk of chunks) {
46644
- totalLength += chunk.length;
46846
+ return message;
46847
+ },
46848
+ fromJSON(object) {
46849
+ return {
46850
+ taskId: isSet5(object.taskId) ? globalThis.String(object.taskId) : "",
46851
+ execId: isSet5(object.execId) ? globalThis.String(object.execId) : "",
46852
+ commandArgs: globalThis.Array.isArray(object?.commandArgs) ? object.commandArgs.map((e) => globalThis.String(e)) : [],
46853
+ stdoutConfig: isSet5(object.stdoutConfig) ? taskExecStdoutConfigFromJSON(object.stdoutConfig) : 0,
46854
+ stderrConfig: isSet5(object.stderrConfig) ? taskExecStderrConfigFromJSON(object.stderrConfig) : 0,
46855
+ timeoutSecs: isSet5(object.timeoutSecs) ? globalThis.Number(object.timeoutSecs) : void 0,
46856
+ workdir: isSet5(object.workdir) ? globalThis.String(object.workdir) : void 0,
46857
+ secretIds: globalThis.Array.isArray(object?.secretIds) ? object.secretIds.map((e) => globalThis.String(e)) : [],
46858
+ ptyInfo: isSet5(object.ptyInfo) ? PTYInfo.fromJSON(object.ptyInfo) : void 0,
46859
+ runtimeDebug: isSet5(object.runtimeDebug) ? globalThis.Boolean(object.runtimeDebug) : false
46860
+ };
46861
+ },
46862
+ toJSON(message) {
46863
+ const obj = {};
46864
+ if (message.taskId !== "") {
46865
+ obj.taskId = message.taskId;
46645
46866
  }
46646
- const result = new Uint8Array(totalLength);
46647
- let offset = 0;
46648
- for (const chunk of chunks) {
46649
- result.set(chunk, offset);
46650
- offset += chunk.length;
46867
+ if (message.execId !== "") {
46868
+ obj.execId = message.execId;
46651
46869
  }
46652
- return result;
46870
+ if (message.commandArgs?.length) {
46871
+ obj.commandArgs = message.commandArgs;
46872
+ }
46873
+ if (message.stdoutConfig !== 0) {
46874
+ obj.stdoutConfig = taskExecStdoutConfigToJSON(message.stdoutConfig);
46875
+ }
46876
+ if (message.stderrConfig !== 0) {
46877
+ obj.stderrConfig = taskExecStderrConfigToJSON(message.stderrConfig);
46878
+ }
46879
+ if (message.timeoutSecs !== void 0) {
46880
+ obj.timeoutSecs = Math.round(message.timeoutSecs);
46881
+ }
46882
+ if (message.workdir !== void 0) {
46883
+ obj.workdir = message.workdir;
46884
+ }
46885
+ if (message.secretIds?.length) {
46886
+ obj.secretIds = message.secretIds;
46887
+ }
46888
+ if (message.ptyInfo !== void 0) {
46889
+ obj.ptyInfo = PTYInfo.toJSON(message.ptyInfo);
46890
+ }
46891
+ if (message.runtimeDebug !== false) {
46892
+ obj.runtimeDebug = message.runtimeDebug;
46893
+ }
46894
+ return obj;
46895
+ },
46896
+ create(base) {
46897
+ return TaskExecStartRequest.fromPartial(base ?? {});
46898
+ },
46899
+ fromPartial(object) {
46900
+ const message = createBaseTaskExecStartRequest();
46901
+ message.taskId = object.taskId ?? "";
46902
+ message.execId = object.execId ?? "";
46903
+ message.commandArgs = object.commandArgs?.map((e) => e) || [];
46904
+ message.stdoutConfig = object.stdoutConfig ?? 0;
46905
+ message.stderrConfig = object.stderrConfig ?? 0;
46906
+ message.timeoutSecs = object.timeoutSecs ?? void 0;
46907
+ message.workdir = object.workdir ?? void 0;
46908
+ message.secretIds = object.secretIds?.map((e) => e) || [];
46909
+ message.ptyInfo = object.ptyInfo !== void 0 && object.ptyInfo !== null ? PTYInfo.fromPartial(object.ptyInfo) : void 0;
46910
+ message.runtimeDebug = object.runtimeDebug ?? false;
46911
+ return message;
46653
46912
  }
46654
46913
  };
46655
- var writeMixin = {
46656
- async writeText(text) {
46657
- const writer = this.getWriter();
46658
- try {
46659
- await writer.write(text);
46660
- } finally {
46661
- writer.releaseLock();
46662
- }
46914
+ function createBaseTaskExecStartResponse() {
46915
+ return {};
46916
+ }
46917
+ var TaskExecStartResponse = {
46918
+ encode(_, writer = new BinaryWriter()) {
46919
+ return writer;
46663
46920
  },
46664
- async writeBytes(bytes) {
46665
- const writer = this.getWriter();
46666
- try {
46667
- await writer.write(bytes);
46668
- } finally {
46669
- writer.releaseLock();
46921
+ decode(input, length) {
46922
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
46923
+ let end = length === void 0 ? reader.len : reader.pos + length;
46924
+ const message = createBaseTaskExecStartResponse();
46925
+ while (reader.pos < end) {
46926
+ const tag = reader.uint32();
46927
+ switch (tag >>> 3) {
46928
+ }
46929
+ if ((tag & 7) === 4 || tag === 0) {
46930
+ break;
46931
+ }
46932
+ reader.skip(tag & 7);
46670
46933
  }
46934
+ return message;
46935
+ },
46936
+ fromJSON(_) {
46937
+ return {};
46938
+ },
46939
+ toJSON(_) {
46940
+ const obj = {};
46941
+ return obj;
46942
+ },
46943
+ create(base) {
46944
+ return TaskExecStartResponse.fromPartial(base ?? {});
46945
+ },
46946
+ fromPartial(_) {
46947
+ const message = createBaseTaskExecStartResponse();
46948
+ return message;
46671
46949
  }
46672
46950
  };
46673
- function streamConsumingIter(iterable, onCancel) {
46674
- const iter = iterable[Symbol.asyncIterator]();
46675
- return new ReadableStream(
46676
- {
46677
- async pull(controller) {
46678
- const { done, value } = await iter.next();
46679
- if (value) {
46680
- controller.enqueue(value);
46681
- }
46682
- if (done) {
46683
- controller.close();
46684
- }
46685
- },
46686
- async cancel() {
46687
- try {
46688
- onCancel?.();
46689
- } finally {
46690
- if (typeof iter.return === "function") {
46691
- await iter.return();
46692
- }
46693
- }
46694
- }
46695
- },
46696
- new ByteLengthQueuingStrategy({
46697
- highWaterMark: 64 * 1024
46698
- // 64 KiB
46699
- })
46700
- );
46951
+ function createBaseTaskExecStdinWriteRequest() {
46952
+ return { taskId: "", execId: "", offset: 0, data: new Uint8Array(0), eof: false };
46701
46953
  }
46702
-
46703
- // src/sandbox.ts
46704
- var SB_LOGS_INITIAL_DELAY_MS = 10;
46705
- var SB_LOGS_DELAY_FACTOR = 2;
46706
- var SB_LOGS_MAX_RETRIES = 10;
46707
- async function buildSandboxCreateRequestProto(appId, imageId, params = {}) {
46708
- checkForRenamedParams(params, {
46709
- memory: "memoryMiB",
46710
- memoryLimit: "memoryLimitMiB",
46711
- timeout: "timeoutMs",
46954
+ var TaskExecStdinWriteRequest = {
46955
+ encode(message, writer = new BinaryWriter()) {
46956
+ if (message.taskId !== "") {
46957
+ writer.uint32(10).string(message.taskId);
46958
+ }
46959
+ if (message.execId !== "") {
46960
+ writer.uint32(18).string(message.execId);
46961
+ }
46962
+ if (message.offset !== 0) {
46963
+ writer.uint32(24).uint64(message.offset);
46964
+ }
46965
+ if (message.data.length !== 0) {
46966
+ writer.uint32(34).bytes(message.data);
46967
+ }
46968
+ if (message.eof !== false) {
46969
+ writer.uint32(40).bool(message.eof);
46970
+ }
46971
+ return writer;
46972
+ },
46973
+ decode(input, length) {
46974
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
46975
+ let end = length === void 0 ? reader.len : reader.pos + length;
46976
+ const message = createBaseTaskExecStdinWriteRequest();
46977
+ while (reader.pos < end) {
46978
+ const tag = reader.uint32();
46979
+ switch (tag >>> 3) {
46980
+ case 1: {
46981
+ if (tag !== 10) {
46982
+ break;
46983
+ }
46984
+ message.taskId = reader.string();
46985
+ continue;
46986
+ }
46987
+ case 2: {
46988
+ if (tag !== 18) {
46989
+ break;
46990
+ }
46991
+ message.execId = reader.string();
46992
+ continue;
46993
+ }
46994
+ case 3: {
46995
+ if (tag !== 24) {
46996
+ break;
46997
+ }
46998
+ message.offset = longToNumber3(reader.uint64());
46999
+ continue;
47000
+ }
47001
+ case 4: {
47002
+ if (tag !== 34) {
47003
+ break;
47004
+ }
47005
+ message.data = reader.bytes();
47006
+ continue;
47007
+ }
47008
+ case 5: {
47009
+ if (tag !== 40) {
47010
+ break;
47011
+ }
47012
+ message.eof = reader.bool();
47013
+ continue;
47014
+ }
47015
+ }
47016
+ if ((tag & 7) === 4 || tag === 0) {
47017
+ break;
47018
+ }
47019
+ reader.skip(tag & 7);
47020
+ }
47021
+ return message;
47022
+ },
47023
+ fromJSON(object) {
47024
+ return {
47025
+ taskId: isSet5(object.taskId) ? globalThis.String(object.taskId) : "",
47026
+ execId: isSet5(object.execId) ? globalThis.String(object.execId) : "",
47027
+ offset: isSet5(object.offset) ? globalThis.Number(object.offset) : 0,
47028
+ data: isSet5(object.data) ? bytesFromBase642(object.data) : new Uint8Array(0),
47029
+ eof: isSet5(object.eof) ? globalThis.Boolean(object.eof) : false
47030
+ };
47031
+ },
47032
+ toJSON(message) {
47033
+ const obj = {};
47034
+ if (message.taskId !== "") {
47035
+ obj.taskId = message.taskId;
47036
+ }
47037
+ if (message.execId !== "") {
47038
+ obj.execId = message.execId;
47039
+ }
47040
+ if (message.offset !== 0) {
47041
+ obj.offset = Math.round(message.offset);
47042
+ }
47043
+ if (message.data.length !== 0) {
47044
+ obj.data = base64FromBytes2(message.data);
47045
+ }
47046
+ if (message.eof !== false) {
47047
+ obj.eof = message.eof;
47048
+ }
47049
+ return obj;
47050
+ },
47051
+ create(base) {
47052
+ return TaskExecStdinWriteRequest.fromPartial(base ?? {});
47053
+ },
47054
+ fromPartial(object) {
47055
+ const message = createBaseTaskExecStdinWriteRequest();
47056
+ message.taskId = object.taskId ?? "";
47057
+ message.execId = object.execId ?? "";
47058
+ message.offset = object.offset ?? 0;
47059
+ message.data = object.data ?? new Uint8Array(0);
47060
+ message.eof = object.eof ?? false;
47061
+ return message;
47062
+ }
47063
+ };
47064
+ function createBaseTaskExecStdinWriteResponse() {
47065
+ return {};
47066
+ }
47067
+ var TaskExecStdinWriteResponse = {
47068
+ encode(_, writer = new BinaryWriter()) {
47069
+ return writer;
47070
+ },
47071
+ decode(input, length) {
47072
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
47073
+ let end = length === void 0 ? reader.len : reader.pos + length;
47074
+ const message = createBaseTaskExecStdinWriteResponse();
47075
+ while (reader.pos < end) {
47076
+ const tag = reader.uint32();
47077
+ switch (tag >>> 3) {
47078
+ }
47079
+ if ((tag & 7) === 4 || tag === 0) {
47080
+ break;
47081
+ }
47082
+ reader.skip(tag & 7);
47083
+ }
47084
+ return message;
47085
+ },
47086
+ fromJSON(_) {
47087
+ return {};
47088
+ },
47089
+ toJSON(_) {
47090
+ const obj = {};
47091
+ return obj;
47092
+ },
47093
+ create(base) {
47094
+ return TaskExecStdinWriteResponse.fromPartial(base ?? {});
47095
+ },
47096
+ fromPartial(_) {
47097
+ const message = createBaseTaskExecStdinWriteResponse();
47098
+ return message;
47099
+ }
47100
+ };
47101
+ function createBaseTaskExecStdioReadRequest() {
47102
+ return { taskId: "", execId: "", offset: 0, fileDescriptor: 0 };
47103
+ }
47104
+ var TaskExecStdioReadRequest = {
47105
+ encode(message, writer = new BinaryWriter()) {
47106
+ if (message.taskId !== "") {
47107
+ writer.uint32(10).string(message.taskId);
47108
+ }
47109
+ if (message.execId !== "") {
47110
+ writer.uint32(18).string(message.execId);
47111
+ }
47112
+ if (message.offset !== 0) {
47113
+ writer.uint32(24).uint64(message.offset);
47114
+ }
47115
+ if (message.fileDescriptor !== 0) {
47116
+ writer.uint32(32).int32(message.fileDescriptor);
47117
+ }
47118
+ return writer;
47119
+ },
47120
+ decode(input, length) {
47121
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
47122
+ let end = length === void 0 ? reader.len : reader.pos + length;
47123
+ const message = createBaseTaskExecStdioReadRequest();
47124
+ while (reader.pos < end) {
47125
+ const tag = reader.uint32();
47126
+ switch (tag >>> 3) {
47127
+ case 1: {
47128
+ if (tag !== 10) {
47129
+ break;
47130
+ }
47131
+ message.taskId = reader.string();
47132
+ continue;
47133
+ }
47134
+ case 2: {
47135
+ if (tag !== 18) {
47136
+ break;
47137
+ }
47138
+ message.execId = reader.string();
47139
+ continue;
47140
+ }
47141
+ case 3: {
47142
+ if (tag !== 24) {
47143
+ break;
47144
+ }
47145
+ message.offset = longToNumber3(reader.uint64());
47146
+ continue;
47147
+ }
47148
+ case 4: {
47149
+ if (tag !== 32) {
47150
+ break;
47151
+ }
47152
+ message.fileDescriptor = reader.int32();
47153
+ continue;
47154
+ }
47155
+ }
47156
+ if ((tag & 7) === 4 || tag === 0) {
47157
+ break;
47158
+ }
47159
+ reader.skip(tag & 7);
47160
+ }
47161
+ return message;
47162
+ },
47163
+ fromJSON(object) {
47164
+ return {
47165
+ taskId: isSet5(object.taskId) ? globalThis.String(object.taskId) : "",
47166
+ execId: isSet5(object.execId) ? globalThis.String(object.execId) : "",
47167
+ offset: isSet5(object.offset) ? globalThis.Number(object.offset) : 0,
47168
+ fileDescriptor: isSet5(object.fileDescriptor) ? taskExecStdioFileDescriptorFromJSON(object.fileDescriptor) : 0
47169
+ };
47170
+ },
47171
+ toJSON(message) {
47172
+ const obj = {};
47173
+ if (message.taskId !== "") {
47174
+ obj.taskId = message.taskId;
47175
+ }
47176
+ if (message.execId !== "") {
47177
+ obj.execId = message.execId;
47178
+ }
47179
+ if (message.offset !== 0) {
47180
+ obj.offset = Math.round(message.offset);
47181
+ }
47182
+ if (message.fileDescriptor !== 0) {
47183
+ obj.fileDescriptor = taskExecStdioFileDescriptorToJSON(message.fileDescriptor);
47184
+ }
47185
+ return obj;
47186
+ },
47187
+ create(base) {
47188
+ return TaskExecStdioReadRequest.fromPartial(base ?? {});
47189
+ },
47190
+ fromPartial(object) {
47191
+ const message = createBaseTaskExecStdioReadRequest();
47192
+ message.taskId = object.taskId ?? "";
47193
+ message.execId = object.execId ?? "";
47194
+ message.offset = object.offset ?? 0;
47195
+ message.fileDescriptor = object.fileDescriptor ?? 0;
47196
+ return message;
47197
+ }
47198
+ };
47199
+ function createBaseTaskExecStdioReadResponse() {
47200
+ return { data: new Uint8Array(0) };
47201
+ }
47202
+ var TaskExecStdioReadResponse = {
47203
+ encode(message, writer = new BinaryWriter()) {
47204
+ if (message.data.length !== 0) {
47205
+ writer.uint32(10).bytes(message.data);
47206
+ }
47207
+ return writer;
47208
+ },
47209
+ decode(input, length) {
47210
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
47211
+ let end = length === void 0 ? reader.len : reader.pos + length;
47212
+ const message = createBaseTaskExecStdioReadResponse();
47213
+ while (reader.pos < end) {
47214
+ const tag = reader.uint32();
47215
+ switch (tag >>> 3) {
47216
+ case 1: {
47217
+ if (tag !== 10) {
47218
+ break;
47219
+ }
47220
+ message.data = reader.bytes();
47221
+ continue;
47222
+ }
47223
+ }
47224
+ if ((tag & 7) === 4 || tag === 0) {
47225
+ break;
47226
+ }
47227
+ reader.skip(tag & 7);
47228
+ }
47229
+ return message;
47230
+ },
47231
+ fromJSON(object) {
47232
+ return { data: isSet5(object.data) ? bytesFromBase642(object.data) : new Uint8Array(0) };
47233
+ },
47234
+ toJSON(message) {
47235
+ const obj = {};
47236
+ if (message.data.length !== 0) {
47237
+ obj.data = base64FromBytes2(message.data);
47238
+ }
47239
+ return obj;
47240
+ },
47241
+ create(base) {
47242
+ return TaskExecStdioReadResponse.fromPartial(base ?? {});
47243
+ },
47244
+ fromPartial(object) {
47245
+ const message = createBaseTaskExecStdioReadResponse();
47246
+ message.data = object.data ?? new Uint8Array(0);
47247
+ return message;
47248
+ }
47249
+ };
47250
+ function createBaseTaskExecWaitRequest() {
47251
+ return { taskId: "", execId: "" };
47252
+ }
47253
+ var TaskExecWaitRequest = {
47254
+ encode(message, writer = new BinaryWriter()) {
47255
+ if (message.taskId !== "") {
47256
+ writer.uint32(10).string(message.taskId);
47257
+ }
47258
+ if (message.execId !== "") {
47259
+ writer.uint32(18).string(message.execId);
47260
+ }
47261
+ return writer;
47262
+ },
47263
+ decode(input, length) {
47264
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
47265
+ let end = length === void 0 ? reader.len : reader.pos + length;
47266
+ const message = createBaseTaskExecWaitRequest();
47267
+ while (reader.pos < end) {
47268
+ const tag = reader.uint32();
47269
+ switch (tag >>> 3) {
47270
+ case 1: {
47271
+ if (tag !== 10) {
47272
+ break;
47273
+ }
47274
+ message.taskId = reader.string();
47275
+ continue;
47276
+ }
47277
+ case 2: {
47278
+ if (tag !== 18) {
47279
+ break;
47280
+ }
47281
+ message.execId = reader.string();
47282
+ continue;
47283
+ }
47284
+ }
47285
+ if ((tag & 7) === 4 || tag === 0) {
47286
+ break;
47287
+ }
47288
+ reader.skip(tag & 7);
47289
+ }
47290
+ return message;
47291
+ },
47292
+ fromJSON(object) {
47293
+ return {
47294
+ taskId: isSet5(object.taskId) ? globalThis.String(object.taskId) : "",
47295
+ execId: isSet5(object.execId) ? globalThis.String(object.execId) : ""
47296
+ };
47297
+ },
47298
+ toJSON(message) {
47299
+ const obj = {};
47300
+ if (message.taskId !== "") {
47301
+ obj.taskId = message.taskId;
47302
+ }
47303
+ if (message.execId !== "") {
47304
+ obj.execId = message.execId;
47305
+ }
47306
+ return obj;
47307
+ },
47308
+ create(base) {
47309
+ return TaskExecWaitRequest.fromPartial(base ?? {});
47310
+ },
47311
+ fromPartial(object) {
47312
+ const message = createBaseTaskExecWaitRequest();
47313
+ message.taskId = object.taskId ?? "";
47314
+ message.execId = object.execId ?? "";
47315
+ return message;
47316
+ }
47317
+ };
47318
+ function createBaseTaskExecWaitResponse() {
47319
+ return { code: void 0, signal: void 0 };
47320
+ }
47321
+ var TaskExecWaitResponse = {
47322
+ encode(message, writer = new BinaryWriter()) {
47323
+ if (message.code !== void 0) {
47324
+ writer.uint32(8).int32(message.code);
47325
+ }
47326
+ if (message.signal !== void 0) {
47327
+ writer.uint32(16).int32(message.signal);
47328
+ }
47329
+ return writer;
47330
+ },
47331
+ decode(input, length) {
47332
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
47333
+ let end = length === void 0 ? reader.len : reader.pos + length;
47334
+ const message = createBaseTaskExecWaitResponse();
47335
+ while (reader.pos < end) {
47336
+ const tag = reader.uint32();
47337
+ switch (tag >>> 3) {
47338
+ case 1: {
47339
+ if (tag !== 8) {
47340
+ break;
47341
+ }
47342
+ message.code = reader.int32();
47343
+ continue;
47344
+ }
47345
+ case 2: {
47346
+ if (tag !== 16) {
47347
+ break;
47348
+ }
47349
+ message.signal = reader.int32();
47350
+ continue;
47351
+ }
47352
+ }
47353
+ if ((tag & 7) === 4 || tag === 0) {
47354
+ break;
47355
+ }
47356
+ reader.skip(tag & 7);
47357
+ }
47358
+ return message;
47359
+ },
47360
+ fromJSON(object) {
47361
+ return {
47362
+ code: isSet5(object.code) ? globalThis.Number(object.code) : void 0,
47363
+ signal: isSet5(object.signal) ? globalThis.Number(object.signal) : void 0
47364
+ };
47365
+ },
47366
+ toJSON(message) {
47367
+ const obj = {};
47368
+ if (message.code !== void 0) {
47369
+ obj.code = Math.round(message.code);
47370
+ }
47371
+ if (message.signal !== void 0) {
47372
+ obj.signal = Math.round(message.signal);
47373
+ }
47374
+ return obj;
47375
+ },
47376
+ create(base) {
47377
+ return TaskExecWaitResponse.fromPartial(base ?? {});
47378
+ },
47379
+ fromPartial(object) {
47380
+ const message = createBaseTaskExecWaitResponse();
47381
+ message.code = object.code ?? void 0;
47382
+ message.signal = object.signal ?? void 0;
47383
+ return message;
47384
+ }
47385
+ };
47386
+ function createBaseTaskMountDirectoryRequest() {
47387
+ return { taskId: "", path: new Uint8Array(0), imageId: "" };
47388
+ }
47389
+ var TaskMountDirectoryRequest = {
47390
+ encode(message, writer = new BinaryWriter()) {
47391
+ if (message.taskId !== "") {
47392
+ writer.uint32(10).string(message.taskId);
47393
+ }
47394
+ if (message.path.length !== 0) {
47395
+ writer.uint32(18).bytes(message.path);
47396
+ }
47397
+ if (message.imageId !== "") {
47398
+ writer.uint32(26).string(message.imageId);
47399
+ }
47400
+ return writer;
47401
+ },
47402
+ decode(input, length) {
47403
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
47404
+ let end = length === void 0 ? reader.len : reader.pos + length;
47405
+ const message = createBaseTaskMountDirectoryRequest();
47406
+ while (reader.pos < end) {
47407
+ const tag = reader.uint32();
47408
+ switch (tag >>> 3) {
47409
+ case 1: {
47410
+ if (tag !== 10) {
47411
+ break;
47412
+ }
47413
+ message.taskId = reader.string();
47414
+ continue;
47415
+ }
47416
+ case 2: {
47417
+ if (tag !== 18) {
47418
+ break;
47419
+ }
47420
+ message.path = reader.bytes();
47421
+ continue;
47422
+ }
47423
+ case 3: {
47424
+ if (tag !== 26) {
47425
+ break;
47426
+ }
47427
+ message.imageId = reader.string();
47428
+ continue;
47429
+ }
47430
+ }
47431
+ if ((tag & 7) === 4 || tag === 0) {
47432
+ break;
47433
+ }
47434
+ reader.skip(tag & 7);
47435
+ }
47436
+ return message;
47437
+ },
47438
+ fromJSON(object) {
47439
+ return {
47440
+ taskId: isSet5(object.taskId) ? globalThis.String(object.taskId) : "",
47441
+ path: isSet5(object.path) ? bytesFromBase642(object.path) : new Uint8Array(0),
47442
+ imageId: isSet5(object.imageId) ? globalThis.String(object.imageId) : ""
47443
+ };
47444
+ },
47445
+ toJSON(message) {
47446
+ const obj = {};
47447
+ if (message.taskId !== "") {
47448
+ obj.taskId = message.taskId;
47449
+ }
47450
+ if (message.path.length !== 0) {
47451
+ obj.path = base64FromBytes2(message.path);
47452
+ }
47453
+ if (message.imageId !== "") {
47454
+ obj.imageId = message.imageId;
47455
+ }
47456
+ return obj;
47457
+ },
47458
+ create(base) {
47459
+ return TaskMountDirectoryRequest.fromPartial(base ?? {});
47460
+ },
47461
+ fromPartial(object) {
47462
+ const message = createBaseTaskMountDirectoryRequest();
47463
+ message.taskId = object.taskId ?? "";
47464
+ message.path = object.path ?? new Uint8Array(0);
47465
+ message.imageId = object.imageId ?? "";
47466
+ return message;
47467
+ }
47468
+ };
47469
+ function createBaseTaskSnapshotDirectoryRequest() {
47470
+ return { taskId: "", path: new Uint8Array(0) };
47471
+ }
47472
+ var TaskSnapshotDirectoryRequest = {
47473
+ encode(message, writer = new BinaryWriter()) {
47474
+ if (message.taskId !== "") {
47475
+ writer.uint32(10).string(message.taskId);
47476
+ }
47477
+ if (message.path.length !== 0) {
47478
+ writer.uint32(18).bytes(message.path);
47479
+ }
47480
+ return writer;
47481
+ },
47482
+ decode(input, length) {
47483
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
47484
+ let end = length === void 0 ? reader.len : reader.pos + length;
47485
+ const message = createBaseTaskSnapshotDirectoryRequest();
47486
+ while (reader.pos < end) {
47487
+ const tag = reader.uint32();
47488
+ switch (tag >>> 3) {
47489
+ case 1: {
47490
+ if (tag !== 10) {
47491
+ break;
47492
+ }
47493
+ message.taskId = reader.string();
47494
+ continue;
47495
+ }
47496
+ case 2: {
47497
+ if (tag !== 18) {
47498
+ break;
47499
+ }
47500
+ message.path = reader.bytes();
47501
+ continue;
47502
+ }
47503
+ }
47504
+ if ((tag & 7) === 4 || tag === 0) {
47505
+ break;
47506
+ }
47507
+ reader.skip(tag & 7);
47508
+ }
47509
+ return message;
47510
+ },
47511
+ fromJSON(object) {
47512
+ return {
47513
+ taskId: isSet5(object.taskId) ? globalThis.String(object.taskId) : "",
47514
+ path: isSet5(object.path) ? bytesFromBase642(object.path) : new Uint8Array(0)
47515
+ };
47516
+ },
47517
+ toJSON(message) {
47518
+ const obj = {};
47519
+ if (message.taskId !== "") {
47520
+ obj.taskId = message.taskId;
47521
+ }
47522
+ if (message.path.length !== 0) {
47523
+ obj.path = base64FromBytes2(message.path);
47524
+ }
47525
+ return obj;
47526
+ },
47527
+ create(base) {
47528
+ return TaskSnapshotDirectoryRequest.fromPartial(base ?? {});
47529
+ },
47530
+ fromPartial(object) {
47531
+ const message = createBaseTaskSnapshotDirectoryRequest();
47532
+ message.taskId = object.taskId ?? "";
47533
+ message.path = object.path ?? new Uint8Array(0);
47534
+ return message;
47535
+ }
47536
+ };
47537
+ function createBaseTaskSnapshotDirectoryResponse() {
47538
+ return { imageId: "" };
47539
+ }
47540
+ var TaskSnapshotDirectoryResponse = {
47541
+ encode(message, writer = new BinaryWriter()) {
47542
+ if (message.imageId !== "") {
47543
+ writer.uint32(10).string(message.imageId);
47544
+ }
47545
+ return writer;
47546
+ },
47547
+ decode(input, length) {
47548
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
47549
+ let end = length === void 0 ? reader.len : reader.pos + length;
47550
+ const message = createBaseTaskSnapshotDirectoryResponse();
47551
+ while (reader.pos < end) {
47552
+ const tag = reader.uint32();
47553
+ switch (tag >>> 3) {
47554
+ case 1: {
47555
+ if (tag !== 10) {
47556
+ break;
47557
+ }
47558
+ message.imageId = reader.string();
47559
+ continue;
47560
+ }
47561
+ }
47562
+ if ((tag & 7) === 4 || tag === 0) {
47563
+ break;
47564
+ }
47565
+ reader.skip(tag & 7);
47566
+ }
47567
+ return message;
47568
+ },
47569
+ fromJSON(object) {
47570
+ return { imageId: isSet5(object.imageId) ? globalThis.String(object.imageId) : "" };
47571
+ },
47572
+ toJSON(message) {
47573
+ const obj = {};
47574
+ if (message.imageId !== "") {
47575
+ obj.imageId = message.imageId;
47576
+ }
47577
+ return obj;
47578
+ },
47579
+ create(base) {
47580
+ return TaskSnapshotDirectoryResponse.fromPartial(base ?? {});
47581
+ },
47582
+ fromPartial(object) {
47583
+ const message = createBaseTaskSnapshotDirectoryResponse();
47584
+ message.imageId = object.imageId ?? "";
47585
+ return message;
47586
+ }
47587
+ };
47588
+ var TaskCommandRouterDefinition = {
47589
+ name: "TaskCommandRouter",
47590
+ fullName: "modal.task_command_router.TaskCommandRouter",
47591
+ methods: {
47592
+ /** Poll for the exit status of an exec'd command. */
47593
+ taskExecPoll: {
47594
+ name: "TaskExecPoll",
47595
+ requestType: TaskExecPollRequest,
47596
+ requestStream: false,
47597
+ responseType: TaskExecPollResponse,
47598
+ responseStream: false,
47599
+ options: {}
47600
+ },
47601
+ /** Execute a command in the task. */
47602
+ taskExecStart: {
47603
+ name: "TaskExecStart",
47604
+ requestType: TaskExecStartRequest,
47605
+ requestStream: false,
47606
+ responseType: TaskExecStartResponse,
47607
+ responseStream: false,
47608
+ options: {}
47609
+ },
47610
+ /** Write to the stdin stream of an exec'd command. */
47611
+ taskExecStdinWrite: {
47612
+ name: "TaskExecStdinWrite",
47613
+ requestType: TaskExecStdinWriteRequest,
47614
+ requestStream: false,
47615
+ responseType: TaskExecStdinWriteResponse,
47616
+ responseStream: false,
47617
+ options: {}
47618
+ },
47619
+ /** Get a stream of output from the stdout or stderr stream of an exec'd command. */
47620
+ taskExecStdioRead: {
47621
+ name: "TaskExecStdioRead",
47622
+ requestType: TaskExecStdioReadRequest,
47623
+ requestStream: false,
47624
+ responseType: TaskExecStdioReadResponse,
47625
+ responseStream: true,
47626
+ options: {}
47627
+ },
47628
+ /** Wait for an exec'd command to exit and return the exit code. */
47629
+ taskExecWait: {
47630
+ name: "TaskExecWait",
47631
+ requestType: TaskExecWaitRequest,
47632
+ requestStream: false,
47633
+ responseType: TaskExecWaitResponse,
47634
+ responseStream: false,
47635
+ options: {}
47636
+ },
47637
+ /** Mount an image at a directory in the container. */
47638
+ taskMountDirectory: {
47639
+ name: "TaskMountDirectory",
47640
+ requestType: TaskMountDirectoryRequest,
47641
+ requestStream: false,
47642
+ responseType: Empty,
47643
+ responseStream: false,
47644
+ options: {}
47645
+ },
47646
+ /** Snapshot a directory with a mounted image, including any local changes, into a new image. */
47647
+ taskSnapshotDirectory: {
47648
+ name: "TaskSnapshotDirectory",
47649
+ requestType: TaskSnapshotDirectoryRequest,
47650
+ requestStream: false,
47651
+ responseType: TaskSnapshotDirectoryResponse,
47652
+ responseStream: false,
47653
+ options: {}
47654
+ }
47655
+ }
47656
+ };
47657
+ function bytesFromBase642(b64) {
47658
+ if (globalThis.Buffer) {
47659
+ return Uint8Array.from(globalThis.Buffer.from(b64, "base64"));
47660
+ } else {
47661
+ const bin = globalThis.atob(b64);
47662
+ const arr = new Uint8Array(bin.length);
47663
+ for (let i = 0; i < bin.length; ++i) {
47664
+ arr[i] = bin.charCodeAt(i);
47665
+ }
47666
+ return arr;
47667
+ }
47668
+ }
47669
+ function base64FromBytes2(arr) {
47670
+ if (globalThis.Buffer) {
47671
+ return globalThis.Buffer.from(arr).toString("base64");
47672
+ } else {
47673
+ const bin = [];
47674
+ arr.forEach((byte) => {
47675
+ bin.push(globalThis.String.fromCharCode(byte));
47676
+ });
47677
+ return globalThis.btoa(bin.join(""));
47678
+ }
47679
+ }
47680
+ function longToNumber3(int64) {
47681
+ const num = globalThis.Number(int64.toString());
47682
+ if (num > globalThis.Number.MAX_SAFE_INTEGER) {
47683
+ throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER");
47684
+ }
47685
+ if (num < globalThis.Number.MIN_SAFE_INTEGER) {
47686
+ throw new globalThis.Error("Value is smaller than Number.MIN_SAFE_INTEGER");
47687
+ }
47688
+ return num;
47689
+ }
47690
+ function isSet5(value) {
47691
+ return value !== null && value !== void 0;
47692
+ }
47693
+
47694
+ // src/task_command_router_client.ts
47695
+ var import_promises = require("timers/promises");
47696
+ var import_nice_grpc8 = require("nice-grpc");
47697
+
47698
+ // src/config.ts
47699
+ var import_node_fs = require("fs");
47700
+ var import_node_os = require("os");
47701
+ var import_node_path = __toESM(require("path"), 1);
47702
+ var import_smol_toml = require("smol-toml");
47703
+ function isLocalhost(profile) {
47704
+ const url = new URL(profile.serverUrl);
47705
+ const hostname = url.hostname;
47706
+ return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "172.21.0.1";
47707
+ }
47708
+ function configFilePath() {
47709
+ const configPath = process.env["MODAL_CONFIG_PATH"];
47710
+ if (configPath && configPath !== "") {
47711
+ return configPath;
47712
+ }
47713
+ return import_node_path.default.join((0, import_node_os.homedir)(), ".modal.toml");
47714
+ }
47715
+ function readConfigFile() {
47716
+ try {
47717
+ const configPath = configFilePath();
47718
+ const configContent = (0, import_node_fs.readFileSync)(configPath, {
47719
+ encoding: "utf-8"
47720
+ });
47721
+ return (0, import_smol_toml.parse)(configContent);
47722
+ } catch (err) {
47723
+ if (err.code === "ENOENT") {
47724
+ return {};
47725
+ }
47726
+ return {};
47727
+ }
47728
+ }
47729
+ var config = readConfigFile();
47730
+ function getProfile(profileName) {
47731
+ if (!profileName) {
47732
+ for (const [name, profileData2] of Object.entries(config)) {
47733
+ if (profileData2.active) {
47734
+ profileName = name;
47735
+ break;
47736
+ }
47737
+ }
47738
+ }
47739
+ const profileData = profileName && Object.hasOwn(config, profileName) ? config[profileName] : {};
47740
+ const profile = {
47741
+ serverUrl: process.env["MODAL_SERVER_URL"] || profileData.server_url || "https://api.modal.com:443",
47742
+ tokenId: process.env["MODAL_TOKEN_ID"] || profileData.token_id,
47743
+ tokenSecret: process.env["MODAL_TOKEN_SECRET"] || profileData.token_secret,
47744
+ environment: process.env["MODAL_ENVIRONMENT"] || profileData.environment,
47745
+ imageBuilderVersion: process.env["MODAL_IMAGE_BUILDER_VERSION"] || profileData.imageBuilderVersion,
47746
+ logLevel: process.env["MODAL_LOGLEVEL"] || profileData.loglevel
47747
+ };
47748
+ return profile;
47749
+ }
47750
+
47751
+ // src/task_command_router_client.ts
47752
+ function parseJwtExpiration(jwtToken, logger) {
47753
+ try {
47754
+ const parts = jwtToken.split(".");
47755
+ if (parts.length !== 3) {
47756
+ return null;
47757
+ }
47758
+ const payloadB64 = parts[1];
47759
+ const padding = "=".repeat((4 - payloadB64.length % 4) % 4);
47760
+ const payloadJson = Buffer.from(payloadB64 + padding, "base64").toString(
47761
+ "utf8"
47762
+ );
47763
+ const payload = JSON.parse(payloadJson);
47764
+ const exp = payload.exp;
47765
+ if (typeof exp === "number") {
47766
+ return exp;
47767
+ }
47768
+ } catch (e) {
47769
+ logger.warn("Failed to parse JWT expiration", "error", e);
47770
+ }
47771
+ return null;
47772
+ }
47773
+ async function callWithRetriesOnTransientErrors(func, baseDelayMs = 10, delayFactor = 2, maxRetries = 10, deadlineMs = null, isClosed) {
47774
+ let delayMs = baseDelayMs;
47775
+ let numRetries = 0;
47776
+ const retryableStatusCodes = /* @__PURE__ */ new Set([
47777
+ import_nice_grpc8.Status.DEADLINE_EXCEEDED,
47778
+ import_nice_grpc8.Status.UNAVAILABLE,
47779
+ import_nice_grpc8.Status.CANCELLED,
47780
+ import_nice_grpc8.Status.INTERNAL,
47781
+ import_nice_grpc8.Status.UNKNOWN
47782
+ ]);
47783
+ while (true) {
47784
+ if (deadlineMs !== null && Date.now() >= deadlineMs) {
47785
+ throw new Error("Deadline exceeded");
47786
+ }
47787
+ try {
47788
+ return await func();
47789
+ } catch (err) {
47790
+ if (err instanceof import_nice_grpc8.ClientError && err.code === import_nice_grpc8.Status.CANCELLED && isClosed?.()) {
47791
+ throw new ClientClosedError();
47792
+ }
47793
+ if (err instanceof import_nice_grpc8.ClientError && retryableStatusCodes.has(err.code) && (maxRetries === null || numRetries < maxRetries)) {
47794
+ if (deadlineMs !== null && Date.now() + delayMs >= deadlineMs) {
47795
+ throw new Error("Deadline exceeded");
47796
+ }
47797
+ await (0, import_promises.setTimeout)(delayMs);
47798
+ delayMs *= delayFactor;
47799
+ numRetries++;
47800
+ } else {
47801
+ throw err;
47802
+ }
47803
+ }
47804
+ }
47805
+ }
47806
+ var TaskCommandRouterClientImpl = class _TaskCommandRouterClientImpl {
47807
+ stub;
47808
+ channel;
47809
+ serverClient;
47810
+ taskId;
47811
+ serverUrl;
47812
+ jwt;
47813
+ jwtExp;
47814
+ jwtRefreshLock = Promise.resolve();
47815
+ logger;
47816
+ closed = false;
47817
+ static async tryInit(serverClient, taskId, logger, profile) {
47818
+ let resp;
47819
+ try {
47820
+ resp = await serverClient.taskGetCommandRouterAccess(
47821
+ TaskGetCommandRouterAccessRequest.create({ taskId })
47822
+ );
47823
+ } catch (err) {
47824
+ if (err instanceof import_nice_grpc8.ClientError && err.code === import_nice_grpc8.Status.FAILED_PRECONDITION) {
47825
+ logger.debug(
47826
+ "Command router access is not enabled for task",
47827
+ "task_id",
47828
+ taskId
47829
+ );
47830
+ return null;
47831
+ }
47832
+ throw err;
47833
+ }
47834
+ logger.debug(
47835
+ "Using command router access for task",
47836
+ "task_id",
47837
+ taskId,
47838
+ "url",
47839
+ resp.url
47840
+ );
47841
+ const url = new URL(resp.url);
47842
+ if (url.protocol !== "https:") {
47843
+ throw new Error(`Task router URL must be https, got: ${resp.url}`);
47844
+ }
47845
+ const host = url.hostname;
47846
+ const port = url.port ? parseInt(url.port) : 443;
47847
+ const serverUrl = `${host}:${port}`;
47848
+ const channelConfig = {
47849
+ "grpc.max_receive_message_length": 100 * 1024 * 1024,
47850
+ "grpc.max_send_message_length": 100 * 1024 * 1024,
47851
+ "grpc-node.flow_control_window": 64 * 1024 * 1024,
47852
+ "grpc.keepalive_time_ms": 3e4,
47853
+ "grpc.keepalive_timeout_ms": 1e4,
47854
+ "grpc.keepalive_permit_without_calls": 1
47855
+ };
47856
+ let channel;
47857
+ if (isLocalhost(profile)) {
47858
+ logger.warn(
47859
+ "Using insecure TLS (skip certificate verification) for task command router"
47860
+ );
47861
+ channel = (0, import_nice_grpc8.createChannel)(
47862
+ serverUrl,
47863
+ import_nice_grpc8.ChannelCredentials.createInsecure(),
47864
+ channelConfig
47865
+ );
47866
+ } else {
47867
+ channel = (0, import_nice_grpc8.createChannel)(
47868
+ serverUrl,
47869
+ import_nice_grpc8.ChannelCredentials.createSsl(),
47870
+ channelConfig
47871
+ );
47872
+ }
47873
+ const client2 = new _TaskCommandRouterClientImpl(
47874
+ serverClient,
47875
+ taskId,
47876
+ resp.url,
47877
+ resp.jwt,
47878
+ channel,
47879
+ logger
47880
+ );
47881
+ logger.debug(
47882
+ "Successfully initialized command router client",
47883
+ "task_id",
47884
+ taskId
47885
+ );
47886
+ return client2;
47887
+ }
47888
+ constructor(serverClient, taskId, serverUrl, jwt, channel, logger) {
47889
+ this.serverClient = serverClient;
47890
+ this.taskId = taskId;
47891
+ this.serverUrl = serverUrl;
47892
+ this.jwt = jwt;
47893
+ this.jwtExp = parseJwtExpiration(jwt, logger);
47894
+ this.logger = logger;
47895
+ this.channel = channel;
47896
+ const self = this;
47897
+ const factory = (0, import_nice_grpc8.createClientFactory)().use(timeoutMiddleware).use(async function* authMiddleware(call, options) {
47898
+ options.metadata ??= new import_nice_grpc8.Metadata();
47899
+ options.metadata.set("authorization", `Bearer ${self.jwt}`);
47900
+ return yield* call.next(call.request, options);
47901
+ });
47902
+ this.stub = factory.create(TaskCommandRouterDefinition, channel);
47903
+ }
47904
+ close() {
47905
+ if (this.closed) {
47906
+ return;
47907
+ }
47908
+ this.closed = true;
47909
+ this.channel.close();
47910
+ }
47911
+ async execStart(request) {
47912
+ return await callWithRetriesOnTransientErrors(
47913
+ () => this.callWithAuthRetry(() => this.stub.taskExecStart(request)),
47914
+ 10,
47915
+ 2,
47916
+ 10,
47917
+ null,
47918
+ () => this.closed
47919
+ );
47920
+ }
47921
+ async *execStdioRead(taskId, execId, fileDescriptor, deadline = null) {
47922
+ let srFd;
47923
+ if (fileDescriptor === 1 /* FILE_DESCRIPTOR_STDOUT */) {
47924
+ srFd = 0 /* TASK_EXEC_STDIO_FILE_DESCRIPTOR_STDOUT */;
47925
+ } else if (fileDescriptor === 2 /* FILE_DESCRIPTOR_STDERR */) {
47926
+ srFd = 1 /* TASK_EXEC_STDIO_FILE_DESCRIPTOR_STDERR */;
47927
+ } else if (fileDescriptor === 3 /* FILE_DESCRIPTOR_INFO */ || fileDescriptor === 0 /* FILE_DESCRIPTOR_UNSPECIFIED */) {
47928
+ throw new Error(`Unsupported file descriptor: ${fileDescriptor}`);
47929
+ } else {
47930
+ throw new Error(`Invalid file descriptor: ${fileDescriptor}`);
47931
+ }
47932
+ yield* this.streamStdio(taskId, execId, srFd, deadline);
47933
+ }
47934
+ async execStdinWrite(taskId, execId, offset, data, eof) {
47935
+ const request = TaskExecStdinWriteRequest.create({
47936
+ taskId,
47937
+ execId,
47938
+ offset,
47939
+ data,
47940
+ eof
47941
+ });
47942
+ return await callWithRetriesOnTransientErrors(
47943
+ () => this.callWithAuthRetry(() => this.stub.taskExecStdinWrite(request)),
47944
+ 10,
47945
+ 2,
47946
+ 10,
47947
+ null,
47948
+ () => this.closed
47949
+ );
47950
+ }
47951
+ async execPoll(taskId, execId, deadline = null) {
47952
+ const request = TaskExecPollRequest.create({ taskId, execId });
47953
+ if (deadline && deadline <= Date.now()) {
47954
+ throw new Error(`Deadline exceeded while polling for exec ${execId}`);
47955
+ }
47956
+ try {
47957
+ return await callWithRetriesOnTransientErrors(
47958
+ () => this.callWithAuthRetry(() => this.stub.taskExecPoll(request)),
47959
+ 10,
47960
+ // baseDelayMs
47961
+ 2,
47962
+ // delayFactor
47963
+ 10,
47964
+ // maxRetries
47965
+ deadline,
47966
+ // Enforce overall deadline.
47967
+ () => this.closed
47968
+ );
47969
+ } catch (err) {
47970
+ if (err instanceof import_nice_grpc8.ClientError && err.code === import_nice_grpc8.Status.DEADLINE_EXCEEDED) {
47971
+ throw new Error(`Deadline exceeded while polling for exec ${execId}`);
47972
+ }
47973
+ throw err;
47974
+ }
47975
+ }
47976
+ async execWait(taskId, execId, deadline = null) {
47977
+ const request = TaskExecWaitRequest.create({ taskId, execId });
47978
+ if (deadline && deadline <= Date.now()) {
47979
+ throw new Error(`Deadline exceeded while waiting for exec ${execId}`);
47980
+ }
47981
+ try {
47982
+ return await callWithRetriesOnTransientErrors(
47983
+ () => this.callWithAuthRetry(
47984
+ () => this.stub.taskExecWait(request, {
47985
+ timeoutMs: 6e4
47986
+ })
47987
+ ),
47988
+ 1e3,
47989
+ // Retry after 1s since total time is expected to be long.
47990
+ 1,
47991
+ // Fixed delay.
47992
+ null,
47993
+ // Retry forever.
47994
+ deadline,
47995
+ // Enforce overall deadline.
47996
+ () => this.closed
47997
+ );
47998
+ } catch (err) {
47999
+ if (err instanceof import_nice_grpc8.ClientError && err.code === import_nice_grpc8.Status.DEADLINE_EXCEEDED) {
48000
+ throw new Error(`Deadline exceeded while waiting for exec ${execId}`);
48001
+ }
48002
+ throw err;
48003
+ }
48004
+ }
48005
+ async mountDirectory(request) {
48006
+ await callWithRetriesOnTransientErrors(
48007
+ () => this.callWithAuthRetry(() => this.stub.taskMountDirectory(request)),
48008
+ 10,
48009
+ 2,
48010
+ 10,
48011
+ null,
48012
+ () => this.closed
48013
+ );
48014
+ }
48015
+ async snapshotDirectory(request) {
48016
+ return await callWithRetriesOnTransientErrors(
48017
+ () => this.callWithAuthRetry(() => this.stub.taskSnapshotDirectory(request)),
48018
+ 10,
48019
+ 2,
48020
+ 10,
48021
+ null,
48022
+ () => this.closed
48023
+ );
48024
+ }
48025
+ async refreshJwt() {
48026
+ let error;
48027
+ this.jwtRefreshLock = this.jwtRefreshLock.then(async () => {
48028
+ if (this.closed) {
48029
+ return;
48030
+ }
48031
+ if (this.jwtExp !== null && this.jwtExp - Date.now() / 1e3 > 30) {
48032
+ this.logger.debug(
48033
+ "Skipping JWT refresh because expiration is far enough in the future",
48034
+ "task_id",
48035
+ this.taskId
48036
+ );
48037
+ return;
48038
+ }
48039
+ try {
48040
+ const resp = await this.serverClient.taskGetCommandRouterAccess(
48041
+ TaskGetCommandRouterAccessRequest.create({ taskId: this.taskId })
48042
+ );
48043
+ if (resp.url !== this.serverUrl) {
48044
+ throw new Error("Task router URL changed during session");
48045
+ }
48046
+ this.jwt = resp.jwt;
48047
+ this.jwtExp = parseJwtExpiration(resp.jwt, this.logger);
48048
+ } catch (err) {
48049
+ error = err;
48050
+ }
48051
+ });
48052
+ await this.jwtRefreshLock;
48053
+ if (error) {
48054
+ throw error;
48055
+ }
48056
+ }
48057
+ async callWithAuthRetry(func) {
48058
+ try {
48059
+ return await func();
48060
+ } catch (err) {
48061
+ if (err instanceof import_nice_grpc8.ClientError && err.code === import_nice_grpc8.Status.UNAUTHENTICATED) {
48062
+ await this.refreshJwt();
48063
+ return await func();
48064
+ }
48065
+ throw err;
48066
+ }
48067
+ }
48068
+ async *streamStdio(taskId, execId, fileDescriptor, deadline) {
48069
+ let offset = 0;
48070
+ let delayMs = 10;
48071
+ const delayFactor = 2;
48072
+ let numRetriesRemaining = 10;
48073
+ let didAuthRetry = false;
48074
+ const retryableStatusCodes = /* @__PURE__ */ new Set([
48075
+ import_nice_grpc8.Status.DEADLINE_EXCEEDED,
48076
+ import_nice_grpc8.Status.UNAVAILABLE,
48077
+ import_nice_grpc8.Status.CANCELLED,
48078
+ import_nice_grpc8.Status.INTERNAL,
48079
+ import_nice_grpc8.Status.UNKNOWN
48080
+ ]);
48081
+ while (true) {
48082
+ try {
48083
+ const timeoutMs = deadline !== null ? Math.max(0, deadline - Date.now()) : void 0;
48084
+ const request = TaskExecStdioReadRequest.create({
48085
+ taskId,
48086
+ execId,
48087
+ offset,
48088
+ fileDescriptor
48089
+ });
48090
+ const stream = this.stub.taskExecStdioRead(request, {
48091
+ timeoutMs
48092
+ });
48093
+ try {
48094
+ for await (const item of stream) {
48095
+ if (didAuthRetry) {
48096
+ didAuthRetry = false;
48097
+ }
48098
+ delayMs = 10;
48099
+ offset += item.data.length;
48100
+ yield item;
48101
+ }
48102
+ return;
48103
+ } catch (err) {
48104
+ if (err instanceof import_nice_grpc8.ClientError && err.code === import_nice_grpc8.Status.UNAUTHENTICATED && !didAuthRetry) {
48105
+ await this.refreshJwt();
48106
+ didAuthRetry = true;
48107
+ continue;
48108
+ }
48109
+ throw err;
48110
+ }
48111
+ } catch (err) {
48112
+ if (err instanceof import_nice_grpc8.ClientError && err.code === import_nice_grpc8.Status.CANCELLED && this.closed) {
48113
+ throw new ClientClosedError();
48114
+ }
48115
+ if (err instanceof import_nice_grpc8.ClientError && retryableStatusCodes.has(err.code) && numRetriesRemaining > 0) {
48116
+ if (deadline && deadline - Date.now() <= delayMs) {
48117
+ throw new Error(
48118
+ `Deadline exceeded while streaming stdio for exec ${execId}`
48119
+ );
48120
+ }
48121
+ this.logger.debug(
48122
+ "Retrying stdio read with delay",
48123
+ "delay_ms",
48124
+ delayMs,
48125
+ "error",
48126
+ err
48127
+ );
48128
+ await (0, import_promises.setTimeout)(delayMs);
48129
+ delayMs *= delayFactor;
48130
+ numRetriesRemaining--;
48131
+ } else {
48132
+ throw err;
48133
+ }
48134
+ }
48135
+ }
48136
+ }
48137
+ };
48138
+
48139
+ // src/sandbox.ts
48140
+ var import_uuid = require("uuid");
48141
+
48142
+ // src/sandbox_filesystem.ts
48143
+ var SandboxFile = class {
48144
+ #client;
48145
+ #fileDescriptor;
48146
+ #taskId;
48147
+ /** @ignore */
48148
+ constructor(client2, fileDescriptor, taskId) {
48149
+ this.#client = client2;
48150
+ this.#fileDescriptor = fileDescriptor;
48151
+ this.#taskId = taskId;
48152
+ }
48153
+ /**
48154
+ * Read data from the file.
48155
+ * @returns Promise that resolves to the read data as Uint8Array
48156
+ */
48157
+ async read() {
48158
+ const resp = await runFilesystemExec(this.#client.cpClient, {
48159
+ fileReadRequest: {
48160
+ fileDescriptor: this.#fileDescriptor
48161
+ },
48162
+ taskId: this.#taskId
48163
+ });
48164
+ const chunks = resp.chunks;
48165
+ const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
48166
+ const result = new Uint8Array(totalLength);
48167
+ let offset = 0;
48168
+ for (const chunk of chunks) {
48169
+ result.set(chunk, offset);
48170
+ offset += chunk.length;
48171
+ }
48172
+ return result;
48173
+ }
48174
+ /**
48175
+ * Write data to the file.
48176
+ * @param data - Data to write (string or Uint8Array)
48177
+ */
48178
+ async write(data) {
48179
+ await runFilesystemExec(this.#client.cpClient, {
48180
+ fileWriteRequest: {
48181
+ fileDescriptor: this.#fileDescriptor,
48182
+ data
48183
+ },
48184
+ taskId: this.#taskId
48185
+ });
48186
+ }
48187
+ /**
48188
+ * Flush any buffered data to the file.
48189
+ */
48190
+ async flush() {
48191
+ await runFilesystemExec(this.#client.cpClient, {
48192
+ fileFlushRequest: {
48193
+ fileDescriptor: this.#fileDescriptor
48194
+ },
48195
+ taskId: this.#taskId
48196
+ });
48197
+ }
48198
+ /**
48199
+ * Close the file handle.
48200
+ */
48201
+ async close() {
48202
+ await runFilesystemExec(this.#client.cpClient, {
48203
+ fileCloseRequest: {
48204
+ fileDescriptor: this.#fileDescriptor
48205
+ },
48206
+ taskId: this.#taskId
48207
+ });
48208
+ }
48209
+ };
48210
+ async function runFilesystemExec(cpClient, request) {
48211
+ const response = await cpClient.containerFilesystemExec(request);
48212
+ const chunks = [];
48213
+ let retries = 10;
48214
+ let completed = false;
48215
+ while (!completed) {
48216
+ try {
48217
+ const outputIterator = cpClient.containerFilesystemExecGetOutput({
48218
+ execId: response.execId,
48219
+ timeout: 55
48220
+ });
48221
+ for await (const batch of outputIterator) {
48222
+ chunks.push(...batch.output);
48223
+ if (batch.eof) {
48224
+ completed = true;
48225
+ break;
48226
+ }
48227
+ if (batch.error !== void 0) {
48228
+ if (retries > 0) {
48229
+ retries--;
48230
+ break;
48231
+ }
48232
+ throw new SandboxFilesystemError(batch.error.errorMessage);
48233
+ }
48234
+ }
48235
+ } catch (err) {
48236
+ if (isRetryableGrpc(err) && retries > 0) {
48237
+ retries--;
48238
+ } else throw err;
48239
+ }
48240
+ }
48241
+ return { chunks, response };
48242
+ }
48243
+
48244
+ // src/streams.ts
48245
+ function toModalReadStream(stream) {
48246
+ return Object.assign(stream, readMixin);
48247
+ }
48248
+ function toModalWriteStream(stream) {
48249
+ return Object.assign(stream, writeMixin);
48250
+ }
48251
+ var readMixin = {
48252
+ async readText() {
48253
+ const reader = this.getReader();
48254
+ try {
48255
+ const decoder2 = new TextDecoder("utf-8");
48256
+ const chunks = [];
48257
+ while (true) {
48258
+ const { value, done } = await reader.read();
48259
+ if (value) {
48260
+ if (typeof value === "string") chunks.push(value);
48261
+ else {
48262
+ chunks.push(decoder2.decode(value.buffer, { stream: true }));
48263
+ }
48264
+ }
48265
+ if (done) {
48266
+ chunks.push(decoder2.decode(void 0, { stream: false }));
48267
+ break;
48268
+ }
48269
+ }
48270
+ return chunks.join("");
48271
+ } finally {
48272
+ reader.releaseLock();
48273
+ }
48274
+ },
48275
+ async readBytes() {
48276
+ const chunks = [];
48277
+ const reader = this.getReader();
48278
+ try {
48279
+ while (true) {
48280
+ const { value, done } = await reader.read();
48281
+ if (value) {
48282
+ if (typeof value === "string") {
48283
+ chunks.push(new TextEncoder().encode(value));
48284
+ } else {
48285
+ chunks.push(value);
48286
+ }
48287
+ }
48288
+ if (done) break;
48289
+ }
48290
+ } finally {
48291
+ reader.releaseLock();
48292
+ }
48293
+ let totalLength = 0;
48294
+ for (const chunk of chunks) {
48295
+ totalLength += chunk.length;
48296
+ }
48297
+ const result = new Uint8Array(totalLength);
48298
+ let offset = 0;
48299
+ for (const chunk of chunks) {
48300
+ result.set(chunk, offset);
48301
+ offset += chunk.length;
48302
+ }
48303
+ return result;
48304
+ }
48305
+ };
48306
+ var writeMixin = {
48307
+ async writeText(text) {
48308
+ const writer = this.getWriter();
48309
+ try {
48310
+ await writer.write(text);
48311
+ } finally {
48312
+ writer.releaseLock();
48313
+ }
48314
+ },
48315
+ async writeBytes(bytes) {
48316
+ const writer = this.getWriter();
48317
+ try {
48318
+ await writer.write(bytes);
48319
+ } finally {
48320
+ writer.releaseLock();
48321
+ }
48322
+ }
48323
+ };
48324
+ function streamConsumingIter(iterable, onCancel) {
48325
+ const iter = iterable[Symbol.asyncIterator]();
48326
+ return new ReadableStream(
48327
+ {
48328
+ async pull(controller) {
48329
+ const { done, value } = await iter.next();
48330
+ if (value) {
48331
+ controller.enqueue(value);
48332
+ }
48333
+ if (done) {
48334
+ controller.close();
48335
+ }
48336
+ },
48337
+ async cancel() {
48338
+ try {
48339
+ onCancel?.();
48340
+ } finally {
48341
+ if (typeof iter.return === "function") {
48342
+ await iter.return();
48343
+ }
48344
+ }
48345
+ }
48346
+ },
48347
+ new ByteLengthQueuingStrategy({
48348
+ highWaterMark: 64 * 1024
48349
+ // 64 KiB
48350
+ })
48351
+ );
48352
+ }
48353
+
48354
+ // src/sandbox.ts
48355
+ var SB_LOGS_INITIAL_DELAY_MS = 10;
48356
+ var SB_LOGS_DELAY_FACTOR = 2;
48357
+ var SB_LOGS_MAX_RETRIES = 10;
48358
+ async function buildSandboxCreateRequestProto(appId, imageId, params = {}) {
48359
+ checkForRenamedParams(params, {
48360
+ memory: "memoryMiB",
48361
+ memoryLimit: "memoryLimitMiB",
48362
+ timeout: "timeoutMs",
46712
48363
  idleTimeout: "idleTimeoutMs"
46713
48364
  });
46714
48365
  const gpuConfig = parseGpuConfig(params.gpu);
@@ -46919,7 +48570,7 @@ var SandboxService = class {
46919
48570
  try {
46920
48571
  createResp = await this.#client.cpClient.sandboxCreate(createReq);
46921
48572
  } catch (err) {
46922
- if (err instanceof import_nice_grpc8.ClientError && err.code === import_nice_grpc8.Status.ALREADY_EXISTS) {
48573
+ if (err instanceof import_nice_grpc9.ClientError && err.code === import_nice_grpc9.Status.ALREADY_EXISTS) {
46923
48574
  throw new AlreadyExistsError(err.details || err.message);
46924
48575
  }
46925
48576
  throw err;
@@ -46942,7 +48593,7 @@ var SandboxService = class {
46942
48593
  timeout: 0
46943
48594
  });
46944
48595
  } catch (err) {
46945
- if (err instanceof import_nice_grpc8.ClientError && err.code === import_nice_grpc8.Status.NOT_FOUND)
48596
+ if (err instanceof import_nice_grpc9.ClientError && err.code === import_nice_grpc9.Status.NOT_FOUND)
46946
48597
  throw new NotFoundError(`Sandbox with id: '${sandboxId}' not found`);
46947
48598
  throw err;
46948
48599
  }
@@ -46967,7 +48618,7 @@ var SandboxService = class {
46967
48618
  });
46968
48619
  return new Sandbox2(this.#client, resp.sandboxId);
46969
48620
  } catch (err) {
46970
- if (err instanceof import_nice_grpc8.ClientError && err.code === import_nice_grpc8.Status.NOT_FOUND)
48621
+ if (err instanceof import_nice_grpc9.ClientError && err.code === import_nice_grpc9.Status.NOT_FOUND)
46971
48622
  throw new NotFoundError(
46972
48623
  `Sandbox with name '${name}' not found in App '${appName}'`
46973
48624
  );
@@ -47002,7 +48653,7 @@ var SandboxService = class {
47002
48653
  }
47003
48654
  beforeTimestamp = resp.sandboxes[resp.sandboxes.length - 1].createdAt;
47004
48655
  } catch (err) {
47005
- if (err instanceof import_nice_grpc8.ClientError && err.code === import_nice_grpc8.Status.INVALID_ARGUMENT) {
48656
+ if (err instanceof import_nice_grpc9.ClientError && err.code === import_nice_grpc9.Status.INVALID_ARGUMENT) {
47006
48657
  throw new InvalidError(err.details || err.message);
47007
48658
  }
47008
48659
  throw err;
@@ -47052,7 +48703,16 @@ function defaultSandboxPTYInfo() {
47052
48703
  noTerminateOnIdleStdin: true
47053
48704
  });
47054
48705
  }
47055
- async function buildContainerExecRequestProto(taskId, command, params) {
48706
+ function validateExecArgs(args) {
48707
+ const ARG_MAX_BYTES = 2 ** 16;
48708
+ const totalArgLen = args.reduce((sum, arg) => sum + arg.length, 0);
48709
+ if (totalArgLen > ARG_MAX_BYTES) {
48710
+ throw new InvalidError(
48711
+ `Total length of CMD arguments must be less than ${ARG_MAX_BYTES} bytes (ARG_MAX). Got ${totalArgLen} bytes.`
48712
+ );
48713
+ }
48714
+ }
48715
+ function buildTaskExecStartRequestProto(taskId, execId, command, params) {
47056
48716
  checkForRenamedParams(params, { timeout: "timeoutMs" });
47057
48717
  if (params?.timeoutMs != void 0 && params.timeoutMs <= 0) {
47058
48718
  throw new Error(`timeoutMs must be positive, got ${params.timeoutMs}`);
@@ -47063,17 +48723,39 @@ async function buildContainerExecRequestProto(taskId, command, params) {
47063
48723
  );
47064
48724
  }
47065
48725
  const secretIds = (params?.secrets || []).map((secret) => secret.secretId);
48726
+ const stdout = params?.stdout ?? "pipe";
48727
+ const stderr = params?.stderr ?? "pipe";
48728
+ let stdoutConfig;
48729
+ if (stdout === "pipe") {
48730
+ stdoutConfig = 1 /* TASK_EXEC_STDOUT_CONFIG_PIPE */;
48731
+ } else if (stdout === "ignore") {
48732
+ stdoutConfig = 0 /* TASK_EXEC_STDOUT_CONFIG_DEVNULL */;
48733
+ } else {
48734
+ throw new Error(`Unsupported stdout behavior: ${stdout}`);
48735
+ }
48736
+ let stderrConfig;
48737
+ if (stderr === "pipe") {
48738
+ stderrConfig = 1 /* TASK_EXEC_STDERR_CONFIG_PIPE */;
48739
+ } else if (stderr === "ignore") {
48740
+ stderrConfig = 0 /* TASK_EXEC_STDERR_CONFIG_DEVNULL */;
48741
+ } else {
48742
+ throw new Error(`Unsupported stderr behavior: ${stderr}`);
48743
+ }
47066
48744
  let ptyInfo;
47067
48745
  if (params?.pty) {
47068
48746
  ptyInfo = defaultSandboxPTYInfo();
47069
48747
  }
47070
- return ContainerExecRequest.create({
48748
+ return TaskExecStartRequest.create({
47071
48749
  taskId,
47072
- command,
48750
+ execId,
48751
+ commandArgs: command,
48752
+ stdoutConfig,
48753
+ stderrConfig,
48754
+ timeoutSecs: params?.timeoutMs ? params.timeoutMs / 1e3 : void 0,
47073
48755
  workdir: params?.workdir,
47074
- timeoutSecs: params?.timeoutMs ? params.timeoutMs / 1e3 : 0,
47075
48756
  secretIds,
47076
- ptyInfo
48757
+ ptyInfo,
48758
+ runtimeDebug: false
47077
48759
  });
47078
48760
  }
47079
48761
  var Sandbox2 = class _Sandbox {
@@ -47086,6 +48768,9 @@ var Sandbox2 = class _Sandbox {
47086
48768
  #stderrAbort;
47087
48769
  #taskId;
47088
48770
  #tunnels;
48771
+ #commandRouterClient;
48772
+ #commandRouterClientPromise;
48773
+ #attached = true;
47089
48774
  /** @ignore */
47090
48775
  constructor(client2, sandboxId) {
47091
48776
  this.#client = client2;
@@ -47137,6 +48822,7 @@ var Sandbox2 = class _Sandbox {
47137
48822
  }
47138
48823
  /** Set tags (key-value pairs) on the Sandbox. Tags can be used to filter results in {@link SandboxService#list Sandbox.list}. */
47139
48824
  async setTags(tags) {
48825
+ this.#ensureAttached();
47140
48826
  const tagsList = Object.entries(tags).map(([tagName, tagValue]) => ({
47141
48827
  tagName,
47142
48828
  tagValue
@@ -47148,7 +48834,7 @@ var Sandbox2 = class _Sandbox {
47148
48834
  tags: tagsList
47149
48835
  });
47150
48836
  } catch (err) {
47151
- if (err instanceof import_nice_grpc8.ClientError && err.code === import_nice_grpc8.Status.INVALID_ARGUMENT) {
48837
+ if (err instanceof import_nice_grpc9.ClientError && err.code === import_nice_grpc9.Status.INVALID_ARGUMENT) {
47152
48838
  throw new InvalidError(err.details || err.message);
47153
48839
  }
47154
48840
  throw err;
@@ -47156,13 +48842,14 @@ var Sandbox2 = class _Sandbox {
47156
48842
  }
47157
48843
  /** Get tags (key-value pairs) currently attached to this Sandbox from the server. */
47158
48844
  async getTags() {
48845
+ this.#ensureAttached();
47159
48846
  let resp;
47160
48847
  try {
47161
48848
  resp = await this.#client.cpClient.sandboxTagsGet({
47162
48849
  sandboxId: this.sandboxId
47163
48850
  });
47164
48851
  } catch (err) {
47165
- if (err instanceof import_nice_grpc8.ClientError && err.code === import_nice_grpc8.Status.INVALID_ARGUMENT) {
48852
+ if (err instanceof import_nice_grpc9.ClientError && err.code === import_nice_grpc9.Status.INVALID_ARGUMENT) {
47166
48853
  throw new InvalidError(err.details || err.message);
47167
48854
  }
47168
48855
  throw err;
@@ -47194,6 +48881,7 @@ var Sandbox2 = class _Sandbox {
47194
48881
  * @returns Promise that resolves to a {@link SandboxFile}
47195
48882
  */
47196
48883
  async open(path2, mode = "r") {
48884
+ this.#ensureAttached();
47197
48885
  const taskId = await this.#getTaskId();
47198
48886
  const resp = await runFilesystemExec(this.#client.cpClient, {
47199
48887
  fileOpenRequest: {
@@ -47206,6 +48894,8 @@ var Sandbox2 = class _Sandbox {
47206
48894
  return new SandboxFile(this.#client, fileDescriptor, taskId);
47207
48895
  }
47208
48896
  async exec(command, params) {
48897
+ this.#ensureAttached();
48898
+ validateExecArgs(command);
47209
48899
  const taskId = await this.#getTaskId();
47210
48900
  const mergedSecrets = await mergeEnvIntoSecrets(
47211
48901
  this.#client,
@@ -47218,22 +48908,37 @@ var Sandbox2 = class _Sandbox {
47218
48908
  env: void 0
47219
48909
  // setting env to undefined just to clarify it's not needed anymore
47220
48910
  };
47221
- const req = await buildContainerExecRequestProto(
48911
+ const commandRouterClient = await this.#getOrCreateCommandRouterClient(taskId);
48912
+ const execId = (0, import_uuid.v4)();
48913
+ const request = buildTaskExecStartRequestProto(
47222
48914
  taskId,
48915
+ execId,
47223
48916
  command,
47224
48917
  mergedParams
47225
48918
  );
47226
- const resp = await this.#client.cpClient.containerExec(req);
48919
+ await commandRouterClient.execStart(request);
47227
48920
  this.#client.logger.debug(
47228
48921
  "Created ContainerProcess",
47229
48922
  "exec_id",
47230
- resp.execId,
48923
+ execId,
47231
48924
  "sandbox_id",
47232
48925
  this.sandboxId,
47233
48926
  "command",
47234
48927
  command
47235
48928
  );
47236
- return new ContainerProcess(this.#client, resp.execId, params);
48929
+ const deadline = mergedParams?.timeoutMs ? Date.now() + mergedParams.timeoutMs : null;
48930
+ return new ContainerProcess(
48931
+ taskId,
48932
+ execId,
48933
+ commandRouterClient,
48934
+ mergedParams,
48935
+ deadline
48936
+ );
48937
+ }
48938
+ #ensureAttached() {
48939
+ if (!this.#attached) {
48940
+ throw new ClientClosedError();
48941
+ }
47237
48942
  }
47238
48943
  async #getTaskId() {
47239
48944
  if (this.#taskId === void 0) {
@@ -47254,19 +48959,74 @@ var Sandbox2 = class _Sandbox {
47254
48959
  }
47255
48960
  return this.#taskId;
47256
48961
  }
48962
+ async #getOrCreateCommandRouterClient(taskId) {
48963
+ if (this.#commandRouterClient !== void 0) {
48964
+ return this.#commandRouterClient;
48965
+ }
48966
+ if (this.#commandRouterClientPromise !== void 0) {
48967
+ return this.#commandRouterClientPromise;
48968
+ }
48969
+ const promise = (async () => {
48970
+ const client2 = await TaskCommandRouterClientImpl.tryInit(
48971
+ this.#client.cpClient,
48972
+ taskId,
48973
+ this.#client.logger,
48974
+ this.#client.profile
48975
+ );
48976
+ if (!client2) {
48977
+ throw new Error(
48978
+ "Command router access is not available for this sandbox"
48979
+ );
48980
+ }
48981
+ if (!this.#attached) {
48982
+ client2.close();
48983
+ throw new ClientClosedError();
48984
+ }
48985
+ this.#commandRouterClient = client2;
48986
+ return client2;
48987
+ })();
48988
+ this.#commandRouterClientPromise = promise;
48989
+ try {
48990
+ return await promise;
48991
+ } catch (err) {
48992
+ if (this.#commandRouterClientPromise === promise) {
48993
+ this.#commandRouterClientPromise = void 0;
48994
+ }
48995
+ throw err;
48996
+ }
48997
+ }
47257
48998
  /**
47258
48999
  * Create a token for making HTTP connections to the Sandbox.
47259
49000
  */
47260
49001
  async createConnectToken(params) {
49002
+ this.#ensureAttached();
47261
49003
  const resp = await this.#client.cpClient.sandboxCreateConnectToken({
47262
49004
  sandboxId: this.sandboxId,
47263
49005
  userMetadata: params?.userMetadata
47264
49006
  });
47265
49007
  return { url: resp.url, token: resp.token };
47266
49008
  }
47267
- async terminate() {
49009
+ async terminate(params) {
49010
+ this.#ensureAttached();
47268
49011
  await this.#client.cpClient.sandboxTerminate({ sandboxId: this.sandboxId });
49012
+ let exitCode;
49013
+ if (params?.wait) {
49014
+ exitCode = await this.wait();
49015
+ }
47269
49016
  this.#taskId = void 0;
49017
+ this.detach();
49018
+ return exitCode;
49019
+ }
49020
+ /**
49021
+ * Disconnect from the Sandbox, cleaning up local resources.
49022
+ * The Sandbox continues running on Modal's infrastructure.
49023
+ * After calling detach(), most operations on this Sandbox object will throw.
49024
+ */
49025
+ detach() {
49026
+ this.#commandRouterClient?.close();
49027
+ this.#attached = false;
49028
+ this.#commandRouterClient = void 0;
49029
+ this.#commandRouterClientPromise = void 0;
47270
49030
  }
47271
49031
  async wait() {
47272
49032
  while (true) {
@@ -47296,6 +49056,7 @@ var Sandbox2 = class _Sandbox {
47296
49056
  * @returns A dictionary of {@link Tunnel} objects which are keyed by the container port.
47297
49057
  */
47298
49058
  async tunnels(timeoutMs = 5e4) {
49059
+ this.#ensureAttached();
47299
49060
  if (this.#tunnels) {
47300
49061
  return this.#tunnels;
47301
49062
  }
@@ -47326,6 +49087,7 @@ var Sandbox2 = class _Sandbox {
47326
49087
  * @returns Promise that resolves to an {@link Image}
47327
49088
  */
47328
49089
  async snapshotFilesystem(timeoutMs = 55e3) {
49090
+ this.#ensureAttached();
47329
49091
  const resp = await this.#client.cpClient.sandboxSnapshotFs({
47330
49092
  sandboxId: this.sandboxId,
47331
49093
  timeout: timeoutMs / 1e3
@@ -47340,12 +49102,58 @@ var Sandbox2 = class _Sandbox {
47340
49102
  }
47341
49103
  return new Image2(this.#client, resp.imageId, "");
47342
49104
  }
49105
+ /**
49106
+ * Mount an {@link Image} at a path in the Sandbox filesystem.
49107
+ *
49108
+ * @param path - The path where the directory should be mounted
49109
+ * @param image - Optional {@link Image} to mount. If undefined, mounts an empty directory.
49110
+ */
49111
+ async mountImage(path2, image) {
49112
+ this.#ensureAttached();
49113
+ const taskId = await this.#getTaskId();
49114
+ const commandRouterClient = await this.#getOrCreateCommandRouterClient(taskId);
49115
+ if (image && !image.imageId) {
49116
+ throw new Error(
49117
+ "Image must be built before mounting. Call `image.build(app)` first."
49118
+ );
49119
+ }
49120
+ const pathBytes = new TextEncoder().encode(path2);
49121
+ const imageId = image?.imageId ?? "";
49122
+ const request = TaskMountDirectoryRequest.create({
49123
+ taskId,
49124
+ path: pathBytes,
49125
+ imageId
49126
+ });
49127
+ await commandRouterClient.mountDirectory(request);
49128
+ }
49129
+ /**
49130
+ * Snapshots and creates a new {@link Image} from a directory in the running sandbox.
49131
+ *
49132
+ * @param path - The path of the directory to snapshot
49133
+ * @returns Promise that resolves to an {@link Image}
49134
+ */
49135
+ async snapshotDirectory(path2) {
49136
+ this.#ensureAttached();
49137
+ const taskId = await this.#getTaskId();
49138
+ const commandRouterClient = await this.#getOrCreateCommandRouterClient(taskId);
49139
+ const pathBytes = new TextEncoder().encode(path2);
49140
+ const request = TaskSnapshotDirectoryRequest.create({
49141
+ taskId,
49142
+ path: pathBytes
49143
+ });
49144
+ const response = await commandRouterClient.snapshotDirectory(request);
49145
+ if (!response.imageId) {
49146
+ throw new Error("Sandbox snapshot directory response missing `imageId`");
49147
+ }
49148
+ return new Image2(this.#client, response.imageId, "");
49149
+ }
47343
49150
  /**
47344
49151
  * Check if the Sandbox has finished running.
47345
49152
  *
47346
49153
  * Returns `null` if the Sandbox is still running, else returns the exit code.
47347
49154
  */
47348
49155
  async poll() {
49156
+ this.#ensureAttached();
47349
49157
  const resp = await this.#client.cpClient.sandboxWait({
47350
49158
  sandboxId: this.sandboxId,
47351
49159
  timeout: 0
@@ -47375,38 +49183,40 @@ var ContainerProcess = class {
47375
49183
  stdin;
47376
49184
  stdout;
47377
49185
  stderr;
47378
- returncode = null;
47379
- #client;
49186
+ #taskId;
47380
49187
  #execId;
47381
- constructor(client2, execId, params) {
47382
- this.#client = client2;
49188
+ #commandRouterClient;
49189
+ #deadline;
49190
+ /** @ignore */
49191
+ constructor(taskId, execId, commandRouterClient, params, deadline) {
49192
+ this.#taskId = taskId;
49193
+ this.#execId = execId;
49194
+ this.#commandRouterClient = commandRouterClient;
49195
+ this.#deadline = deadline ?? null;
47383
49196
  const mode = params?.mode ?? "text";
47384
49197
  const stdout = params?.stdout ?? "pipe";
47385
49198
  const stderr = params?.stderr ?? "pipe";
47386
- this.#execId = execId;
47387
- this.stdin = toModalWriteStream(inputStreamCp(client2.cpClient, execId));
47388
- let stdoutStream = streamConsumingIter(
49199
+ this.stdin = toModalWriteStream(
49200
+ inputStreamCp(commandRouterClient, taskId, execId)
49201
+ );
49202
+ const stdoutStream = stdout === "ignore" ? ReadableStream.from([]) : streamConsumingIter(
47389
49203
  outputStreamCp(
47390
- client2.cpClient,
49204
+ commandRouterClient,
49205
+ taskId,
47391
49206
  execId,
47392
- 1 /* FILE_DESCRIPTOR_STDOUT */
49207
+ 1 /* FILE_DESCRIPTOR_STDOUT */,
49208
+ this.#deadline
47393
49209
  )
47394
49210
  );
47395
- if (stdout === "ignore") {
47396
- stdoutStream.cancel();
47397
- stdoutStream = ReadableStream.from([]);
47398
- }
47399
- let stderrStream = streamConsumingIter(
49211
+ const stderrStream = stderr === "ignore" ? ReadableStream.from([]) : streamConsumingIter(
47400
49212
  outputStreamCp(
47401
- client2.cpClient,
49213
+ commandRouterClient,
49214
+ taskId,
47402
49215
  execId,
47403
- 2 /* FILE_DESCRIPTOR_STDERR */
49216
+ 2 /* FILE_DESCRIPTOR_STDERR */,
49217
+ this.#deadline
47404
49218
  )
47405
49219
  );
47406
- if (stderr === "ignore") {
47407
- stderrStream.cancel();
47408
- stderrStream = ReadableStream.from([]);
47409
- }
47410
49220
  if (mode === "text") {
47411
49221
  this.stdout = toModalReadStream(
47412
49222
  stdoutStream.pipeThrough(new TextDecoderStream())
@@ -47421,14 +49231,17 @@ var ContainerProcess = class {
47421
49231
  }
47422
49232
  /** Wait for process completion and return the exit code. */
47423
49233
  async wait() {
47424
- while (true) {
47425
- const resp = await this.#client.cpClient.containerExecWait({
47426
- execId: this.#execId,
47427
- timeout: 55
47428
- });
47429
- if (resp.completed) {
47430
- return resp.exitCode ?? 0;
47431
- }
49234
+ const resp = await this.#commandRouterClient.execWait(
49235
+ this.#taskId,
49236
+ this.#execId,
49237
+ this.#deadline
49238
+ );
49239
+ if (resp.code !== void 0) {
49240
+ return resp.code;
49241
+ } else if (resp.signal !== void 0) {
49242
+ return 128 + resp.signal;
49243
+ } else {
49244
+ throw new InvalidError("Unexpected exit status");
47432
49245
  }
47433
49246
  }
47434
49247
  };
@@ -47464,7 +49277,7 @@ async function* outputStreamSb(cpClient, sandboxId, fileDescriptor, signal) {
47464
49277
  }
47465
49278
  if (isRetryableGrpc(err) && retriesRemaining > 0) {
47466
49279
  try {
47467
- await (0, import_promises.setTimeout)(delayMs, void 0, { signal });
49280
+ await (0, import_promises2.setTimeout)(delayMs, void 0, { signal });
47468
49281
  } catch {
47469
49282
  return;
47470
49283
  }
@@ -47477,33 +49290,6 @@ async function* outputStreamSb(cpClient, sandboxId, fileDescriptor, signal) {
47477
49290
  }
47478
49291
  }
47479
49292
  }
47480
- async function* outputStreamCp(cpClient, execId, fileDescriptor) {
47481
- let lastIndex = 0;
47482
- let completed = false;
47483
- let retries = 10;
47484
- while (!completed) {
47485
- try {
47486
- const outputIterator = cpClient.containerExecGetOutput({
47487
- execId,
47488
- fileDescriptor,
47489
- timeout: 55,
47490
- getRawBytes: true,
47491
- lastBatchIndex: lastIndex
47492
- });
47493
- for await (const batch of outputIterator) {
47494
- lastIndex = batch.batchIndex;
47495
- yield* batch.items.map((item) => item.messageBytes);
47496
- if (batch.exitCode !== void 0) {
47497
- completed = true;
47498
- break;
47499
- }
47500
- }
47501
- } catch (err) {
47502
- if (isRetryableGrpc(err) && retries > 0) retries--;
47503
- else throw err;
47504
- }
47505
- }
47506
- }
47507
49293
  function inputStreamSb(cpClient, sandboxId) {
47508
49294
  let index = 1;
47509
49295
  return new WritableStream({
@@ -47524,27 +49310,40 @@ function inputStreamSb(cpClient, sandboxId) {
47524
49310
  }
47525
49311
  });
47526
49312
  }
47527
- function inputStreamCp(cpClient, execId) {
47528
- let messageIndex = 1;
49313
+ async function* outputStreamCp(commandRouterClient, taskId, execId, fileDescriptor, deadline) {
49314
+ for await (const batch of commandRouterClient.execStdioRead(
49315
+ taskId,
49316
+ execId,
49317
+ fileDescriptor,
49318
+ deadline
49319
+ )) {
49320
+ yield batch.data;
49321
+ }
49322
+ }
49323
+ function inputStreamCp(commandRouterClient, taskId, execId) {
49324
+ let offset = 0;
47529
49325
  return new WritableStream({
47530
49326
  async write(chunk) {
47531
- await cpClient.containerExecPutInput({
49327
+ const data = encodeIfString(chunk);
49328
+ await commandRouterClient.execStdinWrite(
49329
+ taskId,
47532
49330
  execId,
47533
- input: {
47534
- message: encodeIfString(chunk),
47535
- messageIndex
47536
- }
47537
- });
47538
- messageIndex++;
49331
+ offset,
49332
+ data,
49333
+ false
49334
+ // eof
49335
+ );
49336
+ offset += data.length;
47539
49337
  },
47540
49338
  async close() {
47541
- await cpClient.containerExecPutInput({
49339
+ await commandRouterClient.execStdinWrite(
49340
+ taskId,
47542
49341
  execId,
47543
- input: {
47544
- messageIndex,
47545
- eof: true
47546
- }
47547
- });
49342
+ offset,
49343
+ new Uint8Array(0),
49344
+ true
49345
+ // eof
49346
+ );
47548
49347
  }
47549
49348
  });
47550
49349
  }
@@ -47553,7 +49352,7 @@ function encodeIfString(chunk) {
47553
49352
  }
47554
49353
 
47555
49354
  // src/volume.ts
47556
- var import_nice_grpc9 = require("nice-grpc");
49355
+ var import_nice_grpc10 = require("nice-grpc");
47557
49356
  var VolumeService = class {
47558
49357
  #client;
47559
49358
  constructor(client2) {
@@ -47578,7 +49377,7 @@ var VolumeService = class {
47578
49377
  );
47579
49378
  return new Volume(resp.volumeId, name);
47580
49379
  } catch (err) {
47581
- if (err instanceof import_nice_grpc9.ClientError && err.code === import_nice_grpc9.Status.NOT_FOUND)
49380
+ if (err instanceof import_nice_grpc10.ClientError && err.code === import_nice_grpc10.Status.NOT_FOUND)
47582
49381
  throw new NotFoundError(err.details);
47583
49382
  throw err;
47584
49383
  }
@@ -47624,7 +49423,7 @@ var VolumeService = class {
47624
49423
  volume.volumeId
47625
49424
  );
47626
49425
  } catch (err) {
47627
- const isNotFound = err instanceof NotFoundError || err instanceof import_nice_grpc9.ClientError && err.code === import_nice_grpc9.Status.NOT_FOUND;
49426
+ const isNotFound = err instanceof NotFoundError || err instanceof import_nice_grpc10.ClientError && err.code === import_nice_grpc10.Status.NOT_FOUND;
47628
49427
  if (isNotFound && params?.allowMissing) {
47629
49428
  return;
47630
49429
  }
@@ -47673,54 +49472,6 @@ var Volume = class _Volume {
47673
49472
  }
47674
49473
  };
47675
49474
 
47676
- // src/config.ts
47677
- var import_node_fs = require("fs");
47678
- var import_node_os = require("os");
47679
- var import_node_path = __toESM(require("path"), 1);
47680
- var import_smol_toml = require("smol-toml");
47681
- function configFilePath() {
47682
- const configPath = process.env["MODAL_CONFIG_PATH"];
47683
- if (configPath && configPath !== "") {
47684
- return configPath;
47685
- }
47686
- return import_node_path.default.join((0, import_node_os.homedir)(), ".modal.toml");
47687
- }
47688
- function readConfigFile() {
47689
- try {
47690
- const configPath = configFilePath();
47691
- const configContent = (0, import_node_fs.readFileSync)(configPath, {
47692
- encoding: "utf-8"
47693
- });
47694
- return (0, import_smol_toml.parse)(configContent);
47695
- } catch (err) {
47696
- if (err.code === "ENOENT") {
47697
- return {};
47698
- }
47699
- return {};
47700
- }
47701
- }
47702
- var config = readConfigFile();
47703
- function getProfile(profileName) {
47704
- if (!profileName) {
47705
- for (const [name, profileData2] of Object.entries(config)) {
47706
- if (profileData2.active) {
47707
- profileName = name;
47708
- break;
47709
- }
47710
- }
47711
- }
47712
- const profileData = profileName && Object.hasOwn(config, profileName) ? config[profileName] : {};
47713
- const profile = {
47714
- serverUrl: process.env["MODAL_SERVER_URL"] || profileData.server_url || "https://api.modal.com:443",
47715
- tokenId: process.env["MODAL_TOKEN_ID"] || profileData.token_id,
47716
- tokenSecret: process.env["MODAL_TOKEN_SECRET"] || profileData.token_secret,
47717
- environment: process.env["MODAL_ENVIRONMENT"] || profileData.environment,
47718
- imageBuilderVersion: process.env["MODAL_IMAGE_BUILDER_VERSION"] || profileData.imageBuilderVersion,
47719
- logLevel: process.env["MODAL_LOGLEVEL"] || profileData.loglevel
47720
- };
47721
- return profile;
47722
- }
47723
-
47724
49475
  // src/auth_token_manager.ts
47725
49476
  var REFRESH_WINDOW = 5 * 60;
47726
49477
  var DEFAULT_EXPIRY_OFFSET = 20 * 60;
@@ -47879,7 +49630,7 @@ var AuthTokenManager = class {
47879
49630
 
47880
49631
  // src/version.ts
47881
49632
  function getSDKVersion() {
47882
- return true ? "0.6.3" : "0.0.0";
49633
+ return true ? "0.7.1" : "0.0.0";
47883
49634
  }
47884
49635
 
47885
49636
  // src/logger.ts
@@ -48072,7 +49823,7 @@ var ModalClient2 = class {
48072
49823
  return getSDKVersion();
48073
49824
  }
48074
49825
  createClient(profile) {
48075
- const channel = (0, import_nice_grpc10.createChannel)(profile.serverUrl, void 0, {
49826
+ const channel = (0, import_nice_grpc11.createChannel)(profile.serverUrl, void 0, {
48076
49827
  "grpc.max_receive_message_length": 100 * 1024 * 1024,
48077
49828
  "grpc.max_send_message_length": 100 * 1024 * 1024,
48078
49829
  "grpc-node.flow_control_window": 64 * 1024 * 1024,
@@ -48080,7 +49831,7 @@ var ModalClient2 = class {
48080
49831
  "grpc.keepalive_timeout_ms": 1e4,
48081
49832
  "grpc.keepalive_permit_without_calls": 1
48082
49833
  });
48083
- let factory = (0, import_nice_grpc10.createClientFactory)().use(this.authMiddleware(profile)).use(this.retryMiddleware()).use(timeoutMiddleware);
49834
+ let factory = (0, import_nice_grpc11.createClientFactory)().use(this.authMiddleware(profile)).use(this.retryMiddleware()).use(timeoutMiddleware);
48084
49835
  for (const middleware of this.customMiddleware) {
48085
49836
  factory = factory.use(middleware);
48086
49837
  }
@@ -48106,13 +49857,13 @@ var ModalClient2 = class {
48106
49857
  ...retryableGrpcStatusCodes,
48107
49858
  ...additionalStatusCodes
48108
49859
  ]);
48109
- const idempotencyKey = (0, import_uuid.v4)();
49860
+ const idempotencyKey = (0, import_uuid2.v4)();
48110
49861
  const startTime = Date.now();
48111
49862
  let attempt = 0;
48112
49863
  let delayMs = baseDelay;
48113
49864
  logger.debug("Sending gRPC request", "method", call.method.path);
48114
49865
  while (true) {
48115
- const metadata = new import_nice_grpc10.Metadata(restOptions.metadata ?? {});
49866
+ const metadata = new import_nice_grpc11.Metadata(restOptions.metadata ?? {});
48116
49867
  metadata.set("x-idempotency-key", idempotencyKey);
48117
49868
  metadata.set("x-retry-attempt", String(attempt));
48118
49869
  if (attempt > 0) {
@@ -48128,7 +49879,7 @@ var ModalClient2 = class {
48128
49879
  signal
48129
49880
  });
48130
49881
  } catch (err) {
48131
- if (!(err instanceof import_nice_grpc10.ClientError) || !retryableCodes.has(err.code) || attempt >= retries) {
49882
+ if (!(err instanceof import_nice_grpc11.ClientError) || !retryableCodes.has(err.code) || attempt >= retries) {
48132
49883
  if (attempt === retries && attempt > 0) {
48133
49884
  logger.debug(
48134
49885
  "Final retry attempt failed",
@@ -48186,7 +49937,7 @@ var ModalClient2 = class {
48186
49937
  );
48187
49938
  }
48188
49939
  const { tokenId, tokenSecret } = profile;
48189
- options.metadata ??= new import_nice_grpc10.Metadata();
49940
+ options.metadata ??= new import_nice_grpc11.Metadata();
48190
49941
  options.metadata.set(
48191
49942
  "x-modal-client-type",
48192
49943
  String(8 /* CLIENT_TYPE_LIBMODAL_JS */)
@@ -48231,23 +49982,23 @@ var timeoutMiddleware = async function* timeoutMiddleware2(call, options) {
48231
49982
  origSignal?.removeEventListener("abort", abortListener);
48232
49983
  clearTimeout(timer);
48233
49984
  if (timedOut) {
48234
- throw new import_nice_grpc10.ClientError(
49985
+ throw new import_nice_grpc11.ClientError(
48235
49986
  call.method.path,
48236
- import_nice_grpc10.Status.DEADLINE_EXCEEDED,
49987
+ import_nice_grpc11.Status.DEADLINE_EXCEEDED,
48237
49988
  `Timed out after ${timeoutMs}ms`
48238
49989
  );
48239
49990
  }
48240
49991
  }
48241
49992
  };
48242
49993
  var retryableGrpcStatusCodes = /* @__PURE__ */ new Set([
48243
- import_nice_grpc10.Status.DEADLINE_EXCEEDED,
48244
- import_nice_grpc10.Status.UNAVAILABLE,
48245
- import_nice_grpc10.Status.CANCELLED,
48246
- import_nice_grpc10.Status.INTERNAL,
48247
- import_nice_grpc10.Status.UNKNOWN
49994
+ import_nice_grpc11.Status.DEADLINE_EXCEEDED,
49995
+ import_nice_grpc11.Status.UNAVAILABLE,
49996
+ import_nice_grpc11.Status.CANCELLED,
49997
+ import_nice_grpc11.Status.INTERNAL,
49998
+ import_nice_grpc11.Status.UNKNOWN
48248
49999
  ]);
48249
50000
  function isRetryableGrpc(err) {
48250
- if (err instanceof import_nice_grpc10.ClientError) {
50001
+ if (err instanceof import_nice_grpc11.ClientError) {
48251
50002
  return retryableGrpcStatusCodes.has(err.code);
48252
50003
  }
48253
50004
  return false;
@@ -48316,7 +50067,7 @@ var AppService = class {
48316
50067
  );
48317
50068
  return new App2(resp.appId, name);
48318
50069
  } catch (err) {
48319
- if (err instanceof import_nice_grpc11.ClientError && err.code === import_nice_grpc11.Status.NOT_FOUND)
50070
+ if (err instanceof import_nice_grpc12.ClientError && err.code === import_nice_grpc12.Status.NOT_FOUND)
48320
50071
  throw new NotFoundError(`App '${name}' not found`);
48321
50072
  throw err;
48322
50073
  }
@@ -48388,6 +50139,7 @@ var App2 = class {
48388
50139
  AlreadyExistsError,
48389
50140
  App,
48390
50141
  AppService,
50142
+ ClientClosedError,
48391
50143
  CloudBucketMount,
48392
50144
  CloudBucketMountService,
48393
50145
  Cls,