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.cjs
CHANGED
|
@@ -75,6 +75,7 @@ __export(index_exports, {
|
|
|
75
75
|
SandboxFilesystemNotFoundError: () => SandboxFilesystemNotFoundError,
|
|
76
76
|
SandboxFilesystemPathAlreadyExistsError: () => SandboxFilesystemPathAlreadyExistsError,
|
|
77
77
|
SandboxFilesystemPermissionError: () => SandboxFilesystemPermissionError,
|
|
78
|
+
SandboxLogsManager: () => SandboxLogsManager,
|
|
78
79
|
SandboxService: () => SandboxService,
|
|
79
80
|
SandboxSnapshot: () => SandboxSnapshot,
|
|
80
81
|
SandboxSnapshotService: () => SandboxSnapshotService,
|
|
@@ -48067,6 +48068,108 @@ var SecretDeleteRequest = {
|
|
|
48067
48068
|
return message;
|
|
48068
48069
|
}
|
|
48069
48070
|
};
|
|
48071
|
+
function createBaseSecretGetInfoRequest() {
|
|
48072
|
+
return { secretId: "" };
|
|
48073
|
+
}
|
|
48074
|
+
var SecretGetInfoRequest = {
|
|
48075
|
+
encode(message, writer = new BinaryWriter()) {
|
|
48076
|
+
if (message.secretId !== "") {
|
|
48077
|
+
writer.uint32(10).string(message.secretId);
|
|
48078
|
+
}
|
|
48079
|
+
return writer;
|
|
48080
|
+
},
|
|
48081
|
+
decode(input, length) {
|
|
48082
|
+
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
48083
|
+
let end = length === void 0 ? reader.len : reader.pos + length;
|
|
48084
|
+
const message = createBaseSecretGetInfoRequest();
|
|
48085
|
+
while (reader.pos < end) {
|
|
48086
|
+
const tag = reader.uint32();
|
|
48087
|
+
switch (tag >>> 3) {
|
|
48088
|
+
case 1: {
|
|
48089
|
+
if (tag !== 10) {
|
|
48090
|
+
break;
|
|
48091
|
+
}
|
|
48092
|
+
message.secretId = reader.string();
|
|
48093
|
+
continue;
|
|
48094
|
+
}
|
|
48095
|
+
}
|
|
48096
|
+
if ((tag & 7) === 4 || tag === 0) {
|
|
48097
|
+
break;
|
|
48098
|
+
}
|
|
48099
|
+
reader.skip(tag & 7);
|
|
48100
|
+
}
|
|
48101
|
+
return message;
|
|
48102
|
+
},
|
|
48103
|
+
fromJSON(object) {
|
|
48104
|
+
return { secretId: isSet5(object.secretId) ? globalThis.String(object.secretId) : "" };
|
|
48105
|
+
},
|
|
48106
|
+
toJSON(message) {
|
|
48107
|
+
const obj = {};
|
|
48108
|
+
if (message.secretId !== "") {
|
|
48109
|
+
obj.secretId = message.secretId;
|
|
48110
|
+
}
|
|
48111
|
+
return obj;
|
|
48112
|
+
},
|
|
48113
|
+
create(base) {
|
|
48114
|
+
return SecretGetInfoRequest.fromPartial(base ?? {});
|
|
48115
|
+
},
|
|
48116
|
+
fromPartial(object) {
|
|
48117
|
+
const message = createBaseSecretGetInfoRequest();
|
|
48118
|
+
message.secretId = object.secretId ?? "";
|
|
48119
|
+
return message;
|
|
48120
|
+
}
|
|
48121
|
+
};
|
|
48122
|
+
function createBaseSecretGetInfoResponse() {
|
|
48123
|
+
return { metadata: void 0 };
|
|
48124
|
+
}
|
|
48125
|
+
var SecretGetInfoResponse = {
|
|
48126
|
+
encode(message, writer = new BinaryWriter()) {
|
|
48127
|
+
if (message.metadata !== void 0) {
|
|
48128
|
+
SecretMetadata.encode(message.metadata, writer.uint32(10).fork()).join();
|
|
48129
|
+
}
|
|
48130
|
+
return writer;
|
|
48131
|
+
},
|
|
48132
|
+
decode(input, length) {
|
|
48133
|
+
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
48134
|
+
let end = length === void 0 ? reader.len : reader.pos + length;
|
|
48135
|
+
const message = createBaseSecretGetInfoResponse();
|
|
48136
|
+
while (reader.pos < end) {
|
|
48137
|
+
const tag = reader.uint32();
|
|
48138
|
+
switch (tag >>> 3) {
|
|
48139
|
+
case 1: {
|
|
48140
|
+
if (tag !== 10) {
|
|
48141
|
+
break;
|
|
48142
|
+
}
|
|
48143
|
+
message.metadata = SecretMetadata.decode(reader, reader.uint32());
|
|
48144
|
+
continue;
|
|
48145
|
+
}
|
|
48146
|
+
}
|
|
48147
|
+
if ((tag & 7) === 4 || tag === 0) {
|
|
48148
|
+
break;
|
|
48149
|
+
}
|
|
48150
|
+
reader.skip(tag & 7);
|
|
48151
|
+
}
|
|
48152
|
+
return message;
|
|
48153
|
+
},
|
|
48154
|
+
fromJSON(object) {
|
|
48155
|
+
return { metadata: isSet5(object.metadata) ? SecretMetadata.fromJSON(object.metadata) : void 0 };
|
|
48156
|
+
},
|
|
48157
|
+
toJSON(message) {
|
|
48158
|
+
const obj = {};
|
|
48159
|
+
if (message.metadata !== void 0) {
|
|
48160
|
+
obj.metadata = SecretMetadata.toJSON(message.metadata);
|
|
48161
|
+
}
|
|
48162
|
+
return obj;
|
|
48163
|
+
},
|
|
48164
|
+
create(base) {
|
|
48165
|
+
return SecretGetInfoResponse.fromPartial(base ?? {});
|
|
48166
|
+
},
|
|
48167
|
+
fromPartial(object) {
|
|
48168
|
+
const message = createBaseSecretGetInfoResponse();
|
|
48169
|
+
message.metadata = object.metadata !== void 0 && object.metadata !== null ? SecretMetadata.fromPartial(object.metadata) : void 0;
|
|
48170
|
+
return message;
|
|
48171
|
+
}
|
|
48172
|
+
};
|
|
48070
48173
|
function createBaseSecretGetOrCreateRequest() {
|
|
48071
48174
|
return { deploymentName: "", environmentName: "", objectCreationType: 0, envDict: {}, appId: "", requiredKeys: [] };
|
|
48072
48175
|
}
|
|
@@ -48613,7 +48716,7 @@ var SecretListResponse = {
|
|
|
48613
48716
|
}
|
|
48614
48717
|
};
|
|
48615
48718
|
function createBaseSecretMetadata() {
|
|
48616
|
-
return { name: "", creationInfo: void 0, keys: [] };
|
|
48719
|
+
return { name: "", creationInfo: void 0, keys: [], environmentName: "" };
|
|
48617
48720
|
}
|
|
48618
48721
|
var SecretMetadata = {
|
|
48619
48722
|
encode(message, writer = new BinaryWriter()) {
|
|
@@ -48626,6 +48729,9 @@ var SecretMetadata = {
|
|
|
48626
48729
|
for (const v of message.keys) {
|
|
48627
48730
|
writer.uint32(26).string(v);
|
|
48628
48731
|
}
|
|
48732
|
+
if (message.environmentName !== "") {
|
|
48733
|
+
writer.uint32(34).string(message.environmentName);
|
|
48734
|
+
}
|
|
48629
48735
|
return writer;
|
|
48630
48736
|
},
|
|
48631
48737
|
decode(input, length) {
|
|
@@ -48656,6 +48762,13 @@ var SecretMetadata = {
|
|
|
48656
48762
|
message.keys.push(reader.string());
|
|
48657
48763
|
continue;
|
|
48658
48764
|
}
|
|
48765
|
+
case 4: {
|
|
48766
|
+
if (tag !== 34) {
|
|
48767
|
+
break;
|
|
48768
|
+
}
|
|
48769
|
+
message.environmentName = reader.string();
|
|
48770
|
+
continue;
|
|
48771
|
+
}
|
|
48659
48772
|
}
|
|
48660
48773
|
if ((tag & 7) === 4 || tag === 0) {
|
|
48661
48774
|
break;
|
|
@@ -48668,7 +48781,8 @@ var SecretMetadata = {
|
|
|
48668
48781
|
return {
|
|
48669
48782
|
name: isSet5(object.name) ? globalThis.String(object.name) : "",
|
|
48670
48783
|
creationInfo: isSet5(object.creationInfo) ? CreationInfo.fromJSON(object.creationInfo) : void 0,
|
|
48671
|
-
keys: globalThis.Array.isArray(object?.keys) ? object.keys.map((e) => globalThis.String(e)) : []
|
|
48784
|
+
keys: globalThis.Array.isArray(object?.keys) ? object.keys.map((e) => globalThis.String(e)) : [],
|
|
48785
|
+
environmentName: isSet5(object.environmentName) ? globalThis.String(object.environmentName) : ""
|
|
48672
48786
|
};
|
|
48673
48787
|
},
|
|
48674
48788
|
toJSON(message) {
|
|
@@ -48682,6 +48796,9 @@ var SecretMetadata = {
|
|
|
48682
48796
|
if (message.keys?.length) {
|
|
48683
48797
|
obj.keys = message.keys;
|
|
48684
48798
|
}
|
|
48799
|
+
if (message.environmentName !== "") {
|
|
48800
|
+
obj.environmentName = message.environmentName;
|
|
48801
|
+
}
|
|
48685
48802
|
return obj;
|
|
48686
48803
|
},
|
|
48687
48804
|
create(base) {
|
|
@@ -48692,6 +48809,7 @@ var SecretMetadata = {
|
|
|
48692
48809
|
message.name = object.name ?? "";
|
|
48693
48810
|
message.creationInfo = object.creationInfo !== void 0 && object.creationInfo !== null ? CreationInfo.fromPartial(object.creationInfo) : void 0;
|
|
48694
48811
|
message.keys = object.keys?.map((e) => e) || [];
|
|
48812
|
+
message.environmentName = object.environmentName ?? "";
|
|
48695
48813
|
return message;
|
|
48696
48814
|
}
|
|
48697
48815
|
};
|
|
@@ -62076,6 +62194,14 @@ var ModalClientDefinition = {
|
|
|
62076
62194
|
responseStream: false,
|
|
62077
62195
|
options: {}
|
|
62078
62196
|
},
|
|
62197
|
+
secretGetInfo: {
|
|
62198
|
+
name: "SecretGetInfo",
|
|
62199
|
+
requestType: SecretGetInfoRequest,
|
|
62200
|
+
requestStream: false,
|
|
62201
|
+
responseType: SecretGetInfoResponse,
|
|
62202
|
+
responseStream: false,
|
|
62203
|
+
options: {}
|
|
62204
|
+
},
|
|
62079
62205
|
secretGetOrCreate: {
|
|
62080
62206
|
name: "SecretGetOrCreate",
|
|
62081
62207
|
requestType: SecretGetOrCreateRequest,
|
|
@@ -70555,8 +70681,151 @@ var SandboxFilesystem = class {
|
|
|
70555
70681
|
};
|
|
70556
70682
|
|
|
70557
70683
|
// src/sandbox_sidecar.ts
|
|
70558
|
-
var
|
|
70684
|
+
var import_nice_grpc11 = require("nice-grpc");
|
|
70559
70685
|
var import_uuid = require("uuid");
|
|
70686
|
+
|
|
70687
|
+
// src/volume.ts
|
|
70688
|
+
var import_nice_grpc10 = require("nice-grpc");
|
|
70689
|
+
var VolumeService = class {
|
|
70690
|
+
#client;
|
|
70691
|
+
constructor(client) {
|
|
70692
|
+
this.#client = client;
|
|
70693
|
+
}
|
|
70694
|
+
/**
|
|
70695
|
+
* Reference a {@link Volume} by its name.
|
|
70696
|
+
*/
|
|
70697
|
+
async fromName(name, params) {
|
|
70698
|
+
try {
|
|
70699
|
+
const resp = await this.#client.cpClient.volumeGetOrCreate({
|
|
70700
|
+
deploymentName: name,
|
|
70701
|
+
environmentName: this.#client.environmentName(params?.environment),
|
|
70702
|
+
objectCreationType: params?.createIfMissing ? 1 /* OBJECT_CREATION_TYPE_CREATE_IF_MISSING */ : 0 /* OBJECT_CREATION_TYPE_UNSPECIFIED */
|
|
70703
|
+
});
|
|
70704
|
+
this.#client.logger.debug(
|
|
70705
|
+
"Retrieved Volume",
|
|
70706
|
+
"volume_id",
|
|
70707
|
+
resp.volumeId,
|
|
70708
|
+
"volume_name",
|
|
70709
|
+
name
|
|
70710
|
+
);
|
|
70711
|
+
return new Volume(resp.volumeId, name);
|
|
70712
|
+
} catch (err) {
|
|
70713
|
+
if (err instanceof import_nice_grpc10.ClientError && err.code === import_nice_grpc10.Status.NOT_FOUND)
|
|
70714
|
+
throw new NotFoundError(err.details);
|
|
70715
|
+
throw err;
|
|
70716
|
+
}
|
|
70717
|
+
}
|
|
70718
|
+
/**
|
|
70719
|
+
* Create a nameless, temporary {@link Volume}.
|
|
70720
|
+
* It persists until closeEphemeral() is called, or the process exits.
|
|
70721
|
+
*/
|
|
70722
|
+
async ephemeral(params = {}) {
|
|
70723
|
+
const resp = await this.#client.cpClient.volumeGetOrCreate({
|
|
70724
|
+
objectCreationType: 5 /* OBJECT_CREATION_TYPE_EPHEMERAL */,
|
|
70725
|
+
environmentName: this.#client.environmentName(params.environment)
|
|
70726
|
+
});
|
|
70727
|
+
this.#client.logger.debug(
|
|
70728
|
+
"Created ephemeral Volume",
|
|
70729
|
+
"volume_id",
|
|
70730
|
+
resp.volumeId
|
|
70731
|
+
);
|
|
70732
|
+
const ephemeralHbManager = new EphemeralHeartbeatManager(
|
|
70733
|
+
() => this.#client.cpClient.volumeHeartbeat({ volumeId: resp.volumeId })
|
|
70734
|
+
);
|
|
70735
|
+
return new Volume(resp.volumeId, void 0, void 0, ephemeralHbManager);
|
|
70736
|
+
}
|
|
70737
|
+
/**
|
|
70738
|
+
* Delete a named {@link Volume}.
|
|
70739
|
+
*
|
|
70740
|
+
* Warning: Deletion is irreversible and will affect any Apps currently using the Volume.
|
|
70741
|
+
*/
|
|
70742
|
+
async delete(name, params) {
|
|
70743
|
+
try {
|
|
70744
|
+
const volume = await this.fromName(name, {
|
|
70745
|
+
environment: params?.environment,
|
|
70746
|
+
createIfMissing: false
|
|
70747
|
+
});
|
|
70748
|
+
await this.#client.cpClient.volumeDelete({
|
|
70749
|
+
volumeId: volume.volumeId
|
|
70750
|
+
});
|
|
70751
|
+
this.#client.logger.debug(
|
|
70752
|
+
"Deleted Volume",
|
|
70753
|
+
"volume_name",
|
|
70754
|
+
name,
|
|
70755
|
+
"volume_id",
|
|
70756
|
+
volume.volumeId
|
|
70757
|
+
);
|
|
70758
|
+
} catch (err) {
|
|
70759
|
+
const isNotFound = err instanceof NotFoundError || err instanceof import_nice_grpc10.ClientError && err.code === import_nice_grpc10.Status.NOT_FOUND;
|
|
70760
|
+
if (isNotFound && params?.allowMissing) {
|
|
70761
|
+
return;
|
|
70762
|
+
}
|
|
70763
|
+
throw err;
|
|
70764
|
+
}
|
|
70765
|
+
}
|
|
70766
|
+
};
|
|
70767
|
+
var DEFAULT_MOUNT_OPTIONS = {
|
|
70768
|
+
readOnly: false,
|
|
70769
|
+
subPath: void 0
|
|
70770
|
+
};
|
|
70771
|
+
var Volume = class _Volume {
|
|
70772
|
+
volumeId;
|
|
70773
|
+
name;
|
|
70774
|
+
/**
|
|
70775
|
+
* @hidden
|
|
70776
|
+
* @internal
|
|
70777
|
+
*/
|
|
70778
|
+
_mountOptions = DEFAULT_MOUNT_OPTIONS;
|
|
70779
|
+
#ephemeralHbManager;
|
|
70780
|
+
/** @ignore */
|
|
70781
|
+
constructor(volumeId, name, mountOptions, ephemeralHbManager) {
|
|
70782
|
+
this.volumeId = volumeId;
|
|
70783
|
+
this.name = name;
|
|
70784
|
+
if (mountOptions) {
|
|
70785
|
+
this._mountOptions = mountOptions;
|
|
70786
|
+
}
|
|
70787
|
+
this.#ephemeralHbManager = ephemeralHbManager;
|
|
70788
|
+
}
|
|
70789
|
+
/**
|
|
70790
|
+
* Configure options used when mounting this Volume. Fields left undefined preserve their value
|
|
70791
|
+
* from any previous withMountOptions call on the same Volume (stacking).
|
|
70792
|
+
*/
|
|
70793
|
+
withMountOptions(params = {}) {
|
|
70794
|
+
let subPath = this._mountOptions.subPath;
|
|
70795
|
+
if (params.subPath !== void 0) {
|
|
70796
|
+
subPath = params.subPath === "/" ? void 0 : params.subPath;
|
|
70797
|
+
}
|
|
70798
|
+
return new _Volume(
|
|
70799
|
+
this.volumeId,
|
|
70800
|
+
this.name,
|
|
70801
|
+
{
|
|
70802
|
+
readOnly: params.readOnly ?? this._mountOptions.readOnly,
|
|
70803
|
+
subPath
|
|
70804
|
+
},
|
|
70805
|
+
this.#ephemeralHbManager
|
|
70806
|
+
);
|
|
70807
|
+
}
|
|
70808
|
+
/** Delete the ephemeral Volume. Only usable with emphemeral Volumes. */
|
|
70809
|
+
closeEphemeral() {
|
|
70810
|
+
if (this.#ephemeralHbManager) {
|
|
70811
|
+
this.#ephemeralHbManager.stop();
|
|
70812
|
+
} else {
|
|
70813
|
+
throw new InvalidError("Volume is not ephemeral.");
|
|
70814
|
+
}
|
|
70815
|
+
}
|
|
70816
|
+
};
|
|
70817
|
+
function volumeToMountProto(mountPath, volume) {
|
|
70818
|
+
const opts = volume._mountOptions ?? DEFAULT_MOUNT_OPTIONS;
|
|
70819
|
+
return {
|
|
70820
|
+
volumeId: volume.volumeId,
|
|
70821
|
+
mountPath,
|
|
70822
|
+
allowBackgroundCommits: true,
|
|
70823
|
+
readOnly: opts.readOnly,
|
|
70824
|
+
subPath: opts.subPath
|
|
70825
|
+
};
|
|
70826
|
+
}
|
|
70827
|
+
|
|
70828
|
+
// src/sandbox_sidecar.ts
|
|
70560
70829
|
var MAIN_CONTAINER_NAME = "main";
|
|
70561
70830
|
var CONTAINER_WAIT_POLL_TIMEOUT_SECONDS = 10;
|
|
70562
70831
|
var CONTROL_PLANE_SIDECAR_CREATE_ENV_VAR = "MODAL_USE_CONTROL_PLANE_SIDECAR_CREATE";
|
|
@@ -70573,6 +70842,29 @@ function validateSidecarName(name) {
|
|
|
70573
70842
|
);
|
|
70574
70843
|
}
|
|
70575
70844
|
}
|
|
70845
|
+
function buildSidecarVolumeMounts(volumes) {
|
|
70846
|
+
const mountPathsByVolumeId = /* @__PURE__ */ new Map();
|
|
70847
|
+
const volumeMounts = [];
|
|
70848
|
+
for (const [mountPath, volume] of Object.entries(volumes ?? {})) {
|
|
70849
|
+
if (!volume) {
|
|
70850
|
+
throw new InvalidError(
|
|
70851
|
+
`Volume mounted at "${mountPath}" must not be null or undefined`
|
|
70852
|
+
);
|
|
70853
|
+
}
|
|
70854
|
+
const mountPaths = mountPathsByVolumeId.get(volume.volumeId) ?? [];
|
|
70855
|
+
mountPaths.push(mountPath);
|
|
70856
|
+
mountPathsByVolumeId.set(volume.volumeId, mountPaths);
|
|
70857
|
+
volumeMounts.push(volumeToMountProto(mountPath, volume));
|
|
70858
|
+
}
|
|
70859
|
+
for (const mountPaths of mountPathsByVolumeId.values()) {
|
|
70860
|
+
if (mountPaths.length > 1) {
|
|
70861
|
+
throw new InvalidError(
|
|
70862
|
+
"The same Volume cannot be mounted at multiple paths in a sidecar: " + mountPaths.sort().join(", ")
|
|
70863
|
+
);
|
|
70864
|
+
}
|
|
70865
|
+
}
|
|
70866
|
+
return volumeMounts;
|
|
70867
|
+
}
|
|
70576
70868
|
function sidecarContainerFromProto(access, info) {
|
|
70577
70869
|
return new SidecarContainer(
|
|
70578
70870
|
access,
|
|
@@ -70610,6 +70902,7 @@ var SidecarService = class {
|
|
|
70610
70902
|
Object.assign(envDict, params?.env ?? {});
|
|
70611
70903
|
await hydrateSecrets(this.#access.client, resolvableSecrets);
|
|
70612
70904
|
const secretIds = collectSecretIds(resolvableSecrets);
|
|
70905
|
+
const volumeMounts = buildSidecarVolumeMounts(params?.volumes);
|
|
70613
70906
|
const ptyInfo = params?.pty ? defaultSandboxPTYInfo() : void 0;
|
|
70614
70907
|
const networkAccess = buildOutboundNetworkAccess(
|
|
70615
70908
|
false,
|
|
@@ -70629,6 +70922,7 @@ var SidecarService = class {
|
|
|
70629
70922
|
entrypointArgs: command,
|
|
70630
70923
|
workdir: params?.workdir ?? void 0,
|
|
70631
70924
|
secretIds,
|
|
70925
|
+
volumeMounts,
|
|
70632
70926
|
networkAccess,
|
|
70633
70927
|
ptyInfo
|
|
70634
70928
|
}),
|
|
@@ -70646,17 +70940,18 @@ var SidecarService = class {
|
|
|
70646
70940
|
env: envDict,
|
|
70647
70941
|
workdir: params?.workdir ?? "",
|
|
70648
70942
|
secretIds,
|
|
70943
|
+
volumeMounts,
|
|
70649
70944
|
networkAccess,
|
|
70650
70945
|
ptyInfo
|
|
70651
70946
|
})
|
|
70652
70947
|
);
|
|
70653
70948
|
}
|
|
70654
70949
|
} catch (err) {
|
|
70655
|
-
if (err instanceof
|
|
70656
|
-
if (err.code ===
|
|
70950
|
+
if (err instanceof import_nice_grpc11.ClientError) {
|
|
70951
|
+
if (err.code === import_nice_grpc11.Status.ALREADY_EXISTS) {
|
|
70657
70952
|
throw new AlreadyExistsError(err.details || err.message);
|
|
70658
70953
|
}
|
|
70659
|
-
if (err.code ===
|
|
70954
|
+
if (err.code === import_nice_grpc11.Status.INVALID_ARGUMENT) {
|
|
70660
70955
|
throw new InvalidError(err.details || err.message);
|
|
70661
70956
|
}
|
|
70662
70957
|
}
|
|
@@ -70682,7 +70977,7 @@ var SidecarService = class {
|
|
|
70682
70977
|
})
|
|
70683
70978
|
);
|
|
70684
70979
|
} catch (err) {
|
|
70685
|
-
if (err instanceof
|
|
70980
|
+
if (err instanceof import_nice_grpc11.ClientError && err.code === import_nice_grpc11.Status.NOT_FOUND) {
|
|
70686
70981
|
throw new NotFoundError(`Sidecar container "${name}" not found`);
|
|
70687
70982
|
}
|
|
70688
70983
|
throw err;
|
|
@@ -71053,151 +71348,11 @@ var SandboxSnapshotService = class {
|
|
|
71053
71348
|
}
|
|
71054
71349
|
};
|
|
71055
71350
|
|
|
71056
|
-
// src/volume.ts
|
|
71057
|
-
var import_nice_grpc11 = require("nice-grpc");
|
|
71058
|
-
var VolumeService = class {
|
|
71059
|
-
#client;
|
|
71060
|
-
constructor(client) {
|
|
71061
|
-
this.#client = client;
|
|
71062
|
-
}
|
|
71063
|
-
/**
|
|
71064
|
-
* Reference a {@link Volume} by its name.
|
|
71065
|
-
*/
|
|
71066
|
-
async fromName(name, params) {
|
|
71067
|
-
try {
|
|
71068
|
-
const resp = await this.#client.cpClient.volumeGetOrCreate({
|
|
71069
|
-
deploymentName: name,
|
|
71070
|
-
environmentName: this.#client.environmentName(params?.environment),
|
|
71071
|
-
objectCreationType: params?.createIfMissing ? 1 /* OBJECT_CREATION_TYPE_CREATE_IF_MISSING */ : 0 /* OBJECT_CREATION_TYPE_UNSPECIFIED */
|
|
71072
|
-
});
|
|
71073
|
-
this.#client.logger.debug(
|
|
71074
|
-
"Retrieved Volume",
|
|
71075
|
-
"volume_id",
|
|
71076
|
-
resp.volumeId,
|
|
71077
|
-
"volume_name",
|
|
71078
|
-
name
|
|
71079
|
-
);
|
|
71080
|
-
return new Volume(resp.volumeId, name);
|
|
71081
|
-
} catch (err) {
|
|
71082
|
-
if (err instanceof import_nice_grpc11.ClientError && err.code === import_nice_grpc11.Status.NOT_FOUND)
|
|
71083
|
-
throw new NotFoundError(err.details);
|
|
71084
|
-
throw err;
|
|
71085
|
-
}
|
|
71086
|
-
}
|
|
71087
|
-
/**
|
|
71088
|
-
* Create a nameless, temporary {@link Volume}.
|
|
71089
|
-
* It persists until closeEphemeral() is called, or the process exits.
|
|
71090
|
-
*/
|
|
71091
|
-
async ephemeral(params = {}) {
|
|
71092
|
-
const resp = await this.#client.cpClient.volumeGetOrCreate({
|
|
71093
|
-
objectCreationType: 5 /* OBJECT_CREATION_TYPE_EPHEMERAL */,
|
|
71094
|
-
environmentName: this.#client.environmentName(params.environment)
|
|
71095
|
-
});
|
|
71096
|
-
this.#client.logger.debug(
|
|
71097
|
-
"Created ephemeral Volume",
|
|
71098
|
-
"volume_id",
|
|
71099
|
-
resp.volumeId
|
|
71100
|
-
);
|
|
71101
|
-
const ephemeralHbManager = new EphemeralHeartbeatManager(
|
|
71102
|
-
() => this.#client.cpClient.volumeHeartbeat({ volumeId: resp.volumeId })
|
|
71103
|
-
);
|
|
71104
|
-
return new Volume(resp.volumeId, void 0, void 0, ephemeralHbManager);
|
|
71105
|
-
}
|
|
71106
|
-
/**
|
|
71107
|
-
* Delete a named {@link Volume}.
|
|
71108
|
-
*
|
|
71109
|
-
* Warning: Deletion is irreversible and will affect any Apps currently using the Volume.
|
|
71110
|
-
*/
|
|
71111
|
-
async delete(name, params) {
|
|
71112
|
-
try {
|
|
71113
|
-
const volume = await this.fromName(name, {
|
|
71114
|
-
environment: params?.environment,
|
|
71115
|
-
createIfMissing: false
|
|
71116
|
-
});
|
|
71117
|
-
await this.#client.cpClient.volumeDelete({
|
|
71118
|
-
volumeId: volume.volumeId
|
|
71119
|
-
});
|
|
71120
|
-
this.#client.logger.debug(
|
|
71121
|
-
"Deleted Volume",
|
|
71122
|
-
"volume_name",
|
|
71123
|
-
name,
|
|
71124
|
-
"volume_id",
|
|
71125
|
-
volume.volumeId
|
|
71126
|
-
);
|
|
71127
|
-
} catch (err) {
|
|
71128
|
-
const isNotFound = err instanceof NotFoundError || err instanceof import_nice_grpc11.ClientError && err.code === import_nice_grpc11.Status.NOT_FOUND;
|
|
71129
|
-
if (isNotFound && params?.allowMissing) {
|
|
71130
|
-
return;
|
|
71131
|
-
}
|
|
71132
|
-
throw err;
|
|
71133
|
-
}
|
|
71134
|
-
}
|
|
71135
|
-
};
|
|
71136
|
-
var DEFAULT_MOUNT_OPTIONS = {
|
|
71137
|
-
readOnly: false,
|
|
71138
|
-
subPath: void 0
|
|
71139
|
-
};
|
|
71140
|
-
var Volume = class _Volume {
|
|
71141
|
-
volumeId;
|
|
71142
|
-
name;
|
|
71143
|
-
/**
|
|
71144
|
-
* @hidden
|
|
71145
|
-
* @internal
|
|
71146
|
-
*/
|
|
71147
|
-
_mountOptions = DEFAULT_MOUNT_OPTIONS;
|
|
71148
|
-
#ephemeralHbManager;
|
|
71149
|
-
/** @ignore */
|
|
71150
|
-
constructor(volumeId, name, mountOptions, ephemeralHbManager) {
|
|
71151
|
-
this.volumeId = volumeId;
|
|
71152
|
-
this.name = name;
|
|
71153
|
-
if (mountOptions) {
|
|
71154
|
-
this._mountOptions = mountOptions;
|
|
71155
|
-
}
|
|
71156
|
-
this.#ephemeralHbManager = ephemeralHbManager;
|
|
71157
|
-
}
|
|
71158
|
-
/**
|
|
71159
|
-
* Configure options used when mounting this Volume. Fields left undefined preserve their value
|
|
71160
|
-
* from any previous withMountOptions call on the same Volume (stacking).
|
|
71161
|
-
*/
|
|
71162
|
-
withMountOptions(params = {}) {
|
|
71163
|
-
let subPath = this._mountOptions.subPath;
|
|
71164
|
-
if (params.subPath !== void 0) {
|
|
71165
|
-
subPath = params.subPath === "/" ? void 0 : params.subPath;
|
|
71166
|
-
}
|
|
71167
|
-
return new _Volume(
|
|
71168
|
-
this.volumeId,
|
|
71169
|
-
this.name,
|
|
71170
|
-
{
|
|
71171
|
-
readOnly: params.readOnly ?? this._mountOptions.readOnly,
|
|
71172
|
-
subPath
|
|
71173
|
-
},
|
|
71174
|
-
this.#ephemeralHbManager
|
|
71175
|
-
);
|
|
71176
|
-
}
|
|
71177
|
-
/** Delete the ephemeral Volume. Only usable with emphemeral Volumes. */
|
|
71178
|
-
closeEphemeral() {
|
|
71179
|
-
if (this.#ephemeralHbManager) {
|
|
71180
|
-
this.#ephemeralHbManager.stop();
|
|
71181
|
-
} else {
|
|
71182
|
-
throw new InvalidError("Volume is not ephemeral.");
|
|
71183
|
-
}
|
|
71184
|
-
}
|
|
71185
|
-
};
|
|
71186
|
-
function volumeToMountProto(mountPath, volume) {
|
|
71187
|
-
const opts = volume._mountOptions ?? DEFAULT_MOUNT_OPTIONS;
|
|
71188
|
-
return {
|
|
71189
|
-
volumeId: volume.volumeId,
|
|
71190
|
-
mountPath,
|
|
71191
|
-
allowBackgroundCommits: true,
|
|
71192
|
-
readOnly: opts.readOnly,
|
|
71193
|
-
subPath: opts.subPath
|
|
71194
|
-
};
|
|
71195
|
-
}
|
|
71196
|
-
|
|
71197
71351
|
// src/sandbox.ts
|
|
71198
71352
|
var SB_LOGS_INITIAL_DELAY_MS = 10;
|
|
71199
71353
|
var SB_LOGS_DELAY_FACTOR = 2;
|
|
71200
71354
|
var SB_LOGS_MAX_RETRIES = 10;
|
|
71355
|
+
var SB_LOGS_TASK_ID_TIMEOUT_SECONDS = 0.5;
|
|
71201
71356
|
var TTL_NO_EXPIRY_SENTINEL = -1;
|
|
71202
71357
|
var CUSTOMER_SUPPLIED_ENCRYPTION_KEY_MIN_LENGTH = 16;
|
|
71203
71358
|
var CUSTOMER_SUPPLIED_ENCRYPTION_KEY_MAX_LENGTH = 512;
|
|
@@ -72055,6 +72210,7 @@ function buildTaskSnapshotDirectoryRequestProto(taskId, path2, snapshotId, ttlSe
|
|
|
72055
72210
|
var Sandbox2 = class _Sandbox {
|
|
72056
72211
|
#client;
|
|
72057
72212
|
sandboxId;
|
|
72213
|
+
#appId;
|
|
72058
72214
|
#stdin;
|
|
72059
72215
|
#stdout;
|
|
72060
72216
|
#stderr;
|
|
@@ -72101,6 +72257,25 @@ var Sandbox2 = class _Sandbox {
|
|
|
72101
72257
|
}
|
|
72102
72258
|
return this.#stderr;
|
|
72103
72259
|
}
|
|
72260
|
+
/**
|
|
72261
|
+
* Access persisted entrypoint logs emitted by this Sandbox.
|
|
72262
|
+
*
|
|
72263
|
+
* Use {@link SandboxLogsManager#fetch fetch()} to read logs from a UTC time
|
|
72264
|
+
* range and {@link SandboxLogsManager#tail tail()} to read the most recent
|
|
72265
|
+
* logs.
|
|
72266
|
+
*
|
|
72267
|
+
* This is separate from {@link Sandbox#stdout stdout} and
|
|
72268
|
+
* {@link Sandbox#stderr stderr}, which expose the Sandbox's live output
|
|
72269
|
+
* streams.
|
|
72270
|
+
*/
|
|
72271
|
+
get logs() {
|
|
72272
|
+
return new SandboxLogsManager(
|
|
72273
|
+
this.#client,
|
|
72274
|
+
this.sandboxId,
|
|
72275
|
+
() => this.#getAppId(),
|
|
72276
|
+
() => this.#resolveTaskIdForLogs()
|
|
72277
|
+
);
|
|
72278
|
+
}
|
|
72104
72279
|
#outputStream(fileDescriptor) {
|
|
72105
72280
|
if (this.#isV2) {
|
|
72106
72281
|
this.#ensureAttached();
|
|
@@ -72333,8 +72508,11 @@ var Sandbox2 = class _Sandbox {
|
|
|
72333
72508
|
}
|
|
72334
72509
|
return this.#client.cpClient.sandboxWait(req);
|
|
72335
72510
|
}
|
|
72336
|
-
#sandboxGetTaskId(signal) {
|
|
72337
|
-
const req = {
|
|
72511
|
+
#sandboxGetTaskId(signal, timeout) {
|
|
72512
|
+
const req = SandboxGetTaskIdRequest.create({
|
|
72513
|
+
sandboxId: this.sandboxId,
|
|
72514
|
+
timeout
|
|
72515
|
+
});
|
|
72338
72516
|
if (this.#isV2) {
|
|
72339
72517
|
return this.#client.cpClient.sandboxGetTaskIdV2(req, { signal });
|
|
72340
72518
|
}
|
|
@@ -72364,6 +72542,42 @@ var Sandbox2 = class _Sandbox {
|
|
|
72364
72542
|
}
|
|
72365
72543
|
static #maxGetTaskIdAttempts = 600;
|
|
72366
72544
|
// 5 minutes at 500ms intervals
|
|
72545
|
+
async #getAppId() {
|
|
72546
|
+
if (this.#appId !== void 0) {
|
|
72547
|
+
return this.#appId;
|
|
72548
|
+
}
|
|
72549
|
+
const resp = await this.#sandboxWait(0);
|
|
72550
|
+
const appId = resp.metadata?.appId;
|
|
72551
|
+
if (!appId) {
|
|
72552
|
+
throw new ExecutionError(
|
|
72553
|
+
"Sandbox app ID should have been set during hydration"
|
|
72554
|
+
);
|
|
72555
|
+
}
|
|
72556
|
+
this.#appId = appId;
|
|
72557
|
+
return appId;
|
|
72558
|
+
}
|
|
72559
|
+
async #resolveTaskIdForLogs() {
|
|
72560
|
+
if (this.#taskId !== void 0) {
|
|
72561
|
+
return this.#taskId;
|
|
72562
|
+
}
|
|
72563
|
+
let resp;
|
|
72564
|
+
try {
|
|
72565
|
+
resp = await this.#sandboxGetTaskId(
|
|
72566
|
+
void 0,
|
|
72567
|
+
SB_LOGS_TASK_ID_TIMEOUT_SECONDS
|
|
72568
|
+
);
|
|
72569
|
+
} catch (error) {
|
|
72570
|
+
if (error instanceof import_nice_grpc12.ClientError && error.code === import_nice_grpc12.Status.DEADLINE_EXCEEDED) {
|
|
72571
|
+
throw new ExecutionError("Sandbox task ID is not available yet.");
|
|
72572
|
+
}
|
|
72573
|
+
throw error;
|
|
72574
|
+
}
|
|
72575
|
+
if (!resp.taskId) {
|
|
72576
|
+
throw new ExecutionError("Sandbox task ID is not available.");
|
|
72577
|
+
}
|
|
72578
|
+
this.#taskId = resp.taskId;
|
|
72579
|
+
return this.#taskId;
|
|
72580
|
+
}
|
|
72367
72581
|
async #getTaskId(signal) {
|
|
72368
72582
|
if (this.#taskId !== void 0) {
|
|
72369
72583
|
return this.#taskId;
|
|
@@ -73372,7 +73586,7 @@ var AuthTokenManager = class {
|
|
|
73372
73586
|
};
|
|
73373
73587
|
|
|
73374
73588
|
// src/version.ts
|
|
73375
|
-
var SDK_VERSION = "0.10.2-dev.
|
|
73589
|
+
var SDK_VERSION = "0.10.2-dev.7";
|
|
73376
73590
|
function getSDKVersion() {
|
|
73377
73591
|
return SDK_VERSION;
|
|
73378
73592
|
}
|
|
@@ -74113,6 +74327,8 @@ function contextIds(batch, item, ObjectId) {
|
|
|
74113
74327
|
item.inputId || batch.inputId,
|
|
74114
74328
|
item.containerId || batch.taskId
|
|
74115
74329
|
].filter((id) => id);
|
|
74330
|
+
case "sb":
|
|
74331
|
+
return [item.containerId || batch.taskId].filter((id) => id);
|
|
74116
74332
|
default:
|
|
74117
74333
|
return [];
|
|
74118
74334
|
}
|
|
@@ -74933,6 +75149,97 @@ var FunctionCallLogsManager = class extends LogsManager {
|
|
|
74933
75149
|
);
|
|
74934
75150
|
}
|
|
74935
75151
|
};
|
|
75152
|
+
var SandboxLogsManager = class {
|
|
75153
|
+
/** @ignore */
|
|
75154
|
+
constructor(client, sandboxId, getAppId, getTaskId) {
|
|
75155
|
+
this.client = client;
|
|
75156
|
+
this.sandboxId = sandboxId;
|
|
75157
|
+
this.getAppId = getAppId;
|
|
75158
|
+
this.getTaskId = getTaskId;
|
|
75159
|
+
}
|
|
75160
|
+
/**
|
|
75161
|
+
* Fetch Sandbox entrypoint logs corresponding to a UTC time range and
|
|
75162
|
+
* optional filters.
|
|
75163
|
+
*
|
|
75164
|
+
* Entries are returned in chronological order.
|
|
75165
|
+
*
|
|
75166
|
+
* @returns An async iterable of {@link LogEntry} objects.
|
|
75167
|
+
*
|
|
75168
|
+
* @example
|
|
75169
|
+
* ```typescript
|
|
75170
|
+
* import { ModalClient } from "modal";
|
|
75171
|
+
*
|
|
75172
|
+
* const modal = new ModalClient();
|
|
75173
|
+
* const sandbox = await modal.sandboxes.fromId("sb-...");
|
|
75174
|
+
*
|
|
75175
|
+
* for await (const entry of sandbox.logs.fetch({
|
|
75176
|
+
* since: new Date(Date.now() - 60 * 60 * 1_000),
|
|
75177
|
+
* source: "stdout",
|
|
75178
|
+
* })) {
|
|
75179
|
+
* process.stdout.write(entry.message);
|
|
75180
|
+
* }
|
|
75181
|
+
* ```
|
|
75182
|
+
*/
|
|
75183
|
+
async *fetch(params) {
|
|
75184
|
+
const [appId, taskId] = await Promise.all([
|
|
75185
|
+
this.getAppId(),
|
|
75186
|
+
this.getTaskId()
|
|
75187
|
+
]);
|
|
75188
|
+
if (!taskId) {
|
|
75189
|
+
throw new ExecutionError(
|
|
75190
|
+
"Cannot resolve Sandbox metadata needed for fetching logs. Wait for the Sandbox to be scheduled."
|
|
75191
|
+
);
|
|
75192
|
+
}
|
|
75193
|
+
yield* fetchLogs(
|
|
75194
|
+
this.client,
|
|
75195
|
+
{
|
|
75196
|
+
appId,
|
|
75197
|
+
objectId: this.sandboxId,
|
|
75198
|
+
taskId,
|
|
75199
|
+
source: sourceToFileDescriptor(params.source),
|
|
75200
|
+
searchText: params.searchText
|
|
75201
|
+
},
|
|
75202
|
+
params.since,
|
|
75203
|
+
params.until
|
|
75204
|
+
);
|
|
75205
|
+
}
|
|
75206
|
+
/**
|
|
75207
|
+
* Fetch the most recent Sandbox entrypoint logs.
|
|
75208
|
+
*
|
|
75209
|
+
* Entries are returned in chronological order.
|
|
75210
|
+
*
|
|
75211
|
+
* @returns An async iterable of {@link LogEntry} objects.
|
|
75212
|
+
*
|
|
75213
|
+
* @example
|
|
75214
|
+
* ```typescript
|
|
75215
|
+
* import { ModalClient } from "modal";
|
|
75216
|
+
*
|
|
75217
|
+
* const modal = new ModalClient();
|
|
75218
|
+
* const sandbox = await modal.sandboxes.fromId("sb-...");
|
|
75219
|
+
*
|
|
75220
|
+
* for await (const entry of sandbox.logs.tail({ entries: 20 })) {
|
|
75221
|
+
* process.stdout.write(entry.message);
|
|
75222
|
+
* }
|
|
75223
|
+
* ```
|
|
75224
|
+
*/
|
|
75225
|
+
async *tail(params = {}) {
|
|
75226
|
+
const [appId, taskId] = await Promise.all([
|
|
75227
|
+
this.getAppId(),
|
|
75228
|
+
this.getTaskId()
|
|
75229
|
+
]);
|
|
75230
|
+
if (!taskId) {
|
|
75231
|
+
throw new ExecutionError(
|
|
75232
|
+
"Sandbox task ID cannot be empty when fetching logs. Wait for the Sandbox to be scheduled."
|
|
75233
|
+
);
|
|
75234
|
+
}
|
|
75235
|
+
yield* tailLogs(this.client, params.entries ?? 100, {
|
|
75236
|
+
appId,
|
|
75237
|
+
objectId: this.sandboxId,
|
|
75238
|
+
taskId,
|
|
75239
|
+
source: sourceToFileDescriptor(params.source)
|
|
75240
|
+
});
|
|
75241
|
+
}
|
|
75242
|
+
};
|
|
74936
75243
|
|
|
74937
75244
|
// src/function_call.ts
|
|
74938
75245
|
var FunctionCallService = class {
|
|
@@ -75870,6 +76177,7 @@ var OutboundPolicy2 = class _OutboundPolicy {
|
|
|
75870
76177
|
SandboxFilesystemNotFoundError,
|
|
75871
76178
|
SandboxFilesystemPathAlreadyExistsError,
|
|
75872
76179
|
SandboxFilesystemPermissionError,
|
|
76180
|
+
SandboxLogsManager,
|
|
75873
76181
|
SandboxService,
|
|
75874
76182
|
SandboxSnapshot,
|
|
75875
76183
|
SandboxSnapshotService,
|