@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 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]="582fe27b-e777-538c-bbd5-5055c01e366b")}catch(e){}}();
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.78";
88692
- const rawGitSha = "47fdfa1265d82766958857c6dcfcc196103475be";
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.78";
120683
- const rawGitSha = "47fdfa1265d82766958857c6dcfcc196103475be";
120684
- const rawSentryRelease = "boxes-dev-dvb@1.0.78+47fdfa1265d82766958857c6dcfcc196103475be";
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, alias),
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=582fe27b-e777-538c-bbd5-5055c01e366b
220250
+ //# debugId=b785e941-0159-5a32-9ac9-c3686e30d3af