modal 0.3.15 → 0.3.17

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
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  App: () => App,
34
+ CloudBucketMount: () => CloudBucketMount2,
34
35
  Cls: () => Cls,
35
36
  ClsInstance: () => ClsInstance,
36
37
  ContainerProcess: () => ContainerProcess,
@@ -41,6 +42,7 @@ __export(index_exports, {
41
42
  InternalFailure: () => InternalFailure,
42
43
  InvalidError: () => InvalidError,
43
44
  NotFoundError: () => NotFoundError,
45
+ Proxy: () => Proxy3,
44
46
  Queue: () => Queue,
45
47
  QueueEmptyError: () => QueueEmptyError,
46
48
  QueueFullError: () => QueueFullError,
@@ -55,7 +57,7 @@ __export(index_exports, {
55
57
  module.exports = __toCommonJS(index_exports);
56
58
 
57
59
  // src/app.ts
58
- var import_nice_grpc3 = require("nice-grpc");
60
+ var import_nice_grpc4 = require("nice-grpc");
59
61
 
60
62
  // node_modules/@bufbuild/protobuf/dist/esm/wire/varint.js
61
63
  function varint64read() {
@@ -38847,68 +38849,8 @@ function initializeClient(options) {
38847
38849
  client = createClient(mergedProfile);
38848
38850
  }
38849
38851
 
38850
- // src/image.ts
38851
- var Image2 = class {
38852
- imageId;
38853
- /** @ignore */
38854
- constructor(imageId) {
38855
- this.imageId = imageId;
38856
- }
38857
- };
38858
- async function fromRegistryInternal(appId, tag, imageRegistryConfig) {
38859
- const resp = await client.imageGetOrCreate({
38860
- appId,
38861
- image: {
38862
- dockerfileCommands: [`FROM ${tag}`],
38863
- imageRegistryConfig
38864
- },
38865
- builderVersion: imageBuilderVersion()
38866
- });
38867
- let result;
38868
- let metadata = void 0;
38869
- if (resp.result?.status) {
38870
- result = resp.result;
38871
- metadata = resp.metadata;
38872
- } else {
38873
- let lastEntryId = "";
38874
- let resultJoined = void 0;
38875
- while (!resultJoined) {
38876
- for await (const item of client.imageJoinStreaming({
38877
- imageId: resp.imageId,
38878
- timeout: 55,
38879
- lastEntryId
38880
- })) {
38881
- if (item.entryId) lastEntryId = item.entryId;
38882
- if (item.result?.status) {
38883
- resultJoined = item.result;
38884
- metadata = item.metadata;
38885
- break;
38886
- }
38887
- }
38888
- }
38889
- result = resultJoined;
38890
- }
38891
- void metadata;
38892
- if (result.status === 2 /* GENERIC_STATUS_FAILURE */) {
38893
- throw new Error(
38894
- `Image build for ${resp.imageId} failed with the exception:
38895
- ${result.exception}`
38896
- );
38897
- } else if (result.status === 3 /* GENERIC_STATUS_TERMINATED */) {
38898
- throw new Error(
38899
- `Image build for ${resp.imageId} terminated due to external shut-down. Please try again.`
38900
- );
38901
- } else if (result.status === 4 /* GENERIC_STATUS_TIMEOUT */) {
38902
- throw new Error(
38903
- `Image build for ${resp.imageId} timed out. Please try again with a larger timeout parameter.`
38904
- );
38905
- } else if (result.status !== 1 /* GENERIC_STATUS_SUCCESS */) {
38906
- throw new Error(
38907
- `Image build for ${resp.imageId} failed with unknown status: ${result.status}`
38908
- );
38909
- }
38910
- return new Image2(resp.imageId);
38911
- }
38852
+ // src/secret.ts
38853
+ var import_nice_grpc2 = require("nice-grpc");
38912
38854
 
38913
38855
  // src/errors.ts
38914
38856
  var FunctionTimeoutError = class extends Error {
@@ -38966,6 +38908,200 @@ var SandboxTimeoutError = class extends Error {
38966
38908
  }
38967
38909
  };
38968
38910
 
38911
+ // src/secret.ts
38912
+ var Secret = class _Secret {
38913
+ secretId;
38914
+ name;
38915
+ /** @ignore */
38916
+ constructor(secretId, name) {
38917
+ this.secretId = secretId;
38918
+ this.name = name;
38919
+ }
38920
+ /** Reference a Secret by its name. */
38921
+ static async fromName(name, options) {
38922
+ try {
38923
+ const resp = await client.secretGetOrCreate({
38924
+ deploymentName: name,
38925
+ environmentName: environmentName(options?.environment),
38926
+ requiredKeys: options?.requiredKeys ?? []
38927
+ });
38928
+ return new _Secret(resp.secretId, name);
38929
+ } catch (err) {
38930
+ if (err instanceof import_nice_grpc2.ClientError && err.code === import_nice_grpc2.Status.NOT_FOUND)
38931
+ throw new NotFoundError(err.details);
38932
+ if (err instanceof import_nice_grpc2.ClientError && err.code === import_nice_grpc2.Status.FAILED_PRECONDITION && err.details.includes("Secret is missing key"))
38933
+ throw new NotFoundError(err.details);
38934
+ throw err;
38935
+ }
38936
+ }
38937
+ /** Create a Secret from a plain object of key-value pairs. */
38938
+ static async fromObject(entries, options) {
38939
+ for (const [, value] of Object.entries(entries)) {
38940
+ if (value == null || typeof value !== "string") {
38941
+ throw new InvalidError(
38942
+ "entries must be an object mapping string keys to string values, but got:\n" + JSON.stringify(entries)
38943
+ );
38944
+ }
38945
+ }
38946
+ try {
38947
+ const resp = await client.secretGetOrCreate({
38948
+ objectCreationType: 5 /* OBJECT_CREATION_TYPE_EPHEMERAL */,
38949
+ envDict: entries,
38950
+ environmentName: environmentName(options?.environment)
38951
+ });
38952
+ return new _Secret(resp.secretId);
38953
+ } catch (err) {
38954
+ if (err instanceof import_nice_grpc2.ClientError && (err.code === import_nice_grpc2.Status.INVALID_ARGUMENT || err.code === import_nice_grpc2.Status.FAILED_PRECONDITION))
38955
+ throw new InvalidError(err.details);
38956
+ throw err;
38957
+ }
38958
+ }
38959
+ };
38960
+
38961
+ // src/image.ts
38962
+ var Image2 = class _Image {
38963
+ #imageId;
38964
+ #tag;
38965
+ #imageRegistryConfig;
38966
+ /** @ignore */
38967
+ constructor(imageId, tag, imageRegistryConfig) {
38968
+ this.#imageId = imageId;
38969
+ this.#tag = tag;
38970
+ this.#imageRegistryConfig = imageRegistryConfig;
38971
+ }
38972
+ get imageId() {
38973
+ return this.#imageId;
38974
+ }
38975
+ /**
38976
+ * Creates an `Image` instance from a raw registry tag, optionally using a secret for authentication.
38977
+ *
38978
+ * @param tag - The registry tag for the image.
38979
+ * @param secret - Optional. A `Secret` instance containing credentials for registry authentication.
38980
+ */
38981
+ static fromRegistry(tag, secret) {
38982
+ let imageRegistryConfig;
38983
+ if (secret) {
38984
+ if (!(secret instanceof Secret)) {
38985
+ throw new TypeError(
38986
+ "secret must be a reference to an existing Secret, e.g. `await Secret.fromName('my_secret')`"
38987
+ );
38988
+ }
38989
+ imageRegistryConfig = {
38990
+ registryAuthType: 4 /* REGISTRY_AUTH_TYPE_STATIC_CREDS */,
38991
+ secretId: secret.secretId
38992
+ };
38993
+ }
38994
+ return new _Image("", tag, imageRegistryConfig);
38995
+ }
38996
+ /**
38997
+ * Creates an `Image` instance from a raw registry tag, optionally using a secret for authentication.
38998
+ *
38999
+ * @param tag - The registry tag for the image.
39000
+ * @param secret - A `Secret` instance containing credentials for registry authentication.
39001
+ */
39002
+ static fromAwsEcr(tag, secret) {
39003
+ let imageRegistryConfig;
39004
+ if (secret) {
39005
+ if (!(secret instanceof Secret)) {
39006
+ throw new TypeError(
39007
+ "secret must be a reference to an existing Secret, e.g. `await Secret.fromName('my_secret')`"
39008
+ );
39009
+ }
39010
+ imageRegistryConfig = {
39011
+ registryAuthType: 1 /* REGISTRY_AUTH_TYPE_AWS */,
39012
+ secretId: secret.secretId
39013
+ };
39014
+ }
39015
+ return new _Image("", tag, imageRegistryConfig);
39016
+ }
39017
+ /**
39018
+ * Creates an `Image` instance from a raw registry tag, optionally using a secret for authentication.
39019
+ *
39020
+ * @param tag - The registry tag for the image.
39021
+ * @param secret - A `Secret` instance containing credentials for registry authentication.
39022
+ */
39023
+ static fromGcpArtifactRegistry(tag, secret) {
39024
+ let imageRegistryConfig;
39025
+ if (secret) {
39026
+ if (!(secret instanceof Secret)) {
39027
+ throw new TypeError(
39028
+ "secret must be a reference to an existing Secret, e.g. `await Secret.fromName('my_secret')`"
39029
+ );
39030
+ }
39031
+ imageRegistryConfig = {
39032
+ registryAuthType: 2 /* REGISTRY_AUTH_TYPE_GCP */,
39033
+ secretId: secret.secretId
39034
+ };
39035
+ }
39036
+ return new _Image("", tag, imageRegistryConfig);
39037
+ }
39038
+ /**
39039
+ * @internal
39040
+ * Build image object
39041
+ */
39042
+ async _build(appId) {
39043
+ if (this.imageId !== "") {
39044
+ return this;
39045
+ }
39046
+ const resp = await client.imageGetOrCreate({
39047
+ appId,
39048
+ image: {
39049
+ dockerfileCommands: [`FROM ${this.#tag}`],
39050
+ imageRegistryConfig: this.#imageRegistryConfig
39051
+ },
39052
+ builderVersion: imageBuilderVersion()
39053
+ });
39054
+ let result;
39055
+ let metadata = void 0;
39056
+ if (resp.result?.status) {
39057
+ result = resp.result;
39058
+ metadata = resp.metadata;
39059
+ } else {
39060
+ let lastEntryId = "";
39061
+ let resultJoined = void 0;
39062
+ while (!resultJoined) {
39063
+ for await (const item of client.imageJoinStreaming({
39064
+ imageId: resp.imageId,
39065
+ timeout: 55,
39066
+ lastEntryId
39067
+ })) {
39068
+ if (item.entryId) lastEntryId = item.entryId;
39069
+ if (item.result?.status) {
39070
+ resultJoined = item.result;
39071
+ metadata = item.metadata;
39072
+ break;
39073
+ }
39074
+ }
39075
+ }
39076
+ result = resultJoined;
39077
+ }
39078
+ void metadata;
39079
+ if (result.status === 2 /* GENERIC_STATUS_FAILURE */) {
39080
+ throw new Error(
39081
+ `Image build for ${resp.imageId} failed with the exception:
39082
+ ${result.exception}`
39083
+ );
39084
+ } else if (result.status === 3 /* GENERIC_STATUS_TERMINATED */) {
39085
+ throw new Error(
39086
+ `Image build for ${resp.imageId} terminated due to external shut-down. Please try again.`
39087
+ );
39088
+ } else if (result.status === 4 /* GENERIC_STATUS_TIMEOUT */) {
39089
+ throw new Error(
39090
+ `Image build for ${resp.imageId} timed out. Please try again with a larger timeout parameter.`
39091
+ );
39092
+ } else if (result.status !== 1 /* GENERIC_STATUS_SUCCESS */) {
39093
+ throw new Error(
39094
+ `Image build for ${resp.imageId} failed with unknown status: ${result.status}`
39095
+ );
39096
+ }
39097
+ this.#imageId = resp.imageId;
39098
+ return this;
39099
+ }
39100
+ };
39101
+
39102
+ // src/sandbox.ts
39103
+ var import_nice_grpc3 = require("nice-grpc");
39104
+
38969
39105
  // src/sandbox_filesystem.ts
38970
39106
  var SandboxFile = class {
38971
39107
  #fileDescriptor;
@@ -39229,6 +39365,42 @@ var Sandbox2 = class _Sandbox {
39229
39365
  ).pipeThrough(new TextDecoderStream())
39230
39366
  );
39231
39367
  }
39368
+ /** Set tags (key-value pairs) on the Sandbox. Tags can be used to filter results in `Sandbox.list`. */
39369
+ async setTags(tags) {
39370
+ const tagsList = Object.entries(tags).map(([tagName, tagValue]) => ({
39371
+ tagName,
39372
+ tagValue
39373
+ }));
39374
+ try {
39375
+ await client.sandboxTagsSet({
39376
+ environmentName: environmentName(),
39377
+ sandboxId: this.sandboxId,
39378
+ tags: tagsList
39379
+ });
39380
+ } catch (err) {
39381
+ if (err instanceof import_nice_grpc3.ClientError && err.code === import_nice_grpc3.Status.INVALID_ARGUMENT) {
39382
+ throw new InvalidError(err.details || err.message);
39383
+ }
39384
+ throw err;
39385
+ }
39386
+ }
39387
+ /** Returns a running Sandbox object from an ID.
39388
+ *
39389
+ * @returns Sandbox with ID
39390
+ */
39391
+ static async fromId(sandboxId) {
39392
+ try {
39393
+ await client.sandboxWait({
39394
+ sandboxId,
39395
+ timeout: 0
39396
+ });
39397
+ } catch (err) {
39398
+ if (err instanceof import_nice_grpc3.ClientError && err.code === import_nice_grpc3.Status.NOT_FOUND)
39399
+ throw new NotFoundError(`Sandbox with id: '${sandboxId}' not found`);
39400
+ throw err;
39401
+ }
39402
+ return new _Sandbox(sandboxId);
39403
+ }
39232
39404
  /**
39233
39405
  * Open a file in the sandbox filesystem.
39234
39406
  * @param path - Path to the file to open
@@ -39286,7 +39458,7 @@ var Sandbox2 = class _Sandbox {
39286
39458
  while (true) {
39287
39459
  const resp = await client.sandboxWait({
39288
39460
  sandboxId: this.sandboxId,
39289
- timeout: 55
39461
+ timeout: 10
39290
39462
  });
39291
39463
  if (resp.result) {
39292
39464
  return _Sandbox.#getReturnCode(resp.result);
@@ -39343,7 +39515,7 @@ var Sandbox2 = class _Sandbox {
39343
39515
  if (!resp.imageId) {
39344
39516
  throw new Error("Sandbox snapshot response missing image ID");
39345
39517
  }
39346
- return new Image2(resp.imageId);
39518
+ return new Image2(resp.imageId, "");
39347
39519
  }
39348
39520
  /**
39349
39521
  * Check if the Sandbox has finished running.
@@ -39357,6 +39529,41 @@ var Sandbox2 = class _Sandbox {
39357
39529
  });
39358
39530
  return _Sandbox.#getReturnCode(resp.result);
39359
39531
  }
39532
+ /**
39533
+ * List all Sandboxes for the current Environment or App ID (if specified).
39534
+ * If tags are specified, only Sandboxes that have at least those tags are returned.
39535
+ */
39536
+ static async *list(options = {}) {
39537
+ const env = environmentName(options.environment);
39538
+ const tagsList = options.tags ? Object.entries(options.tags).map(([tagName, tagValue]) => ({
39539
+ tagName,
39540
+ tagValue
39541
+ })) : [];
39542
+ let beforeTimestamp = void 0;
39543
+ while (true) {
39544
+ try {
39545
+ const resp = await client.sandboxList({
39546
+ appId: options.appId,
39547
+ beforeTimestamp,
39548
+ environmentName: env,
39549
+ includeFinished: false,
39550
+ tags: tagsList
39551
+ });
39552
+ if (!resp.sandboxes || resp.sandboxes.length === 0) {
39553
+ return;
39554
+ }
39555
+ for (const info of resp.sandboxes) {
39556
+ yield new _Sandbox(info.id);
39557
+ }
39558
+ beforeTimestamp = resp.sandboxes[resp.sandboxes.length - 1].createdAt;
39559
+ } catch (err) {
39560
+ if (err instanceof import_nice_grpc3.ClientError && err.code === import_nice_grpc3.Status.INVALID_ARGUMENT) {
39561
+ throw new InvalidError(err.details || err.message);
39562
+ }
39563
+ throw err;
39564
+ }
39565
+ }
39566
+ }
39360
39567
  static #getReturnCode(result) {
39361
39568
  if (result === void 0 || result.status === 0 /* GENERIC_STATUS_UNSPECIFIED */) {
39362
39569
  return null;
@@ -39522,39 +39729,99 @@ function encodeIfString(chunk) {
39522
39729
  return typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk;
39523
39730
  }
39524
39731
 
39525
- // src/secret.ts
39526
- var import_nice_grpc2 = require("nice-grpc");
39527
- var Secret = class _Secret {
39528
- secretId;
39529
- /** @ignore */
39530
- constructor(secretId) {
39531
- this.secretId = secretId;
39532
- }
39533
- /** Reference a Secret by its name. */
39534
- static async fromName(name, options) {
39535
- try {
39536
- const resp = await client.secretGetOrCreate({
39537
- deploymentName: name,
39538
- environmentName: environmentName(options?.environment),
39539
- requiredKeys: options?.requiredKeys ?? []
39540
- });
39541
- return new _Secret(resp.secretId);
39542
- } catch (err) {
39543
- if (err instanceof import_nice_grpc2.ClientError && err.code === import_nice_grpc2.Status.NOT_FOUND)
39544
- throw new NotFoundError(err.details);
39545
- if (err instanceof import_nice_grpc2.ClientError && err.code === import_nice_grpc2.Status.FAILED_PRECONDITION && err.details.includes("Secret is missing key"))
39546
- throw new NotFoundError(err.details);
39547
- throw err;
39732
+ // src/cloud_bucket_mount.ts
39733
+ var CloudBucketMount2 = class {
39734
+ bucketName;
39735
+ secret;
39736
+ readOnly;
39737
+ requesterPays;
39738
+ bucketEndpointUrl;
39739
+ keyPrefix;
39740
+ oidcAuthRoleArn;
39741
+ constructor(bucketName, options = {}) {
39742
+ this.bucketName = bucketName;
39743
+ this.secret = options.secret;
39744
+ this.readOnly = options.readOnly ?? false;
39745
+ this.requesterPays = options.requesterPays ?? false;
39746
+ this.bucketEndpointUrl = options.bucketEndpointUrl;
39747
+ this.keyPrefix = options.keyPrefix;
39748
+ this.oidcAuthRoleArn = options.oidcAuthRoleArn;
39749
+ if (this.bucketEndpointUrl) {
39750
+ const url = new URL(this.bucketEndpointUrl);
39751
+ if (!url.hostname.endsWith("r2.cloudflarestorage.com") && !url.hostname.endsWith("storage.googleapis.com")) {
39752
+ console.warn(
39753
+ "CloudBucketMount received unrecognized bucket endpoint URL. Assuming AWS S3 configuration as fallback."
39754
+ );
39755
+ }
39756
+ }
39757
+ if (this.requesterPays && !this.secret) {
39758
+ throw new Error("Credentials required in order to use Requester Pays.");
39759
+ }
39760
+ if (this.keyPrefix && !this.keyPrefix.endsWith("/")) {
39761
+ throw new Error(
39762
+ "keyPrefix will be prefixed to all object paths, so it must end in a '/'"
39763
+ );
39548
39764
  }
39549
39765
  }
39550
39766
  };
39767
+ function endpointUrlToBucketType(bucketEndpointUrl) {
39768
+ if (!bucketEndpointUrl) {
39769
+ return 1 /* S3 */;
39770
+ }
39771
+ const url = new URL(bucketEndpointUrl);
39772
+ if (url.hostname.endsWith("r2.cloudflarestorage.com")) {
39773
+ return 2 /* R2 */;
39774
+ } else if (url.hostname.endsWith("storage.googleapis.com")) {
39775
+ return 3 /* GCP */;
39776
+ } else {
39777
+ return 1 /* S3 */;
39778
+ }
39779
+ }
39780
+ function cloudBucketMountToProto(mount, mountPath) {
39781
+ return {
39782
+ bucketName: mount.bucketName,
39783
+ mountPath,
39784
+ credentialsSecretId: mount.secret?.secretId ?? "",
39785
+ readOnly: mount.readOnly,
39786
+ bucketType: endpointUrlToBucketType(mount.bucketEndpointUrl),
39787
+ requesterPays: mount.requesterPays,
39788
+ bucketEndpointUrl: mount.bucketEndpointUrl,
39789
+ keyPrefix: mount.keyPrefix,
39790
+ oidcAuthRoleArn: mount.oidcAuthRoleArn
39791
+ };
39792
+ }
39551
39793
 
39552
39794
  // src/app.ts
39795
+ function parseGpuConfig(gpu) {
39796
+ if (!gpu) {
39797
+ return void 0;
39798
+ }
39799
+ let gpuType = gpu;
39800
+ let count = 1;
39801
+ if (gpu.includes(":")) {
39802
+ const [type, countStr] = gpu.split(":", 2);
39803
+ gpuType = type;
39804
+ count = parseInt(countStr, 10);
39805
+ if (isNaN(count) || count < 1) {
39806
+ throw new Error(
39807
+ `Invalid GPU count: ${countStr}. Value must be a positive integer.`
39808
+ );
39809
+ }
39810
+ }
39811
+ return {
39812
+ type: 0,
39813
+ // Deprecated field, but required by proto
39814
+ count,
39815
+ gpuType: gpuType.toUpperCase()
39816
+ };
39817
+ }
39553
39818
  var App = class _App {
39554
39819
  appId;
39820
+ name;
39555
39821
  /** @ignore */
39556
- constructor(appId) {
39822
+ constructor(appId, name) {
39557
39823
  this.appId = appId;
39824
+ this.name = name;
39558
39825
  }
39559
39826
  /** Lookup a deployed app by name, or create if it does not exist. */
39560
39827
  static async lookup(name, options = {}) {
@@ -39564,25 +39831,35 @@ var App = class _App {
39564
39831
  environmentName: environmentName(options.environment),
39565
39832
  objectCreationType: options.createIfMissing ? 1 /* OBJECT_CREATION_TYPE_CREATE_IF_MISSING */ : 0 /* OBJECT_CREATION_TYPE_UNSPECIFIED */
39566
39833
  });
39567
- return new _App(resp.appId);
39834
+ return new _App(resp.appId, name);
39568
39835
  } catch (err) {
39569
- if (err instanceof import_nice_grpc3.ClientError && err.code === import_nice_grpc3.Status.NOT_FOUND)
39836
+ if (err instanceof import_nice_grpc4.ClientError && err.code === import_nice_grpc4.Status.NOT_FOUND)
39570
39837
  throw new NotFoundError(`App '${name}' not found`);
39571
39838
  throw err;
39572
39839
  }
39573
39840
  }
39574
39841
  async createSandbox(image, options = {}) {
39842
+ const gpuConfig = parseGpuConfig(options.gpu);
39575
39843
  if (options.timeout && options.timeout % 1e3 !== 0) {
39576
39844
  throw new Error(
39577
39845
  `Timeout must be a multiple of 1000ms, got ${options.timeout}`
39578
39846
  );
39579
39847
  }
39848
+ await image._build(this.appId);
39849
+ if (options.workdir && !options.workdir.startsWith("/")) {
39850
+ throw new Error(
39851
+ `workdir must be an absolute path, got: ${options.workdir}`
39852
+ );
39853
+ }
39580
39854
  const volumeMounts = options.volumes ? Object.entries(options.volumes).map(([mountPath, volume]) => ({
39581
39855
  volumeId: volume.volumeId,
39582
39856
  mountPath,
39583
39857
  allowBackgroundCommits: true,
39584
- readOnly: false
39858
+ readOnly: volume.isReadOnly
39585
39859
  })) : [];
39860
+ const cloudBucketMounts = options.cloudBucketMounts ? Object.entries(options.cloudBucketMounts).map(
39861
+ ([mountPath, mount]) => cloudBucketMountToProto(mount, mountPath)
39862
+ ) : [];
39586
39863
  const openPorts = [];
39587
39864
  if (options.encryptedPorts) {
39588
39865
  openPorts.push(
@@ -39610,6 +39887,31 @@ var App = class _App {
39610
39887
  );
39611
39888
  }
39612
39889
  const secretIds = options.secrets ? options.secrets.map((secret) => secret.secretId) : [];
39890
+ let networkAccess;
39891
+ if (options.blockNetwork) {
39892
+ if (options.cidrAllowlist) {
39893
+ throw new Error(
39894
+ "cidrAllowlist cannot be used when blockNetwork is enabled"
39895
+ );
39896
+ }
39897
+ networkAccess = {
39898
+ networkAccessType: 2 /* BLOCKED */,
39899
+ allowedCidrs: []
39900
+ };
39901
+ } else if (options.cidrAllowlist) {
39902
+ networkAccess = {
39903
+ networkAccessType: 3 /* ALLOWLIST */,
39904
+ allowedCidrs: options.cidrAllowlist
39905
+ };
39906
+ } else {
39907
+ networkAccess = {
39908
+ networkAccessType: 1 /* OPEN */,
39909
+ allowedCidrs: []
39910
+ };
39911
+ }
39912
+ const schedulerPlacement = SchedulerPlacement.create({
39913
+ regions: options.regions ?? []
39914
+ });
39613
39915
  const createResp = await client.sandboxCreate({
39614
39916
  appId: this.appId,
39615
39917
  definition: {
@@ -39617,64 +39919,48 @@ var App = class _App {
39617
39919
  entrypointArgs: options.command ?? ["sleep", "48h"],
39618
39920
  imageId: image.imageId,
39619
39921
  timeoutSecs: options.timeout != void 0 ? options.timeout / 1e3 : 600,
39620
- networkAccess: {
39621
- networkAccessType: 1 /* OPEN */
39622
- },
39922
+ workdir: options.workdir ?? void 0,
39923
+ networkAccess,
39623
39924
  resources: {
39624
39925
  // https://modal.com/docs/guide/resources
39625
39926
  milliCpu: Math.round(1e3 * (options.cpu ?? 0.125)),
39626
- memoryMb: options.memory ?? 128
39927
+ memoryMb: options.memory ?? 128,
39928
+ gpuConfig
39627
39929
  },
39628
39930
  volumeMounts,
39931
+ cloudBucketMounts,
39629
39932
  secretIds,
39630
- openPorts: openPorts.length > 0 ? { ports: openPorts } : void 0
39933
+ openPorts: openPorts.length > 0 ? { ports: openPorts } : void 0,
39934
+ cloudProviderStr: options.cloud ?? "",
39935
+ schedulerPlacement,
39936
+ verbose: options.verbose ?? false,
39937
+ proxyId: options.proxy?.proxyId
39631
39938
  }
39632
39939
  });
39633
39940
  return new Sandbox2(createResp.sandboxId);
39634
39941
  }
39942
+ /**
39943
+ * @deprecated Use `Image.fromRegistry` instead.
39944
+ */
39635
39945
  async imageFromRegistry(tag, secret) {
39636
- let imageRegistryConfig;
39637
- if (secret) {
39638
- if (!(secret instanceof Secret)) {
39639
- throw new TypeError(
39640
- "secret must be a reference to an existing Secret, e.g. `await Secret.fromName('my_secret')`"
39641
- );
39642
- }
39643
- imageRegistryConfig = {
39644
- registryAuthType: 4 /* REGISTRY_AUTH_TYPE_STATIC_CREDS */,
39645
- secretId: secret.secretId
39646
- };
39647
- }
39648
- return await fromRegistryInternal(this.appId, tag, imageRegistryConfig);
39946
+ return await Image2.fromRegistry(tag, secret)._build(this.appId);
39649
39947
  }
39948
+ /**
39949
+ * @deprecated Use `Image.fromAwsEcr` instead.
39950
+ */
39650
39951
  async imageFromAwsEcr(tag, secret) {
39651
- if (!(secret instanceof Secret)) {
39652
- throw new TypeError(
39653
- "secret must be a reference to an existing Secret, e.g. `await Secret.fromName('my_secret')`"
39654
- );
39655
- }
39656
- const imageRegistryConfig = {
39657
- registryAuthType: 1 /* REGISTRY_AUTH_TYPE_AWS */,
39658
- secretId: secret.secretId
39659
- };
39660
- return await fromRegistryInternal(this.appId, tag, imageRegistryConfig);
39952
+ return await Image2.fromAwsEcr(tag, secret)._build(this.appId);
39661
39953
  }
39954
+ /**
39955
+ * @deprecated Use `Image.fromGcpArtifactRegistry` instead.
39956
+ */
39662
39957
  async imageFromGcpArtifactRegistry(tag, secret) {
39663
- if (!(secret instanceof Secret)) {
39664
- throw new TypeError(
39665
- "secret must be a reference to an existing Secret, e.g. `await Secret.fromName('my_secret')`"
39666
- );
39667
- }
39668
- const imageRegistryConfig = {
39669
- registryAuthType: 2 /* REGISTRY_AUTH_TYPE_GCP */,
39670
- secretId: secret.secretId
39671
- };
39672
- return await fromRegistryInternal(this.appId, tag, imageRegistryConfig);
39958
+ return await Image2.fromGcpArtifactRegistry(tag, secret)._build(this.appId);
39673
39959
  }
39674
39960
  };
39675
39961
 
39676
39962
  // src/cls.ts
39677
- var import_nice_grpc5 = require("nice-grpc");
39963
+ var import_nice_grpc6 = require("nice-grpc");
39678
39964
 
39679
39965
  // src/function.ts
39680
39966
  var import_node_crypto = require("crypto");
@@ -40247,18 +40533,20 @@ var FunctionCall = class _FunctionCall {
40247
40533
  };
40248
40534
 
40249
40535
  // src/function.ts
40250
- var import_nice_grpc4 = require("nice-grpc");
40536
+ var import_nice_grpc5 = require("nice-grpc");
40251
40537
  var maxObjectSizeBytes = 2 * 1024 * 1024;
40252
40538
  var maxSystemRetries = 8;
40253
40539
  var Function_ = class _Function_ {
40254
40540
  functionId;
40255
40541
  methodName;
40256
40542
  #inputPlaneUrl;
40543
+ #webUrl;
40257
40544
  /** @ignore */
40258
- constructor(functionId, methodName, inputPlaneUrl) {
40545
+ constructor(functionId, methodName, inputPlaneUrl, webUrl) {
40259
40546
  this.functionId = functionId;
40260
40547
  this.methodName = methodName;
40261
40548
  this.#inputPlaneUrl = inputPlaneUrl;
40549
+ this.#webUrl = webUrl;
40262
40550
  }
40263
40551
  static async lookup(appName, name, options = {}) {
40264
40552
  try {
@@ -40270,10 +40558,11 @@ var Function_ = class _Function_ {
40270
40558
  return new _Function_(
40271
40559
  resp.functionId,
40272
40560
  void 0,
40273
- resp.handleMetadata?.inputPlaneUrl
40561
+ resp.handleMetadata?.inputPlaneUrl,
40562
+ resp.handleMetadata?.webUrl
40274
40563
  );
40275
40564
  } catch (err) {
40276
- if (err instanceof import_nice_grpc4.ClientError && err.code === import_nice_grpc4.Status.NOT_FOUND)
40565
+ if (err instanceof import_nice_grpc5.ClientError && err.code === import_nice_grpc5.Status.NOT_FOUND)
40277
40566
  throw new NotFoundError(`Function '${appName}/${name}' not found`);
40278
40567
  throw err;
40279
40568
  }
@@ -40320,6 +40609,38 @@ var Function_ = class _Function_ {
40320
40609
  );
40321
40610
  return new FunctionCall(invocation.functionCallId);
40322
40611
  }
40612
+ // Returns statistics about the Function.
40613
+ async getCurrentStats() {
40614
+ const resp = await client.functionGetCurrentStats(
40615
+ { functionId: this.functionId },
40616
+ { timeout: 1e4 }
40617
+ );
40618
+ return {
40619
+ backlog: resp.backlog,
40620
+ numTotalRunners: resp.numTotalTasks
40621
+ };
40622
+ }
40623
+ // Overrides the current autoscaler behavior for this Function.
40624
+ async updateAutoscaler(options) {
40625
+ await client.functionUpdateSchedulingParams({
40626
+ functionId: this.functionId,
40627
+ warmPoolSizeOverride: 0,
40628
+ // Deprecated field, always set to 0
40629
+ settings: {
40630
+ minContainers: options.minContainers,
40631
+ maxContainers: options.maxContainers,
40632
+ bufferContainers: options.bufferContainers,
40633
+ scaledownWindow: options.scaledownWindow
40634
+ }
40635
+ });
40636
+ }
40637
+ /**
40638
+ * URL of a Function running as a web endpoint.
40639
+ * @returns The web URL if this function is a web endpoint, otherwise undefined
40640
+ */
40641
+ async getWebUrl() {
40642
+ return this.#webUrl || void 0;
40643
+ }
40323
40644
  async #createInput(args = [], kwargs = {}) {
40324
40645
  const payload = dumps([args, kwargs]);
40325
40646
  let argsBlobId = void 0;
@@ -40411,7 +40732,7 @@ var Cls = class _Cls {
40411
40732
  serviceFunction.handleMetadata?.inputPlaneUrl
40412
40733
  );
40413
40734
  } catch (err) {
40414
- if (err instanceof import_nice_grpc5.ClientError && err.code === import_nice_grpc5.Status.NOT_FOUND)
40735
+ if (err instanceof import_nice_grpc6.ClientError && err.code === import_nice_grpc6.Status.NOT_FOUND)
40415
40736
  throw new NotFoundError(`Class '${appName}/${name}' not found`);
40416
40737
  throw err;
40417
40738
  }
@@ -40510,17 +40831,19 @@ var ClsInstance = class {
40510
40831
  };
40511
40832
 
40512
40833
  // src/queue.ts
40513
- var import_nice_grpc6 = require("nice-grpc");
40834
+ var import_nice_grpc7 = require("nice-grpc");
40514
40835
  var ephemeralObjectHeartbeatSleep = 3e5;
40515
40836
  var queueInitialPutBackoff = 100;
40516
40837
  var queueDefaultPartitionTtl = 24 * 3600 * 1e3;
40517
40838
  var Queue = class _Queue {
40518
40839
  queueId;
40840
+ name;
40519
40841
  #ephemeral;
40520
40842
  #abortController;
40521
40843
  /** @ignore */
40522
- constructor(queueId, ephemeral = false) {
40844
+ constructor(queueId, name, ephemeral = false) {
40523
40845
  this.queueId = queueId;
40846
+ this.name = name;
40524
40847
  this.#ephemeral = ephemeral;
40525
40848
  this.#abortController = ephemeral ? new AbortController() : void 0;
40526
40849
  }
@@ -40545,7 +40868,7 @@ var Queue = class _Queue {
40545
40868
  objectCreationType: 5 /* OBJECT_CREATION_TYPE_EPHEMERAL */,
40546
40869
  environmentName: environmentName(options.environment)
40547
40870
  });
40548
- const queue = new _Queue(resp.queueId, true);
40871
+ const queue = new _Queue(resp.queueId, void 0, true);
40549
40872
  const signal = queue.#abortController.signal;
40550
40873
  (async () => {
40551
40874
  while (true) {
@@ -40579,7 +40902,7 @@ var Queue = class _Queue {
40579
40902
  objectCreationType: options.createIfMissing ? 1 /* OBJECT_CREATION_TYPE_CREATE_IF_MISSING */ : void 0,
40580
40903
  environmentName: environmentName(options.environment)
40581
40904
  });
40582
- return new _Queue(resp.queueId);
40905
+ return new _Queue(resp.queueId, name);
40583
40906
  }
40584
40907
  /** Delete a queue by name. */
40585
40908
  static async delete(name, options = {}) {
@@ -40664,7 +40987,7 @@ var Queue = class _Queue {
40664
40987
  });
40665
40988
  break;
40666
40989
  } catch (e) {
40667
- if (e instanceof import_nice_grpc6.ClientError && e.code === import_nice_grpc6.Status.RESOURCE_EXHAUSTED) {
40990
+ if (e instanceof import_nice_grpc7.ClientError && e.code === import_nice_grpc7.Status.RESOURCE_EXHAUSTED) {
40668
40991
  delay = Math.min(delay * 2, 3e4);
40669
40992
  if (deadline !== void 0) {
40670
40993
  const remaining = deadline - Date.now();
@@ -40756,12 +41079,16 @@ var Queue = class _Queue {
40756
41079
  };
40757
41080
 
40758
41081
  // src/volume.ts
40759
- var import_nice_grpc7 = require("nice-grpc");
41082
+ var import_nice_grpc8 = require("nice-grpc");
40760
41083
  var Volume = class _Volume {
40761
41084
  volumeId;
41085
+ name;
41086
+ _readOnly = false;
40762
41087
  /** @ignore */
40763
- constructor(volumeId) {
41088
+ constructor(volumeId, name, readOnly = false) {
40764
41089
  this.volumeId = volumeId;
41090
+ this.name = name;
41091
+ this._readOnly = readOnly;
40765
41092
  }
40766
41093
  static async fromName(name, options) {
40767
41094
  try {
@@ -40770,17 +41097,52 @@ var Volume = class _Volume {
40770
41097
  environmentName: environmentName(options?.environment),
40771
41098
  objectCreationType: options?.createIfMissing ? 1 /* OBJECT_CREATION_TYPE_CREATE_IF_MISSING */ : 0 /* OBJECT_CREATION_TYPE_UNSPECIFIED */
40772
41099
  });
40773
- return new _Volume(resp.volumeId);
41100
+ return new _Volume(resp.volumeId, name);
40774
41101
  } catch (err) {
40775
- if (err instanceof import_nice_grpc7.ClientError && err.code === import_nice_grpc7.Status.NOT_FOUND)
41102
+ if (err instanceof import_nice_grpc8.ClientError && err.code === import_nice_grpc8.Status.NOT_FOUND)
40776
41103
  throw new NotFoundError(err.details);
40777
41104
  throw err;
40778
41105
  }
40779
41106
  }
41107
+ /** Configure Volume to mount as read-only. */
41108
+ readOnly() {
41109
+ return new _Volume(this.volumeId, this.name, true);
41110
+ }
41111
+ get isReadOnly() {
41112
+ return this._readOnly;
41113
+ }
41114
+ };
41115
+
41116
+ // src/proxy.ts
41117
+ var import_nice_grpc9 = require("nice-grpc");
41118
+ var Proxy3 = class _Proxy {
41119
+ proxyId;
41120
+ /** @ignore */
41121
+ constructor(proxyId) {
41122
+ this.proxyId = proxyId;
41123
+ }
41124
+ /** Reference a Proxy by its name. */
41125
+ static async fromName(name, options) {
41126
+ try {
41127
+ const resp = await client.proxyGet({
41128
+ name,
41129
+ environmentName: environmentName(options?.environment)
41130
+ });
41131
+ if (!resp.proxy?.proxyId) {
41132
+ throw new NotFoundError(`Proxy '${name}' not found`);
41133
+ }
41134
+ return new _Proxy(resp.proxy.proxyId);
41135
+ } catch (err) {
41136
+ if (err instanceof import_nice_grpc9.ClientError && err.code === import_nice_grpc9.Status.NOT_FOUND)
41137
+ throw new NotFoundError(`Proxy '${name}' not found`);
41138
+ throw err;
41139
+ }
41140
+ }
40780
41141
  };
40781
41142
  // Annotate the CommonJS export names for ESM import in node:
40782
41143
  0 && (module.exports = {
40783
41144
  App,
41145
+ CloudBucketMount,
40784
41146
  Cls,
40785
41147
  ClsInstance,
40786
41148
  ContainerProcess,
@@ -40791,6 +41153,7 @@ var Volume = class _Volume {
40791
41153
  InternalFailure,
40792
41154
  InvalidError,
40793
41155
  NotFoundError,
41156
+ Proxy,
40794
41157
  Queue,
40795
41158
  QueueEmptyError,
40796
41159
  QueueFullError,