modal 0.3.16 → 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,
@@ -38847,70 +38849,7 @@ 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
- }
38912
-
38913
- // src/sandbox.ts
38852
+ // src/secret.ts
38914
38853
  var import_nice_grpc2 = require("nice-grpc");
38915
38854
 
38916
38855
  // src/errors.ts
@@ -38969,6 +38908,200 @@ var SandboxTimeoutError = class extends Error {
38969
38908
  }
38970
38909
  };
38971
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
+
38972
39105
  // src/sandbox_filesystem.ts
38973
39106
  var SandboxFile = class {
38974
39107
  #fileDescriptor;
@@ -39232,6 +39365,25 @@ var Sandbox2 = class _Sandbox {
39232
39365
  ).pipeThrough(new TextDecoderStream())
39233
39366
  );
39234
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
+ }
39235
39387
  /** Returns a running Sandbox object from an ID.
39236
39388
  *
39237
39389
  * @returns Sandbox with ID
@@ -39243,7 +39395,7 @@ var Sandbox2 = class _Sandbox {
39243
39395
  timeout: 0
39244
39396
  });
39245
39397
  } catch (err) {
39246
- if (err instanceof import_nice_grpc2.ClientError && err.code === import_nice_grpc2.Status.NOT_FOUND)
39398
+ if (err instanceof import_nice_grpc3.ClientError && err.code === import_nice_grpc3.Status.NOT_FOUND)
39247
39399
  throw new NotFoundError(`Sandbox with id: '${sandboxId}' not found`);
39248
39400
  throw err;
39249
39401
  }
@@ -39306,7 +39458,7 @@ var Sandbox2 = class _Sandbox {
39306
39458
  while (true) {
39307
39459
  const resp = await client.sandboxWait({
39308
39460
  sandboxId: this.sandboxId,
39309
- timeout: 55
39461
+ timeout: 10
39310
39462
  });
39311
39463
  if (resp.result) {
39312
39464
  return _Sandbox.#getReturnCode(resp.result);
@@ -39363,7 +39515,7 @@ var Sandbox2 = class _Sandbox {
39363
39515
  if (!resp.imageId) {
39364
39516
  throw new Error("Sandbox snapshot response missing image ID");
39365
39517
  }
39366
- return new Image2(resp.imageId);
39518
+ return new Image2(resp.imageId, "");
39367
39519
  }
39368
39520
  /**
39369
39521
  * Check if the Sandbox has finished running.
@@ -39377,6 +39529,41 @@ var Sandbox2 = class _Sandbox {
39377
39529
  });
39378
39530
  return _Sandbox.#getReturnCode(resp.result);
39379
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
+ }
39380
39567
  static #getReturnCode(result) {
39381
39568
  if (result === void 0 || result.status === 0 /* GENERIC_STATUS_UNSPECIFIED */) {
39382
39569
  return null;
@@ -39542,39 +39729,99 @@ function encodeIfString(chunk) {
39542
39729
  return typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk;
39543
39730
  }
39544
39731
 
39545
- // src/secret.ts
39546
- var import_nice_grpc3 = require("nice-grpc");
39547
- var Secret = class _Secret {
39548
- secretId;
39549
- /** @ignore */
39550
- constructor(secretId) {
39551
- this.secretId = secretId;
39552
- }
39553
- /** Reference a Secret by its name. */
39554
- static async fromName(name, options) {
39555
- try {
39556
- const resp = await client.secretGetOrCreate({
39557
- deploymentName: name,
39558
- environmentName: environmentName(options?.environment),
39559
- requiredKeys: options?.requiredKeys ?? []
39560
- });
39561
- return new _Secret(resp.secretId);
39562
- } catch (err) {
39563
- if (err instanceof import_nice_grpc3.ClientError && err.code === import_nice_grpc3.Status.NOT_FOUND)
39564
- throw new NotFoundError(err.details);
39565
- if (err instanceof import_nice_grpc3.ClientError && err.code === import_nice_grpc3.Status.FAILED_PRECONDITION && err.details.includes("Secret is missing key"))
39566
- throw new NotFoundError(err.details);
39567
- 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
+ );
39568
39764
  }
39569
39765
  }
39570
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
+ }
39571
39793
 
