@boxes-dev/dvb 1.0.77 → 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 +636 -546
- package/dist/bin/dvb.cjs.map +1 -1
- package/dist/bin/dvbd.cjs +5 -5
- package/dist/devbox/commands/init/claudeBootstrap.d.ts +2 -1
- package/dist/devbox/commands/init/claudeBootstrap.d.ts.map +1 -1
- package/dist/devbox/commands/init/claudeBootstrap.js +23 -8
- package/dist/devbox/commands/init/claudeBootstrap.js.map +1 -1
- package/dist/devbox/commands/init/codex/remote.d.ts.map +1 -1
- package/dist/devbox/commands/init/codex/remote.js +11 -2
- package/dist/devbox/commands/init/codex/remote.js.map +1 -1
- package/dist/devbox/commands/init/index.d.ts.map +1 -1
- package/dist/devbox/commands/init/index.js +1 -1
- package/dist/devbox/commands/init/index.js.map +1 -1
- package/dist/devbox/commands/init/session.js +1 -1
- package/dist/devbox/commands/init/session.js.map +1 -1
- 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/dist/devbox/ui/statusLine.d.ts.map +1 -1
- package/dist/devbox/ui/statusLine.js +3 -1
- package/dist/devbox/ui/statusLine.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;
|
|
@@ -141302,7 +141302,9 @@ var init_statusLine = __esm({
|
|
|
141302
141302
|
enabled,
|
|
141303
141303
|
stream = process.stderr
|
|
141304
141304
|
}) => {
|
|
141305
|
-
|
|
141305
|
+
const usableColumns = typeof stream.columns !== "number" || stream.columns > 0;
|
|
141306
|
+
const spinnerEnabled = enabled && (!stream.isTTY || usableColumns);
|
|
141307
|
+
if (!spinnerEnabled) {
|
|
141306
141308
|
return {
|
|
141307
141309
|
stage: () => {
|
|
141308
141310
|
},
|
|
@@ -198479,6 +198481,592 @@ ${result.exception}`
|
|
|
198479
198481
|
}
|
|
198480
198482
|
});
|
|
198481
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
|
+
|
|
198482
199070
|
// src/devbox/commands/provider/modalRuntime.ts
|
|
198483
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;
|
|
198484
199072
|
var init_modalRuntime = __esm({
|
|
@@ -198490,6 +199078,7 @@ var init_modalRuntime = __esm({
|
|
|
198490
199078
|
import_ws4 = __toESM(require("ws"), 1);
|
|
198491
199079
|
init_src();
|
|
198492
199080
|
init_daemonClient();
|
|
199081
|
+
init_modalLifecycle();
|
|
198493
199082
|
SERVICE_NAME_PATTERN = /^[a-zA-Z0-9._-]+$/;
|
|
198494
199083
|
CORE_SERVICE_NAMES2 = /* @__PURE__ */ new Set(["devbox-sprite-daemon", "devbox-sshd"]);
|
|
198495
199084
|
MODAL_DAEMON_REQUEST_TIMEOUT_MS = 15e3;
|
|
@@ -198927,15 +199516,19 @@ var init_modalRuntime = __esm({
|
|
|
198927
199516
|
serviceRole: requestedServiceRole
|
|
198928
199517
|
}) => {
|
|
198929
199518
|
let modal = null;
|
|
199519
|
+
let modalSandboxName = alias;
|
|
198930
199520
|
try {
|
|
198931
199521
|
const modalCredentials = resolveModalClientCredentials({
|
|
198932
199522
|
...credentialMode ? { credentialMode } : {},
|
|
198933
199523
|
...credentials !== void 0 ? { credentials } : {},
|
|
198934
199524
|
...cwd ? { cwd } : {}
|
|
198935
199525
|
});
|
|
199526
|
+
const modalEnvironmentName = resolveModalEnvironmentName();
|
|
199527
|
+
modalSandboxName = resolveModalSandboxName(alias, modalEnvironmentName);
|
|
198936
199528
|
modal = new ModalClient2({
|
|
198937
199529
|
tokenId: modalCredentials.tokenId,
|
|
198938
|
-
tokenSecret: modalCredentials.tokenSecret
|
|
199530
|
+
tokenSecret: modalCredentials.tokenSecret,
|
|
199531
|
+
environment: modalEnvironmentName
|
|
198939
199532
|
});
|
|
198940
199533
|
} catch (error2) {
|
|
198941
199534
|
if (!(error2 instanceof ProviderClientError && error2.code === "authentication_required")) {
|
|
@@ -198964,7 +199557,7 @@ var init_modalRuntime = __esm({
|
|
|
198964
199557
|
sandboxPromise = (async () => {
|
|
198965
199558
|
try {
|
|
198966
199559
|
const runningSandbox = await withTimeout3(
|
|
198967
|
-
directModal.sandboxes.fromName(appName,
|
|
199560
|
+
directModal.sandboxes.fromName(appName, modalSandboxName),
|
|
198968
199561
|
MODAL_SANDBOX_RESOLVE_TIMEOUT_MS,
|
|
198969
199562
|
"Timed out resolving running modal sandbox by name."
|
|
198970
199563
|
);
|
|
@@ -199483,530 +200076,6 @@ var init_modalRuntime = __esm({
|
|
|
199483
200076
|
}
|
|
199484
200077
|
});
|
|
199485
200078
|
|
|
199486
|
-
// src/devbox/commands/provider/modalLifecycle.ts
|
|
199487
|
-
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;
|
|
199488
|
-
var init_modalLifecycle = __esm({
|
|
199489
|
-
"src/devbox/commands/provider/modalLifecycle.ts"() {
|
|
199490
|
-
"use strict";
|
|
199491
|
-
init_src();
|
|
199492
|
-
import_node_crypto9 = require("node:crypto");
|
|
199493
|
-
init_dist5();
|
|
199494
|
-
init_controlPlane();
|
|
199495
|
-
DEFAULT_APP_NAME = "sandbox-modal-smoke";
|
|
199496
|
-
DEFAULT_MODAL_DEVBOX_IMAGE = "public.ecr.aws/d8m4p4w9/modal-devbox:latest";
|
|
199497
|
-
DEFAULT_TIMEOUT_MS = 24 * 60 * 60 * 1e3;
|
|
199498
|
-
IMAGE_TAG_RESOLUTION_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
199499
|
-
SANDBOX_LIST_PAGE_LIMIT = 100;
|
|
199500
|
-
MODAL_DAEMON_WRAPPER_PATH = "/root/.devbox/daemon/run-daemon.sh";
|
|
199501
|
-
MODAL_DAEMON_SUPERVISOR_ENTRYPOINT = [
|
|
199502
|
-
"/bin/sh",
|
|
199503
|
-
"-lc",
|
|
199504
|
-
[
|
|
199505
|
-
"set -u",
|
|
199506
|
-
`wrapper=${JSON.stringify(MODAL_DAEMON_WRAPPER_PATH)}`,
|
|
199507
|
-
'until [ -x "$wrapper" ]; do sleep 0.25; done',
|
|
199508
|
-
"while true; do",
|
|
199509
|
-
' "$wrapper"',
|
|
199510
|
-
" status=$?",
|
|
199511
|
-
' echo "sprite-daemon exited with status $status; restarting" >&2',
|
|
199512
|
-
" sleep 1",
|
|
199513
|
-
"done"
|
|
199514
|
-
].join("\n")
|
|
199515
|
-
];
|
|
199516
|
-
FINISHED_STATUS_LABELS = {
|
|
199517
|
-
1: "success",
|
|
199518
|
-
2: "failure",
|
|
199519
|
-
3: "terminated",
|
|
199520
|
-
4: "timeout",
|
|
199521
|
-
5: "init_failure",
|
|
199522
|
-
6: "internal_failure",
|
|
199523
|
-
7: "idle_timeout"
|
|
199524
|
-
};
|
|
199525
|
-
REGISTRY_MANIFEST_ACCEPT_HEADER = [
|
|
199526
|
-
"application/vnd.oci.image.index.v1+json",
|
|
199527
|
-
"application/vnd.oci.image.manifest.v1+json",
|
|
199528
|
-
"application/vnd.docker.distribution.manifest.list.v2+json",
|
|
199529
|
-
"application/vnd.docker.distribution.manifest.v2+json"
|
|
199530
|
-
].join(", ");
|
|
199531
|
-
resolvedImageTagCache = /* @__PURE__ */ new Map();
|
|
199532
|
-
trimEnv2 = (value) => value?.trim() ?? "";
|
|
199533
|
-
parseRegistryImageTag = (imageTag) => {
|
|
199534
|
-
const trimmed = imageTag.trim();
|
|
199535
|
-
if (!trimmed || trimmed.includes("@")) {
|
|
199536
|
-
return null;
|
|
199537
|
-
}
|
|
199538
|
-
const lastSlashIndex = trimmed.lastIndexOf("/");
|
|
199539
|
-
const lastColonIndex = trimmed.lastIndexOf(":");
|
|
199540
|
-
if (lastColonIndex <= lastSlashIndex) {
|
|
199541
|
-
return null;
|
|
199542
|
-
}
|
|
199543
|
-
const repositoryWithHost = trimmed.slice(0, lastColonIndex);
|
|
199544
|
-
const tag = trimmed.slice(lastColonIndex + 1).trim();
|
|
199545
|
-
if (!repositoryWithHost || !tag) {
|
|
199546
|
-
return null;
|
|
199547
|
-
}
|
|
199548
|
-
const firstSlashIndex = repositoryWithHost.indexOf("/");
|
|
199549
|
-
if (firstSlashIndex <= 0) {
|
|
199550
|
-
return null;
|
|
199551
|
-
}
|
|
199552
|
-
const registryHost = repositoryWithHost.slice(0, firstSlashIndex);
|
|
199553
|
-
const repository = repositoryWithHost.slice(firstSlashIndex + 1);
|
|
199554
|
-
if (!repository) {
|
|
199555
|
-
return null;
|
|
199556
|
-
}
|
|
199557
|
-
const hasExplicitRegistryHost = registryHost.includes(".") || registryHost.includes(":") || registryHost === "localhost";
|
|
199558
|
-
if (!hasExplicitRegistryHost) {
|
|
199559
|
-
return null;
|
|
199560
|
-
}
|
|
199561
|
-
return {
|
|
199562
|
-
registryHost,
|
|
199563
|
-
repository,
|
|
199564
|
-
tag,
|
|
199565
|
-
repositoryWithHost
|
|
199566
|
-
};
|
|
199567
|
-
};
|
|
199568
|
-
parseWwwAuthenticateBearer = (headerValue) => {
|
|
199569
|
-
const trimmed = headerValue.trim();
|
|
199570
|
-
if (!trimmed.toLowerCase().startsWith("bearer ")) {
|
|
199571
|
-
return null;
|
|
199572
|
-
}
|
|
199573
|
-
const attributes = /* @__PURE__ */ new Map();
|
|
199574
|
-
for (const match2 of trimmed.slice("bearer ".length).matchAll(/([A-Za-z0-9_-]+)="([^"]*)"/g)) {
|
|
199575
|
-
const [, key, value] = match2;
|
|
199576
|
-
if (!key) {
|
|
199577
|
-
continue;
|
|
199578
|
-
}
|
|
199579
|
-
attributes.set(key.toLowerCase(), value ?? "");
|
|
199580
|
-
}
|
|
199581
|
-
const realm = attributes.get("realm");
|
|
199582
|
-
const service = attributes.get("service");
|
|
199583
|
-
const scope = attributes.get("scope");
|
|
199584
|
-
if (!realm || !service) {
|
|
199585
|
-
return null;
|
|
199586
|
-
}
|
|
199587
|
-
return {
|
|
199588
|
-
realm,
|
|
199589
|
-
service,
|
|
199590
|
-
scope: scope || null
|
|
199591
|
-
};
|
|
199592
|
-
};
|
|
199593
|
-
fetchRegistryToken = async ({
|
|
199594
|
-
realm,
|
|
199595
|
-
service,
|
|
199596
|
-
scope
|
|
199597
|
-
}) => {
|
|
199598
|
-
const tokenUrl = new URL(realm);
|
|
199599
|
-
tokenUrl.searchParams.set("service", service);
|
|
199600
|
-
if (scope) {
|
|
199601
|
-
tokenUrl.searchParams.set("scope", scope);
|
|
199602
|
-
}
|
|
199603
|
-
const response = await fetch(tokenUrl.toString());
|
|
199604
|
-
if (!response.ok) {
|
|
199605
|
-
throw new Error(
|
|
199606
|
-
`Container registry auth token request failed (${response.status}).`
|
|
199607
|
-
);
|
|
199608
|
-
}
|
|
199609
|
-
const payload = await response.json();
|
|
199610
|
-
const token = typeof payload.token === "string" ? payload.token.trim() : typeof payload.access_token === "string" ? payload.access_token.trim() : "";
|
|
199611
|
-
if (!token) {
|
|
199612
|
-
throw new Error("Container registry auth token response was empty.");
|
|
199613
|
-
}
|
|
199614
|
-
return token;
|
|
199615
|
-
};
|
|
199616
|
-
resolveLatestImageTagToDigest = async (parsed) => {
|
|
199617
|
-
const manifestUrl = `https://${parsed.registryHost}/v2/${parsed.repository}/manifests/${encodeURIComponent(parsed.tag)}`;
|
|
199618
|
-
const fetchManifest = async ({
|
|
199619
|
-
method,
|
|
199620
|
-
token: token2
|
|
199621
|
-
}) => {
|
|
199622
|
-
const headers = {
|
|
199623
|
-
Accept: REGISTRY_MANIFEST_ACCEPT_HEADER
|
|
199624
|
-
};
|
|
199625
|
-
if (token2) {
|
|
199626
|
-
headers.Authorization = `Bearer ${token2}`;
|
|
199627
|
-
}
|
|
199628
|
-
return await fetch(manifestUrl, {
|
|
199629
|
-
headers,
|
|
199630
|
-
method
|
|
199631
|
-
});
|
|
199632
|
-
};
|
|
199633
|
-
let token = null;
|
|
199634
|
-
let headResponse = await fetchManifest({ method: "HEAD" });
|
|
199635
|
-
if (headResponse.status === 401) {
|
|
199636
|
-
const authHeader = headResponse.headers.get("www-authenticate") ?? "";
|
|
199637
|
-
const challenge = parseWwwAuthenticateBearer(authHeader);
|
|
199638
|
-
if (!challenge) {
|
|
199639
|
-
throw new Error(
|
|
199640
|
-
`Container registry auth challenge missing or invalid for ${parsed.repositoryWithHost}:${parsed.tag}.`
|
|
199641
|
-
);
|
|
199642
|
-
}
|
|
199643
|
-
token = await fetchRegistryToken(challenge);
|
|
199644
|
-
headResponse = await fetchManifest({
|
|
199645
|
-
method: "HEAD",
|
|
199646
|
-
token
|
|
199647
|
-
});
|
|
199648
|
-
}
|
|
199649
|
-
if (!headResponse.ok) {
|
|
199650
|
-
throw new Error(
|
|
199651
|
-
`Container registry manifest lookup failed for ${parsed.repositoryWithHost}:${parsed.tag} (${headResponse.status}).`
|
|
199652
|
-
);
|
|
199653
|
-
}
|
|
199654
|
-
const headDigest = headResponse.headers.get("docker-content-digest")?.trim();
|
|
199655
|
-
if (headDigest) {
|
|
199656
|
-
return `${parsed.repositoryWithHost}@${headDigest}`;
|
|
199657
|
-
}
|
|
199658
|
-
const getResponse = await fetchManifest(
|
|
199659
|
-
token ? {
|
|
199660
|
-
method: "GET",
|
|
199661
|
-
token
|
|
199662
|
-
} : {
|
|
199663
|
-
method: "GET"
|
|
199664
|
-
}
|
|
199665
|
-
);
|
|
199666
|
-
if (!getResponse.ok) {
|
|
199667
|
-
throw new Error(
|
|
199668
|
-
`Container registry manifest body lookup failed for ${parsed.repositoryWithHost}:${parsed.tag} (${getResponse.status}).`
|
|
199669
|
-
);
|
|
199670
|
-
}
|
|
199671
|
-
const headerDigest = getResponse.headers.get("docker-content-digest")?.trim();
|
|
199672
|
-
if (headerDigest) {
|
|
199673
|
-
return `${parsed.repositoryWithHost}@${headerDigest}`;
|
|
199674
|
-
}
|
|
199675
|
-
const manifestBytes = Buffer.from(await getResponse.arrayBuffer());
|
|
199676
|
-
const bodyDigest = `sha256:${(0, import_node_crypto9.createHash)("sha256").update(manifestBytes).digest("hex")}`;
|
|
199677
|
-
return `${parsed.repositoryWithHost}@${bodyDigest}`;
|
|
199678
|
-
};
|
|
199679
|
-
resolveImageTagForBuild = async (imageTag) => {
|
|
199680
|
-
const parsed = parseRegistryImageTag(imageTag);
|
|
199681
|
-
if (!parsed || parsed.tag !== "latest") {
|
|
199682
|
-
return imageTag;
|
|
199683
|
-
}
|
|
199684
|
-
const cacheKey = `${parsed.repositoryWithHost}:${parsed.tag}`;
|
|
199685
|
-
const now = Date.now();
|
|
199686
|
-
const cached = resolvedImageTagCache.get(cacheKey);
|
|
199687
|
-
if (cached && cached.expiresAt > now) {
|
|
199688
|
-
return cached.value;
|
|
199689
|
-
}
|
|
199690
|
-
const resolved = await resolveLatestImageTagToDigest(parsed);
|
|
199691
|
-
resolvedImageTagCache.set(cacheKey, {
|
|
199692
|
-
value: resolved,
|
|
199693
|
-
expiresAt: now + IMAGE_TAG_RESOLUTION_CACHE_TTL_MS
|
|
199694
|
-
});
|
|
199695
|
-
return resolved;
|
|
199696
|
-
};
|
|
199697
|
-
decodeJwtExpMs = (token) => {
|
|
199698
|
-
const segments = token.split(".");
|
|
199699
|
-
if (segments.length < 2) return null;
|
|
199700
|
-
const payload = segments[1];
|
|
199701
|
-
if (!payload) return null;
|
|
199702
|
-
const normalized = payload.replace(/-/g, "+").replace(/_/g, "/");
|
|
199703
|
-
const padLength = (4 - normalized.length % 4) % 4;
|
|
199704
|
-
const padded = `${normalized}${"=".repeat(padLength)}`;
|
|
199705
|
-
try {
|
|
199706
|
-
const parsed = JSON.parse(
|
|
199707
|
-
Buffer.from(padded, "base64").toString("utf8")
|
|
199708
|
-
);
|
|
199709
|
-
const exp = parsed.exp;
|
|
199710
|
-
if (typeof exp !== "number" || !Number.isFinite(exp) || exp <= 0) {
|
|
199711
|
-
return null;
|
|
199712
|
-
}
|
|
199713
|
-
return Math.floor(exp * 1e3);
|
|
199714
|
-
} catch {
|
|
199715
|
-
return null;
|
|
199716
|
-
}
|
|
199717
|
-
};
|
|
199718
|
-
createSafeModalAuthTokenManager = (modal) => {
|
|
199719
|
-
let token = "";
|
|
199720
|
-
let tokenExpMs = 0;
|
|
199721
|
-
let inFlight = null;
|
|
199722
|
-
const TOKEN_REFRESH_SKEW_MS = 3e4;
|
|
199723
|
-
const FALLBACK_TOKEN_TTL_MS = 15 * 60 * 1e3;
|
|
199724
|
-
const hasFreshToken = () => token.length > 0 && Date.now() + TOKEN_REFRESH_SKEW_MS < tokenExpMs;
|
|
199725
|
-
const fetchToken = async () => {
|
|
199726
|
-
const authTokenGet = modal.cpClient.authTokenGet;
|
|
199727
|
-
if (typeof authTokenGet !== "function") {
|
|
199728
|
-
throw new Error("Modal auth token endpoint unavailable.");
|
|
199729
|
-
}
|
|
199730
|
-
const response = await authTokenGet({});
|
|
199731
|
-
const nextToken = typeof response?.token === "string" ? response.token.trim() : "";
|
|
199732
|
-
if (!nextToken) {
|
|
199733
|
-
throw new Error("Modal auth token unavailable.");
|
|
199734
|
-
}
|
|
199735
|
-
token = nextToken;
|
|
199736
|
-
tokenExpMs = decodeJwtExpMs(nextToken) ?? Date.now() + FALLBACK_TOKEN_TTL_MS;
|
|
199737
|
-
return nextToken;
|
|
199738
|
-
};
|
|
199739
|
-
return {
|
|
199740
|
-
start: () => {
|
|
199741
|
-
},
|
|
199742
|
-
stop: () => {
|
|
199743
|
-
token = "";
|
|
199744
|
-
tokenExpMs = 0;
|
|
199745
|
-
inFlight = null;
|
|
199746
|
-
},
|
|
199747
|
-
getToken: async () => {
|
|
199748
|
-
if (hasFreshToken()) return token;
|
|
199749
|
-
if (!inFlight) {
|
|
199750
|
-
inFlight = fetchToken().finally(() => {
|
|
199751
|
-
inFlight = null;
|
|
199752
|
-
});
|
|
199753
|
-
}
|
|
199754
|
-
return await inFlight;
|
|
199755
|
-
}
|
|
199756
|
-
};
|
|
199757
|
-
};
|
|
199758
|
-
installSafeModalAuthTokenManager = (modal) => {
|
|
199759
|
-
const candidate = modal;
|
|
199760
|
-
if (candidate.authTokenManager) return;
|
|
199761
|
-
candidate.authTokenManager = createSafeModalAuthTokenManager(candidate);
|
|
199762
|
-
};
|
|
199763
|
-
parsePositiveInt = (value, fallback2) => {
|
|
199764
|
-
const parsed = Number.parseInt(value, 10);
|
|
199765
|
-
if (!Number.isFinite(parsed) || parsed <= 0) return fallback2;
|
|
199766
|
-
return parsed;
|
|
199767
|
-
};
|
|
199768
|
-
resolveRegions = () => {
|
|
199769
|
-
const raw = trimEnv2(process.env.MODAL_SANDBOX_REGION);
|
|
199770
|
-
if (!raw) return [];
|
|
199771
|
-
return raw.split(",").map((value) => value.trim()).filter((value) => value.length > 0);
|
|
199772
|
-
};
|
|
199773
|
-
resolveAppName = () => trimEnv2(process.env.MODAL_SANDBOX_APP) || DEFAULT_APP_NAME;
|
|
199774
|
-
resolveModalSandboxTimeoutMs = () => parsePositiveInt(
|
|
199775
|
-
trimEnv2(process.env.MODAL_SANDBOX_TIMEOUT_MS),
|
|
199776
|
-
DEFAULT_TIMEOUT_MS
|
|
199777
|
-
);
|
|
199778
|
-
isNotFoundError = (error2) => error2 instanceof NotFoundError;
|
|
199779
|
-
isModalAlreadyExistsError = (error2) => {
|
|
199780
|
-
if (error2 instanceof AlreadyExistsError) {
|
|
199781
|
-
return true;
|
|
199782
|
-
}
|
|
199783
|
-
const message = error2 instanceof Error ? `${error2.name} ${error2.message}` : String(error2 ?? "");
|
|
199784
|
-
if (/\bALREADY_EXISTS\b/i.test(message)) {
|
|
199785
|
-
return true;
|
|
199786
|
-
}
|
|
199787
|
-
return /already exists/i.test(message);
|
|
199788
|
-
};
|
|
199789
|
-
trimToNull = (value) => {
|
|
199790
|
-
if (typeof value !== "string") return null;
|
|
199791
|
-
const trimmed = value.trim();
|
|
199792
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
199793
|
-
};
|
|
199794
|
-
resolveControlPlaneToken = (options) => trimToNull(options?.credentials?.controlPlaneToken);
|
|
199795
|
-
hasContextModalCredentialPair = (options) => Boolean(
|
|
199796
|
-
trimToNull(options?.credentials?.modalTokenId) && trimToNull(options?.credentials?.modalTokenSecret)
|
|
199797
|
-
);
|
|
199798
|
-
shouldUseControlPlaneFallback = (options) => !options?.client && Boolean(resolveControlPlaneToken(options)) && !hasContextModalCredentialPair(options);
|
|
199799
|
-
withModalClient = async (options, fn) => {
|
|
199800
|
-
if (options?.client) {
|
|
199801
|
-
return await fn(options.client);
|
|
199802
|
-
}
|
|
199803
|
-
const modalCredentials = resolveModalClientCredentials({
|
|
199804
|
-
...options?.credentialMode ? { credentialMode: options.credentialMode } : {},
|
|
199805
|
-
...options?.credentials !== void 0 ? { credentials: options.credentials } : {},
|
|
199806
|
-
...options?.cwd ? { cwd: options.cwd } : {}
|
|
199807
|
-
});
|
|
199808
|
-
const modal = new ModalClient2({
|
|
199809
|
-
tokenId: modalCredentials.tokenId,
|
|
199810
|
-
tokenSecret: modalCredentials.tokenSecret
|
|
199811
|
-
});
|
|
199812
|
-
installSafeModalAuthTokenManager(modal);
|
|
199813
|
-
try {
|
|
199814
|
-
return await fn(modal);
|
|
199815
|
-
} finally {
|
|
199816
|
-
modal.close();
|
|
199817
|
-
}
|
|
199818
|
-
};
|
|
199819
|
-
resolveModalApp = async (modal, appName, createIfMissing) => {
|
|
199820
|
-
try {
|
|
199821
|
-
const app = await modal.apps.fromName(appName, { createIfMissing });
|
|
199822
|
-
return { appId: app.appId, appName };
|
|
199823
|
-
} catch (error2) {
|
|
199824
|
-
if (!createIfMissing && isNotFoundError(error2)) {
|
|
199825
|
-
return null;
|
|
199826
|
-
}
|
|
199827
|
-
throw error2;
|
|
199828
|
-
}
|
|
199829
|
-
};
|
|
199830
|
-
listSandboxesRaw = async (modal, appId, includeFinished) => {
|
|
199831
|
-
const sandboxes = [];
|
|
199832
|
-
let beforeTimestamp = 0;
|
|
199833
|
-
let guard = 0;
|
|
199834
|
-
while (true) {
|
|
199835
|
-
guard += 1;
|
|
199836
|
-
if (guard > SANDBOX_LIST_PAGE_LIMIT) {
|
|
199837
|
-
throw new Error("Modal sandbox list pagination exceeded safety limit.");
|
|
199838
|
-
}
|
|
199839
|
-
const response = await modal.cpClient.sandboxList({
|
|
199840
|
-
appId,
|
|
199841
|
-
beforeTimestamp,
|
|
199842
|
-
environmentName: modal.environmentName(),
|
|
199843
|
-
includeFinished,
|
|
199844
|
-
tags: []
|
|
199845
|
-
});
|
|
199846
|
-
if (!response.sandboxes.length) break;
|
|
199847
|
-
sandboxes.push(...response.sandboxes);
|
|
199848
|
-
const nextCursor = response.sandboxes[response.sandboxes.length - 1];
|
|
199849
|
-
if (!nextCursor || nextCursor.createdAt === beforeTimestamp) break;
|
|
199850
|
-
beforeTimestamp = nextCursor.createdAt;
|
|
199851
|
-
}
|
|
199852
|
-
return sandboxes;
|
|
199853
|
-
};
|
|
199854
|
-
formatSandboxStatus = (sandbox) => {
|
|
199855
|
-
const result = sandbox.taskInfo?.result;
|
|
199856
|
-
const status = result?.status ?? 0;
|
|
199857
|
-
if (status === 0) return "running";
|
|
199858
|
-
const label = FINISHED_STATUS_LABELS[status] ?? String(status);
|
|
199859
|
-
const exitCode = result?.exitcode ?? "unknown";
|
|
199860
|
-
return `finished:${label}:exit=${String(exitCode)}`;
|
|
199861
|
-
};
|
|
199862
|
-
isRunningSandbox = (sandbox) => (sandbox.taskInfo?.result?.status ?? 0) === 0;
|
|
199863
|
-
resolveImageFromTag = async (modal, imageTag) => {
|
|
199864
|
-
const secretName = trimEnv2(process.env.MODAL_SANDBOX_IMAGE_SECRET);
|
|
199865
|
-
if (!secretName) {
|
|
199866
|
-
return modal.images.fromRegistry(imageTag);
|
|
199867
|
-
}
|
|
199868
|
-
const secret = await modal.secrets.fromName(secretName);
|
|
199869
|
-
if (imageTag.includes(".dkr.ecr.")) {
|
|
199870
|
-
return modal.images.fromAwsEcr(imageTag, secret);
|
|
199871
|
-
}
|
|
199872
|
-
return modal.images.fromRegistry(imageTag, secret);
|
|
199873
|
-
};
|
|
199874
|
-
provisionModalSandbox = async (alias, options) => {
|
|
199875
|
-
if (shouldUseControlPlaneFallback(options)) {
|
|
199876
|
-
const controlPlaneToken = resolveControlPlaneToken(options);
|
|
199877
|
-
if (!controlPlaneToken) {
|
|
199878
|
-
throw new Error(
|
|
199879
|
-
"Control plane token is required for modal provisioning."
|
|
199880
|
-
);
|
|
199881
|
-
}
|
|
199882
|
-
return await provisionModalSandboxViaControlPlane(controlPlaneToken, alias);
|
|
199883
|
-
}
|
|
199884
|
-
const appName = resolveAppName();
|
|
199885
|
-
const envImageTag = trimEnv2(process.env.MODAL_SANDBOX_IMAGE);
|
|
199886
|
-
const imageTag = envImageTag || DEFAULT_MODAL_DEVBOX_IMAGE;
|
|
199887
|
-
const resolvedImageTag = await resolveImageTagForBuild(imageTag);
|
|
199888
|
-
const timeoutMs = resolveModalSandboxTimeoutMs();
|
|
199889
|
-
const timeoutSecs = Math.max(1, Math.floor(timeoutMs / 1e3));
|
|
199890
|
-
const regions = resolveRegions();
|
|
199891
|
-
return await withModalClient(options, async (modal) => {
|
|
199892
|
-
const app = await resolveModalApp(modal, appName, true);
|
|
199893
|
-
if (!app) {
|
|
199894
|
-
throw new Error(`Could not resolve Modal app "${appName}".`);
|
|
199895
|
-
}
|
|
199896
|
-
const buildImage = async (tag) => {
|
|
199897
|
-
const image = await resolveImageFromTag(modal, tag);
|
|
199898
|
-
return await image.build({ appId: app.appId });
|
|
199899
|
-
};
|
|
199900
|
-
const builtImage = await buildImage(resolvedImageTag);
|
|
199901
|
-
const createResponse = await modal.cpClient.sandboxCreate({
|
|
199902
|
-
appId: app.appId,
|
|
199903
|
-
definition: {
|
|
199904
|
-
imageId: builtImage.imageId,
|
|
199905
|
-
timeoutSecs,
|
|
199906
|
-
name: alias,
|
|
199907
|
-
...regions.length > 0 ? { schedulerPlacement: { regions } } : {},
|
|
199908
|
-
entrypointArgs: MODAL_DAEMON_SUPERVISOR_ENTRYPOINT,
|
|
199909
|
-
enableSnapshot: true
|
|
199910
|
-
}
|
|
199911
|
-
});
|
|
199912
|
-
return {
|
|
199913
|
-
sandboxId: createResponse.sandboxId,
|
|
199914
|
-
appId: app.appId,
|
|
199915
|
-
appName,
|
|
199916
|
-
imageTag: resolvedImageTag,
|
|
199917
|
-
timeoutMs,
|
|
199918
|
-
memorySnapshotEnabled: false,
|
|
199919
|
-
regions
|
|
199920
|
-
};
|
|
199921
|
-
});
|
|
199922
|
-
};
|
|
199923
|
-
findModalSandbox = async (options, operationOptions) => {
|
|
199924
|
-
if (shouldUseControlPlaneFallback(operationOptions)) {
|
|
199925
|
-
const controlPlaneToken = resolveControlPlaneToken(operationOptions);
|
|
199926
|
-
if (!controlPlaneToken) {
|
|
199927
|
-
throw new Error(
|
|
199928
|
-
"Control plane token is required for modal sandbox lookup."
|
|
199929
|
-
);
|
|
199930
|
-
}
|
|
199931
|
-
return await findModalSandboxViaControlPlane(controlPlaneToken, options);
|
|
199932
|
-
}
|
|
199933
|
-
const appName = resolveAppName();
|
|
199934
|
-
const includeFinished = options.includeFinished ?? true;
|
|
199935
|
-
return await withModalClient(operationOptions, async (modal) => {
|
|
199936
|
-
const app = await resolveModalApp(modal, appName, false);
|
|
199937
|
-
if (!app) return null;
|
|
199938
|
-
const sandboxes = await listSandboxesRaw(modal, app.appId, includeFinished);
|
|
199939
|
-
const matching = sandboxes.filter((sandbox) => {
|
|
199940
|
-
if (options.sandboxId && sandbox.id === options.sandboxId) return true;
|
|
199941
|
-
return sandbox.name === options.alias;
|
|
199942
|
-
});
|
|
199943
|
-
if (matching.length === 0) return null;
|
|
199944
|
-
matching.sort((left, right) => {
|
|
199945
|
-
const runningOrder = Number(isRunningSandbox(right)) - Number(isRunningSandbox(left));
|
|
199946
|
-
if (runningOrder !== 0) return runningOrder;
|
|
199947
|
-
return right.createdAt - left.createdAt;
|
|
199948
|
-
});
|
|
199949
|
-
const selected = matching[0];
|
|
199950
|
-
if (!selected) {
|
|
199951
|
-
throw new Error("Modal sandbox selection failed.");
|
|
199952
|
-
}
|
|
199953
|
-
return {
|
|
199954
|
-
sandboxId: selected.id,
|
|
199955
|
-
appId: app.appId,
|
|
199956
|
-
appName: app.appName,
|
|
199957
|
-
name: selected.name,
|
|
199958
|
-
createdAt: selected.createdAt,
|
|
199959
|
-
status: formatSandboxStatus(selected),
|
|
199960
|
-
regions: selected.regions
|
|
199961
|
-
};
|
|
199962
|
-
});
|
|
199963
|
-
};
|
|
199964
|
-
terminateModalSandboxesByAlias = async (alias, options) => {
|
|
199965
|
-
if (shouldUseControlPlaneFallback(options)) {
|
|
199966
|
-
const controlPlaneToken = resolveControlPlaneToken(options);
|
|
199967
|
-
if (!controlPlaneToken) {
|
|
199968
|
-
throw new Error(
|
|
199969
|
-
"Control plane token is required for modal sandbox termination."
|
|
199970
|
-
);
|
|
199971
|
-
}
|
|
199972
|
-
return await terminateModalSandboxesByAliasViaControlPlane(
|
|
199973
|
-
controlPlaneToken,
|
|
199974
|
-
{
|
|
199975
|
-
alias,
|
|
199976
|
-
...typeof options?.includeFinished === "boolean" ? { includeFinished: options.includeFinished } : {}
|
|
199977
|
-
}
|
|
199978
|
-
);
|
|
199979
|
-
}
|
|
199980
|
-
const appName = resolveAppName();
|
|
199981
|
-
const includeFinished = options?.includeFinished ?? false;
|
|
199982
|
-
return await withModalClient(options, async (modal) => {
|
|
199983
|
-
const app = await resolveModalApp(modal, appName, false);
|
|
199984
|
-
if (!app) {
|
|
199985
|
-
return {
|
|
199986
|
-
appName,
|
|
199987
|
-
appId: null,
|
|
199988
|
-
matchedSandboxIds: [],
|
|
199989
|
-
terminatedSandboxIds: []
|
|
199990
|
-
};
|
|
199991
|
-
}
|
|
199992
|
-
const sandboxes = await listSandboxesRaw(modal, app.appId, includeFinished);
|
|
199993
|
-
const matching = sandboxes.filter((sandbox) => sandbox.name === alias);
|
|
199994
|
-
const terminatedSandboxIds = [];
|
|
199995
|
-
for (const sandbox of matching) {
|
|
199996
|
-
await modal.cpClient.sandboxTerminate({ sandboxId: sandbox.id });
|
|
199997
|
-
terminatedSandboxIds.push(sandbox.id);
|
|
199998
|
-
}
|
|
199999
|
-
return {
|
|
200000
|
-
appName: app.appName,
|
|
200001
|
-
appId: app.appId,
|
|
200002
|
-
matchedSandboxIds: matching.map((sandbox) => sandbox.id),
|
|
200003
|
-
terminatedSandboxIds
|
|
200004
|
-
};
|
|
200005
|
-
});
|
|
200006
|
-
};
|
|
200007
|
-
}
|
|
200008
|
-
});
|
|
200009
|
-
|
|
200010
200079
|
// src/devbox/commands/providerClient.ts
|
|
200011
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;
|
|
200012
200081
|
var init_providerClient = __esm({
|
|
@@ -205365,7 +205434,7 @@ var init_session3 = __esm({
|
|
|
205365
205434
|
nonInteractive || shouldResume && initState?.steps.codexApplied
|
|
205366
205435
|
);
|
|
205367
205436
|
const skipCodexCliEnsure = Boolean(
|
|
205368
|
-
|
|
205437
|
+
shouldResume && initState?.steps.codexCliEnsured
|
|
205369
205438
|
);
|
|
205370
205439
|
return {
|
|
205371
205440
|
initState,
|
|
@@ -206416,7 +206485,16 @@ var init_remote2 = __esm({
|
|
|
206416
206485
|
});
|
|
206417
206486
|
};
|
|
206418
206487
|
ensureRemoteCodexInstalled = async (client2, spriteAlias) => {
|
|
206419
|
-
const
|
|
206488
|
+
const installScript = [
|
|
206489
|
+
"set -euo pipefail",
|
|
206490
|
+
'prefix="${HOME}/.local"',
|
|
206491
|
+
'npm install -g --prefix "$prefix" @openai/codex --loglevel=error',
|
|
206492
|
+
'if [ ! -x "$prefix/bin/codex" ]; then',
|
|
206493
|
+
' echo "codex binary missing at $prefix/bin/codex" >&2',
|
|
206494
|
+
" exit 1",
|
|
206495
|
+
"fi",
|
|
206496
|
+
'"$prefix/bin/codex" --version >/dev/null'
|
|
206497
|
+
].join("\n");
|
|
206420
206498
|
const install = await client2.exec(spriteAlias, [
|
|
206421
206499
|
"/bin/bash",
|
|
206422
206500
|
"--noprofile",
|
|
@@ -206426,8 +206504,7 @@ var init_remote2 = __esm({
|
|
|
206426
206504
|
"-o",
|
|
206427
206505
|
"pipefail",
|
|
206428
206506
|
"-c",
|
|
206429
|
-
|
|
206430
|
-
npm install -g @openai/codex`
|
|
206507
|
+
installScript
|
|
206431
206508
|
]);
|
|
206432
206509
|
if (install.exitCode !== 0) {
|
|
206433
206510
|
throw new Error(install.stderr || "Failed to install/upgrade Codex.");
|
|
@@ -211015,7 +211092,7 @@ ${sshResult.stderr}`.trim();
|
|
|
211015
211092
|
});
|
|
211016
211093
|
|
|
211017
211094
|
// src/devbox/commands/init/claudeBootstrap.ts
|
|
211018
|
-
var import_promises29, import_node_path32, import_node_crypto16, import_node_child_process11, import_node_os17, import_node_util5, REMOTE_CLAUDE_DIR, REMOTE_CLAUDE_JSON_PATH, REMOTE_CLAUDE_CONFIG_OVERRIDE_PATH, REMOTE_CLAUDE_SETTINGS_PATH, REMOTE_CLAUDE_CREDENTIALS_PATH, REMOTE_CLAUDE_MD_PATH, REMOTE_CLAUDE_PLUGINS_DIR, REMOTE_CLAUDE_PLUGINS_CONFIG_PATH, CLAUDE_STATE_VARIANT_PATTERN, SECURITY_TIMEOUT_MS, OAUTH_SERVICE_SUFFIX_CANDIDATES, CLAUDE_ROOT_ALLOWLIST, CLAUDE_PROJECT_ALLOWLIST, isRecord2, hasOwn, execFileAsync, stripLeadingBom, getExecErrorStatus,
|
|
211095
|
+
var import_promises29, import_node_path32, import_node_crypto16, import_node_child_process11, import_node_os17, import_node_util5, REMOTE_CLAUDE_DIR, REMOTE_CLAUDE_JSON_PATH, REMOTE_CLAUDE_CONFIG_OVERRIDE_PATH, REMOTE_CLAUDE_SETTINGS_PATH, REMOTE_CLAUDE_CREDENTIALS_PATH, REMOTE_CLAUDE_MD_PATH, REMOTE_CLAUDE_PLUGINS_DIR, REMOTE_CLAUDE_PLUGINS_CONFIG_PATH, CLAUDE_STATE_VARIANT_PATTERN, SECURITY_TIMEOUT_MS, OAUTH_SERVICE_SUFFIX_CANDIDATES, CLAUDE_ROOT_ALLOWLIST, CLAUDE_PROJECT_ALLOWLIST, isRecord2, hasOwn, execFileAsync, stripLeadingBom, getExecErrorStatus, getExecErrorExitCode, parseJsonRecord3, uniquePaths, resolveLocalClaudeDirCandidates, resolveLocalClaudeStateBaseDir, resolveLocalClaudeStorageDir, getCredentialStorageHashSuffix, getOauthServiceSuffixCandidates, resolveClaudeCredentialKeychainServices, resolveClaudeCredentialKeychainAccounts, listClaudeStateVariantPaths, readFileIfExists, findFirstExistingFile, readLocalClaudeStateSource, resolveLocalClaudeFilePath, readLocalClaudeFile, readLocalClaudeSettings, extractClaudeOauthRecord, readClaudeOauthFromKeychain, readLocalClaudeOauthCredentials, normalizeLocalRepoRootCandidates, copyAllowlistedKeys, buildBootstrapClaudeState, mergeClaudeSettingsForDevbox, isNotFoundError2, readRemoteFileIfExists, ensureRemoteClaudeDirectories, applyRemoteClaudePermissions, bootstrapRemoteClaudeConfig;
|
|
211019
211096
|
var init_claudeBootstrap = __esm({
|
|
211020
211097
|
"src/devbox/commands/init/claudeBootstrap.ts"() {
|
|
211021
211098
|
"use strict";
|
|
@@ -211094,10 +211171,15 @@ var init_claudeBootstrap = __esm({
|
|
|
211094
211171
|
const status = error2.status;
|
|
211095
211172
|
return typeof status === "number" ? status : null;
|
|
211096
211173
|
};
|
|
211097
|
-
|
|
211174
|
+
getExecErrorExitCode = (error2) => {
|
|
211098
211175
|
if (!error2 || typeof error2 !== "object") return null;
|
|
211099
211176
|
const code2 = error2.code;
|
|
211100
|
-
|
|
211177
|
+
if (typeof code2 === "number") return code2;
|
|
211178
|
+
if (typeof code2 === "string") {
|
|
211179
|
+
const parsed = Number.parseInt(code2, 10);
|
|
211180
|
+
return Number.isNaN(parsed) ? null : parsed;
|
|
211181
|
+
}
|
|
211182
|
+
return null;
|
|
211101
211183
|
};
|
|
211102
211184
|
parseJsonRecord3 = (value, sourcePath) => {
|
|
211103
211185
|
const parsed = JSON.parse(stripLeadingBom(value.toString("utf8")));
|
|
@@ -211141,7 +211223,15 @@ var init_claudeBootstrap = __esm({
|
|
|
211141
211223
|
};
|
|
211142
211224
|
getOauthServiceSuffixCandidates = () => {
|
|
211143
211225
|
const preferred = process.env.CLAUDE_CODE_CUSTOM_OAUTH_URL ? "-custom-oauth" : "";
|
|
211144
|
-
|
|
211226
|
+
const ordered = [preferred, ...OAUTH_SERVICE_SUFFIX_CANDIDATES];
|
|
211227
|
+
const seen = /* @__PURE__ */ new Set();
|
|
211228
|
+
const candidates = [];
|
|
211229
|
+
for (const suffix of ordered) {
|
|
211230
|
+
if (seen.has(suffix)) continue;
|
|
211231
|
+
seen.add(suffix);
|
|
211232
|
+
candidates.push(suffix);
|
|
211233
|
+
}
|
|
211234
|
+
return candidates;
|
|
211145
211235
|
};
|
|
211146
211236
|
resolveClaudeCredentialKeychainServices = () => {
|
|
211147
211237
|
const storageHashSuffix = getCredentialStorageHashSuffix();
|
|
@@ -211323,13 +211413,13 @@ var init_claudeBootstrap = __esm({
|
|
|
211323
211413
|
};
|
|
211324
211414
|
} catch (error2) {
|
|
211325
211415
|
const status = getExecErrorStatus(error2);
|
|
211326
|
-
|
|
211416
|
+
const exitCode = getExecErrorExitCode(error2);
|
|
211417
|
+
if (status === 44 || exitCode === 44) {
|
|
211327
211418
|
continue;
|
|
211328
211419
|
}
|
|
211329
211420
|
if (!warning) {
|
|
211330
|
-
const code2 = getExecErrorCode(error2);
|
|
211331
211421
|
const rawMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
211332
|
-
const detail = status ? `status ${status}` :
|
|
211422
|
+
const detail = status ? `status ${status}` : exitCode !== null ? `code ${exitCode}` : rawMessage;
|
|
211333
211423
|
warning = `Failed to copy Claude OAuth credentials from macOS Keychain (${detail}).`;
|
|
211334
211424
|
}
|
|
211335
211425
|
continue;
|
|
@@ -213663,7 +213753,7 @@ var init_init = __esm({
|
|
|
213663
213753
|
".devbox",
|
|
213664
213754
|
"setup-artifacts.parts.json"
|
|
213665
213755
|
);
|
|
213666
|
-
const pathSetup = 'export PATH="$(npm bin -g 2>/dev/null):$PATH"';
|
|
213756
|
+
const pathSetup = 'export PATH="$HOME/.local/bin:$(npm bin -g 2>/dev/null || true):$PATH"';
|
|
213667
213757
|
let canonical = alias;
|
|
213668
213758
|
let projectCreatedAt = existingEntry?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
213669
213759
|
let projectLocalPaths = mergeLocalPaths(
|
|
@@ -220157,4 +220247,4 @@ smol-toml/dist/index.js:
|
|
|
220157
220247
|
*/
|
|
220158
220248
|
//# sourceMappingURL=dvb.cjs.map
|
|
220159
220249
|
|
|
220160
|
-
//# debugId=
|
|
220250
|
+
//# debugId=b785e941-0159-5a32-9ac9-c3686e30d3af
|