@boxes-dev/dvb 1.0.78 → 1.0.79
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/bin/dvb.cjs +600 -533
- package/dist/bin/dvb.cjs.map +1 -1
- package/dist/bin/dvbd.cjs +5 -5
- package/dist/devbox/commands/provider/modalLifecycle.d.ts +3 -1
- package/dist/devbox/commands/provider/modalLifecycle.d.ts.map +1 -1
- package/dist/devbox/commands/provider/modalLifecycle.js +63 -6
- package/dist/devbox/commands/provider/modalLifecycle.js.map +1 -1
- package/dist/devbox/commands/provider/modalRuntime.d.ts.map +1 -1
- package/dist/devbox/commands/provider/modalRuntime.js +6 -1
- package/dist/devbox/commands/provider/modalRuntime.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/dvb.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="b785e941-0159-5a32-9ac9-c3686e30d3af")}catch(e){}}();
|
|
4
4
|
|
|
5
5
|
var __create = Object.create;
|
|
6
6
|
var __defProp = Object.defineProperty;
|
|
@@ -88688,8 +88688,8 @@ var init_otel = __esm({
|
|
|
88688
88688
|
return trimmed && trimmed.length > 0 ? trimmed : void 0;
|
|
88689
88689
|
};
|
|
88690
88690
|
readBuildMetadata = () => {
|
|
88691
|
-
const rawPackageVersion = "1.0.
|
|
88692
|
-
const rawGitSha = "
|
|
88691
|
+
const rawPackageVersion = "1.0.79";
|
|
88692
|
+
const rawGitSha = "ceaceb54444acf1719c1f5fc72074b5048324e4a";
|
|
88693
88693
|
const packageVersion = typeof rawPackageVersion === "string" ? rawPackageVersion : void 0;
|
|
88694
88694
|
const gitSha = typeof rawGitSha === "string" ? rawGitSha : void 0;
|
|
88695
88695
|
return { packageVersion, gitSha };
|
|
@@ -120679,9 +120679,9 @@ var init_sentry = __esm({
|
|
|
120679
120679
|
sentryEnabled = false;
|
|
120680
120680
|
uncaughtExceptionMonitorInstalled = false;
|
|
120681
120681
|
readBuildMetadata2 = () => {
|
|
120682
|
-
const rawPackageVersion = "1.0.
|
|
120683
|
-
const rawGitSha = "
|
|
120684
|
-
const rawSentryRelease = "boxes-dev-dvb@1.0.
|
|
120682
|
+
const rawPackageVersion = "1.0.79";
|
|
120683
|
+
const rawGitSha = "ceaceb54444acf1719c1f5fc72074b5048324e4a";
|
|
120684
|
+
const rawSentryRelease = "boxes-dev-dvb@1.0.79+ceaceb54444acf1719c1f5fc72074b5048324e4a";
|
|
120685
120685
|
const packageVersion = typeof rawPackageVersion === "string" ? rawPackageVersion : void 0;
|
|
120686
120686
|
const gitSha = typeof rawGitSha === "string" ? rawGitSha : void 0;
|
|
120687
120687
|
const sentryRelease = typeof rawSentryRelease === "string" ? rawSentryRelease : void 0;
|
|
@@ -198481,6 +198481,592 @@ ${result.exception}`
|
|
|
198481
198481
|
}
|
|
198482
198482
|
});
|
|
198483
198483
|
|
|
198484
|
+
// src/devbox/commands/provider/modalLifecycle.ts
|
|
198485
|
+
var import_node_crypto9, DEFAULT_APP_NAME, DEFAULT_MODAL_ENVIRONMENT, DEFAULT_MODAL_DEVBOX_IMAGE, DEFAULT_TIMEOUT_MS, IMAGE_TAG_RESOLUTION_CACHE_TTL_MS, SANDBOX_LIST_PAGE_LIMIT, MODAL_DAEMON_WRAPPER_PATH, MODAL_DAEMON_SUPERVISOR_ENTRYPOINT, FINISHED_STATUS_LABELS, REGISTRY_MANIFEST_ACCEPT_HEADER, resolvedImageTagCache, trimEnv2, EMBEDDED_BUILD_PROFILE, resolveModalEnvironmentName, resolveConvexInstanceSeed, resolveDevModalSandboxPrefix, resolveModalSandboxName, parseRegistryImageTag, parseWwwAuthenticateBearer, fetchRegistryToken, resolveLatestImageTagToDigest, resolveImageTagForBuild, decodeJwtExpMs, createSafeModalAuthTokenManager, installSafeModalAuthTokenManager, parsePositiveInt, resolveRegions, resolveAppName, resolveModalSandboxTimeoutMs, isNotFoundError, isModalAlreadyExistsError, trimToNull, resolveControlPlaneToken, hasContextModalCredentialPair, shouldUseControlPlaneFallback, withModalClient, resolveModalApp, listSandboxesRaw, formatSandboxStatus, isRunningSandbox, resolveImageFromTag, provisionModalSandbox, findModalSandbox, terminateModalSandboxesByAlias;
|
|
198486
|
+
var init_modalLifecycle = __esm({
|
|
198487
|
+
"src/devbox/commands/provider/modalLifecycle.ts"() {
|
|
198488
|
+
"use strict";
|
|
198489
|
+
init_src();
|
|
198490
|
+
import_node_crypto9 = require("node:crypto");
|
|
198491
|
+
init_dist5();
|
|
198492
|
+
init_controlPlane();
|
|
198493
|
+
DEFAULT_APP_NAME = "sandbox-modal-smoke";
|
|
198494
|
+
DEFAULT_MODAL_ENVIRONMENT = "main";
|
|
198495
|
+
DEFAULT_MODAL_DEVBOX_IMAGE = "public.ecr.aws/d8m4p4w9/modal-devbox:latest";
|
|
198496
|
+
DEFAULT_TIMEOUT_MS = 24 * 60 * 60 * 1e3;
|
|
198497
|
+
IMAGE_TAG_RESOLUTION_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
198498
|
+
SANDBOX_LIST_PAGE_LIMIT = 100;
|
|
198499
|
+
MODAL_DAEMON_WRAPPER_PATH = "/root/.devbox/daemon/run-daemon.sh";
|
|
198500
|
+
MODAL_DAEMON_SUPERVISOR_ENTRYPOINT = [
|
|
198501
|
+
"/bin/sh",
|
|
198502
|
+
"-lc",
|
|
198503
|
+
[
|
|
198504
|
+
"set -u",
|
|
198505
|
+
`wrapper=${JSON.stringify(MODAL_DAEMON_WRAPPER_PATH)}`,
|
|
198506
|
+
'until [ -x "$wrapper" ]; do sleep 0.25; done',
|
|
198507
|
+
"while true; do",
|
|
198508
|
+
' "$wrapper"',
|
|
198509
|
+
" status=$?",
|
|
198510
|
+
' echo "sprite-daemon exited with status $status; restarting" >&2',
|
|
198511
|
+
" sleep 1",
|
|
198512
|
+
"done"
|
|
198513
|
+
].join("\n")
|
|
198514
|
+
];
|
|
198515
|
+
FINISHED_STATUS_LABELS = {
|
|
198516
|
+
1: "success",
|
|
198517
|
+
2: "failure",
|
|
198518
|
+
3: "terminated",
|
|
198519
|
+
4: "timeout",
|
|
198520
|
+
5: "init_failure",
|
|
198521
|
+
6: "internal_failure",
|
|
198522
|
+
7: "idle_timeout"
|
|
198523
|
+
};
|
|
198524
|
+
REGISTRY_MANIFEST_ACCEPT_HEADER = [
|
|
198525
|
+
"application/vnd.oci.image.index.v1+json",
|
|
198526
|
+
"application/vnd.oci.image.manifest.v1+json",
|
|
198527
|
+
"application/vnd.docker.distribution.manifest.list.v2+json",
|
|
198528
|
+
"application/vnd.docker.distribution.manifest.v2+json"
|
|
198529
|
+
].join(", ");
|
|
198530
|
+
resolvedImageTagCache = /* @__PURE__ */ new Map();
|
|
198531
|
+
trimEnv2 = (value) => value?.trim() ?? "";
|
|
198532
|
+
EMBEDDED_BUILD_PROFILE = resolveDevboxProfile();
|
|
198533
|
+
resolveModalEnvironmentName = () => {
|
|
198534
|
+
if (!EMBEDDED_BUILD_PROFILE) {
|
|
198535
|
+
return DEFAULT_MODAL_ENVIRONMENT;
|
|
198536
|
+
}
|
|
198537
|
+
return trimEnv2(process.env.MODAL_ENVIRONMENT) || "dev";
|
|
198538
|
+
};
|
|
198539
|
+
resolveConvexInstanceSeed = () => {
|
|
198540
|
+
const candidates = [
|
|
198541
|
+
trimEnv2(process.env.DEVBOX_CONVEX_URL),
|
|
198542
|
+
trimEnv2(process.env.CONVEX_CLOUD_URL),
|
|
198543
|
+
trimEnv2(process.env.CONVEX_SITE_URL)
|
|
198544
|
+
].filter((value) => value.length > 0);
|
|
198545
|
+
const raw = candidates[0];
|
|
198546
|
+
if (!raw) {
|
|
198547
|
+
return null;
|
|
198548
|
+
}
|
|
198549
|
+
let normalized = raw;
|
|
198550
|
+
if (normalized.startsWith("dev:")) {
|
|
198551
|
+
normalized = normalized.slice(4);
|
|
198552
|
+
}
|
|
198553
|
+
if (normalized.includes(".convex.site")) {
|
|
198554
|
+
normalized = normalized.replace(".convex.site", ".convex.cloud");
|
|
198555
|
+
}
|
|
198556
|
+
if (!normalized.startsWith("http://") && !normalized.startsWith("https://")) {
|
|
198557
|
+
normalized = `https://${normalized}`;
|
|
198558
|
+
}
|
|
198559
|
+
try {
|
|
198560
|
+
return new URL(normalized).host.toLowerCase();
|
|
198561
|
+
} catch {
|
|
198562
|
+
return normalized.toLowerCase();
|
|
198563
|
+
}
|
|
198564
|
+
};
|
|
198565
|
+
resolveDevModalSandboxPrefix = () => {
|
|
198566
|
+
const seed = resolveConvexInstanceSeed();
|
|
198567
|
+
if (!seed) {
|
|
198568
|
+
throw new Error(
|
|
198569
|
+
"Missing Convex deployment URL context for MODAL_ENVIRONMENT=dev. Set DEVBOX_CONVEX_URL or CONVEX_CLOUD_URL."
|
|
198570
|
+
);
|
|
198571
|
+
}
|
|
198572
|
+
return (0, import_node_crypto9.createHash)("sha256").update(seed).digest("hex").slice(0, 8);
|
|
198573
|
+
};
|
|
198574
|
+
resolveModalSandboxName = (alias, environmentName) => {
|
|
198575
|
+
const normalizedAlias = alias.trim();
|
|
198576
|
+
if (!normalizedAlias) {
|
|
198577
|
+
throw new Error("Modal alias is required.");
|
|
198578
|
+
}
|
|
198579
|
+
if (environmentName !== "dev") {
|
|
198580
|
+
return normalizedAlias;
|
|
198581
|
+
}
|
|
198582
|
+
return `${resolveDevModalSandboxPrefix()}-${normalizedAlias}`;
|
|
198583
|
+
};
|
|
198584
|
+
parseRegistryImageTag = (imageTag) => {
|
|
198585
|
+
const trimmed = imageTag.trim();
|
|
198586
|
+
if (!trimmed || trimmed.includes("@")) {
|
|
198587
|
+
return null;
|
|
198588
|
+
}
|
|
198589
|
+
const lastSlashIndex = trimmed.lastIndexOf("/");
|
|
198590
|
+
const lastColonIndex = trimmed.lastIndexOf(":");
|
|
198591
|
+
if (lastColonIndex <= lastSlashIndex) {
|
|
198592
|
+
return null;
|
|
198593
|
+
}
|
|
198594
|
+
const repositoryWithHost = trimmed.slice(0, lastColonIndex);
|
|
198595
|
+
const tag = trimmed.slice(lastColonIndex + 1).trim();
|
|
198596
|
+
if (!repositoryWithHost || !tag) {
|
|
198597
|
+
return null;
|
|
198598
|
+
}
|
|
198599
|
+
const firstSlashIndex = repositoryWithHost.indexOf("/");
|
|
198600
|
+
if (firstSlashIndex <= 0) {
|
|
198601
|
+
return null;
|
|
198602
|
+
}
|
|
198603
|
+
const registryHost = repositoryWithHost.slice(0, firstSlashIndex);
|
|
198604
|
+
const repository = repositoryWithHost.slice(firstSlashIndex + 1);
|
|
198605
|
+
if (!repository) {
|
|
198606
|
+
return null;
|
|
198607
|
+
}
|
|
198608
|
+
const hasExplicitRegistryHost = registryHost.includes(".") || registryHost.includes(":") || registryHost === "localhost";
|
|
198609
|
+
if (!hasExplicitRegistryHost) {
|
|
198610
|
+
return null;
|
|
198611
|
+
}
|
|
198612
|
+
return {
|
|
198613
|
+
registryHost,
|
|
198614
|
+
repository,
|
|
198615
|
+
tag,
|
|
198616
|
+
repositoryWithHost
|
|
198617
|
+
};
|
|
198618
|
+
};
|
|
198619
|
+
parseWwwAuthenticateBearer = (headerValue) => {
|
|
198620
|
+
const trimmed = headerValue.trim();
|
|
198621
|
+
if (!trimmed.toLowerCase().startsWith("bearer ")) {
|
|
198622
|
+
return null;
|
|
198623
|
+
}
|
|
198624
|
+
const attributes = /* @__PURE__ */ new Map();
|
|
198625
|
+
for (const match2 of trimmed.slice("bearer ".length).matchAll(/([A-Za-z0-9_-]+)="([^"]*)"/g)) {
|
|
198626
|
+
const [, key, value] = match2;
|
|
198627
|
+
if (!key) {
|
|
198628
|
+
continue;
|
|
198629
|
+
}
|
|
198630
|
+
attributes.set(key.toLowerCase(), value ?? "");
|
|
198631
|
+
}
|
|
198632
|
+
const realm = attributes.get("realm");
|
|
198633
|
+
const service = attributes.get("service");
|
|
198634
|
+
const scope = attributes.get("scope");
|
|
198635
|
+
if (!realm || !service) {
|
|
198636
|
+
return null;
|
|
198637
|
+
}
|
|
198638
|
+
return {
|
|
198639
|
+
realm,
|
|
198640
|
+
service,
|
|
198641
|
+
scope: scope || null
|
|
198642
|
+
};
|
|
198643
|
+
};
|
|
198644
|
+
fetchRegistryToken = async ({
|
|
198645
|
+
realm,
|
|
198646
|
+
service,
|
|
198647
|
+
scope
|
|
198648
|
+
}) => {
|
|
198649
|
+
const tokenUrl = new URL(realm);
|
|
198650
|
+
tokenUrl.searchParams.set("service", service);
|
|
198651
|
+
if (scope) {
|
|
198652
|
+
tokenUrl.searchParams.set("scope", scope);
|
|
198653
|
+
}
|
|
198654
|
+
const response = await fetch(tokenUrl.toString());
|
|
198655
|
+
if (!response.ok) {
|
|
198656
|
+
throw new Error(
|
|
198657
|
+
`Container registry auth token request failed (${response.status}).`
|
|
198658
|
+
);
|
|
198659
|
+
}
|
|
198660
|
+
const payload = await response.json();
|
|
198661
|
+
const token = typeof payload.token === "string" ? payload.token.trim() : typeof payload.access_token === "string" ? payload.access_token.trim() : "";
|
|
198662
|
+
if (!token) {
|
|
198663
|
+
throw new Error("Container registry auth token response was empty.");
|
|
198664
|
+
}
|
|
198665
|
+
return token;
|
|
198666
|
+
};
|
|
198667
|
+
resolveLatestImageTagToDigest = async (parsed) => {
|
|
198668
|
+
const manifestUrl = `https://${parsed.registryHost}/v2/${parsed.repository}/manifests/${encodeURIComponent(parsed.tag)}`;
|
|
198669
|
+
const fetchManifest = async ({
|
|
198670
|
+
method,
|
|
198671
|
+
token: token2
|
|
198672
|
+
}) => {
|
|
198673
|
+
const headers = {
|
|
198674
|
+
Accept: REGISTRY_MANIFEST_ACCEPT_HEADER
|
|
198675
|
+
};
|
|
198676
|
+
if (token2) {
|
|
198677
|
+
headers.Authorization = `Bearer ${token2}`;
|
|
198678
|
+
}
|
|
198679
|
+
return await fetch(manifestUrl, {
|
|
198680
|
+
headers,
|
|
198681
|
+
method
|
|
198682
|
+
});
|
|
198683
|
+
};
|
|
198684
|
+
let token = null;
|
|
198685
|
+
let headResponse = await fetchManifest({ method: "HEAD" });
|
|
198686
|
+
if (headResponse.status === 401) {
|
|
198687
|
+
const authHeader = headResponse.headers.get("www-authenticate") ?? "";
|
|
198688
|
+
const challenge = parseWwwAuthenticateBearer(authHeader);
|
|
198689
|
+
if (!challenge) {
|
|
198690
|
+
throw new Error(
|
|
198691
|
+
`Container registry auth challenge missing or invalid for ${parsed.repositoryWithHost}:${parsed.tag}.`
|
|
198692
|
+
);
|
|
198693
|
+
}
|
|
198694
|
+
token = await fetchRegistryToken(challenge);
|
|
198695
|
+
headResponse = await fetchManifest({
|
|
198696
|
+
method: "HEAD",
|
|
198697
|
+
token
|
|
198698
|
+
});
|
|
198699
|
+
}
|
|
198700
|
+
if (!headResponse.ok) {
|
|
198701
|
+
throw new Error(
|
|
198702
|
+
`Container registry manifest lookup failed for ${parsed.repositoryWithHost}:${parsed.tag} (${headResponse.status}).`
|
|
198703
|
+
);
|
|
198704
|
+
}
|
|
198705
|
+
const headDigest = headResponse.headers.get("docker-content-digest")?.trim();
|
|
198706
|
+
if (headDigest) {
|
|
198707
|
+
return `${parsed.repositoryWithHost}@${headDigest}`;
|
|
198708
|
+
}
|
|
198709
|
+
const getResponse = await fetchManifest(
|
|
198710
|
+
token ? {
|
|
198711
|
+
method: "GET",
|
|
198712
|
+
token
|
|
198713
|
+
} : {
|
|
198714
|
+
method: "GET"
|
|
198715
|
+
}
|
|
198716
|
+
);
|
|
198717
|
+
if (!getResponse.ok) {
|
|
198718
|
+
throw new Error(
|
|
198719
|
+
`Container registry manifest body lookup failed for ${parsed.repositoryWithHost}:${parsed.tag} (${getResponse.status}).`
|
|
198720
|
+
);
|
|
198721
|
+
}
|
|
198722
|
+
const headerDigest = getResponse.headers.get("docker-content-digest")?.trim();
|
|
198723
|
+
if (headerDigest) {
|
|
198724
|
+
return `${parsed.repositoryWithHost}@${headerDigest}`;
|
|
198725
|
+
}
|
|
198726
|
+
const manifestBytes = Buffer.from(await getResponse.arrayBuffer());
|
|
198727
|
+
const bodyDigest = `sha256:${(0, import_node_crypto9.createHash)("sha256").update(manifestBytes).digest("hex")}`;
|
|
198728
|
+
return `${parsed.repositoryWithHost}@${bodyDigest}`;
|
|
198729
|
+
};
|
|
198730
|
+
resolveImageTagForBuild = async (imageTag) => {
|
|
198731
|
+
const parsed = parseRegistryImageTag(imageTag);
|
|
198732
|
+
if (!parsed || parsed.tag !== "latest") {
|
|
198733
|
+
return imageTag;
|
|
198734
|
+
}
|
|
198735
|
+
const cacheKey = `${parsed.repositoryWithHost}:${parsed.tag}`;
|
|
198736
|
+
const now = Date.now();
|
|
198737
|
+
const cached = resolvedImageTagCache.get(cacheKey);
|
|
198738
|
+
if (cached && cached.expiresAt > now) {
|
|
198739
|
+
return cached.value;
|
|
198740
|
+
}
|
|
198741
|
+
const resolved = await resolveLatestImageTagToDigest(parsed);
|
|
198742
|
+
resolvedImageTagCache.set(cacheKey, {
|
|
198743
|
+
value: resolved,
|
|
198744
|
+
expiresAt: now + IMAGE_TAG_RESOLUTION_CACHE_TTL_MS
|
|
198745
|
+
});
|
|
198746
|
+
return resolved;
|
|
198747
|
+
};
|
|
198748
|
+
decodeJwtExpMs = (token) => {
|
|
198749
|
+
const segments = token.split(".");
|
|
198750
|
+
if (segments.length < 2) return null;
|
|
198751
|
+
const payload = segments[1];
|
|
198752
|
+
if (!payload) return null;
|
|
198753
|
+
const normalized = payload.replace(/-/g, "+").replace(/_/g, "/");
|
|
198754
|
+
const padLength = (4 - normalized.length % 4) % 4;
|
|
198755
|
+
const padded = `${normalized}${"=".repeat(padLength)}`;
|
|
198756
|
+
try {
|
|
198757
|
+
const parsed = JSON.parse(
|
|
198758
|
+
Buffer.from(padded, "base64").toString("utf8")
|
|
198759
|
+
);
|
|
198760
|
+
const exp = parsed.exp;
|
|
198761
|
+
if (typeof exp !== "number" || !Number.isFinite(exp) || exp <= 0) {
|
|
198762
|
+
return null;
|
|
198763
|
+
}
|
|
198764
|
+
return Math.floor(exp * 1e3);
|
|
198765
|
+
} catch {
|
|
198766
|
+
return null;
|
|
198767
|
+
}
|
|
198768
|
+
};
|
|
198769
|
+
createSafeModalAuthTokenManager = (modal) => {
|
|
198770
|
+
let token = "";
|
|
198771
|
+
let tokenExpMs = 0;
|
|
198772
|
+
let inFlight = null;
|
|
198773
|
+
const TOKEN_REFRESH_SKEW_MS = 3e4;
|
|
198774
|
+
const FALLBACK_TOKEN_TTL_MS = 15 * 60 * 1e3;
|
|
198775
|
+
const hasFreshToken = () => token.length > 0 && Date.now() + TOKEN_REFRESH_SKEW_MS < tokenExpMs;
|
|
198776
|
+
const fetchToken = async () => {
|
|
198777
|
+
const authTokenGet = modal.cpClient.authTokenGet;
|
|
198778
|
+
if (typeof authTokenGet !== "function") {
|
|
198779
|
+
throw new Error("Modal auth token endpoint unavailable.");
|
|
198780
|
+
}
|
|
198781
|
+
const response = await authTokenGet({});
|
|
198782
|
+
const nextToken = typeof response?.token === "string" ? response.token.trim() : "";
|
|
198783
|
+
if (!nextToken) {
|
|
198784
|
+
throw new Error("Modal auth token unavailable.");
|
|
198785
|
+
}
|
|
198786
|
+
token = nextToken;
|
|
198787
|
+
tokenExpMs = decodeJwtExpMs(nextToken) ?? Date.now() + FALLBACK_TOKEN_TTL_MS;
|
|
198788
|
+
return nextToken;
|
|
198789
|
+
};
|
|
198790
|
+
return {
|
|
198791
|
+
start: () => {
|
|
198792
|
+
},
|
|
198793
|
+
stop: () => {
|
|
198794
|
+
token = "";
|
|
198795
|
+
tokenExpMs = 0;
|
|
198796
|
+
inFlight = null;
|
|
198797
|
+
},
|
|
198798
|
+
getToken: async () => {
|
|
198799
|
+
if (hasFreshToken()) return token;
|
|
198800
|
+
if (!inFlight) {
|
|
198801
|
+
inFlight = fetchToken().finally(() => {
|
|
198802
|
+
inFlight = null;
|
|
198803
|
+
});
|
|
198804
|
+
}
|
|
198805
|
+
return await inFlight;
|
|
198806
|
+
}
|
|
198807
|
+
};
|
|
198808
|
+
};
|
|
198809
|
+
installSafeModalAuthTokenManager = (modal) => {
|
|
198810
|
+
const candidate = modal;
|
|
198811
|
+
if (candidate.authTokenManager) return;
|
|
198812
|
+
candidate.authTokenManager = createSafeModalAuthTokenManager(candidate);
|
|
198813
|
+
};
|
|
198814
|
+
parsePositiveInt = (value, fallback2) => {
|
|
198815
|
+
const parsed = Number.parseInt(value, 10);
|
|
198816
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return fallback2;
|
|
198817
|
+
return parsed;
|
|
198818
|
+
};
|
|
198819
|
+
resolveRegions = () => {
|
|
198820
|
+
const raw = trimEnv2(process.env.MODAL_SANDBOX_REGION);
|
|
198821
|
+
if (!raw) return [];
|
|
198822
|
+
return raw.split(",").map((value) => value.trim()).filter((value) => value.length > 0);
|
|
198823
|
+
};
|
|
198824
|
+
resolveAppName = () => trimEnv2(process.env.MODAL_SANDBOX_APP) || DEFAULT_APP_NAME;
|
|
198825
|
+
resolveModalSandboxTimeoutMs = () => parsePositiveInt(
|
|
198826
|
+
trimEnv2(process.env.MODAL_SANDBOX_TIMEOUT_MS),
|
|
198827
|
+
DEFAULT_TIMEOUT_MS
|
|
198828
|
+
);
|
|
198829
|
+
isNotFoundError = (error2) => error2 instanceof NotFoundError;
|
|
198830
|
+
isModalAlreadyExistsError = (error2) => {
|
|
198831
|
+
if (error2 instanceof AlreadyExistsError) {
|
|
198832
|
+
return true;
|
|
198833
|
+
}
|
|
198834
|
+
const message = error2 instanceof Error ? `${error2.name} ${error2.message}` : String(error2 ?? "");
|
|
198835
|
+
if (/\bALREADY_EXISTS\b/i.test(message)) {
|
|
198836
|
+
return true;
|
|
198837
|
+
}
|
|
198838
|
+
return /already exists/i.test(message);
|
|
198839
|
+
};
|
|
198840
|
+
trimToNull = (value) => {
|
|
198841
|
+
if (typeof value !== "string") return null;
|
|
198842
|
+
const trimmed = value.trim();
|
|
198843
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
198844
|
+
};
|
|
198845
|
+
resolveControlPlaneToken = (options) => trimToNull(options?.credentials?.controlPlaneToken);
|
|
198846
|
+
hasContextModalCredentialPair = (options) => Boolean(
|
|
198847
|
+
trimToNull(options?.credentials?.modalTokenId) && trimToNull(options?.credentials?.modalTokenSecret)
|
|
198848
|
+
);
|
|
198849
|
+
shouldUseControlPlaneFallback = (options) => !options?.client && Boolean(resolveControlPlaneToken(options)) && !hasContextModalCredentialPair(options);
|
|
198850
|
+
withModalClient = async (options, fn) => {
|
|
198851
|
+
if (options?.client) {
|
|
198852
|
+
return await fn(options.client);
|
|
198853
|
+
}
|
|
198854
|
+
const modalCredentials = resolveModalClientCredentials({
|
|
198855
|
+
...options?.credentialMode ? { credentialMode: options.credentialMode } : {},
|
|
198856
|
+
...options?.credentials !== void 0 ? { credentials: options.credentials } : {},
|
|
198857
|
+
...options?.cwd ? { cwd: options.cwd } : {}
|
|
198858
|
+
});
|
|
198859
|
+
const modal = new ModalClient2({
|
|
198860
|
+
tokenId: modalCredentials.tokenId,
|
|
198861
|
+
tokenSecret: modalCredentials.tokenSecret,
|
|
198862
|
+
environment: resolveModalEnvironmentName()
|
|
198863
|
+
});
|
|
198864
|
+
installSafeModalAuthTokenManager(modal);
|
|
198865
|
+
try {
|
|
198866
|
+
return await fn(modal);
|
|
198867
|
+
} finally {
|
|
198868
|
+
modal.close();
|
|
198869
|
+
}
|
|
198870
|
+
};
|
|
198871
|
+
resolveModalApp = async (modal, appName, createIfMissing) => {
|
|
198872
|
+
try {
|
|
198873
|
+
const app = await modal.apps.fromName(appName, { createIfMissing });
|
|
198874
|
+
return { appId: app.appId, appName };
|
|
198875
|
+
} catch (error2) {
|
|
198876
|
+
if (!createIfMissing && isNotFoundError(error2)) {
|
|
198877
|
+
return null;
|
|
198878
|
+
}
|
|
198879
|
+
throw error2;
|
|
198880
|
+
}
|
|
198881
|
+
};
|
|
198882
|
+
listSandboxesRaw = async (modal, appId, includeFinished) => {
|
|
198883
|
+
const sandboxes = [];
|
|
198884
|
+
let beforeTimestamp = 0;
|
|
198885
|
+
let guard = 0;
|
|
198886
|
+
while (true) {
|
|
198887
|
+
guard += 1;
|
|
198888
|
+
if (guard > SANDBOX_LIST_PAGE_LIMIT) {
|
|
198889
|
+
throw new Error("Modal sandbox list pagination exceeded safety limit.");
|
|
198890
|
+
}
|
|
198891
|
+
const response = await modal.cpClient.sandboxList({
|
|
198892
|
+
appId,
|
|
198893
|
+
beforeTimestamp,
|
|
198894
|
+
environmentName: modal.environmentName(),
|
|
198895
|
+
includeFinished,
|
|
198896
|
+
tags: []
|
|
198897
|
+
});
|
|
198898
|
+
if (!response.sandboxes.length) break;
|
|
198899
|
+
sandboxes.push(...response.sandboxes);
|
|
198900
|
+
const nextCursor = response.sandboxes[response.sandboxes.length - 1];
|
|
198901
|
+
if (!nextCursor || nextCursor.createdAt === beforeTimestamp) break;
|
|
198902
|
+
beforeTimestamp = nextCursor.createdAt;
|
|
198903
|
+
}
|
|
198904
|
+
return sandboxes;
|
|
198905
|
+
};
|
|
198906
|
+
formatSandboxStatus = (sandbox) => {
|
|
198907
|
+
const result = sandbox.taskInfo?.result;
|
|
198908
|
+
const status = result?.status ?? 0;
|
|
198909
|
+
if (status === 0) return "running";
|
|
198910
|
+
const label = FINISHED_STATUS_LABELS[status] ?? String(status);
|
|
198911
|
+
const exitCode = result?.exitcode ?? "unknown";
|
|
198912
|
+
return `finished:${label}:exit=${String(exitCode)}`;
|
|
198913
|
+
};
|
|
198914
|
+
isRunningSandbox = (sandbox) => (sandbox.taskInfo?.result?.status ?? 0) === 0;
|
|
198915
|
+
resolveImageFromTag = async (modal, imageTag) => {
|
|
198916
|
+
const secretName = trimEnv2(process.env.MODAL_SANDBOX_IMAGE_SECRET);
|
|
198917
|
+
if (!secretName) {
|
|
198918
|
+
return modal.images.fromRegistry(imageTag);
|
|
198919
|
+
}
|
|
198920
|
+
const secret = await modal.secrets.fromName(secretName);
|
|
198921
|
+
if (imageTag.includes(".dkr.ecr.")) {
|
|
198922
|
+
return modal.images.fromAwsEcr(imageTag, secret);
|
|
198923
|
+
}
|
|
198924
|
+
return modal.images.fromRegistry(imageTag, secret);
|
|
198925
|
+
};
|
|
198926
|
+
provisionModalSandbox = async (alias, options) => {
|
|
198927
|
+
if (shouldUseControlPlaneFallback(options)) {
|
|
198928
|
+
const controlPlaneToken = resolveControlPlaneToken(options);
|
|
198929
|
+
if (!controlPlaneToken) {
|
|
198930
|
+
throw new Error(
|
|
198931
|
+
"Control plane token is required for modal provisioning."
|
|
198932
|
+
);
|
|
198933
|
+
}
|
|
198934
|
+
return await provisionModalSandboxViaControlPlane(controlPlaneToken, alias);
|
|
198935
|
+
}
|
|
198936
|
+
const appName = resolveAppName();
|
|
198937
|
+
const envImageTag = trimEnv2(process.env.MODAL_SANDBOX_IMAGE);
|
|
198938
|
+
const imageTag = envImageTag || DEFAULT_MODAL_DEVBOX_IMAGE;
|
|
198939
|
+
const resolvedImageTag = await resolveImageTagForBuild(imageTag);
|
|
198940
|
+
const timeoutMs = resolveModalSandboxTimeoutMs();
|
|
198941
|
+
const timeoutSecs = Math.max(1, Math.floor(timeoutMs / 1e3));
|
|
198942
|
+
const regions = resolveRegions();
|
|
198943
|
+
return await withModalClient(options, async (modal) => {
|
|
198944
|
+
const sandboxName = resolveModalSandboxName(alias, modal.environmentName());
|
|
198945
|
+
const app = await resolveModalApp(modal, appName, true);
|
|
198946
|
+
if (!app) {
|
|
198947
|
+
throw new Error(`Could not resolve Modal app "${appName}".`);
|
|
198948
|
+
}
|
|
198949
|
+
const buildImage = async (tag) => {
|
|
198950
|
+
const image = await resolveImageFromTag(modal, tag);
|
|
198951
|
+
return await image.build({ appId: app.appId });
|
|
198952
|
+
};
|
|
198953
|
+
const builtImage = await buildImage(resolvedImageTag);
|
|
198954
|
+
const createResponse = await modal.cpClient.sandboxCreate({
|
|
198955
|
+
appId: app.appId,
|
|
198956
|
+
definition: {
|
|
198957
|
+
imageId: builtImage.imageId,
|
|
198958
|
+
timeoutSecs,
|
|
198959
|
+
name: sandboxName,
|
|
198960
|
+
...regions.length > 0 ? { schedulerPlacement: { regions } } : {},
|
|
198961
|
+
entrypointArgs: MODAL_DAEMON_SUPERVISOR_ENTRYPOINT,
|
|
198962
|
+
enableSnapshot: true
|
|
198963
|
+
}
|
|
198964
|
+
});
|
|
198965
|
+
return {
|
|
198966
|
+
sandboxId: createResponse.sandboxId,
|
|
198967
|
+
appId: app.appId,
|
|
198968
|
+
appName,
|
|
198969
|
+
imageTag: resolvedImageTag,
|
|
198970
|
+
timeoutMs,
|
|
198971
|
+
memorySnapshotEnabled: false,
|
|
198972
|
+
regions
|
|
198973
|
+
};
|
|
198974
|
+
});
|
|
198975
|
+
};
|
|
198976
|
+
findModalSandbox = async (options, operationOptions) => {
|
|
198977
|
+
if (shouldUseControlPlaneFallback(operationOptions)) {
|
|
198978
|
+
const controlPlaneToken = resolveControlPlaneToken(operationOptions);
|
|
198979
|
+
if (!controlPlaneToken) {
|
|
198980
|
+
throw new Error(
|
|
198981
|
+
"Control plane token is required for modal sandbox lookup."
|
|
198982
|
+
);
|
|
198983
|
+
}
|
|
198984
|
+
return await findModalSandboxViaControlPlane(controlPlaneToken, options);
|
|
198985
|
+
}
|
|
198986
|
+
const appName = resolveAppName();
|
|
198987
|
+
const includeFinished = options.includeFinished ?? true;
|
|
198988
|
+
return await withModalClient(operationOptions, async (modal) => {
|
|
198989
|
+
const sandboxName = resolveModalSandboxName(
|
|
198990
|
+
options.alias,
|
|
198991
|
+
modal.environmentName()
|
|
198992
|
+
);
|
|
198993
|
+
const app = await resolveModalApp(modal, appName, false);
|
|
198994
|
+
if (!app) return null;
|
|
198995
|
+
const sandboxes = await listSandboxesRaw(modal, app.appId, includeFinished);
|
|
198996
|
+
const matching = sandboxes.filter((sandbox) => {
|
|
198997
|
+
if (options.sandboxId && sandbox.id === options.sandboxId) return true;
|
|
198998
|
+
return sandbox.name === sandboxName;
|
|
198999
|
+
});
|
|
199000
|
+
if (matching.length === 0) return null;
|
|
199001
|
+
matching.sort((left, right) => {
|
|
199002
|
+
const runningOrder = Number(isRunningSandbox(right)) - Number(isRunningSandbox(left));
|
|
199003
|
+
if (runningOrder !== 0) return runningOrder;
|
|
199004
|
+
return right.createdAt - left.createdAt;
|
|
199005
|
+
});
|
|
199006
|
+
const selected = matching[0];
|
|
199007
|
+
if (!selected) {
|
|
199008
|
+
throw new Error("Modal sandbox selection failed.");
|
|
199009
|
+
}
|
|
199010
|
+
return {
|
|
199011
|
+
sandboxId: selected.id,
|
|
199012
|
+
appId: app.appId,
|
|
199013
|
+
appName: app.appName,
|
|
199014
|
+
name: options.alias,
|
|
199015
|
+
createdAt: selected.createdAt,
|
|
199016
|
+
status: formatSandboxStatus(selected),
|
|
199017
|
+
regions: selected.regions
|
|
199018
|
+
};
|
|
199019
|
+
});
|
|
199020
|
+
};
|
|
199021
|
+
terminateModalSandboxesByAlias = async (alias, options) => {
|
|
199022
|
+
if (shouldUseControlPlaneFallback(options)) {
|
|
199023
|
+
const controlPlaneToken = resolveControlPlaneToken(options);
|
|
199024
|
+
if (!controlPlaneToken) {
|
|
199025
|
+
throw new Error(
|
|
199026
|
+
"Control plane token is required for modal sandbox termination."
|
|
199027
|
+
);
|
|
199028
|
+
}
|
|
199029
|
+
return await terminateModalSandboxesByAliasViaControlPlane(
|
|
199030
|
+
controlPlaneToken,
|
|
199031
|
+
{
|
|
199032
|
+
alias,
|
|
199033
|
+
...typeof options?.includeFinished === "boolean" ? { includeFinished: options.includeFinished } : {}
|
|
199034
|
+
}
|
|
199035
|
+
);
|
|
199036
|
+
}
|
|
199037
|
+
const appName = resolveAppName();
|
|
199038
|
+
const includeFinished = options?.includeFinished ?? false;
|
|
199039
|
+
return await withModalClient(options, async (modal) => {
|
|
199040
|
+
const sandboxName = resolveModalSandboxName(alias, modal.environmentName());
|
|
199041
|
+
const app = await resolveModalApp(modal, appName, false);
|
|
199042
|
+
if (!app) {
|
|
199043
|
+
return {
|
|
199044
|
+
appName,
|
|
199045
|
+
appId: null,
|
|
199046
|
+
matchedSandboxIds: [],
|
|
199047
|
+
terminatedSandboxIds: []
|
|
199048
|
+
};
|
|
199049
|
+
}
|
|
199050
|
+
const sandboxes = await listSandboxesRaw(modal, app.appId, includeFinished);
|
|
199051
|
+
const matching = sandboxes.filter(
|
|
199052
|
+
(sandbox) => sandbox.name === sandboxName
|
|
199053
|
+
);
|
|
199054
|
+
const terminatedSandboxIds = [];
|
|
199055
|
+
for (const sandbox of matching) {
|
|
199056
|
+
await modal.cpClient.sandboxTerminate({ sandboxId: sandbox.id });
|
|
199057
|
+
terminatedSandboxIds.push(sandbox.id);
|
|
199058
|
+
}
|
|
199059
|
+
return {
|
|
199060
|
+
appName: app.appName,
|
|
199061
|
+
appId: app.appId,
|
|
199062
|
+
matchedSandboxIds: matching.map((sandbox) => sandbox.id),
|
|
199063
|
+
terminatedSandboxIds
|
|
199064
|
+
};
|
|
199065
|
+
});
|
|
199066
|
+
};
|
|
199067
|
+
}
|
|
199068
|
+
});
|
|
199069
|
+
|
|
198484
199070
|
// src/devbox/commands/provider/modalRuntime.ts
|
|
198485
199071
|
var import_node_path15, import_node_net3, import_ws4, SERVICE_NAME_PATTERN, CORE_SERVICE_NAMES2, MODAL_DAEMON_REQUEST_TIMEOUT_MS, MODAL_DAEMON_TTY_HANDSHAKE_TIMEOUT_MS, MODAL_SANDBOX_RESOLVE_TIMEOUT_MS, MODAL_DAEMON_CONTROL_HTTP_TIMEOUT_MS, MODAL_DAEMON_TTY_WS_PATH, validateServiceName, isSandboxNotFoundError, resolveReadPath, decodeBase642, parseJsonRecord2, withTimeout3, parseControlError, mapControlSessionRecord, normalizeServiceScope, normalizeServiceRestartPolicy, normalizeServiceStatus2, ModalDaemonExecSocket, createModalRuntimeClient;
|
|
198486
199072
|
var init_modalRuntime = __esm({
|
|
@@ -198492,6 +199078,7 @@ var init_modalRuntime = __esm({
|
|
|
198492
199078
|
import_ws4 = __toESM(require("ws"), 1);
|
|
198493
199079
|
init_src();
|
|
198494
199080
|
init_daemonClient();
|
|
199081
|
+
init_modalLifecycle();
|
|
198495
199082
|
SERVICE_NAME_PATTERN = /^[a-zA-Z0-9._-]+$/;
|
|
198496
199083
|
CORE_SERVICE_NAMES2 = /* @__PURE__ */ new Set(["devbox-sprite-daemon", "devbox-sshd"]);
|
|
198497
199084
|
MODAL_DAEMON_REQUEST_TIMEOUT_MS = 15e3;
|
|
@@ -198929,15 +199516,19 @@ var init_modalRuntime = __esm({
|
|
|
198929
199516
|
serviceRole: requestedServiceRole
|
|
198930
199517
|
}) => {
|
|
198931
199518
|
let modal = null;
|
|
199519
|
+
let modalSandboxName = alias;
|
|
198932
199520
|
try {
|
|
198933
199521
|
const modalCredentials = resolveModalClientCredentials({
|
|
198934
199522
|
...credentialMode ? { credentialMode } : {},
|
|
198935
199523
|
...credentials !== void 0 ? { credentials } : {},
|
|
198936
199524
|
...cwd ? { cwd } : {}
|
|
198937
199525
|
});
|
|
199526
|
+
const modalEnvironmentName = resolveModalEnvironmentName();
|
|
199527
|
+
modalSandboxName = resolveModalSandboxName(alias, modalEnvironmentName);
|
|
198938
199528
|
modal = new ModalClient2({
|
|
198939
199529
|
tokenId: modalCredentials.tokenId,
|
|
198940
|
-
tokenSecret: modalCredentials.tokenSecret
|
|
199530
|
+
tokenSecret: modalCredentials.tokenSecret,
|
|
199531
|
+
environment: modalEnvironmentName
|
|
198941
199532
|
});
|
|
198942
199533
|
} catch (error2) {
|
|
198943
199534
|
if (!(error2 instanceof ProviderClientError && error2.code === "authentication_required")) {
|
|
@@ -198966,7 +199557,7 @@ var init_modalRuntime = __esm({
|
|
|
198966
199557
|
sandboxPromise = (async () => {
|
|
198967
199558
|
try {
|
|
198968
199559
|
const runningSandbox = await withTimeout3(
|
|
198969
|
-
directModal.sandboxes.fromName(appName,
|
|
199560
|
+
directModal.sandboxes.fromName(appName, modalSandboxName),
|
|
198970
199561
|
MODAL_SANDBOX_RESOLVE_TIMEOUT_MS,
|
|
198971
199562
|
"Timed out resolving running modal sandbox by name."
|
|
198972
199563
|
);
|
|
@@ -199485,530 +200076,6 @@ var init_modalRuntime = __esm({
|
|
|
199485
200076
|
}
|
|
199486
200077
|
});
|
|
199487
200078
|
|
|
199488
|
-
// src/devbox/commands/provider/modalLifecycle.ts
|
|
199489
|
-
var import_node_crypto9, DEFAULT_APP_NAME, DEFAULT_MODAL_DEVBOX_IMAGE, DEFAULT_TIMEOUT_MS, IMAGE_TAG_RESOLUTION_CACHE_TTL_MS, SANDBOX_LIST_PAGE_LIMIT, MODAL_DAEMON_WRAPPER_PATH, MODAL_DAEMON_SUPERVISOR_ENTRYPOINT, FINISHED_STATUS_LABELS, REGISTRY_MANIFEST_ACCEPT_HEADER, resolvedImageTagCache, trimEnv2, parseRegistryImageTag, parseWwwAuthenticateBearer, fetchRegistryToken, resolveLatestImageTagToDigest, resolveImageTagForBuild, decodeJwtExpMs, createSafeModalAuthTokenManager, installSafeModalAuthTokenManager, parsePositiveInt, resolveRegions, resolveAppName, resolveModalSandboxTimeoutMs, isNotFoundError, isModalAlreadyExistsError, trimToNull, resolveControlPlaneToken, hasContextModalCredentialPair, shouldUseControlPlaneFallback, withModalClient, resolveModalApp, listSandboxesRaw, formatSandboxStatus, isRunningSandbox, resolveImageFromTag, provisionModalSandbox, findModalSandbox, terminateModalSandboxesByAlias;
|
|
199490
|
-
var init_modalLifecycle = __esm({
|
|
199491
|
-
"src/devbox/commands/provider/modalLifecycle.ts"() {
|
|
199492
|
-
"use strict";
|
|
199493
|
-
init_src();
|
|
199494
|
-
import_node_crypto9 = require("node:crypto");
|
|
199495
|
-
init_dist5();
|
|
199496
|
-
init_controlPlane();
|
|
199497
|
-
DEFAULT_APP_NAME = "sandbox-modal-smoke";
|
|
199498
|
-
DEFAULT_MODAL_DEVBOX_IMAGE = "public.ecr.aws/d8m4p4w9/modal-devbox:latest";
|
|
199499
|
-
DEFAULT_TIMEOUT_MS = 24 * 60 * 60 * 1e3;
|
|
199500
|
-
IMAGE_TAG_RESOLUTION_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
199501
|
-
SANDBOX_LIST_PAGE_LIMIT = 100;
|
|
199502
|
-
MODAL_DAEMON_WRAPPER_PATH = "/root/.devbox/daemon/run-daemon.sh";
|
|
199503
|
-
MODAL_DAEMON_SUPERVISOR_ENTRYPOINT = [
|
|
199504
|
-
"/bin/sh",
|
|
199505
|
-
"-lc",
|
|
199506
|
-
[
|
|
199507
|
-
"set -u",
|
|
199508
|
-
`wrapper=${JSON.stringify(MODAL_DAEMON_WRAPPER_PATH)}`,
|
|
199509
|
-
'until [ -x "$wrapper" ]; do sleep 0.25; done',
|
|
199510
|
-
"while true; do",
|
|
199511
|
-
' "$wrapper"',
|
|
199512
|
-
" status=$?",
|
|
199513
|
-
' echo "sprite-daemon exited with status $status; restarting" >&2',
|
|
199514
|
-
" sleep 1",
|
|
199515
|
-
"done"
|
|
199516
|
-
].join("\n")
|
|
199517
|
-
];
|
|
199518
|
-
FINISHED_STATUS_LABELS = {
|
|
199519
|
-
1: "success",
|
|
199520
|
-
2: "failure",
|
|
199521
|
-
3: "terminated",
|
|
199522
|
-
4: "timeout",
|
|
199523
|
-
5: "init_failure",
|
|
199524
|
-
6: "internal_failure",
|
|
199525
|
-
7: "idle_timeout"
|
|
199526
|
-
};
|
|
199527
|
-
REGISTRY_MANIFEST_ACCEPT_HEADER = [
|
|
199528
|
-
"application/vnd.oci.image.index.v1+json",
|
|
199529
|
-
"application/vnd.oci.image.manifest.v1+json",
|
|
199530
|
-
"application/vnd.docker.distribution.manifest.list.v2+json",
|
|
199531
|
-
"application/vnd.docker.distribution.manifest.v2+json"
|
|
199532
|
-
].join(", ");
|
|
199533
|
-
resolvedImageTagCache = /* @__PURE__ */ new Map();
|
|
199534
|
-
trimEnv2 = (value) => value?.trim() ?? "";
|
|
199535
|
-
parseRegistryImageTag = (imageTag) => {
|
|
199536
|
-
const trimmed = imageTag.trim();
|
|
199537
|
-
if (!trimmed || trimmed.includes("@")) {
|
|
199538
|
-
return null;
|
|
199539
|
-
}
|
|
199540
|
-
const lastSlashIndex = trimmed.lastIndexOf("/");
|
|
199541
|
-
const lastColonIndex = trimmed.lastIndexOf(":");
|
|
199542
|
-
if (lastColonIndex <= lastSlashIndex) {
|
|
199543
|
-
return null;
|
|
199544
|
-
}
|
|
199545
|
-
const repositoryWithHost = trimmed.slice(0, lastColonIndex);
|
|
199546
|
-
const tag = trimmed.slice(lastColonIndex + 1).trim();
|
|
199547
|
-
if (!repositoryWithHost || !tag) {
|
|
199548
|
-
return null;
|
|
199549
|
-
}
|
|
199550
|
-
const firstSlashIndex = repositoryWithHost.indexOf("/");
|
|
199551
|
-
if (firstSlashIndex <= 0) {
|
|
199552
|
-
return null;
|
|
199553
|
-
}
|
|
199554
|
-
const registryHost = repositoryWithHost.slice(0, firstSlashIndex);
|
|
199555
|
-
const repository = repositoryWithHost.slice(firstSlashIndex + 1);
|
|
199556
|
-
if (!repository) {
|
|
199557
|
-
return null;
|
|
199558
|
-
}
|
|
199559
|
-
const hasExplicitRegistryHost = registryHost.includes(".") || registryHost.includes(":") || registryHost === "localhost";
|
|
199560
|
-
if (!hasExplicitRegistryHost) {
|
|
199561
|
-
return null;
|
|
199562
|
-
}
|
|
199563
|
-
return {
|
|
199564
|
-
registryHost,
|
|
199565
|
-
repository,
|
|
199566
|
-
tag,
|
|
199567
|
-
repositoryWithHost
|
|
199568
|
-
};
|
|
199569
|
-
};
|
|
199570
|
-
parseWwwAuthenticateBearer = (headerValue) => {
|
|
199571
|
-
const trimmed = headerValue.trim();
|
|
199572
|
-
if (!trimmed.toLowerCase().startsWith("bearer ")) {
|
|
199573
|
-
return null;
|
|
199574
|
-
}
|
|
199575
|
-
const attributes = /* @__PURE__ */ new Map();
|
|
199576
|
-
for (const match2 of trimmed.slice("bearer ".length).matchAll(/([A-Za-z0-9_-]+)="([^"]*)"/g)) {
|
|
199577
|
-
const [, key, value] = match2;
|
|
199578
|
-
if (!key) {
|
|
199579
|
-
continue;
|
|
199580
|
-
}
|
|
199581
|
-
attributes.set(key.toLowerCase(), value ?? "");
|
|
199582
|
-
}
|
|
199583
|
-
const realm = attributes.get("realm");
|
|
199584
|
-
const service = attributes.get("service");
|
|
199585
|
-
const scope = attributes.get("scope");
|
|
199586
|
-
if (!realm || !service) {
|
|
199587
|
-
return null;
|
|
199588
|
-
}
|
|
199589
|
-
return {
|
|
199590
|
-
realm,
|
|
199591
|
-
service,
|
|
199592
|
-
scope: scope || null
|
|
199593
|
-
};
|
|
199594
|
-
};
|
|
199595
|
-
fetchRegistryToken = async ({
|
|
199596
|
-
realm,
|
|
199597
|
-
service,
|
|
199598
|
-
scope
|
|
199599
|
-
}) => {
|
|
199600
|
-
const tokenUrl = new URL(realm);
|
|
199601
|
-
tokenUrl.searchParams.set("service", service);
|
|
199602
|
-
if (scope) {
|
|
199603
|
-
tokenUrl.searchParams.set("scope", scope);
|
|
199604
|
-
}
|
|
199605
|
-
const response = await fetch(tokenUrl.toString());
|
|
199606
|
-
if (!response.ok) {
|
|
199607
|
-
throw new Error(
|
|
199608
|
-
`Container registry auth token request failed (${response.status}).`
|
|
199609
|
-
);
|
|
199610
|
-
}
|
|
199611
|
-
const payload = await response.json();
|
|
199612
|
-
const token = typeof payload.token === "string" ? payload.token.trim() : typeof payload.access_token === "string" ? payload.access_token.trim() : "";
|
|
199613
|
-
if (!token) {
|
|
199614
|
-
throw new Error("Container registry auth token response was empty.");
|
|
199615
|
-
}
|
|
199616
|
-
return token;
|
|
199617
|
-
};
|
|
199618
|
-
resolveLatestImageTagToDigest = async (parsed) => {
|
|
199619
|
-
const manifestUrl = `https://${parsed.registryHost}/v2/${parsed.repository}/manifests/${encodeURIComponent(parsed.tag)}`;
|
|
199620
|
-
const fetchManifest = async ({
|
|
199621
|
-
method,
|
|
199622
|
-
token: token2
|
|
199623
|
-
}) => {
|
|
199624
|
-
const headers = {
|
|
199625
|
-
Accept: REGISTRY_MANIFEST_ACCEPT_HEADER
|
|
199626
|
-
};
|
|
199627
|
-
if (token2) {
|
|
199628
|
-
headers.Authorization = `Bearer ${token2}`;
|
|
199629
|
-
}
|
|
199630
|
-
return await fetch(manifestUrl, {
|
|
199631
|
-
headers,
|
|
199632
|
-
method
|
|
199633
|
-
});
|
|
199634
|
-
};
|
|
199635
|
-
let token = null;
|
|
199636
|
-
let headResponse = await fetchManifest({ method: "HEAD" });
|
|
199637
|
-
if (headResponse.status === 401) {
|
|
199638
|
-
const authHeader = headResponse.headers.get("www-authenticate") ?? "";
|
|
199639
|
-
const challenge = parseWwwAuthenticateBearer(authHeader);
|
|
199640
|
-
if (!challenge) {
|
|
199641
|
-
throw new Error(
|
|
199642
|
-
`Container registry auth challenge missing or invalid for ${parsed.repositoryWithHost}:${parsed.tag}.`
|
|
199643
|
-
);
|
|
199644
|
-
}
|
|
199645
|
-
token = await fetchRegistryToken(challenge);
|
|
199646
|
-
headResponse = await fetchManifest({
|
|
199647
|
-
method: "HEAD",
|
|
199648
|
-
token
|
|
199649
|
-
});
|
|
199650
|
-
}
|
|
199651
|
-
if (!headResponse.ok) {
|
|
199652
|
-
throw new Error(
|
|
199653
|
-
`Container registry manifest lookup failed for ${parsed.repositoryWithHost}:${parsed.tag} (${headResponse.status}).`
|
|
199654
|
-
);
|
|
199655
|
-
}
|
|
199656
|
-
const headDigest = headResponse.headers.get("docker-content-digest")?.trim();
|
|
199657
|
-
if (headDigest) {
|
|
199658
|
-
return `${parsed.repositoryWithHost}@${headDigest}`;
|
|
199659
|
-
}
|
|
199660
|
-
const getResponse = await fetchManifest(
|
|
199661
|
-
token ? {
|
|
199662
|
-
method: "GET",
|
|
199663
|
-
token
|
|
199664
|
-
} : {
|
|
199665
|
-
method: "GET"
|
|
199666
|
-
}
|
|
199667
|
-
);
|
|
199668
|
-
if (!getResponse.ok) {
|
|
199669
|
-
throw new Error(
|
|
199670
|
-
`Container registry manifest body lookup failed for ${parsed.repositoryWithHost}:${parsed.tag} (${getResponse.status}).`
|
|
199671
|
-
);
|
|
199672
|
-
}
|
|
199673
|
-
const headerDigest = getResponse.headers.get("docker-content-digest")?.trim();
|
|
199674
|
-
if (headerDigest) {
|
|
199675
|
-
return `${parsed.repositoryWithHost}@${headerDigest}`;
|
|
199676
|
-
}
|
|
199677
|
-
const manifestBytes = Buffer.from(await getResponse.arrayBuffer());
|
|
199678
|
-
const bodyDigest = `sha256:${(0, import_node_crypto9.createHash)("sha256").update(manifestBytes).digest("hex")}`;
|
|
199679
|
-
return `${parsed.repositoryWithHost}@${bodyDigest}`;
|
|
199680
|
-
};
|
|
199681
|
-
resolveImageTagForBuild = async (imageTag) => {
|
|
199682
|
-
const parsed = parseRegistryImageTag(imageTag);
|
|
199683
|
-
if (!parsed || parsed.tag !== "latest") {
|
|
199684
|
-
return imageTag;
|
|
199685
|
-
}
|
|
199686
|
-
const cacheKey = `${parsed.repositoryWithHost}:${parsed.tag}`;
|
|
199687
|
-
const now = Date.now();
|
|
199688
|
-
const cached = resolvedImageTagCache.get(cacheKey);
|
|
199689
|
-
if (cached && cached.expiresAt > now) {
|
|
199690
|
-
return cached.value;
|
|
199691
|
-
}
|
|
199692
|
-
const resolved = await resolveLatestImageTagToDigest(parsed);
|
|
199693
|
-
resolvedImageTagCache.set(cacheKey, {
|
|
199694
|
-
value: resolved,
|
|
199695
|
-
expiresAt: now + IMAGE_TAG_RESOLUTION_CACHE_TTL_MS
|
|
199696
|
-
});
|
|
199697
|
-
return resolved;
|
|
199698
|
-
};
|
|
199699
|
-
decodeJwtExpMs = (token) => {
|
|
199700
|
-
const segments = token.split(".");
|
|
199701
|
-
if (segments.length < 2) return null;
|
|
199702
|
-
const payload = segments[1];
|
|
199703
|
-
if (!payload) return null;
|
|
199704
|
-
const normalized = payload.replace(/-/g, "+").replace(/_/g, "/");
|
|
199705
|
-
const padLength = (4 - normalized.length % 4) % 4;
|
|
199706
|
-
const padded = `${normalized}${"=".repeat(padLength)}`;
|
|
199707
|
-
try {
|
|
199708
|
-
const parsed = JSON.parse(
|
|
199709
|
-
Buffer.from(padded, "base64").toString("utf8")
|
|
199710
|
-
);
|
|
199711
|
-
const exp = parsed.exp;
|
|
199712
|
-
if (typeof exp !== "number" || !Number.isFinite(exp) || exp <= 0) {
|
|
199713
|
-
return null;
|
|
199714
|
-
}
|
|
199715
|
-
return Math.floor(exp * 1e3);
|
|
199716
|
-
} catch {
|
|
199717
|
-
return null;
|
|
199718
|
-
}
|
|
199719
|
-
};
|
|
199720
|
-
createSafeModalAuthTokenManager = (modal) => {
|
|
199721
|
-
let token = "";
|
|
199722
|
-
let tokenExpMs = 0;
|
|
199723
|
-
let inFlight = null;
|
|
199724
|
-
const TOKEN_REFRESH_SKEW_MS = 3e4;
|
|
199725
|
-
const FALLBACK_TOKEN_TTL_MS = 15 * 60 * 1e3;
|
|
199726
|
-
const hasFreshToken = () => token.length > 0 && Date.now() + TOKEN_REFRESH_SKEW_MS < tokenExpMs;
|
|
199727
|
-
const fetchToken = async () => {
|
|
199728
|
-
const authTokenGet = modal.cpClient.authTokenGet;
|
|
199729
|
-
if (typeof authTokenGet !== "function") {
|
|
199730
|
-
throw new Error("Modal auth token endpoint unavailable.");
|
|
199731
|
-
}
|
|
199732
|
-
const response = await authTokenGet({});
|
|
199733
|
-
const nextToken = typeof response?.token === "string" ? response.token.trim() : "";
|
|
199734
|
-
if (!nextToken) {
|
|
199735
|
-
throw new Error("Modal auth token unavailable.");
|
|
199736
|
-
}
|
|
199737
|
-
token = nextToken;
|
|
199738
|
-
tokenExpMs = decodeJwtExpMs(nextToken) ?? Date.now() + FALLBACK_TOKEN_TTL_MS;
|
|
199739
|
-
return nextToken;
|
|
199740
|
-
};
|
|
199741
|
-
return {
|
|
199742
|
-
start: () => {
|
|
199743
|
-
},
|
|
199744
|
-
stop: () => {
|
|
199745
|
-
token = "";
|
|
199746
|
-
tokenExpMs = 0;
|
|
199747
|
-
inFlight = null;
|
|
199748
|
-
},
|
|
199749
|
-
getToken: async () => {
|
|
199750
|
-
if (hasFreshToken()) return token;
|
|
199751
|
-
if (!inFlight) {
|
|
199752
|
-
inFlight = fetchToken().finally(() => {
|
|
199753
|
-
inFlight = null;
|
|
199754
|
-
});
|
|
199755
|
-
}
|
|
199756
|
-
return await inFlight;
|
|
199757
|
-
}
|
|
199758
|
-
};
|
|
199759
|
-
};
|
|
199760
|
-
installSafeModalAuthTokenManager = (modal) => {
|
|
199761
|
-
const candidate = modal;
|
|
199762
|
-
if (candidate.authTokenManager) return;
|
|
199763
|
-
candidate.authTokenManager = createSafeModalAuthTokenManager(candidate);
|
|
199764
|
-
};
|
|
199765
|
-
parsePositiveInt = (value, fallback2) => {
|
|
199766
|
-
const parsed = Number.parseInt(value, 10);
|
|
199767
|
-
if (!Number.isFinite(parsed) || parsed <= 0) return fallback2;
|
|
199768
|
-
return parsed;
|
|
199769
|
-
};
|
|
199770
|
-
resolveRegions = () => {
|
|
199771
|
-
const raw = trimEnv2(process.env.MODAL_SANDBOX_REGION);
|
|
199772
|
-
if (!raw) return [];
|
|
199773
|
-
return raw.split(",").map((value) => value.trim()).filter((value) => value.length > 0);
|
|
199774
|
-
};
|
|
199775
|
-
resolveAppName = () => trimEnv2(process.env.MODAL_SANDBOX_APP) || DEFAULT_APP_NAME;
|
|
199776
|
-
resolveModalSandboxTimeoutMs = () => parsePositiveInt(
|
|
199777
|
-
trimEnv2(process.env.MODAL_SANDBOX_TIMEOUT_MS),
|
|
199778
|
-
DEFAULT_TIMEOUT_MS
|
|
199779
|
-
);
|
|
199780
|
-
isNotFoundError = (error2) => error2 instanceof NotFoundError;
|
|
199781
|
-
isModalAlreadyExistsError = (error2) => {
|
|
199782
|
-
if (error2 instanceof AlreadyExistsError) {
|
|
199783
|
-
return true;
|
|
199784
|
-
}
|
|
199785
|
-
const message = error2 instanceof Error ? `${error2.name} ${error2.message}` : String(error2 ?? "");
|
|
199786
|
-
if (/\bALREADY_EXISTS\b/i.test(message)) {
|
|
199787
|
-
return true;
|
|
199788
|
-
}
|
|
199789
|
-
return /already exists/i.test(message);
|
|
199790
|
-
};
|
|
199791
|
-
trimToNull = (value) => {
|
|
199792
|
-
if (typeof value !== "string") return null;
|
|
199793
|
-
const trimmed = value.trim();
|
|
199794
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
199795
|
-
};
|
|
199796
|
-
resolveControlPlaneToken = (options) => trimToNull(options?.credentials?.controlPlaneToken);
|
|
199797
|
-
hasContextModalCredentialPair = (options) => Boolean(
|
|
199798
|
-
trimToNull(options?.credentials?.modalTokenId) && trimToNull(options?.credentials?.modalTokenSecret)
|
|
199799
|
-
);
|
|
199800
|
-
shouldUseControlPlaneFallback = (options) => !options?.client && Boolean(resolveControlPlaneToken(options)) && !hasContextModalCredentialPair(options);
|
|
199801
|
-
withModalClient = async (options, fn) => {
|
|
199802
|
-
if (options?.client) {
|
|
199803
|
-
return await fn(options.client);
|
|
199804
|
-
}
|
|
199805
|
-
const modalCredentials = resolveModalClientCredentials({
|
|
199806
|
-
...options?.credentialMode ? { credentialMode: options.credentialMode } : {},
|
|
199807
|
-
...options?.credentials !== void 0 ? { credentials: options.credentials } : {},
|
|
199808
|
-
...options?.cwd ? { cwd: options.cwd } : {}
|
|
199809
|
-
});
|
|
199810
|
-
const modal = new ModalClient2({
|
|
199811
|
-
tokenId: modalCredentials.tokenId,
|
|
199812
|
-
tokenSecret: modalCredentials.tokenSecret
|
|
199813
|
-
});
|
|
199814
|
-
installSafeModalAuthTokenManager(modal);
|
|
199815
|
-
try {
|
|
199816
|
-
return await fn(modal);
|
|
199817
|
-
} finally {
|
|
199818
|
-
modal.close();
|
|
199819
|
-
}
|
|
199820
|
-
};
|
|
199821
|
-
resolveModalApp = async (modal, appName, createIfMissing) => {
|
|
199822
|
-
try {
|
|
199823
|
-
const app = await modal.apps.fromName(appName, { createIfMissing });
|
|
199824
|
-
return { appId: app.appId, appName };
|
|
199825
|
-
} catch (error2) {
|
|
199826
|
-
if (!createIfMissing && isNotFoundError(error2)) {
|
|
199827
|
-
return null;
|
|
199828
|
-
}
|
|
199829
|
-
throw error2;
|
|
199830
|
-
}
|
|
199831
|
-
};
|
|
199832
|
-
listSandboxesRaw = async (modal, appId, includeFinished) => {
|
|
199833
|
-
const sandboxes = [];
|
|
199834
|
-
let beforeTimestamp = 0;
|
|
199835
|
-
let guard = 0;
|
|
199836
|
-
while (true) {
|
|
199837
|
-
guard += 1;
|
|
199838
|
-
if (guard > SANDBOX_LIST_PAGE_LIMIT) {
|
|
199839
|
-
throw new Error("Modal sandbox list pagination exceeded safety limit.");
|
|
199840
|
-
}
|
|
199841
|
-
const response = await modal.cpClient.sandboxList({
|
|
199842
|
-
appId,
|
|
199843
|
-
beforeTimestamp,
|
|
199844
|
-
environmentName: modal.environmentName(),
|
|
199845
|
-
includeFinished,
|
|
199846
|
-
tags: []
|
|
199847
|
-
});
|
|
199848
|
-
if (!response.sandboxes.length) break;
|
|
199849
|
-
sandboxes.push(...response.sandboxes);
|
|
199850
|
-
const nextCursor = response.sandboxes[response.sandboxes.length - 1];
|
|
199851
|
-
if (!nextCursor || nextCursor.createdAt === beforeTimestamp) break;
|
|
199852
|
-
beforeTimestamp = nextCursor.createdAt;
|
|
199853
|
-
}
|
|
199854
|
-
return sandboxes;
|
|
199855
|
-
};
|
|
199856
|
-
formatSandboxStatus = (sandbox) => {
|
|
199857
|
-
const result = sandbox.taskInfo?.result;
|
|
199858
|
-
const status = result?.status ?? 0;
|
|
199859
|
-
if (status === 0) return "running";
|
|
199860
|
-
const label = FINISHED_STATUS_LABELS[status] ?? String(status);
|
|
199861
|
-
const exitCode = result?.exitcode ?? "unknown";
|
|
199862
|
-
return `finished:${label}:exit=${String(exitCode)}`;
|
|
199863
|
-
};
|
|
199864
|
-
isRunningSandbox = (sandbox) => (sandbox.taskInfo?.result?.status ?? 0) === 0;
|
|
199865
|
-
resolveImageFromTag = async (modal, imageTag) => {
|
|
199866
|
-
const secretName = trimEnv2(process.env.MODAL_SANDBOX_IMAGE_SECRET);
|
|
199867
|
-
if (!secretName) {
|
|
199868
|
-
return modal.images.fromRegistry(imageTag);
|
|
199869
|
-
}
|
|
199870
|
-
const secret = await modal.secrets.fromName(secretName);
|
|
199871
|
-
if (imageTag.includes(".dkr.ecr.")) {
|
|
199872
|
-
return modal.images.fromAwsEcr(imageTag, secret);
|
|
199873
|
-
}
|
|
199874
|
-
return modal.images.fromRegistry(imageTag, secret);
|
|
199875
|
-
};
|
|
199876
|
-
provisionModalSandbox = async (alias, options) => {
|
|
199877
|
-
if (shouldUseControlPlaneFallback(options)) {
|
|
199878
|
-
const controlPlaneToken = resolveControlPlaneToken(options);
|
|
199879
|
-
if (!controlPlaneToken) {
|
|
199880
|
-
throw new Error(
|
|
199881
|
-
"Control plane token is required for modal provisioning."
|
|
199882
|
-
);
|
|
199883
|
-
}
|
|
199884
|
-
return await provisionModalSandboxViaControlPlane(controlPlaneToken, alias);
|
|
199885
|
-
}
|
|
199886
|
-
const appName = resolveAppName();
|
|
199887
|
-
const envImageTag = trimEnv2(process.env.MODAL_SANDBOX_IMAGE);
|
|
199888
|
-
const imageTag = envImageTag || DEFAULT_MODAL_DEVBOX_IMAGE;
|
|
199889
|
-
const resolvedImageTag = await resolveImageTagForBuild(imageTag);
|
|
199890
|
-
const timeoutMs = resolveModalSandboxTimeoutMs();
|
|
199891
|
-
const timeoutSecs = Math.max(1, Math.floor(timeoutMs / 1e3));
|
|
199892
|
-
const regions = resolveRegions();
|
|
199893
|
-
return await withModalClient(options, async (modal) => {
|
|
199894
|
-
const app = await resolveModalApp(modal, appName, true);
|
|
199895
|
-
if (!app) {
|
|
199896
|
-
throw new Error(`Could not resolve Modal app "${appName}".`);
|
|
199897
|
-
}
|
|
199898
|
-
const buildImage = async (tag) => {
|
|
199899
|
-
const image = await resolveImageFromTag(modal, tag);
|
|
199900
|
-
return await image.build({ appId: app.appId });
|
|
199901
|
-
};
|
|
199902
|
-
const builtImage = await buildImage(resolvedImageTag);
|
|
199903
|
-
const createResponse = await modal.cpClient.sandboxCreate({
|
|
199904
|
-
appId: app.appId,
|
|
199905
|
-
definition: {
|
|
199906
|
-
imageId: builtImage.imageId,
|
|
199907
|
-
timeoutSecs,
|
|
199908
|
-
name: alias,
|
|
199909
|
-
...regions.length > 0 ? { schedulerPlacement: { regions } } : {},
|
|
199910
|
-
entrypointArgs: MODAL_DAEMON_SUPERVISOR_ENTRYPOINT,
|
|
199911
|
-
enableSnapshot: true
|
|
199912
|
-
}
|
|
199913
|
-
});
|
|
199914
|
-
return {
|
|
199915
|
-
sandboxId: createResponse.sandboxId,
|
|
199916
|
-
appId: app.appId,
|
|
199917
|
-
appName,
|
|
199918
|
-
imageTag: resolvedImageTag,
|
|
199919
|
-
timeoutMs,
|
|
199920
|
-
memorySnapshotEnabled: false,
|
|
199921
|
-
regions
|
|
199922
|
-
};
|
|
199923
|
-
});
|
|
199924
|
-
};
|
|
199925
|
-
findModalSandbox = async (options, operationOptions) => {
|
|
199926
|
-
if (shouldUseControlPlaneFallback(operationOptions)) {
|
|
199927
|
-
const controlPlaneToken = resolveControlPlaneToken(operationOptions);
|
|
199928
|
-
if (!controlPlaneToken) {
|
|
199929
|
-
throw new Error(
|
|
199930
|
-
"Control plane token is required for modal sandbox lookup."
|
|
199931
|
-
);
|
|
199932
|
-
}
|
|
199933
|
-
return await findModalSandboxViaControlPlane(controlPlaneToken, options);
|
|
199934
|
-
}
|
|
199935
|
-
const appName = resolveAppName();
|
|
199936
|
-
const includeFinished = options.includeFinished ?? true;
|
|
199937
|
-
return await withModalClient(operationOptions, async (modal) => {
|
|
199938
|
-
const app = await resolveModalApp(modal, appName, false);
|
|
199939
|
-
if (!app) return null;
|
|
199940
|
-
const sandboxes = await listSandboxesRaw(modal, app.appId, includeFinished);
|
|
199941
|
-
const matching = sandboxes.filter((sandbox) => {
|
|
199942
|
-
if (options.sandboxId && sandbox.id === options.sandboxId) return true;
|
|
199943
|
-
return sandbox.name === options.alias;
|
|
199944
|
-
});
|
|
199945
|
-
if (matching.length === 0) return null;
|
|
199946
|
-
matching.sort((left, right) => {
|
|
199947
|
-
const runningOrder = Number(isRunningSandbox(right)) - Number(isRunningSandbox(left));
|
|
199948
|
-
if (runningOrder !== 0) return runningOrder;
|
|
199949
|
-
return right.createdAt - left.createdAt;
|
|
199950
|
-
});
|
|
199951
|
-
const selected = matching[0];
|
|
199952
|
-
if (!selected) {
|
|
199953
|
-
throw new Error("Modal sandbox selection failed.");
|
|
199954
|
-
}
|
|
199955
|
-
return {
|
|
199956
|
-
sandboxId: selected.id,
|
|
199957
|
-
appId: app.appId,
|
|
199958
|
-
appName: app.appName,
|
|
199959
|
-
name: selected.name,
|
|
199960
|
-
createdAt: selected.createdAt,
|
|
199961
|
-
status: formatSandboxStatus(selected),
|
|
199962
|
-
regions: selected.regions
|
|
199963
|
-
};
|
|
199964
|
-
});
|
|
199965
|
-
};
|
|
199966
|
-
terminateModalSandboxesByAlias = async (alias, options) => {
|
|
199967
|
-
if (shouldUseControlPlaneFallback(options)) {
|
|
199968
|
-
const controlPlaneToken = resolveControlPlaneToken(options);
|
|
199969
|
-
if (!controlPlaneToken) {
|
|
199970
|
-
throw new Error(
|
|
199971
|
-
"Control plane token is required for modal sandbox termination."
|
|
199972
|
-
);
|
|
199973
|
-
}
|
|
199974
|
-
return await terminateModalSandboxesByAliasViaControlPlane(
|
|
199975
|
-
controlPlaneToken,
|
|
199976
|
-
{
|
|
199977
|
-
alias,
|
|
199978
|
-
...typeof options?.includeFinished === "boolean" ? { includeFinished: options.includeFinished } : {}
|
|
199979
|
-
}
|
|
199980
|
-
);
|
|
199981
|
-
}
|
|
199982
|
-
const appName = resolveAppName();
|
|
199983
|
-
const includeFinished = options?.includeFinished ?? false;
|
|
199984
|
-
return await withModalClient(options, async (modal) => {
|
|
199985
|
-
const app = await resolveModalApp(modal, appName, false);
|
|
199986
|
-
if (!app) {
|
|
199987
|
-
return {
|
|
199988
|
-
appName,
|
|
199989
|
-
appId: null,
|
|
199990
|
-
matchedSandboxIds: [],
|
|
199991
|
-
terminatedSandboxIds: []
|
|
199992
|
-
};
|
|
199993
|
-
}
|
|
199994
|
-
const sandboxes = await listSandboxesRaw(modal, app.appId, includeFinished);
|
|
199995
|
-
const matching = sandboxes.filter((sandbox) => sandbox.name === alias);
|
|
199996
|
-
const terminatedSandboxIds = [];
|
|
199997
|
-
for (const sandbox of matching) {
|
|
199998
|
-
await modal.cpClient.sandboxTerminate({ sandboxId: sandbox.id });
|
|
199999
|
-
terminatedSandboxIds.push(sandbox.id);
|
|
200000
|
-
}
|
|
200001
|
-
return {
|
|
200002
|
-
appName: app.appName,
|
|
200003
|
-
appId: app.appId,
|
|
200004
|
-
matchedSandboxIds: matching.map((sandbox) => sandbox.id),
|
|
200005
|
-
terminatedSandboxIds
|
|
200006
|
-
};
|
|
200007
|
-
});
|
|
200008
|
-
};
|
|
200009
|
-
}
|
|
200010
|
-
});
|
|
200011
|
-
|
|
200012
200079
|
// src/devbox/commands/providerClient.ts
|
|
200013
200080
|
var CORE_SERVICE_NAMES3, DEFAULT_MODAL_APP_NAME, normalizeServiceStatus3, mapSpriteServiceToProviderRecord2, mapProviderUpsertToSpriteInput2, trimToNull2, normalizeEpochToIso, resolveModalRuntimeSeedAppName, createProviderCredentialContext, resolveModalCommandOperationOptions, throwModalNotImplemented2, MODAL_AUTH_ERROR_CODES, normalizeModalErrorCode, extractModalErrorCode, isModalAuthError, rethrowModalOperationError, mapModalRecordToProviderInstance, createModalCommandProviderClient, createCommandProviderClient;
|
|
200014
200081
|
var init_providerClient = __esm({
|
|
@@ -220180,4 +220247,4 @@ smol-toml/dist/index.js:
|
|
|
220180
220247
|
*/
|
|
220181
220248
|
//# sourceMappingURL=dvb.cjs.map
|
|
220182
220249
|
|
|
220183
|
-
//# debugId=
|
|
220250
|
+
//# debugId=b785e941-0159-5a32-9ac9-c3686e30d3af
|