39572
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
+ }
39573
39818
  var App = class _App {
39574
39819
  appId;
39820
+ name;
39575
39821
  /** @ignore */
39576
- constructor(appId) {
39822
+ constructor(appId, name) {
39577
39823
  this.appId = appId;
39824
+ this.name = name;
39578
39825
  }
39579
39826
  /** Lookup a deployed app by name, or create if it does not exist. */
39580
39827
  static async lookup(name, options = {}) {
@@ -39584,7 +39831,7 @@ var App = class _App {
39584
39831
  environmentName: environmentName(options.environment),
39585
39832
  objectCreationType: options.createIfMissing ? 1 /* OBJECT_CREATION_TYPE_CREATE_IF_MISSING */ : 0 /* OBJECT_CREATION_TYPE_UNSPECIFIED */
39586
39833
  });
39587
- return new _App(resp.appId);
39834
+ return new _App(resp.appId, name);
39588
39835
  } catch (err) {
39589
39836
  if (err instanceof import_nice_grpc4.ClientError && err.code === import_nice_grpc4.Status.NOT_FOUND)
39590
39837
  throw new NotFoundError(`App '${name}' not found`);
@@ -39592,17 +39839,27 @@ var App = class _App {
39592
39839
  }
39593
39840
  }
39594
39841
  async createSandbox(image, options = {}) {
39842
+ const gpuConfig = parseGpuConfig(options.gpu);
39595
39843
  if (options.timeout && options.timeout % 1e3 !== 0) {
39596
39844
  throw new Error(
39597
39845
  `Timeout must be a multiple of 1000ms, got ${options.timeout}`
39598
39846
  );
39599
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
+ }
39600
39854
  const volumeMounts = options.volumes ? Object.entries(options.volumes).map(([mountPath, volume]) => ({
39601
39855
  volumeId: volume.volumeId,
39602
39856
  mountPath,
39603
39857
  allowBackgroundCommits: true,
39604
- readOnly: false
39858
+ readOnly: volume.isReadOnly
39605
39859
  })) : [];
39860
+ const cloudBucketMounts = options.cloudBucketMounts ? Object.entries(options.cloudBucketMounts).map(
39861
+ ([mountPath, mount]) => cloudBucketMountToProto(mount, mountPath)
39862
+ ) : [];
39606
39863
  const openPorts = [];
39607
39864
  if (options.encryptedPorts) {
39608
39865
  openPorts.push(
@@ -39630,6 +39887,31 @@ var App = class _App {
39630
39887
  );
39631
39888
  }
39632
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
+ });
39633
39915
  const createResp = await client.sandboxCreate({
39634
39916
  appId: this.appId,
39635
39917
  definition: {
@@ -39637,59 +39919,43 @@ var App = class _App {
39637
39919
  entrypointArgs: options.command ?? ["sleep", "48h"],
39638
39920
  imageId: image.imageId,
39639
39921
  timeoutSecs: options.timeout != void 0 ? options.timeout / 1e3 : 600,
39640
- networkAccess: {
39641
- networkAccessType: 1 /* OPEN */
39642
- },
39922
+ workdir: options.workdir ?? void 0,
39923
+ networkAccess,
39643
39924
  resources: {
39644
39925
  // https://modal.com/docs/guide/resources
39645
39926
  milliCpu: Math.round(1e3 * (options.cpu ?? 0.125)),
39646
- memoryMb: options.memory ?? 128
39927
+ memoryMb: options.memory ?? 128,
39928
+ gpuConfig
39647
39929
  },
39648
39930
  volumeMounts,
39931
+ cloudBucketMounts,
39649
39932
  secretIds,
39650
- 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
39651
39938
  }
39652
39939
  });
39653
39940
  return new Sandbox2(createResp.sandboxId);
39654
39941
  }
39942
+ /**
39943
+ * @deprecated Use `Image.fromRegistry` instead.
39944
+ */
39655
39945
  async imageFromRegistry(tag, secret) {
39656
- let imageRegistryConfig;
39657
- if (secret) {
39658
- if (!(secret instanceof Secret)) {
39659
- throw new TypeError(
39660
- "secret must be a reference to an existing Secret, e.g. `await Secret.fromName('my_secret')`"
39661
- );
39662
- }
39663
- imageRegistryConfig = {
39664
- registryAuthType: 4 /* REGISTRY_AUTH_TYPE_STATIC_CREDS */,
39665
- secretId: secret.secretId
39666
- };
39667
- }
39668
- return await fromRegistryInternal(this.appId, tag, imageRegistryConfig);
39946
+ return await Image2.fromRegistry(tag, secret)._build(this.appId);
39669
39947
  }
39948
+ /**
39949
+ * @deprecated Use `Image.fromAwsEcr` instead.
39950
+ */
39670
39951
  async imageFromAwsEcr(tag, secret) {
39671
- if (!(secret instanceof Secret)) {
39672
- throw new TypeError(
39673
- "secret must be a reference to an existing Secret, e.g. `await Secret.fromName('my_secret')`"
39674
- );
39675
- }
39676
- const imageRegistryConfig = {
39677
- registryAuthType: 1 /* REGISTRY_AUTH_TYPE_AWS */,
39678
- secretId: secret.secretId
39679
- };
39680
- return await fromRegistryInternal(this.appId, tag, imageRegistryConfig);
39952
+ return await Image2.fromAwsEcr(tag, secret)._build(this.appId);
39681
39953
  }
39954
+ /**
39955
+ * @deprecated Use `Image.fromGcpArtifactRegistry` instead.
39956
+ */
39682
39957
  async imageFromGcpArtifactRegistry(tag, secret) {
39683
- if (!(secret instanceof Secret)) {
39684
- throw new TypeError(
39685
- "secret must be a reference to an existing Secret, e.g. `await Secret.fromName('my_secret')`"
39686
- );
39687
- }
39688
- const imageRegistryConfig = {
39689
- registryAuthType: 2 /* REGISTRY_AUTH_TYPE_GCP */,
39690
- secretId: secret.secretId
39691
- };
39692
- return await fromRegistryInternal(this.appId, tag, imageRegistryConfig);
39958
+ return await Image2.fromGcpArtifactRegistry(tag, secret)._build(this.appId);
39693
39959
  }
39694
39960
  };
