modal 0.10.2-dev.5 → 0.10.2-dev.7
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/README.md +1 -0
- package/dist/index.cjs +459 -151
- package/dist/index.d.cts +91 -1
- package/dist/index.d.ts +91 -1
- package/dist/index.js +458 -151
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -47974,6 +47974,108 @@ var SecretDeleteRequest = {
|
|
|
47974
47974
|
return message;
|
|
47975
47975
|
}
|
|
47976
47976
|
};
|
|
47977
|
+
function createBaseSecretGetInfoRequest() {
|
|
47978
|
+
return { secretId: "" };
|
|
47979
|
+
}
|
|
47980
|
+
var SecretGetInfoRequest = {
|
|
47981
|
+
encode(message, writer = new BinaryWriter()) {
|
|
47982
|
+
if (message.secretId !== "") {
|
|
47983
|
+
writer.uint32(10).string(message.secretId);
|
|
47984
|
+
}
|
|
47985
|
+
return writer;
|
|
47986
|
+
},
|
|
47987
|
+
decode(input, length) {
|
|
47988
|
+
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
47989
|
+
let end = length === void 0 ? reader.len : reader.pos + length;
|
|
47990
|
+
const message = createBaseSecretGetInfoRequest();
|
|
47991
|
+
while (reader.pos < end) {
|
|
47992
|
+
const tag = reader.uint32();
|
|
47993
|
+
switch (tag >>> 3) {
|
|
47994
|
+
case 1: {
|
|
47995
|
+
if (tag !== 10) {
|
|
47996
|
+
break;
|
|
47997
|
+
}
|
|
47998
|
+
message.secretId = reader.string();
|
|
47999
|
+
continue;
|
|
48000
|
+
}
|
|
48001
|
+
}
|
|
48002
|
+
if ((tag & 7) === 4 || tag === 0) {
|
|
48003
|
+
break;
|
|
48004
|
+
}
|
|
48005
|
+
reader.skip(tag & 7);
|
|
48006
|
+
}
|
|
48007
|
+
return message;
|
|
48008
|
+
},
|
|
48009
|
+
fromJSON(object) {
|
|
48010
|
+
return { secretId: isSet5(object.secretId) ? globalThis.String(object.secretId) : "" };
|
|
48011
|
+
},
|
|
48012
|
+
toJSON(message) {
|
|
48013
|
+
const obj = {};
|
|
48014
|
+
if (message.secretId !== "") {
|
|
48015
|
+
obj.secretId = message.secretId;
|
|
48016
|
+
}
|
|
48017
|
+
return obj;
|
|
48018
|
+
},
|
|
48019
|
+
create(base) {
|
|
48020
|
+
return SecretGetInfoRequest.fromPartial(base ?? {});
|
|
48021
|
+
},
|
|
48022
|
+
fromPartial(object) {
|
|
48023
|
+
const message = createBaseSecretGetInfoRequest();
|
|
48024
|
+
message.secretId = object.secretId ?? "";
|
|
48025
|
+
return message;
|
|
48026
|
+
}
|
|
48027
|
+
};
|
|
48028
|
+
function createBaseSecretGetInfoResponse() {
|
|
48029
|
+
return { metadata: void 0 };
|
|
48030
|
+
}
|
|
48031
|
+
var SecretGetInfoResponse = {
|
|
48032
|
+
encode(message, writer = new BinaryWriter()) {
|
|
48033
|
+
if (message.metadata !== void 0) {
|
|
48034
|
+
SecretMetadata.encode(message.metadata, writer.uint32(10).fork()).join();
|
|
48035
|
+
}
|
|
48036
|
+
return writer;
|
|
48037
|
+
},
|
|
48038
|
+
decode(input, length) {
|
|
48039
|
+
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
48040
|
+
let end = length === void 0 ? reader.len : reader.pos + length;
|
|
48041
|
+
const message = createBaseSecretGetInfoResponse();
|
|
48042
|
+
while (reader.pos < end) {
|
|
48043
|
+
const tag = reader.uint32();
|
|
48044
|
+
switch (tag >>> 3) {
|
|
48045
|
+
case 1: {
|
|
48046
|
+
if (tag !== 10) {
|
|
48047
|
+
break;
|
|
48048
|
+
}
|
|
48049
|
+
message.metadata = SecretMetadata.decode(reader, reader.uint32());
|
|
48050
|
+
continue;
|
|
48051
|
+
}
|
|
48052
|
+
}
|
|
48053
|
+
if ((tag & 7) === 4 || tag === 0) {
|
|
48054
|
+
break;
|
|
48055
|
+
}
|
|
48056
|
+
reader.skip(tag & 7);
|
|
48057
|
+
}
|
|
48058
|
+
return message;
|
|
48059
|
+
},
|
|
48060
|
+
fromJSON(object) {
|
|
48061
|
+
return { metadata: isSet5(object.metadata) ? SecretMetadata.fromJSON(object.metadata) : void 0 };
|
|
48062
|
+
},
|
|
48063
|
+
toJSON(message) {
|
|
48064
|
+
const obj = {};
|
|
48065
|
+
if (message.metadata !== void 0) {
|
|
48066
|
+
obj.metadata = SecretMetadata.toJSON(message.metadata);
|
|
48067
|
+
}
|
|
48068
|
+
return obj;
|
|
48069
|
+
},
|
|
48070
|
+
create(base) {
|
|
48071
|
+
return SecretGetInfoResponse.fromPartial(base ?? {});
|
|
48072
|
+
},
|
|
48073
|
+
fromPartial(object) {
|
|
48074
|
+
const message = createBaseSecretGetInfoResponse();
|
|
48075
|
+
message.metadata = object.metadata !== void 0 && object.metadata !== null ? SecretMetadata.fromPartial(object.metadata) : void 0;
|
|
48076
|
+
return message;
|
|
48077
|
+
}
|
|
48078
|
+
};
|
|
47977
48079
|
function createBaseSecretGetOrCreateRequest() {
|
|
47978
48080
|
return { deploymentName: "", environmentName: "", objectCreationType: 0, envDict: {}, appId: "", requiredKeys: [] };
|
|
47979
48081
|
}
|
|
@@ -48520,7 +48622,7 @@ var SecretListResponse = {
|
|
|
48520
48622
|
}
|
|
48521
48623
|
};
|
|
48522
48624
|
function createBaseSecretMetadata() {
|
|
48523
|
-
return { name: "", creationInfo: void 0, keys: [] };
|
|
48625
|
+
return { name: "", creationInfo: void 0, keys: [], environmentName: "" };
|
|
48524
48626
|
}
|
|
48525
48627
|
var SecretMetadata = {
|
|
48526
48628
|
encode(message, writer = new BinaryWriter()) {
|
|
@@ -48533,6 +48635,9 @@ var SecretMetadata = {
|
|
|
48533
48635
|
for (const v of message.keys) {
|
|
48534
48636
|
writer.uint32(26).string(v);
|
|
48535
48637
|
}
|
|
48638
|
+
if (message.environmentName !== "") {
|
|
48639
|
+
writer.uint32(34).string(message.environmentName);
|
|
48640
|
+
}
|
|
48536
48641
|
return writer;
|
|
48537
48642
|
},
|
|
48538
48643
|
decode(input, length) {
|
|
@@ -48563,6 +48668,13 @@ var SecretMetadata = {
|
|
|
48563
48668
|
message.keys.push(reader.string());
|
|
48564
48669
|
continue;
|
|
48565
48670
|
}
|
|
48671
|
+
case 4: {
|
|
48672
|
+
if (tag !== 34) {
|
|
48673
|
+
break;
|
|
48674
|
+
}
|
|
48675
|
+
message.environmentName = reader.string();
|
|
48676
|
+
continue;
|
|
48677
|
+
}
|
|
48566
48678
|
}
|
|
48567
48679
|
if ((tag & 7) === 4 || tag === 0) {
|
|
48568
48680
|
break;
|
|
@@ -48575,7 +48687,8 @@ var SecretMetadata = {
|
|
|
48575
48687
|
return {
|
|
48576
48688
|
name: isSet5(object.name) ? globalThis.String(object.name) : "",
|
|
48577
48689
|
creationInfo: isSet5(object.creationInfo) ? CreationInfo.fromJSON(object.creationInfo) : void 0,
|
|
48578
|
-
keys: globalThis.Array.isArray(object?.keys) ? object.keys.map((e) => globalThis.String(e)) : []
|
|
48690
|
+
keys: globalThis.Array.isArray(object?.keys) ? object.keys.map((e) => globalThis.String(e)) : [],
|
|
48691
|
+
environmentName: isSet5(object.environmentName) ? globalThis.String(object.environmentName) : ""
|
|
48579
48692
|
};
|
|
48580
48693
|
},
|
|
48581
48694
|
toJSON(message) {
|
|
@@ -48589,6 +48702,9 @@ var SecretMetadata = {
|
|
|
48589
48702
|
if (message.keys?.length) {
|
|
48590
48703
|
obj.keys = message.keys;
|
|
48591
48704
|
}
|
|
48705
|
+
if (message.environmentName !== "") {
|
|
48706
|
+
obj.environmentName = message.environmentName;
|
|
48707
|
+
}
|
|
48592
48708
|
return obj;
|
|
48593
48709
|
},
|
|
48594
48710
|
create(base) {
|
|
@@ -48599,6 +48715,7 @@ var SecretMetadata = {
|
|
|
48599
48715
|
message.name = object.name ?? "";
|
|
48600
48716
|
message.creationInfo = object.creationInfo !== void 0 && object.creationInfo !== null ? CreationInfo.fromPartial(object.creationInfo) : void 0;
|
|
48601
48717
|
message.keys = object.keys?.map((e) => e) || [];
|
|
48718
|
+
message.environmentName = object.environmentName ?? "";
|
|
48602
48719
|
return message;
|
|
48603
48720
|
}
|
|
48604
48721
|
};
|
|
@@ -61983,6 +62100,14 @@ var ModalClientDefinition = {
|
|
|
61983
62100
|
responseStream: false,
|
|
61984
62101
|
options: {}
|
|
61985
62102
|
},
|
|
62103
|
+
secretGetInfo: {
|
|
62104
|
+
name: "SecretGetInfo",
|
|
62105
|
+
requestType: SecretGetInfoRequest,
|
|
62106
|
+
requestStream: false,
|
|
62107
|
+
responseType: SecretGetInfoResponse,
|
|
62108
|
+
responseStream: false,
|
|
62109
|
+
options: {}
|
|
62110
|
+
},
|
|
61986
62111
|
secretGetOrCreate: {
|
|
61987
62112
|
name: "SecretGetOrCreate",
|
|
61988
62113
|
requestType: SecretGetOrCreateRequest,
|
|
@@ -70475,8 +70600,151 @@ var SandboxFilesystem = class {
|
|
|
70475
70600
|
};
|
|
70476
70601
|
|
|
70477
70602
|
// src/sandbox_sidecar.ts
|
|
70478
|
-
import { ClientError as
|
|
70603
|
+
import { ClientError as ClientError10, Status as Status10 } from "nice-grpc";
|
|
70479
70604
|
import { v4 as uuidv4 } from "uuid";
|
|
70605
|
+
|
|
70606
|
+
// src/volume.ts
|
|
70607
|
+
import { ClientError as ClientError9, Status as Status9 } from "nice-grpc";
|
|
70608
|
+
var VolumeService = class {
|
|
70609
|
+
#client;
|
|
70610
|
+
constructor(client) {
|
|
70611
|
+
this.#client = client;
|
|
70612
|
+
}
|
|
70613
|
+
/**
|
|
70614
|
+
* Reference a {@link Volume} by its name.
|
|
70615
|
+
*/
|
|
70616
|
+
async fromName(name, params) {
|
|
70617
|
+
try {
|
|
70618
|
+
const resp = await this.#client.cpClient.volumeGetOrCreate({
|
|
70619
|
+
deploymentName: name,
|
|
70620
|
+
environmentName: this.#client.environmentName(params?.environment),
|
|
70621
|
+
objectCreationType: params?.createIfMissing ? 1 /* OBJECT_CREATION_TYPE_CREATE_IF_MISSING */ : 0 /* OBJECT_CREATION_TYPE_UNSPECIFIED */
|
|
70622
|
+
});
|
|
70623
|
+
this.#client.logger.debug(
|
|
70624
|
+
"Retrieved Volume",
|
|
70625
|
+
"volume_id",
|
|
70626
|
+
resp.volumeId,
|
|
70627
|
+
"volume_name",
|
|
70628
|
+
name
|
|
70629
|
+
);
|
|
70630
|
+
return new Volume(resp.volumeId, name);
|
|
70631
|
+
} catch (err) {
|
|
70632
|
+
if (err instanceof ClientError9 && err.code === Status9.NOT_FOUND)
|
|
70633
|
+
throw new NotFoundError(err.details);
|
|
70634
|
+
throw err;
|
|
70635
|
+
}
|
|
70636
|
+
}
|
|
70637
|
+
/**
|
|
70638
|
+
* Create a nameless, temporary {@link Volume}.
|
|
70639
|
+
* It persists until closeEphemeral() is called, or the process exits.
|
|
70640
|
+
*/
|
|
70641
|
+
async ephemeral(params = {}) {
|
|
70642
|
+
const resp = await this.#client.cpClient.volumeGetOrCreate({
|
|
70643
|
+
objectCreationType: 5 /* OBJECT_CREATION_TYPE_EPHEMERAL */,
|
|
70644
|
+
environmentName: this.#client.environmentName(params.environment)
|
|
70645
|
+
});
|
|
70646
|
+
this.#client.logger.debug(
|
|
70647
|
+
"Created ephemeral Volume",
|
|
70648
|
+
"volume_id",
|
|
70649
|
+
resp.volumeId
|
|
70650
|
+
);
|
|
70651
|
+
const ephemeralHbManager = new EphemeralHeartbeatManager(
|
|
70652
|
+
() => this.#client.cpClient.volumeHeartbeat({ volumeId: resp.volumeId })
|
|
70653
|
+
);
|
|
70654
|
+
return new Volume(resp.volumeId, void 0, void 0, ephemeralHbManager);
|
|
70655
|
+
}
|
|
70656
|
+
/**
|
|
70657
|
+
* Delete a named {@link Volume}.
|
|
70658
|
+
*
|
|
70659
|
+
* Warning: Deletion is irreversible and will affect any Apps currently using the Volume.
|
|
70660
|
+
*/
|
|
70661
|
+
async delete(name, params) {
|
|
70662
|
+
try {
|
|
70663
|
+
const volume = await this.fromName(name, {
|
|
70664
|
+
environment: params?.environment,
|
|
70665
|
+
createIfMissing: false
|
|
70666
|
+
});
|
|
70667
|
+
await this.#client.cpClient.volumeDelete({
|
|
70668
|
+
volumeId: volume.volumeId
|
|
70669
|
+
});
|
|
70670
|
+
this.#client.logger.debug(
|
|
70671
|
+
"Deleted Volume",
|
|
70672
|
+
"volume_name",
|
|
70673
|
+
name,
|
|
70674
|
+
"volume_id",
|
|
70675
|
+
volume.volumeId
|
|
70676
|
+
);
|
|
70677
|
+
} catch (err) {
|
|
70678
|
+
const isNotFound = err instanceof NotFoundError || err instanceof ClientError9 && err.code === Status9.NOT_FOUND;
|
|
70679
|
+
if (isNotFound && params?.allowMissing) {
|
|
70680
|
+
return;
|
|
70681
|
+
}
|
|
70682
|
+
throw err;
|
|
70683
|
+
}
|
|
70684
|
+
}
|
|
70685
|
+
};
|
|
70686
|
+
var DEFAULT_MOUNT_OPTIONS = {
|
|
70687
|
+
readOnly: false,
|
|
70688
|
+
subPath: void 0
|
|
70689
|
+
};
|
|
70690
|
+
var Volume = class _Volume {
|
|
70691
|
+
volumeId;
|
|
70692
|
+
name;
|
|
70693
|
+
/**
|
|
70694
|
+
* @hidden
|
|
70695
|
+
* @internal
|
|
70696
|
+
*/
|
|
70697
|
+
_mountOptions = DEFAULT_MOUNT_OPTIONS;
|
|
70698
|
+
#ephemeralHbManager;
|
|
70699
|
+
/** @ignore */
|
|
70700
|
+
constructor(volumeId, name, mountOptions, ephemeralHbManager) {
|
|
70701
|
+
this.volumeId = volumeId;
|
|
70702
|
+
this.name = name;
|
|
70703
|
+
if (mountOptions) {
|
|
70704
|
+
this._mountOptions = mountOptions;
|
|
70705
|
+
}
|
|
70706
|
+
this.#ephemeralHbManager = ephemeralHbManager;
|
|
70707
|
+
}
|
|
70708
|
+
/**
|
|
70709
|
+
* Configure options used when mounting this Volume. Fields left undefined preserve their value
|
|
70710
|
+
* from any previous withMountOptions call on the same Volume (stacking).
|
|
70711
|
+
*/
|
|
70712
|
+
withMountOptions(params = {}) {
|
|
70713
|
+
let subPath = this._mountOptions.subPath;
|
|
70714
|
+
if (params.subPath !== void 0) {
|
|
70715
|
+
subPath = params.subPath === "/" ? void 0 : params.subPath;
|
|
70716
|
+
}
|
|
70717
|
+
return new _Volume(
|
|
70718
|
+
this.volumeId,
|
|
70719
|
+
this.name,
|
|
70720
|
+
{
|
|
70721
|
+
readOnly: params.readOnly ?? this._mountOptions.readOnly,
|
|
70722
|
+
subPath
|
|
70723
|
+
},
|
|
70724
|
+
this.#ephemeralHbManager
|
|
70725
|
+
);
|
|
70726
|
+
}
|
|
70727
|
+
/** Delete the ephemeral Volume. Only usable with emphemeral Volumes. */
|
|
70728
|
+
closeEphemeral() {
|
|
70729
|
+
if (this.#ephemeralHbManager) {
|
|
70730
|
+
this.#ephemeralHbManager.stop();
|
|
70731
|
+
} else {
|
|
70732
|
+
throw new InvalidError("Volume is not ephemeral.");
|
|
70733
|
+
}
|
|
70734
|
+
}
|
|
70735
|
+
};
|
|
70736
|
+
function volumeToMountProto(mountPath, volume) {
|
|
70737
|
+
const opts = volume._mountOptions ?? DEFAULT_MOUNT_OPTIONS;
|
|
70738
|
+
return {
|
|
70739
|
+
volumeId: volume.volumeId,
|
|
70740
|
+
mountPath,
|
|
70741
|
+
allowBackgroundCommits: true,
|
|
70742
|
+
readOnly: opts.readOnly,
|
|
70743
|
+
subPath: opts.subPath
|
|
70744
|
+
};
|
|
70745
|
+
}
|
|
70746
|
+
|
|
70747
|
+
// src/sandbox_sidecar.ts
|
|
70480
70748
|
var MAIN_CONTAINER_NAME = "main";
|
|
70481
70749
|
var CONTAINER_WAIT_POLL_TIMEOUT_SECONDS = 10;
|
|
70482
70750
|
var CONTROL_PLANE_SIDECAR_CREATE_ENV_VAR = "MODAL_USE_CONTROL_PLANE_SIDECAR_CREATE";
|
|
@@ -70493,6 +70761,29 @@ function validateSidecarName(name) {
|
|
|
70493
70761
|
);
|
|
70494
70762
|
}
|
|
70495
70763
|
}
|
|
70764
|
+
function buildSidecarVolumeMounts(volumes) {
|
|
70765
|
+
const mountPathsByVolumeId = /* @__PURE__ */ new Map();
|
|
70766
|
+
const volumeMounts = [];
|
|
70767
|
+
for (const [mountPath, volume] of Object.entries(volumes ?? {})) {
|
|
70768
|
+
if (!volume) {
|
|
70769
|
+
throw new InvalidError(
|
|
70770
|
+
`Volume mounted at "${mountPath}" must not be null or undefined`
|
|
70771
|
+
);
|
|
70772
|
+
}
|
|
70773
|
+
const mountPaths = mountPathsByVolumeId.get(volume.volumeId) ?? [];
|
|
70774
|
+
mountPaths.push(mountPath);
|
|
70775
|
+
mountPathsByVolumeId.set(volume.volumeId, mountPaths);
|
|
70776
|
+
volumeMounts.push(volumeToMountProto(mountPath, volume));
|
|
70777
|
+
}
|
|
70778
|
+
for (const mountPaths of mountPathsByVolumeId.values()) {
|
|
70779
|
+
if (mountPaths.length > 1) {
|
|
70780
|
+
throw new InvalidError(
|
|
70781
|
+
"The same Volume cannot be mounted at multiple paths in a sidecar: " + mountPaths.sort().join(", ")
|
|
70782
|
+
);
|
|
70783
|
+
}
|
|
70784
|
+
}
|
|
70785
|
+
return volumeMounts;
|
|
70786
|
+
}
|
|
70496
70787
|
function sidecarContainerFromProto(access, info) {
|
|
70497
70788
|
return new SidecarContainer(
|
|
70498
70789
|
access,
|
|
@@ -70530,6 +70821,7 @@ var SidecarService = class {
|
|
|
70530
70821
|
Object.assign(envDict, params?.env ?? {});
|
|
70531
70822
|
await hydrateSecrets(this.#access.client, resolvableSecrets);
|
|
70532
70823
|
const secretIds = collectSecretIds(resolvableSecrets);
|
|
70824
|
+
const volumeMounts = buildSidecarVolumeMounts(params?.volumes);
|
|
70533
70825
|
const ptyInfo = params?.pty ? defaultSandboxPTYInfo() : void 0;
|
|
70534
70826
|
const networkAccess = buildOutboundNetworkAccess(
|
|
70535
70827
|
false,
|
|
@@ -70549,6 +70841,7 @@ var SidecarService = class {
|
|
|
70549
70841
|
entrypointArgs: command,
|
|
70550
70842
|
workdir: params?.workdir ?? void 0,
|
|
70551
70843
|
secretIds,
|
|
70844
|
+
volumeMounts,
|
|
70552
70845
|
networkAccess,
|
|
70553
70846
|
ptyInfo
|
|
70554
70847
|
}),
|
|
@@ -70566,17 +70859,18 @@ var SidecarService = class {
|
|
|
70566
70859
|
env: envDict,
|
|
70567
70860
|
workdir: params?.workdir ?? "",
|
|
70568
70861
|
secretIds,
|
|
70862
|
+
volumeMounts,
|
|
70569
70863
|
networkAccess,
|
|
70570
70864
|
ptyInfo
|
|
70571
70865
|
})
|
|
70572
70866
|
);
|
|
70573
70867
|
}
|
|
70574
70868
|
} catch (err) {
|
|
70575
|
-
if (err instanceof
|
|
70576
|
-
if (err.code ===
|
|
70869
|
+
if (err instanceof ClientError10) {
|
|
70870
|
+
if (err.code === Status10.ALREADY_EXISTS) {
|
|
70577
70871
|
throw new AlreadyExistsError(err.details || err.message);
|
|
70578
70872
|
}
|
|
70579
|
-
if (err.code ===
|
|
70873
|
+
if (err.code === Status10.INVALID_ARGUMENT) {
|
|
70580
70874
|
throw new InvalidError(err.details || err.message);
|
|
70581
70875
|
}
|
|
70582
70876
|
}
|
|
@@ -70602,7 +70896,7 @@ var SidecarService = class {
|
|
|
70602
70896
|
})
|
|
70603
70897
|
);
|
|
70604
70898
|
} catch (err) {
|
|
70605
|
-
if (err instanceof
|
|
70899
|
+
if (err instanceof ClientError10 && err.code === Status10.NOT_FOUND) {
|
|
70606
70900
|
throw new NotFoundError(`Sidecar container "${name}" not found`);
|
|
70607
70901
|
}
|
|
70608
70902
|
throw err;
|
|
@@ -70973,151 +71267,11 @@ var SandboxSnapshotService = class {
|
|
|
70973
71267
|
}
|
|
70974
71268
|
};
|
|
70975
71269
|
|
|
70976
|
-
// src/volume.ts
|
|
70977
|
-
import { ClientError as ClientError10, Status as Status10 } from "nice-grpc";
|
|
70978
|
-
var VolumeService = class {
|
|
70979
|
-
#client;
|
|
70980
|
-
constructor(client) {
|
|
70981
|
-
this.#client = client;
|
|
70982
|
-
}
|
|
70983
|
-
/**
|
|
70984
|
-
* Reference a {@link Volume} by its name.
|
|
70985
|
-
*/
|
|
70986
|
-
async fromName(name, params) {
|
|
70987
|
-
try {
|
|
70988
|
-
const resp = await this.#client.cpClient.volumeGetOrCreate({
|
|
70989
|
-
deploymentName: name,
|
|
70990
|
-
environmentName: this.#client.environmentName(params?.environment),
|
|
70991
|
-
objectCreationType: params?.createIfMissing ? 1 /* OBJECT_CREATION_TYPE_CREATE_IF_MISSING */ : 0 /* OBJECT_CREATION_TYPE_UNSPECIFIED */
|
|
70992
|
-
});
|
|
70993
|
-
this.#client.logger.debug(
|
|
70994
|
-
"Retrieved Volume",
|
|
70995
|
-
"volume_id",
|
|
70996
|
-
resp.volumeId,
|
|
70997
|
-
"volume_name",
|
|
70998
|
-
name
|
|
70999
|
-
);
|
|
71000
|
-
return new Volume(resp.volumeId, name);
|
|
71001
|
-
} catch (err) {
|
|
71002
|
-
if (err instanceof ClientError10 && err.code === Status10.NOT_FOUND)
|
|
71003
|
-
throw new NotFoundError(err.details);
|
|
71004
|
-
throw err;
|
|
71005
|
-
}
|
|
71006
|
-
}
|
|
71007
|
-
/**
|
|
71008
|
-
* Create a nameless, temporary {@link Volume}.
|
|
71009
|
-
* It persists until closeEphemeral() is called, or the process exits.
|
|
71010
|
-
*/
|
|
71011
|
-
async ephemeral(params = {}) {
|
|
71012
|
-
const resp = await this.#client.cpClient.volumeGetOrCreate({
|
|
71013
|
-
objectCreationType: 5 /* OBJECT_CREATION_TYPE_EPHEMERAL */,
|
|
71014
|
-
environmentName: this.#client.environmentName(params.environment)
|
|
71015
|
-
});
|
|
71016
|
-
this.#client.logger.debug(
|
|
71017
|
-
"Created ephemeral Volume",
|
|
71018
|
-
"volume_id",
|
|
71019
|
-
resp.volumeId
|
|
71020
|
-
);
|
|
71021
|
-
const ephemeralHbManager = new EphemeralHeartbeatManager(
|
|
71022
|
-
() => this.#client.cpClient.volumeHeartbeat({ volumeId: resp.volumeId })
|
|
71023
|
-
);
|
|
71024
|
-
return new Volume(resp.volumeId, void 0, void 0, ephemeralHbManager);
|
|
71025
|
-
}
|
|
71026
|
-
/**
|
|
71027
|
-
* Delete a named {@link Volume}.
|
|
71028
|
-
*
|
|
71029
|
-
* Warning: Deletion is irreversible and will affect any Apps currently using the Volume.
|
|
71030
|
-
*/
|
|
71031
|
-
async delete(name, params) {
|
|
71032
|
-
try {
|
|
71033
|
-
const volume = await this.fromName(name, {
|
|
71034
|
-
environment: params?.environment,
|
|
71035
|
-
createIfMissing: false
|
|
71036
|
-
});
|
|
71037
|
-
await this.#client.cpClient.volumeDelete({
|
|
71038
|
-
volumeId: volume.volumeId
|
|
71039
|
-
});
|
|
71040
|
-
this.#client.logger.debug(
|
|
71041
|
-
"Deleted Volume",
|
|
71042
|
-
"volume_name",
|
|
71043
|
-
name,
|
|
71044
|
-
"volume_id",
|
|
71045
|
-
volume.volumeId
|
|
71046
|
-
);
|
|
71047
|
-
} catch (err) {
|
|
71048
|
-
const isNotFound = err instanceof NotFoundError || err instanceof ClientError10 && err.code === Status10.NOT_FOUND;
|
|
71049
|
-
if (isNotFound && params?.allowMissing) {
|
|
71050
|
-
return;
|
|
71051
|
-
}
|
|
71052
|
-
throw err;
|
|
71053
|
-
}
|
|
71054
|
-
}
|
|
71055
|
-
};
|
|
71056
|
-
var DEFAULT_MOUNT_OPTIONS = {
|
|
71057
|
-
readOnly: false,
|
|
71058
|
-
subPath: void 0
|
|
71059
|
-
};
|
|
71060
|
-
var Volume = class _Volume {
|
|
71061
|
-
volumeId;
|
|
71062
|
-
name;
|
|
71063
|
-
/**
|
|
71064
|
-
* @hidden
|
|
71065
|
-
* @internal
|
|
71066
|
-
*/
|
|
71067
|
-
_mountOptions = DEFAULT_MOUNT_OPTIONS;
|
|
71068
|
-
#ephemeralHbManager;
|
|
71069
|
-
/** @ignore */
|
|
71070
|
-
constructor(volumeId, name, mountOptions, ephemeralHbManager) {
|
|
71071
|
-
this.volumeId = volumeId;
|
|
71072
|
-
this.name = name;
|
|
71073
|
-
if (mountOptions) {
|
|
71074
|
-
this._mountOptions = mountOptions;
|
|
71075
|
-
}
|
|
71076
|
-
this.#ephemeralHbManager = ephemeralHbManager;
|
|
71077
|
-
}
|
|
71078
|
-
/**
|
|
71079
|
-
* Configure options used when mounting this Volume. Fields left undefined preserve their value
|
|
71080
|
-
* from any previous withMountOptions call on the same Volume (stacking).
|
|
71081
|
-
*/
|
|
71082
|
-
withMountOptions(params = {}) {
|
|
71083
|
-
let subPath = this._mountOptions.subPath;
|
|
71084
|
-
if (params.subPath !== void 0) {
|
|
71085
|
-
subPath = params.subPath === "/" ? void 0 : params.subPath;
|
|
71086
|
-
}
|
|
71087
|
-
return new _Volume(
|
|
71088
|
-
this.volumeId,
|
|
71089
|
-
this.name,
|
|
71090
|
-
{
|
|
71091
|
-
readOnly: params.readOnly ?? this._mountOptions.readOnly,
|
|
71092
|
-
subPath
|
|
71093
|
-
},
|
|
71094
|
-
this.#ephemeralHbManager
|
|
71095
|
-
);
|
|
71096
|
-
}
|
|
71097
|
-
/** Delete the ephemeral Volume. Only usable with emphemeral Volumes. */
|
|
71098
|
-
closeEphemeral() {
|
|
71099
|
-
if (this.#ephemeralHbManager) {
|
|
71100
|
-
this.#ephemeralHbManager.stop();
|
|
71101
|
-
} else {
|
|
71102
|
-
throw new InvalidError("Volume is not ephemeral.");
|
|
71103
|
-
}
|
|
71104
|
-
}
|
|
71105
|
-
};
|
|
71106
|
-
function volumeToMountProto(mountPath, volume) {
|
|
71107
|
-
const opts = volume._mountOptions ?? DEFAULT_MOUNT_OPTIONS;
|
|
71108
|
-
return {
|
|
71109
|
-
volumeId: volume.volumeId,
|
|
71110
|
-
mountPath,
|
|
71111
|
-
allowBackgroundCommits: true,
|
|
71112
|
-
readOnly: opts.readOnly,
|
|
71113
|
-
subPath: opts.subPath
|
|
71114
|
-
};
|
|
71115
|
-
}
|
|
71116
|
-
|
|
71117
71270
|
// src/sandbox.ts
|
|
71118
71271
|
var SB_LOGS_INITIAL_DELAY_MS = 10;
|
|
71119
71272
|
var SB_LOGS_DELAY_FACTOR = 2;
|
|
71120
71273
|
var SB_LOGS_MAX_RETRIES = 10;
|
|
71274
|
+
var SB_LOGS_TASK_ID_TIMEOUT_SECONDS = 0.5;
|
|
71121
71275
|
var TTL_NO_EXPIRY_SENTINEL = -1;
|
|
71122
71276
|
var CUSTOMER_SUPPLIED_ENCRYPTION_KEY_MIN_LENGTH = 16;
|
|
71123
71277
|
var CUSTOMER_SUPPLIED_ENCRYPTION_KEY_MAX_LENGTH = 512;
|
|
@@ -71975,6 +72129,7 @@ function buildTaskSnapshotDirectoryRequestProto(taskId, path2, snapshotId, ttlSe
|
|
|
71975
72129
|
var Sandbox2 = class _Sandbox {
|
|
71976
72130
|
#client;
|
|
71977
72131
|
sandboxId;
|
|
72132
|
+
#appId;
|
|
71978
72133
|
#stdin;
|
|
71979
72134
|
#stdout;
|
|
71980
72135
|
#stderr;
|
|
@@ -72021,6 +72176,25 @@ var Sandbox2 = class _Sandbox {
|
|
|
72021
72176
|
}
|
|
72022
72177
|
return this.#stderr;
|
|
72023
72178
|
}
|
|
72179
|
+
/**
|
|
72180
|
+
* Access persisted entrypoint logs emitted by this Sandbox.
|
|
72181
|
+
*
|
|
72182
|
+
* Use {@link SandboxLogsManager#fetch fetch()} to read logs from a UTC time
|
|
72183
|
+
* range and {@link SandboxLogsManager#tail tail()} to read the most recent
|
|
72184
|
+
* logs.
|
|
72185
|
+
*
|
|
72186
|
+
* This is separate from {@link Sandbox#stdout stdout} and
|
|
72187
|
+
* {@link Sandbox#stderr stderr}, which expose the Sandbox's live output
|
|
72188
|
+
* streams.
|
|
72189
|
+
*/
|
|
72190
|
+
get logs() {
|
|
72191
|
+
return new SandboxLogsManager(
|
|
72192
|
+
this.#client,
|
|
72193
|
+
this.sandboxId,
|
|
72194
|
+
() => this.#getAppId(),
|
|
72195
|
+
() => this.#resolveTaskIdForLogs()
|
|
72196
|
+
);
|
|
72197
|
+
}
|
|
72024
72198
|
#outputStream(fileDescriptor) {
|
|
72025
72199
|
if (this.#isV2) {
|
|
72026
72200
|
this.#ensureAttached();
|
|
@@ -72253,8 +72427,11 @@ var Sandbox2 = class _Sandbox {
|
|
|
72253
72427
|
}
|
|
72254
72428
|
return this.#client.cpClient.sandboxWait(req);
|
|
72255
72429
|
}
|
|
72256
|
-
#sandboxGetTaskId(signal) {
|
|
72257
|
-
const req = {
|
|
72430
|
+
#sandboxGetTaskId(signal, timeout) {
|
|
72431
|
+
const req = SandboxGetTaskIdRequest.create({
|
|
72432
|
+
sandboxId: this.sandboxId,
|
|
72433
|
+
timeout
|
|
72434
|
+
});
|
|
72258
72435
|
if (this.#isV2) {
|
|
72259
72436
|
return this.#client.cpClient.sandboxGetTaskIdV2(req, { signal });
|
|
72260
72437
|
}
|
|
@@ -72284,6 +72461,42 @@ var Sandbox2 = class _Sandbox {
|
|
|
72284
72461
|
}
|
|
72285
72462
|
static #maxGetTaskIdAttempts = 600;
|
|
72286
72463
|
// 5 minutes at 500ms intervals
|
|
72464
|
+
async #getAppId() {
|
|
72465
|
+
if (this.#appId !== void 0) {
|
|
72466
|
+
return this.#appId;
|
|
72467
|
+
}
|
|
72468
|
+
const resp = await this.#sandboxWait(0);
|
|
72469
|
+
const appId = resp.metadata?.appId;
|
|
72470
|
+
if (!appId) {
|
|
72471
|
+
throw new ExecutionError(
|
|
72472
|
+
"Sandbox app ID should have been set during hydration"
|
|
72473
|
+
);
|
|
72474
|
+
}
|
|
72475
|
+
this.#appId = appId;
|
|
72476
|
+
return appId;
|
|
72477
|
+
}
|
|
72478
|
+
async #resolveTaskIdForLogs() {
|
|
72479
|
+
if (this.#taskId !== void 0) {
|
|
72480
|
+
return this.#taskId;
|
|
72481
|
+
}
|
|
72482
|
+
let resp;
|
|
72483
|
+
try {
|
|
72484
|
+
resp = await this.#sandboxGetTaskId(
|
|
72485
|
+
void 0,
|
|
72486
|
+
SB_LOGS_TASK_ID_TIMEOUT_SECONDS
|
|
72487
|
+
);
|
|
72488
|
+
} catch (error) {
|
|
72489
|
+
if (error instanceof ClientError11 && error.code === Status11.DEADLINE_EXCEEDED) {
|
|
72490
|
+
throw new ExecutionError("Sandbox task ID is not available yet.");
|
|
72491
|
+
}
|
|
72492
|
+
throw error;
|
|
72493
|
+
}
|
|
72494
|
+
if (!resp.taskId) {
|
|
72495
|
+
throw new ExecutionError("Sandbox task ID is not available.");
|
|
72496
|
+
}
|
|
72497
|
+
this.#taskId = resp.taskId;
|
|
72498
|
+
return this.#taskId;
|
|
72499
|
+
}
|
|
72287
72500
|
async #getTaskId(signal) {
|
|
72288
72501
|
if (this.#taskId !== void 0) {
|
|
72289
72502
|
return this.#taskId;
|
|
@@ -73292,7 +73505,7 @@ var AuthTokenManager = class {
|
|
|
73292
73505
|
};
|
|
73293
73506
|
|
|
73294
73507
|
// src/version.ts
|
|
73295
|
-
var SDK_VERSION = "0.10.2-dev.
|
|
73508
|
+
var SDK_VERSION = "0.10.2-dev.7";
|
|
73296
73509
|
function getSDKVersion() {
|
|
73297
73510
|
return SDK_VERSION;
|
|
73298
73511
|
}
|
|
@@ -74038,6 +74251,8 @@ function contextIds(batch, item, ObjectId) {
|
|
|
74038
74251
|
item.inputId || batch.inputId,
|
|
74039
74252
|
item.containerId || batch.taskId
|
|
74040
74253
|
].filter((id) => id);
|
|
74254
|
+
case "sb":
|
|
74255
|
+
return [item.containerId || batch.taskId].filter((id) => id);
|
|
74041
74256
|
default:
|
|
74042
74257
|
return [];
|
|
74043
74258
|
}
|
|
@@ -74858,6 +75073,97 @@ var FunctionCallLogsManager = class extends LogsManager {
|
|
|
74858
75073
|
);
|
|
74859
75074
|
}
|
|
74860
75075
|
};
|
|
75076
|
+
var SandboxLogsManager = class {
|
|
75077
|
+
/** @ignore */
|
|
75078
|
+
constructor(client, sandboxId, getAppId, getTaskId) {
|
|
75079
|
+
this.client = client;
|
|
75080
|
+
this.sandboxId = sandboxId;
|
|
75081
|
+
this.getAppId = getAppId;
|
|
75082
|
+
this.getTaskId = getTaskId;
|
|
75083
|
+
}
|
|
75084
|
+
/**
|
|
75085
|
+
* Fetch Sandbox entrypoint logs corresponding to a UTC time range and
|
|
75086
|
+
* optional filters.
|
|
75087
|
+
*
|
|
75088
|
+
* Entries are returned in chronological order.
|
|
75089
|
+
*
|
|
75090
|
+
* @returns An async iterable of {@link LogEntry} objects.
|
|
75091
|
+
*
|
|
75092
|
+
* @example
|
|
75093
|
+
* ```typescript
|
|
75094
|
+
* import { ModalClient } from "modal";
|
|
75095
|
+
*
|
|
75096
|
+
* const modal = new ModalClient();
|
|
75097
|
+
* const sandbox = await modal.sandboxes.fromId("sb-...");
|
|
75098
|
+
*
|
|
75099
|
+
* for await (const entry of sandbox.logs.fetch({
|
|
75100
|
+
* since: new Date(Date.now() - 60 * 60 * 1_000),
|
|
75101
|
+
* source: "stdout",
|
|
75102
|
+
* })) {
|
|
75103
|
+
* process.stdout.write(entry.message);
|
|
75104
|
+
* }
|
|
75105
|
+
* ```
|
|
75106
|
+
*/
|
|
75107
|
+
async *fetch(params) {
|
|
75108
|
+
const [appId, taskId] = await Promise.all([
|
|
75109
|
+
this.getAppId(),
|
|
75110
|
+
this.getTaskId()
|
|
75111
|
+
]);
|
|
75112
|
+
if (!taskId) {
|
|
75113
|
+
throw new ExecutionError(
|
|
75114
|
+
"Cannot resolve Sandbox metadata needed for fetching logs. Wait for the Sandbox to be scheduled."
|
|
75115
|
+
);
|
|
75116
|
+
}
|
|
75117
|
+
yield* fetchLogs(
|
|
75118
|
+
this.client,
|
|
75119
|
+
{
|
|
75120
|
+
appId,
|
|
75121
|
+
objectId: this.sandboxId,
|
|
75122
|
+
taskId,
|
|
75123
|
+
source: sourceToFileDescriptor(params.source),
|
|
75124
|
+
searchText: params.searchText
|
|
75125
|
+
},
|
|
75126
|
+
params.since,
|
|
75127
|
+
params.until
|
|
75128
|
+
);
|
|
75129
|
+
}
|
|
75130
|
+
/**
|
|
75131
|
+
* Fetch the most recent Sandbox entrypoint logs.
|
|
75132
|
+
*
|
|
75133
|
+
* Entries are returned in chronological order.
|
|
75134
|
+
*
|
|
75135
|
+
* @returns An async iterable of {@link LogEntry} objects.
|
|
75136
|
+
*
|
|
75137
|
+
* @example
|
|
75138
|
+
* ```typescript
|
|
75139
|
+
* import { ModalClient } from "modal";
|
|
75140
|
+
*
|
|
75141
|
+
* const modal = new ModalClient();
|
|
75142
|
+
* const sandbox = await modal.sandboxes.fromId("sb-...");
|
|
75143
|
+
*
|
|
75144
|
+
* for await (const entry of sandbox.logs.tail({ entries: 20 })) {
|
|
75145
|
+
* process.stdout.write(entry.message);
|
|
75146
|
+
* }
|
|
75147
|
+
* ```
|
|
75148
|
+
*/
|
|
75149
|
+
async *tail(params = {}) {
|
|
75150
|
+
const [appId, taskId] = await Promise.all([
|
|
75151
|
+
this.getAppId(),
|
|
75152
|
+
this.getTaskId()
|
|
75153
|
+
]);
|
|
75154
|
+
if (!taskId) {
|
|
75155
|
+
throw new ExecutionError(
|
|
75156
|
+
"Sandbox task ID cannot be empty when fetching logs. Wait for the Sandbox to be scheduled."
|
|
75157
|
+
);
|
|
75158
|
+
}
|
|
75159
|
+
yield* tailLogs(this.client, params.entries ?? 100, {
|
|
75160
|
+
appId,
|
|
75161
|
+
objectId: this.sandboxId,
|
|
75162
|
+
taskId,
|
|
75163
|
+
source: sourceToFileDescriptor(params.source)
|
|
75164
|
+
});
|
|
75165
|
+
}
|
|
75166
|
+
};
|
|
74861
75167
|
|
|
74862
75168
|
// src/function_call.ts
|
|
74863
75169
|
var FunctionCallService = class {
|
|
@@ -75794,6 +76100,7 @@ export {
|
|
|
75794
76100
|
SandboxFilesystemNotFoundError,
|
|
75795
76101
|
SandboxFilesystemPathAlreadyExistsError,
|
|
75796
76102
|
SandboxFilesystemPermissionError,
|
|
76103
|
+
SandboxLogsManager,
|
|
75797
76104
|
SandboxService,
|
|
75798
76105
|
SandboxSnapshot,
|
|
75799
76106
|
SandboxSnapshotService,
|