@cloudflare/sandbox 0.13.0-next.802.1 → 0.13.0-next.816.1
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 +7 -0
- package/dist/bridge/index.js +21 -12
- package/dist/bridge/index.js.map +1 -1
- package/dist/extensions/index.d.ts +2 -2
- package/dist/extensions/index.js +1 -1
- package/dist/{extensions-BKL2zqL4.js → extensions-038QzSIg.js} +5 -1
- package/dist/extensions-038QzSIg.js.map +1 -0
- package/dist/{filesystem-Y5aF3nmJ.d.ts → filesystem-Cd6xd_Pe.d.ts} +5 -1
- package/dist/filesystem-Cd6xd_Pe.d.ts.map +1 -0
- package/dist/git/index.d.ts +2 -2
- package/dist/git/index.js +1 -1
- package/dist/{index-DfXx3uZL.d.ts → index-Fbdwkfft.d.ts} +9 -3
- package/dist/index-Fbdwkfft.d.ts.map +1 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/interpreter/index.d.ts +2 -2
- package/dist/interpreter/index.js +1 -1
- package/dist/openai/index.d.ts +2 -2
- package/dist/opencode/index.d.ts +2 -2
- package/dist/opencode/index.js +1 -1
- package/dist/{sandbox-CaesWCLh.js → sandbox-CpelK4pU.js} +140 -51
- package/dist/sandbox-CpelK4pU.js.map +1 -0
- package/dist/{sandbox-CBkS3tGv.d.ts → sandbox-D1BoB5f7.d.ts} +2 -2
- package/dist/{sandbox-CBkS3tGv.d.ts.map → sandbox-D1BoB5f7.d.ts.map} +1 -1
- package/package.json +1 -1
- package/dist/extensions-BKL2zqL4.js.map +0 -1
- package/dist/filesystem-Y5aF3nmJ.d.ts.map +0 -1
- package/dist/index-DfXx3uZL.d.ts.map +0 -1
- package/dist/sandbox-CaesWCLh.js.map +0 -1
package/dist/openai/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../process-types-GStiZ8f8.js";
|
|
2
|
-
import "../filesystem-
|
|
3
|
-
import { t as ISandbox } from "../sandbox-
|
|
2
|
+
import "../filesystem-Cd6xd_Pe.js";
|
|
3
|
+
import { t as ISandbox } from "../sandbox-D1BoB5f7.js";
|
|
4
4
|
import { ApplyPatchOperation, ApplyPatchResult, Editor as Editor$1, Shell as Shell$1, ShellAction, ShellResult } from "@openai/agents";
|
|
5
5
|
|
|
6
6
|
//#region src/openai/index.d.ts
|
package/dist/opencode/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { D as OpenCodeStartupContext } from "../contexts-DNFVmC9N.js";
|
|
2
2
|
import "../process-types-GStiZ8f8.js";
|
|
3
|
-
import "../filesystem-
|
|
4
|
-
import { c as SandboxExtension, l as SandboxLike } from "../index-
|
|
3
|
+
import "../filesystem-Cd6xd_Pe.js";
|
|
4
|
+
import { c as SandboxExtension, l as SandboxLike } from "../index-Fbdwkfft.js";
|
|
5
5
|
import { OpencodeClient } from "@opencode-ai/sdk/v2/client";
|
|
6
6
|
import { Config } from "@opencode-ai/sdk/v2";
|
|
7
7
|
|
package/dist/opencode/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { i as ErrorCode } from "../errors-Bb3s6nBS.js";
|
|
2
2
|
import "../errors--yR3zLC_.js";
|
|
3
3
|
import { r as createLogger } from "../dist-n_eniPAR.js";
|
|
4
|
-
import { n as createExtensionProcessSandbox, t as SandboxExtension } from "../extensions-
|
|
4
|
+
import { n as createExtensionProcessSandbox, t as SandboxExtension } from "../extensions-038QzSIg.js";
|
|
5
5
|
|
|
6
6
|
//#region ../../extensions/opencode/src/client.ts
|
|
7
7
|
let createSDKClient;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { i as ErrorCode, n as getSuggestion, r as getHttpStatus } from "./errors-Bb3s6nBS.js";
|
|
2
2
|
import { $ as TerminalControlError, G as BackupRestoreError, H as BackupCreateError, Q as StaleTerminalHandleError, U as BackupExpiredError, W as BackupNotFoundError, X as OperationInterruptedError, Z as RPCTransportError, _ as StaleProcessHandleError, n as RuntimeIdentityInactiveError, p as ProcessNotFoundError, q as InvalidBackupConfigError, r as RuntimeControlProtocolError, t as createErrorFromResponse, tt as SandboxError, v as CustomDomainRequiredError } from "./errors--yR3zLC_.js";
|
|
3
3
|
import { a as TraceContext, d as partitionEnvVars, i as createNoOpLogger, o as logCanonicalEvent, r as createLogger, t as parseSSEFrames, u as getEnvString } from "./dist-n_eniPAR.js";
|
|
4
|
-
import { a as PullSubscriptionTarget, i as createSandboxProcess, o as openRemoteSubscription, r as sandboxRuntimeCall, s as translateRPCError, t as SandboxExtension } from "./extensions-
|
|
4
|
+
import { a as PullSubscriptionTarget, i as createSandboxProcess, o as openRemoteSubscription, r as sandboxRuntimeCall, s as translateRPCError, t as SandboxExtension } from "./extensions-038QzSIg.js";
|
|
5
5
|
import { Container, ContainerProxy, getContainer, switchPort } from "@cloudflare/containers";
|
|
6
6
|
import { RpcTarget } from "cloudflare:workers";
|
|
7
7
|
import { AwsClient } from "aws4fetch";
|
|
@@ -190,7 +190,7 @@ function isPlatformTransientError(error) {
|
|
|
190
190
|
|
|
191
191
|
//#endregion
|
|
192
192
|
//#region src/pty/proxy.ts
|
|
193
|
-
function terminalHandle(stub, snapshot, runtimeIncarnationID, outputProtocol = "stream") {
|
|
193
|
+
function terminalHandle(stub, snapshot, runtimeIncarnationID, outputProtocol = "stream", release = () => void 0) {
|
|
194
194
|
const id = snapshot.id;
|
|
195
195
|
return {
|
|
196
196
|
id,
|
|
@@ -211,7 +211,8 @@ function terminalHandle(stub, snapshot, runtimeIncarnationID, outputProtocol = "
|
|
|
211
211
|
...options,
|
|
212
212
|
runtimeIncarnationID
|
|
213
213
|
});
|
|
214
|
-
}
|
|
214
|
+
},
|
|
215
|
+
[Symbol.dispose]: release
|
|
215
216
|
};
|
|
216
217
|
}
|
|
217
218
|
function terminalHandleFromRPCDescriptor(descriptor, fetch$1) {
|
|
@@ -224,7 +225,7 @@ function terminalHandleFromRPCDescriptor(descriptor, fetch$1) {
|
|
|
224
225
|
interrupt: () => capability.interrupt(),
|
|
225
226
|
terminate: () => capability.terminate(),
|
|
226
227
|
fetch: fetch$1
|
|
227
|
-
}, descriptor.snapshot, descriptor.runtimeIncarnationID, "pull");
|
|
228
|
+
}, descriptor.snapshot, descriptor.runtimeIncarnationID, "pull", () => capability[Symbol.dispose]?.());
|
|
228
229
|
}
|
|
229
230
|
async function terminalOutput(stub, id, options, protocol) {
|
|
230
231
|
const { signal, ...rpcOptions } = options ?? {};
|
|
@@ -1530,16 +1531,53 @@ var ContainerProxy$1 = class extends ContainerProxy {
|
|
|
1530
1531
|
};
|
|
1531
1532
|
ContainerProxy$1.outboundHandlers = SDK_OUTBOUND_HANDLERS;
|
|
1532
1533
|
|
|
1534
|
+
//#endregion
|
|
1535
|
+
//#region src/storage-mount/outbound/params.ts
|
|
1536
|
+
function hasExcludedID(excludedIDs, mountId) {
|
|
1537
|
+
if (!excludedIDs) return false;
|
|
1538
|
+
for (const excludedID of excludedIDs) if (excludedID === mountId) return true;
|
|
1539
|
+
return false;
|
|
1540
|
+
}
|
|
1541
|
+
function buildR2EgressParams(mounts, options) {
|
|
1542
|
+
const buckets = {};
|
|
1543
|
+
for (const [, mountInfo] of mounts) if (mountInfo.mountType === "r2-egress" && mountInfo.mountId !== options?.excludeMountId && !hasExcludedID(options?.excludeMountIds, mountInfo.mountId)) buckets[mountInfo.bucket] = {
|
|
1544
|
+
prefix: mountInfo.prefix,
|
|
1545
|
+
readOnly: mountInfo.readOnly
|
|
1546
|
+
};
|
|
1547
|
+
return { buckets };
|
|
1548
|
+
}
|
|
1549
|
+
function buildS3CredentialProxyParams(mounts, options) {
|
|
1550
|
+
const params = {};
|
|
1551
|
+
const addMount = (mountInfo) => {
|
|
1552
|
+
if (!mountInfo.credentialProxy || mountInfo.mountId === options?.excludeMountId || hasExcludedID(options?.excludeMountIds, mountInfo.mountId)) return;
|
|
1553
|
+
params[mountInfo.mountId] = {
|
|
1554
|
+
endpoint: mountInfo.credentialProxy.endpoint,
|
|
1555
|
+
bucket: mountInfo.credentialProxy.bucket,
|
|
1556
|
+
...mountInfo.credentialProxy.prefix !== void 0 ? { prefix: mountInfo.credentialProxy.prefix } : {},
|
|
1557
|
+
credentials: mountInfo.credentialProxy.credentials,
|
|
1558
|
+
readOnly: mountInfo.credentialProxy.readOnly,
|
|
1559
|
+
provider: mountInfo.credentialProxy.provider,
|
|
1560
|
+
authStrategy: mountInfo.credentialProxy.authStrategy
|
|
1561
|
+
};
|
|
1562
|
+
};
|
|
1563
|
+
for (const [, mountInfo] of mounts) if (mountInfo.mountType === "fuse") addMount(mountInfo);
|
|
1564
|
+
if (options?.includeMount) addMount(options.includeMount);
|
|
1565
|
+
return { mounts: params };
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1533
1568
|
//#endregion
|
|
1534
1569
|
//#region src/storage-mount/outbound/index.ts
|
|
1535
1570
|
function isFetcher(value) {
|
|
1536
1571
|
return typeof value === "object" && value !== null && "fetch" in value && typeof value.fetch === "function";
|
|
1537
1572
|
}
|
|
1538
|
-
async function configureR2EgressOutbound(host,
|
|
1573
|
+
async function configureR2EgressOutbound(host, activeParams) {
|
|
1574
|
+
const params = { buckets: {
|
|
1575
|
+
...host.restoredMountRoutes.r2Buckets,
|
|
1576
|
+
...activeParams.buckets
|
|
1577
|
+
} };
|
|
1539
1578
|
const ctx = host.ctx;
|
|
1540
1579
|
if (!ctx.container?.interceptOutboundHttp) throw new InvalidMountConfigError("R2 binding mounts require container outbound interception support");
|
|
1541
1580
|
if (!ctx.exports?.ContainerProxy) throw new InvalidMountConfigError("R2 binding mounts require exporting ContainerProxy from the Worker entrypoint");
|
|
1542
|
-
installSDKOutboundHandlers(host.constructorRef);
|
|
1543
1581
|
if (Object.keys(params.buckets).length > 0) await host.setOutboundByHost("r2.internal", "r2EgressMount", params);
|
|
1544
1582
|
else await host.removeOutboundByHost("r2.internal");
|
|
1545
1583
|
host.logger.debug("r2 egress: registering host interception", {
|
|
@@ -1563,7 +1601,6 @@ async function configureGitAuthInterceptor(host, params) {
|
|
|
1563
1601
|
const ctx = host.ctx;
|
|
1564
1602
|
if (!ctx.container?.interceptOutboundHttp) throw new InvalidMountConfigError("Git extension authentication requires container outbound interception support");
|
|
1565
1603
|
if (!ctx.exports?.ContainerProxy) throw new InvalidMountConfigError("Git extension authentication requires exporting ContainerProxy from the Worker entrypoint. Import ContainerProxy from @cloudflare/sandbox and export it from your Worker to use git auth interception.");
|
|
1566
|
-
installSDKOutboundHandlers(host.constructorRef);
|
|
1567
1604
|
const hostOverrides = {};
|
|
1568
1605
|
for (const outboundHost of Object.keys(params.hosts)) {
|
|
1569
1606
|
hostOverrides[outboundHost] = {
|
|
@@ -1581,12 +1618,15 @@ async function configureGitAuthInterceptor(host, params) {
|
|
|
1581
1618
|
if (!isFetcher(fetcher)) throw new InvalidMountConfigError("Git extension authentication requires ContainerProxy to return a valid Fetcher");
|
|
1582
1619
|
for (const outboundHost of Object.keys(params.hosts)) await ctx.container.interceptOutboundHttp(outboundHost, fetcher);
|
|
1583
1620
|
}
|
|
1584
|
-
async function configureS3CredentialProxyOutbound(host,
|
|
1621
|
+
async function configureS3CredentialProxyOutbound(host, activeParams) {
|
|
1622
|
+
const params = { mounts: {
|
|
1623
|
+
...host.restoredMountRoutes.credentialProxyMounts,
|
|
1624
|
+
...activeParams.mounts
|
|
1625
|
+
} };
|
|
1585
1626
|
const ctx = host.ctx;
|
|
1586
1627
|
if (!ctx.container?.interceptOutboundHttp) throw new InvalidMountConfigError("Credential proxy bucket mounts require container outbound interception support");
|
|
1587
1628
|
if (!ctx.exports?.ContainerProxy) throw new InvalidMountConfigError("Credential proxy bucket mounts require exporting ContainerProxy from the Worker entrypoint");
|
|
1588
1629
|
const hosts = [S3_CREDENTIAL_PROXY_HOST, S3_CREDENTIAL_PROXY_DIAGNOSTIC_HOST];
|
|
1589
|
-
installSDKOutboundHandlers(host.constructorRef);
|
|
1590
1630
|
if (Object.keys(params.mounts).length > 0) for (const outboundHost of hosts) await host.setOutboundByHost(outboundHost, "s3CredentialProxyMount", params);
|
|
1591
1631
|
else for (const outboundHost of hosts) await host.removeOutboundByHost(outboundHost);
|
|
1592
1632
|
const hostOverrides = {};
|
|
@@ -1615,6 +1655,70 @@ async function configureS3CredentialProxyOutbound(host, params) {
|
|
|
1615
1655
|
}
|
|
1616
1656
|
for (const outboundHost of hosts) await ctx.container.interceptOutboundHttp(outboundHost, fetcher);
|
|
1617
1657
|
}
|
|
1658
|
+
/**
|
|
1659
|
+
* Drop the routes restored for the mounts of a container that has stopped.
|
|
1660
|
+
*/
|
|
1661
|
+
async function releaseRestoredMountRoutes(host, mounts) {
|
|
1662
|
+
const routes = host.restoredMountRoutes;
|
|
1663
|
+
for (const mountId of Object.keys(routes.credentialProxyMounts)) {
|
|
1664
|
+
evictSigV4ClientCacheEntry(mountId);
|
|
1665
|
+
evictDirectoryMarkerCacheForMount(mountId);
|
|
1666
|
+
}
|
|
1667
|
+
if (Object.keys(routes.r2Buckets).length > 0) routes.staleR2 = true;
|
|
1668
|
+
if (Object.keys(routes.credentialProxyMounts).length > 0) routes.staleCredentialProxy = true;
|
|
1669
|
+
routes.r2Buckets = {};
|
|
1670
|
+
routes.credentialProxyMounts = {};
|
|
1671
|
+
await removeStaleMountRoutes(host, mounts);
|
|
1672
|
+
}
|
|
1673
|
+
/**
|
|
1674
|
+
* Rewrite the routes that still carry a stopped container's restored mounts
|
|
1675
|
+
* so they cover only `mounts`. A failed update stays marked and is retried on
|
|
1676
|
+
* the next container start or stop.
|
|
1677
|
+
*/
|
|
1678
|
+
async function removeStaleMountRoutes(host, mounts) {
|
|
1679
|
+
const routes = host.restoredMountRoutes;
|
|
1680
|
+
if (routes.staleR2) try {
|
|
1681
|
+
await configureR2EgressOutbound(host, buildR2EgressParams(mounts));
|
|
1682
|
+
routes.staleR2 = false;
|
|
1683
|
+
} catch (error) {
|
|
1684
|
+
host.logger.warn("Failed to remove stale R2 mount routes", { error: error instanceof Error ? error.message : String(error) });
|
|
1685
|
+
}
|
|
1686
|
+
if (routes.staleCredentialProxy) try {
|
|
1687
|
+
await configureS3CredentialProxyOutbound(host, buildS3CredentialProxyParams(mounts));
|
|
1688
|
+
routes.staleCredentialProxy = false;
|
|
1689
|
+
} catch (error) {
|
|
1690
|
+
host.logger.warn("Failed to remove stale credential proxy mount routes", { error: error instanceof Error ? error.message : String(error) });
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
//#endregion
|
|
1695
|
+
//#region src/storage-mount/outbound/restored-routes.ts
|
|
1696
|
+
/**
|
|
1697
|
+
* Bucket mount routes restored from a previous instance of this Durable
|
|
1698
|
+
* Object. The mount registry starts empty after a restart, but s3fs mounts in
|
|
1699
|
+
* a container that kept running still send requests, so every route update
|
|
1700
|
+
* keeps these routes until onStop() reports that container stopped. The base
|
|
1701
|
+
* class reports a stop it missed before it starts a new container.
|
|
1702
|
+
*/
|
|
1703
|
+
var RestoredMountRoutes = class RestoredMountRoutes {
|
|
1704
|
+
r2Buckets = {};
|
|
1705
|
+
credentialProxyMounts = {};
|
|
1706
|
+
staleR2 = false;
|
|
1707
|
+
staleCredentialProxy = false;
|
|
1708
|
+
/**
|
|
1709
|
+
* Read the overrides the base Container restored from storage in its
|
|
1710
|
+
* constructor. `outboundByHostOverrides` is private in its types.
|
|
1711
|
+
*/
|
|
1712
|
+
static fromContainer(container) {
|
|
1713
|
+
const overrides = container.outboundByHostOverrides ?? {};
|
|
1714
|
+
const routes = new RestoredMountRoutes();
|
|
1715
|
+
const r2 = overrides["r2.internal"];
|
|
1716
|
+
if (r2?.method === "r2EgressMount") routes.r2Buckets = { ...r2.params?.buckets };
|
|
1717
|
+
const credentialProxy = overrides[S3_CREDENTIAL_PROXY_HOST];
|
|
1718
|
+
if (credentialProxy?.method === "s3CredentialProxyMount") routes.credentialProxyMounts = { ...credentialProxy.params?.mounts };
|
|
1719
|
+
return routes;
|
|
1720
|
+
}
|
|
1721
|
+
};
|
|
1618
1722
|
|
|
1619
1723
|
//#endregion
|
|
1620
1724
|
//#region src/storage-mount/registry.ts
|
|
@@ -1695,6 +1799,10 @@ function resolveS3fsOptions(provider, userOptions) {
|
|
|
1695
1799
|
//#endregion
|
|
1696
1800
|
//#region src/storage-mount/s3fs/support-files.ts
|
|
1697
1801
|
const S3FS_DISABLE_EXPECT_HEADER_CONFIG = " Expect:\n";
|
|
1802
|
+
async function writeOwnerOnlyFile(host, operation, path$1, content) {
|
|
1803
|
+
await host.runRuntimeCall(`mount.s3fs.write${operation}`, (control) => control.files.writeFile(path$1, content, { ownerOnly: true }));
|
|
1804
|
+
await host.runRuntimeCall(`mount.s3fs.chmod${operation}`, (control) => control.mounts.chmodOwnerOnly(path$1));
|
|
1805
|
+
}
|
|
1698
1806
|
function generatePasswordFilePath() {
|
|
1699
1807
|
return `/tmp/.passwd-s3fs-${crypto.randomUUID()}`;
|
|
1700
1808
|
}
|
|
@@ -1702,13 +1810,10 @@ function generateS3FSAdditionalHeaderFilePath() {
|
|
|
1702
1810
|
return `/tmp/.s3fs-ahbe-${crypto.randomUUID()}.conf`;
|
|
1703
1811
|
}
|
|
1704
1812
|
async function createDisableExpectHeaderFile(host, headerFilePath) {
|
|
1705
|
-
await host
|
|
1706
|
-
await host.runRuntimeCall("mount.s3fs.chmodHeaderFile", (control) => control.mounts.chmodOwnerOnly(headerFilePath));
|
|
1813
|
+
await writeOwnerOnlyFile(host, "HeaderFile", headerFilePath, S3FS_DISABLE_EXPECT_HEADER_CONFIG);
|
|
1707
1814
|
}
|
|
1708
1815
|
async function createPasswordFile(host, passwordFilePath, bucket, credentials) {
|
|
1709
|
-
|
|
1710
|
-
await host.runRuntimeCall("mount.s3fs.writePasswordFile", (control) => control.files.writeFile(passwordFilePath, content));
|
|
1711
|
-
await host.runRuntimeCall("mount.s3fs.chmodPasswordFile", (control) => control.mounts.chmodOwnerOnly(passwordFilePath));
|
|
1816
|
+
await writeOwnerOnlyFile(host, "PasswordFile", passwordFilePath, `${bucket}:${credentials.accessKeyId}:${credentials.secretAccessKey}`);
|
|
1712
1817
|
}
|
|
1713
1818
|
async function deletePasswordFile(host, passwordFilePath) {
|
|
1714
1819
|
try {
|
|
@@ -1794,40 +1899,6 @@ async function unmountTrackedFuseMount(host, mountPath, mountInfo) {
|
|
|
1794
1899
|
return true;
|
|
1795
1900
|
}
|
|
1796
1901
|
|
|
1797
|
-
//#endregion
|
|
1798
|
-
//#region src/storage-mount/outbound/params.ts
|
|
1799
|
-
function hasExcludedID(excludedIDs, mountId) {
|
|
1800
|
-
if (!excludedIDs) return false;
|
|
1801
|
-
for (const excludedID of excludedIDs) if (excludedID === mountId) return true;
|
|
1802
|
-
return false;
|
|
1803
|
-
}
|
|
1804
|
-
function buildR2EgressParams(mounts, options) {
|
|
1805
|
-
const buckets = {};
|
|
1806
|
-
for (const [, mountInfo] of mounts) if (mountInfo.mountType === "r2-egress" && mountInfo.mountId !== options?.excludeMountId && !hasExcludedID(options?.excludeMountIds, mountInfo.mountId)) buckets[mountInfo.bucket] = {
|
|
1807
|
-
prefix: mountInfo.prefix,
|
|
1808
|
-
readOnly: mountInfo.readOnly
|
|
1809
|
-
};
|
|
1810
|
-
return { buckets };
|
|
1811
|
-
}
|
|
1812
|
-
function buildS3CredentialProxyParams(mounts, options) {
|
|
1813
|
-
const params = {};
|
|
1814
|
-
const addMount = (mountInfo) => {
|
|
1815
|
-
if (!mountInfo.credentialProxy || mountInfo.mountId === options?.excludeMountId || hasExcludedID(options?.excludeMountIds, mountInfo.mountId)) return;
|
|
1816
|
-
params[mountInfo.mountId] = {
|
|
1817
|
-
endpoint: mountInfo.credentialProxy.endpoint,
|
|
1818
|
-
bucket: mountInfo.credentialProxy.bucket,
|
|
1819
|
-
...mountInfo.credentialProxy.prefix !== void 0 ? { prefix: mountInfo.credentialProxy.prefix } : {},
|
|
1820
|
-
credentials: mountInfo.credentialProxy.credentials,
|
|
1821
|
-
readOnly: mountInfo.credentialProxy.readOnly,
|
|
1822
|
-
provider: mountInfo.credentialProxy.provider,
|
|
1823
|
-
authStrategy: mountInfo.credentialProxy.authStrategy
|
|
1824
|
-
};
|
|
1825
|
-
};
|
|
1826
|
-
for (const [, mountInfo] of mounts) if (mountInfo.mountType === "fuse") addMount(mountInfo);
|
|
1827
|
-
if (options?.includeMount) addMount(options.includeMount);
|
|
1828
|
-
return { mounts: params };
|
|
1829
|
-
}
|
|
1830
|
-
|
|
1831
1902
|
//#endregion
|
|
1832
1903
|
//#region src/storage-mount/lifecycle-cleanup.ts
|
|
1833
1904
|
async function cleanupBucketMountsForDestroy(host) {
|
|
@@ -1895,6 +1966,7 @@ async function cleanupBucketMountsForDestroy(host) {
|
|
|
1895
1966
|
}
|
|
1896
1967
|
async function cleanupBucketMountsForStop(host) {
|
|
1897
1968
|
return host.runMountOperation(async () => {
|
|
1969
|
+
await releaseRestoredMountRoutes(host.getOutboundHost(), host.registry);
|
|
1898
1970
|
let hadR2EgressMount = false;
|
|
1899
1971
|
let hadCredentialProxyMount = false;
|
|
1900
1972
|
for (const [, mountInfo] of host.registry) if (mountInfo.mountType === "local-sync") mountInfo.syncManager.interrupt();
|
|
@@ -2510,6 +2582,8 @@ function validateR2EgressMount(context, bucket, mountPath, options) {
|
|
|
2510
2582
|
validateBucketBindingName(bucket, mountPath);
|
|
2511
2583
|
validateMountPath(context.registry.activeMounts, mountPath);
|
|
2512
2584
|
validateProtectedS3fsOptions(options.s3fsOptions, "R2 binding");
|
|
2585
|
+
const restoredRoute = context.getOutboundHost().restoredMountRoutes.r2Buckets[bucket];
|
|
2586
|
+
if (restoredRoute && (restoredRoute.prefix !== prefix || (restoredRoute.readOnly ?? false) !== (options.readOnly ?? false))) throw new InvalidMountConfigError(`R2 binding "${bucket}" is already mounted with a different prefix or readOnly setting. Mount the same binding only once, or use the same settings for additional mounts.`);
|
|
2513
2587
|
for (const [existingMountPath, existingMount] of context.registry) {
|
|
2514
2588
|
if (existingMount.mountType === "r2-egress" && existingMount.bucket === bucket && existingMount.prefix !== prefix) throw new InvalidMountConfigError(`R2 binding "${bucket}" is already mounted at ${existingMountPath} with a different prefix. Mount the same binding only once, or use the same prefix for additional mounts.`);
|
|
2515
2589
|
if (existingMount.mountType === "r2-egress" && existingMount.bucket === bucket && existingMount.readOnly !== (options.readOnly ?? false)) throw new InvalidMountConfigError(`R2 binding "${bucket}" is already mounted at ${existingMountPath} with a different readOnly setting. Mount the same binding only once, or use the same readOnly value for additional mounts.`);
|
|
@@ -2977,7 +3051,10 @@ var BucketMountService = class {
|
|
|
2977
3051
|
});
|
|
2978
3052
|
}
|
|
2979
3053
|
async mountBucketR2Egress(bucket, mountPath, options) {
|
|
2980
|
-
validateR2EgressMount({
|
|
3054
|
+
validateR2EgressMount({
|
|
3055
|
+
registry: this.registry,
|
|
3056
|
+
getOutboundHost: () => this.deps.getOutboundHost()
|
|
3057
|
+
}, bucket, mountPath, options);
|
|
2981
3058
|
await this.deps.runMountAttempt("mount.r2-egress", async (lease) => {
|
|
2982
3059
|
const runRuntimeCall = callWithMountControl(lease.control);
|
|
2983
3060
|
await mountR2EgressBucket({
|
|
@@ -3092,6 +3169,14 @@ var BucketMountService = class {
|
|
|
3092
3169
|
runMountOperation: (operation) => operation()
|
|
3093
3170
|
});
|
|
3094
3171
|
}
|
|
3172
|
+
/**
|
|
3173
|
+
* Retry removing a stopped container's restored mount routes. Runs outside
|
|
3174
|
+
* the mount operation queue because a queued mount can be what started the
|
|
3175
|
+
* container.
|
|
3176
|
+
*/
|
|
3177
|
+
async removeStaleRoutes() {
|
|
3178
|
+
await removeStaleMountRoutes(this.deps.getOutboundHost(), this.registry);
|
|
3179
|
+
}
|
|
3095
3180
|
async cleanupForStop() {
|
|
3096
3181
|
return cleanupBucketMountsForStop({
|
|
3097
3182
|
registry: this.registry,
|
|
@@ -8886,6 +8971,7 @@ var Sandbox = class extends Container {
|
|
|
8886
8971
|
logger;
|
|
8887
8972
|
keepAliveEnabled = false;
|
|
8888
8973
|
bucketMounts;
|
|
8974
|
+
restoredMountRoutes;
|
|
8889
8975
|
currentLifetime;
|
|
8890
8976
|
backupService;
|
|
8891
8977
|
previewService;
|
|
@@ -8954,7 +9040,9 @@ var Sandbox = class extends Container {
|
|
|
8954
9040
|
return stub;
|
|
8955
9041
|
}
|
|
8956
9042
|
constructor(ctx, env$1) {
|
|
9043
|
+
if (ctx.exports?.ContainerProxy) installSDKOutboundHandlers(new.target);
|
|
8957
9044
|
super(ctx, env$1);
|
|
9045
|
+
this.restoredMountRoutes = RestoredMountRoutes.fromContainer(this);
|
|
8958
9046
|
const envObj = env$1;
|
|
8959
9047
|
["SANDBOX_LOG_LEVEL", "SANDBOX_LOG_FORMAT"].forEach((key) => {
|
|
8960
9048
|
if (envObj?.[key]) this.envVars[key] = String(envObj[key]);
|
|
@@ -9327,6 +9415,7 @@ var Sandbox = class extends Container {
|
|
|
9327
9415
|
async onStart() {
|
|
9328
9416
|
const replacementStartTransitionCompleted = this.runtimeLifecycle.markRuntimeStarted();
|
|
9329
9417
|
this.logger.debug("Sandbox started", { replacementStartTransitionCompleted });
|
|
9418
|
+
await this.bucketMounts.removeStaleRoutes();
|
|
9330
9419
|
}
|
|
9331
9420
|
async start(options) {
|
|
9332
9421
|
await this.runtimeRunner.runWaking("runtime.start", async () => void 0, { startOptions: options });
|
|
@@ -10191,7 +10280,7 @@ var Sandbox = class extends Container {
|
|
|
10191
10280
|
getMountOutboundHost() {
|
|
10192
10281
|
return {
|
|
10193
10282
|
ctx: this.ctx,
|
|
10194
|
-
|
|
10283
|
+
restoredMountRoutes: this.restoredMountRoutes,
|
|
10195
10284
|
enableInternet: this.enableInternet,
|
|
10196
10285
|
logger: this.logger,
|
|
10197
10286
|
setOutboundByHost: (host, method, params) => this.setOutboundByHost(host, method, params),
|
|
@@ -10202,4 +10291,4 @@ var Sandbox = class extends Container {
|
|
|
10202
10291
|
|
|
10203
10292
|
//#endregion
|
|
10204
10293
|
export { proxyTerminal as _, responseToAsyncIterable as a, collectFile as b, BucketUnmountError as c, S3FSMountError as d, parsePreviewRoute as f, validateTunnelName as g, validatePort as h, parseSSEStream as i, InvalidMountConfigError as l, SandboxSecurityError as m, getSandbox as n, ContainerProxy$1 as o, withPreviewProxyMetadata as p, asyncIterableToSSEStream as r, BucketMountError as s, Sandbox as t, MissingCredentialsError as u, isDurableObjectCodeUpdateReset as v, streamFile as x, isPlatformTransientError as y };
|
|
10205
|
-
//# sourceMappingURL=sandbox-
|
|
10294
|
+
//# sourceMappingURL=sandbox-CpelK4pU.js.map
|