39695
39961
 
@@ -40274,11 +40540,13 @@ var Function_ = class _Function_ {
40274
40540
  functionId;
40275
40541
  methodName;
40276
40542
  #inputPlaneUrl;
40543
+ #webUrl;
40277
40544
  /** @ignore */
40278
- constructor(functionId, methodName, inputPlaneUrl) {
40545
+ constructor(functionId, methodName, inputPlaneUrl, webUrl) {
40279
40546
  this.functionId = functionId;
40280
40547
  this.methodName = methodName;
40281
40548
  this.#inputPlaneUrl = inputPlaneUrl;
40549
+ this.#webUrl = webUrl;
40282
40550
  }
40283
40551
  static async lookup(appName, name, options = {}) {
40284
40552
  try {
@@ -40290,7 +40558,8 @@ var Function_ = class _Function_ {
40290
40558
  return new _Function_(
40291
40559
  resp.functionId,
40292
40560
  void 0,
40293
- resp.handleMetadata?.inputPlaneUrl
40561
+ resp.handleMetadata?.inputPlaneUrl,
40562
+ resp.handleMetadata?.webUrl
40294
40563
  );
40295
40564
  } catch (err) {
40296
40565
  if (err instanceof import_nice_grpc5.ClientError && err.code === import_nice_grpc5.Status.NOT_FOUND)
@@ -40340,6 +40609,38 @@ var Function_ = class _Function_ {
40340
40609
  );
40341
40610
  return new FunctionCall(invocation.functionCallId);
40342
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
+ }
40343
40644
  async #createInput(args = [], kwargs = {}) {
40344
40645
  const payload = dumps([args, kwargs]);
40345
40646
  let argsBlobId = void 0;
@@ -40536,11 +40837,13 @@ var queueInitialPutBackoff = 100;
40536
40837
  var queueDefaultPartitionTtl = 24 * 3600 * 1e3;
40537
40838
  var Queue = class _Queue {
40538
40839
  queueId;
40840
+ name;
40539
40841
  #ephemeral;
40540
40842
  #abortController;
40541
40843
  /** @ignore */
40542
- constructor(queueId, ephemeral = false) {
40844
+ constructor(queueId, name, ephemeral = false) {
40543
40845
  this.queueId = queueId;
40846
+ this.name = name;
40544
40847
  this.#ephemeral = ephemeral;
40545
40848
  this.#abortController = ephemeral ? new AbortController() : void 0;
40546
40849
  }
@@ -40565,7 +40868,7 @@ var Queue = class _Queue {
40565
40868
  objectCreationType: 5 /* OBJECT_CREATION_TYPE_EPHEMERAL */,
40566
40869
  environmentName: environmentName(options.environment)
40567
40870
  });
40568
- const queue = new _Queue(resp.queueId, true);
40871
+ const queue = new _Queue(resp.queueId, void 0, true);
40569
40872
  const signal = queue.#abortController.signal;
40570
40873
  (async () => {
40571
40874
  while (true) {
@@ -40599,7 +40902,7 @@ var Queue = class _Queue {
40599
40902
  objectCreationType: options.createIfMissing ? 1 /* OBJECT_CREATION_TYPE_CREATE_IF_MISSING */ : void 0,
40600
40903
  environmentName: environmentName(options.environment)
40601
40904
  });
40602
- return new _Queue(resp.queueId);
40905
+ return new _Queue(resp.queueId, name);
40603
40906
  }
40604
40907
  /** Delete a queue by name. */
40605
40908
  static async delete(name, options = {}) {
@@ -40779,9 +41082,13 @@ var Queue = class _Queue {
40779
41082
  var import_nice_grpc8 = require("nice-grpc");
40780
41083
  var Volume = class _Volume {
40781
41084
  volumeId;
41085
+ name;
41086
+ _readOnly = false;
40782
41087
  /** @ignore */
40783
- constructor(volumeId) {
41088
+ constructor(volumeId, name, readOnly = false) {
40784
41089
  this.volumeId = volumeId;
41090
+ this.name = name;
41091
+ this._readOnly = readOnly;
40785
41092
  }
40786
41093
  static async fromName(name, options) {
40787
41094
  try {
@@ -40790,17 +41097,52 @@ var Volume = class _Volume {
40790
41097
  environmentName: environmentName(options?.environment),
40791
41098
  objectCreationType: options?.createIfMissing ? 1 /* OBJECT_CREATION_TYPE_CREATE_IF_MISSING */ : 0 /* OBJECT_CREATION_TYPE_UNSPECIFIED */
40792
41099
  });
40793
- return new _Volume(resp.volumeId);
41100
+ return new _Volume(resp.volumeId, name);
40794
41101
  } catch (err) {
40795
41102
  if (err instanceof import_nice_grpc8.ClientError && err.code === import_nice_grpc8.Status.NOT_FOUND)
40796
41103
  throw new NotFoundError(err.details);
40797
41104
  throw err;
40798
41105
  }
40799
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
+ }
40800
41141
  };
40801
41142
  // Annotate the CommonJS export names for ESM import in node:
40802
41143
  0 && (module.exports = {
40803
41144
  App,
41145
+ CloudBucketMount,
40804
41146
  Cls,
40805
41147
  ClsInstance,
40806
41148
  ContainerProcess,
@@ -40811,6 +41153,7 @@ var Volume = class _Volume {
40811
41153
  InternalFailure,
40812
41154
  InvalidError,
40813
41155
  NotFoundError,
41156
+ Proxy,
40814
41157
  Queue,
40815
41158
  QueueEmptyError,
40816
41159
  QueueFullError,