modal 0.3.7 → 0.3.8

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.js CHANGED
@@ -37797,13 +37797,13 @@ import {
37797
37797
  } from "nice-grpc";
37798
37798
 
37799
37799
  // src/config.ts
37800
- import { readFile } from "node:fs/promises";
37801
- import path from "node:path";
37800
+ import { readFileSync } from "node:fs";
37802
37801
  import { homedir } from "node:os";
37802
+ import path from "node:path";
37803
37803
  import { parse as parseToml } from "smol-toml";
37804
- async function readConfigFile() {
37804
+ function readConfigFile() {
37805
37805
  try {
37806
- const configContent = await readFile(path.join(homedir(), ".modal.toml"), {
37806
+ const configContent = readFileSync(path.join(homedir(), ".modal.toml"), {
37807
37807
  encoding: "utf-8"
37808
37808
  });
37809
37809
  return parseToml(configContent);
@@ -37814,7 +37814,7 @@ async function readConfigFile() {
37814
37814
  throw new Error(`Failed to read or parse .modal.toml: ${err.message}`);
37815
37815
  }
37816
37816
  }
37817
- var config = await readConfigFile();
37817
+ var config = readConfigFile();
37818
37818
  function getProfile(profileName) {
37819
37819
  profileName = profileName || process.env["MODAL_PROFILE"] || void 0;
37820
37820
  if (!profileName) {
@@ -38505,31 +38505,6 @@ import { ClientError as ClientError5, Status as Status5 } from "nice-grpc";
38505
38505
  // src/function.ts
38506
38506
  import { createHash } from "node:crypto";
38507
38507
 
38508
- // src/function_call.ts
38509
- var FunctionCall = class _FunctionCall {
38510
- functionCallId;
38511
- /** @ignore */
38512
- constructor(functionCallId) {
38513
- this.functionCallId = functionCallId;
38514
- }
38515
- /** Create a new function call from ID. */
38516
- fromId(functionCallId) {
38517
- return new _FunctionCall(functionCallId);
38518
- }
38519
- /** Get the result of a function call, optionally waiting with a timeout. */
38520
- async get(options = {}) {
38521
- const timeout = options.timeout;
38522
- return await pollFunctionOutput(this.functionCallId, timeout);
38523
- }
38524
- /** Cancel a running function call. */
38525
- async cancel(options = {}) {
38526
- await client.functionCallCancel({
38527
- functionCallId: this.functionCallId,
38528
- terminateContainers: options.terminateContainers
38529
- });
38530
- }
38531
- };
38532
-
38533
38508
  // src/pickle.ts
38534
38509
  var PickleError = class extends Error {
38535
38510
  constructor(message) {
@@ -38877,79 +38852,62 @@ function loads(buf) {
38877
38852
  throw new PickleError("pickle stream ended without STOP");
38878
38853
  }
38879
38854
 
38880
- // src/function.ts
38881
- import { ClientError as ClientError4, Status as Status4 } from "nice-grpc";
38882
- var maxObjectSizeBytes = 2 * 1024 * 1024;
38855
+ // src/invocation.ts
38883
38856
  var outputsTimeout = 55 * 1e3;
38884
- function timeNowSeconds() {
38885
- return Date.now() / 1e3;
38886
- }
38887
- var Function_ = class _Function_ {
38888
- functionId;
38889
- methodName;
38890
- /** @ignore */
38891
- constructor(functionId, methodName) {
38892
- this.functionId = functionId;
38893
- this.methodName = methodName;
38894
- }
38895
- static async lookup(appName, name, options = {}) {
38896
- try {
38897
- const resp = await client.functionGet({
38898
- appName,
38899
- objectTag: name,
38900
- namespace: 1 /* DEPLOYMENT_NAMESPACE_WORKSPACE */,
38901
- environmentName: environmentName(options.environment)
38902
- });
38903
- return new _Function_(resp.functionId);
38904
- } catch (err) {
38905
- if (err instanceof ClientError4 && err.code === Status4.NOT_FOUND)
38906
- throw new NotFoundError(`Function '${appName}/${name}' not found`);
38907
- throw err;
38908
- }
38857
+ var ControlPlaneInvocation = class _ControlPlaneInvocation {
38858
+ functionCallId;
38859
+ input;
38860
+ functionCallJwt;
38861
+ inputJwt;
38862
+ constructor(functionCallId, input, functionCallJwt, inputJwt) {
38863
+ this.functionCallId = functionCallId;
38864
+ this.input = input;
38865
+ this.functionCallJwt = functionCallJwt;
38866
+ this.inputJwt = inputJwt;
38909
38867
  }
38910
- // Execute a single input into a remote Function.
38911
- async remote(args = [], kwargs = {}) {
38912
- const functionCallId = await this.#execFunctionCall(
38913
- args,
38914
- kwargs,
38915
- 4 /* FUNCTION_CALL_INVOCATION_TYPE_SYNC */
38868
+ static async create(functionId, input, invocationType) {
38869
+ const functionPutInputsItem = {
38870
+ idx: 0,
38871
+ input
38872
+ };
38873
+ const functionMapResponse = await client.functionMap({
38874
+ functionId,
38875
+ functionCallType: 1 /* FUNCTION_CALL_TYPE_UNARY */,
38876
+ functionCallInvocationType: invocationType,
38877
+ pipelinedInputs: [functionPutInputsItem]
38878
+ });
38879
+ return new _ControlPlaneInvocation(
38880
+ functionMapResponse.functionCallId,
38881
+ input,
38882
+ functionMapResponse.functionCallJwt,
38883
+ functionMapResponse.pipelinedInputs[0].inputJwt
38916
38884
  );
38917
- return await pollFunctionOutput(functionCallId);
38918
38885
  }
38919
- // Spawn a single input into a remote function.
38920
- async spawn(args = [], kwargs = {}) {
38921
- const functionCallId = await this.#execFunctionCall(
38922
- args,
38923
- kwargs,
38924
- 4 /* FUNCTION_CALL_INVOCATION_TYPE_SYNC */
38925
- );
38926
- return new FunctionCall(functionCallId);
38886
+ static fromFunctionCallId(functionCallId) {
38887
+ return new _ControlPlaneInvocation(functionCallId);
38927
38888
  }
38928
- async #execFunctionCall(args = [], kwargs = {}, invocationType = 4 /* FUNCTION_CALL_INVOCATION_TYPE_SYNC */) {
38929
- const payload = dumps([args, kwargs]);
38930
- let argsBlobId = void 0;
38931
- if (payload.length > maxObjectSizeBytes) {
38932
- argsBlobId = await blobUpload(payload);
38889
+ async awaitOutput(timeout) {
38890
+ return await pollFunctionOutput(this.functionCallId, timeout);
38891
+ }
38892
+ async retry(retryCount) {
38893
+ if (!this.input) {
38894
+ throw new Error("Cannot retry function invocation - input missing");
38933
38895
  }
38934
- const functionMapResponse = await client.functionMap({
38935
- functionId: this.functionId,
38936
- functionCallType: 1 /* FUNCTION_CALL_TYPE_UNARY */,
38937
- functionCallInvocationType: invocationType,
38938
- pipelinedInputs: [
38939
- {
38940
- idx: 0,
38941
- input: {
38942
- args: argsBlobId ? void 0 : payload,
38943
- argsBlobId,
38944
- dataFormat: 1 /* DATA_FORMAT_PICKLE */,
38945
- methodName: this.methodName
38946
- }
38947
- }
38948
- ]
38896
+ const retryItem = {
38897
+ inputJwt: this.inputJwt,
38898
+ input: this.input,
38899
+ retryCount
38900
+ };
38901
+ const functionRetryResponse = await client.functionRetryInputs({
38902
+ functionCallJwt: this.functionCallJwt,
38903
+ inputs: [retryItem]
38949
38904
  });
38950
- return functionMapResponse.functionCallId;
38905
+ this.inputJwt = functionRetryResponse.inputJwts[0];
38951
38906
  }
38952
38907
  };
38908
+ function timeNowSeconds() {
38909
+ return Date.now() / 1e3;
38910
+ }
38953
38911
  async function pollFunctionOutput(functionCallId, timeout) {
38954
38912
  const startTime = Date.now();
38955
38913
  let pollTimeout = outputsTimeout;
@@ -39007,6 +38965,134 @@ async function processResult(result, dataFormat) {
39007
38965
  }
39008
38966
  return deserializeDataFormat(data, dataFormat);
39009
38967
  }
38968
+ async function blobDownload(blobId) {
38969
+ const resp = await client.blobGet({ blobId });
38970
+ const s3resp = await fetch(resp.downloadUrl);
38971
+ if (!s3resp.ok) {
38972
+ throw new Error(`Failed to download blob: ${s3resp.statusText}`);
38973
+ }
38974
+ const buf = await s3resp.arrayBuffer();
38975
+ return new Uint8Array(buf);
38976
+ }
38977
+ function deserializeDataFormat(data, dataFormat) {
38978
+ if (!data) {
38979
+ return null;
38980
+ }
38981
+ switch (dataFormat) {
38982
+ case 1 /* DATA_FORMAT_PICKLE */:
38983
+ return loads(data);
38984
+ case 2 /* DATA_FORMAT_ASGI */:
38985
+ throw new Error("ASGI data format is not supported in Go");
38986
+ case 3 /* DATA_FORMAT_GENERATOR_DONE */:
38987
+ return GeneratorDone.decode(data);
38988
+ default:
38989
+ throw new Error(`Unsupported data format: ${dataFormat}`);
38990
+ }
38991
+ }
38992
+
38993
+ // src/function_call.ts
38994
+ var FunctionCall = class _FunctionCall {
38995
+ functionCallId;
38996
+ /** @ignore */
38997
+ constructor(functionCallId) {
38998
+ this.functionCallId = functionCallId;
38999
+ }
39000
+ /** Create a new function call from ID. */
39001
+ fromId(functionCallId) {
39002
+ return new _FunctionCall(functionCallId);
39003
+ }
39004
+ /** Get the result of a function call, optionally waiting with a timeout. */
39005
+ async get(options = {}) {
39006
+ const timeout = options.timeout;
39007
+ const invocation = ControlPlaneInvocation.fromFunctionCallId(
39008
+ this.functionCallId
39009
+ );
39010
+ return invocation.awaitOutput(timeout);
39011
+ }
39012
+ /** Cancel a running function call. */
39013
+ async cancel(options = {}) {
39014
+ await client.functionCallCancel({
39015
+ functionCallId: this.functionCallId,
39016
+ terminateContainers: options.terminateContainers
39017
+ });
39018
+ }
39019
+ };
39020
+
39021
+ // src/function.ts
39022
+ import { ClientError as ClientError4, Status as Status4 } from "nice-grpc";
39023
+ var maxObjectSizeBytes = 2 * 1024 * 1024;
39024
+ var maxSystemRetries = 8;
39025
+ var Function_ = class _Function_ {
39026
+ functionId;
39027
+ methodName;
39028
+ /** @ignore */
39029
+ constructor(functionId, methodName) {
39030
+ this.functionId = functionId;
39031
+ this.methodName = methodName;
39032
+ }
39033
+ static async lookup(appName, name, options = {}) {
39034
+ try {
39035
+ const resp = await client.functionGet({
39036
+ appName,
39037
+ objectTag: name,
39038
+ namespace: 1 /* DEPLOYMENT_NAMESPACE_WORKSPACE */,
39039
+ environmentName: environmentName(options.environment)
39040
+ });
39041
+ return new _Function_(resp.functionId);
39042
+ } catch (err) {
39043
+ if (err instanceof ClientError4 && err.code === Status4.NOT_FOUND)
39044
+ throw new NotFoundError(`Function '${appName}/${name}' not found`);
39045
+ throw err;
39046
+ }
39047
+ }
39048
+ // Execute a single input into a remote Function.
39049
+ async remote(args = [], kwargs = {}) {
39050
+ const input = await this.#createInput(args, kwargs);
39051
+ const invocation = await ControlPlaneInvocation.create(
39052
+ this.functionId,
39053
+ input,
39054
+ 4 /* FUNCTION_CALL_INVOCATION_TYPE_SYNC */
39055
+ );
39056
+ let retryCount = 0;
39057
+ while (true) {
39058
+ try {
39059
+ return await invocation.awaitOutput();
39060
+ } catch (err) {
39061
+ if (err instanceof InternalFailure && retryCount <= maxSystemRetries) {
39062
+ await invocation.retry(retryCount);
39063
+ retryCount++;
39064
+ } else {
39065
+ throw err;
39066
+ }
39067
+ }
39068
+ }
39069
+ }
39070
+ // Spawn a single input into a remote function.
39071
+ async spawn(args = [], kwargs = {}) {
39072
+ const input = await this.#createInput(args, kwargs);
39073
+ const invocation = await ControlPlaneInvocation.create(
39074
+ this.functionId,
39075
+ input,
39076
+ 3 /* FUNCTION_CALL_INVOCATION_TYPE_ASYNC */
39077
+ );
39078
+ return new FunctionCall(invocation.functionCallId);
39079
+ }
39080
+ async #createInput(args = [], kwargs = {}) {
39081
+ const payload = dumps([args, kwargs]);
39082
+ let argsBlobId = void 0;
39083
+ if (payload.length > maxObjectSizeBytes) {
39084
+ argsBlobId = await blobUpload(payload);
39085
+ }
39086
+ return {
39087
+ args: argsBlobId ? void 0 : payload,
39088
+ argsBlobId,
39089
+ dataFormat: 1 /* DATA_FORMAT_PICKLE */,
39090
+ methodName: this.methodName,
39091
+ finalInput: false
39092
+ // This field isn't specified in the Python client, so it defaults to false.
39093
+ };
39094
+ }
39095
+ };
39010
39096
  async function blobUpload(data) {
39011
39097
  const contentMd5 = createHash("md5").update(data).digest("base64");
39012
39098
  const contentSha256 = createHash("sha256").update(data).digest("base64");
@@ -39036,30 +39122,6 @@ async function blobUpload(data) {
39036
39122
  throw new Error("Missing upload URL in BlobCreate response");
39037
39123
  }
39038
39124
  }
39039
- async function blobDownload(blobId) {
39040
- const resp = await client.blobGet({ blobId });
39041
- const s3resp = await fetch(resp.downloadUrl);
39042
- if (!s3resp.ok) {
39043
- throw new Error(`Failed to download blob: ${s3resp.statusText}`);
39044
- }
39045
- const buf = await s3resp.arrayBuffer();
39046
- return new Uint8Array(buf);
39047
- }
39048
- function deserializeDataFormat(data, dataFormat) {
39049
- if (!data) {
39050
- return null;
39051
- }
39052
- switch (dataFormat) {
39053
- case 1 /* DATA_FORMAT_PICKLE */:
39054
- return loads(data);
39055
- case 2 /* DATA_FORMAT_ASGI */:
39056
- throw new Error("ASGI data format is not supported in Go");
39057
- case 3 /* DATA_FORMAT_GENERATOR_DONE */:
39058
- return GeneratorDone.decode(data);
39059
- default:
39060
- throw new Error(`Unsupported data format: ${dataFormat}`);
39061
- }
39062
- }
39063
39125
 
39064
39126
  // src/cls.ts
39065
39127
  var Cls = class _Cls {
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "modal",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "description": "Modal client library for JavaScript",
5
- "license": "MIT",
5
+ "license": "Apache-2.0",
6
6
  "homepage": "https://modal.com/docs",
7
7
  "repository": "github:modal-labs/libmodal",
8
8
  "bugs": "https://github.com/modal-labs/libmodal/issues",