#!/usr/bin/env node
import {
  CLAUDE_FORWARDED_ENV_KEYS,
  CODEX_CREDENTIALS_BACKUP_FILE,
  CODEX_FORWARDED_ENV_KEYS,
  CREDENTIALS_BACKUP_FILE,
  OPENCODE_CREDENTIALS_BACKUP_FILE,
  OPENCODE_FORWARDED_ENV_KEYS,
  buildHostEnvFindArgs,
  buildTmuxConfigShellSnippet,
  ensureRelay,
  forgetBoxFromRelay,
  generateBoxId,
  generateRelayToken,
  generateVncPassword,
  hashProjectPath,
  isRealAgentCredential,
  portlessAlias,
  portlessGetUrl,
  portlessUnalias,
  projectDirSegment,
  registerBoxWithRelay,
  sanitizeMnemonic,
  stageClaudeCredentialsForUpload,
  stageClaudeStaticForUpload,
  stageCodexCredentialsForUpload,
  stageCodexStaticForUpload,
  stageOpencodeCredentialsForUpload,
  stageOpencodeStateForUpload,
  stageOpencodeStaticForUpload
} from "./chunk-ZJXTIH6C.js";
import {
  allocateProjectIndex,
  detectGitRepos,
  readState,
  recordBox,
  removeBoxRecord
} from "./chunk-SNTHHWKY.js";

// ../../packages/sandbox-cloud/dist/index.js
import { basename as basename2 } from "path";
import { chmod, mkdir, writeFile } from "fs/promises";
import { dirname } from "path";
import { mkdir as mkdir2, readFile, readdir, rm, writeFile as writeFile2 } from "fs/promises";
import { homedir } from "os";
import { basename, join } from "path";
import { mkdtemp, rm as rm2, writeFile as writeFile3 } from "fs/promises";
import { tmpdir } from "os";
import { join as join2 } from "path";
import { execa } from "execa";
import { mkdtemp as mkdtemp2, rm as rm3 } from "fs/promises";
import { tmpdir as tmpdir2 } from "os";
import { join as join3 } from "path";
import { execa as execa2 } from "execa";
import { readFile as readFile2 } from "fs/promises";
import { join as join4 } from "path";
import { parse as parseYaml } from "yaml";
import { execa as execa3 } from "execa";
import { existsSync, mkdirSync, renameSync, statSync } from "fs";
import { mkdtemp as mkdtemp3, rm as rm4 } from "fs/promises";
import { tmpdir as tmpdir3 } from "os";
import {
  basename as hostBasename,
  dirname as hostDirname,
  join as hostJoin,
  resolve as hostResolve
} from "path";
import { posix } from "path";
import { execa as execa4 } from "execa";
import { mkdtemp as mkdtemp4, rm as rm5, stat } from "fs/promises";
import { tmpdir as tmpdir4 } from "os";
import { join as join5 } from "path";
var CREDENTIALS_VOLUME = "agentbox-credentials";
var AGENT_SPECS = [
  {
    kind: "claude",
    staticMountPath: "/home/vscode/.claude",
    credentialsMountPath: "/home/vscode/.agentbox-creds/claude",
    credentialsSubpath: "claude/",
    stageStatic: (opts) => stageClaudeStaticForUpload({ hostWorkspace: opts.hostWorkspace }),
    stageCredentials: () => stageClaudeCredentialsForUpload()
  },
  {
    kind: "codex",
    staticMountPath: "/home/vscode/.codex",
    credentialsMountPath: "/home/vscode/.agentbox-creds/codex",
    credentialsSubpath: "codex/",
    stageStatic: () => stageCodexStaticForUpload(),
    stageCredentials: () => stageCodexCredentialsForUpload()
  },
  {
    kind: "opencode",
    staticMountPath: "/home/vscode/.local/share/opencode",
    credentialsMountPath: "/home/vscode/.agentbox-creds/opencode",
    credentialsSubpath: "opencode/",
    stageStatic: () => stageOpencodeStaticForUpload(),
    stageCredentials: () => stageOpencodeCredentialsForUpload()
  }
];
var SEED_MARKER = ".agentbox-seeded-at";
async function ensureAgentVolumesForCloud(backend, opts = {}) {
  const log = opts.onLog ?? (() => {
  });
  if (typeof backend.ensureVolume !== "function") {
    log(
      `cloud backend '${backend.name}' has no volume primitive \u2014 agent credentials will not persist across boxes`
    );
    return { mounts: [], env: buildForwardedEnv([]), agents: [] };
  }
  let volumeId;
  try {
    const ensured = await backend.ensureVolume(CREDENTIALS_VOLUME);
    volumeId = ensured.volumeId;
  } catch (err) {
    const msg = err instanceof Error ? err.message : String(err);
    log(`ensureVolume(${CREDENTIALS_VOLUME}) failed (skipping credentials seed): ${msg}`);
    return { mounts: [], env: buildForwardedEnv([]), agents: [] };
  }
  const mounts = AGENT_SPECS.map((spec) => ({
    volumeId,
    mountPath: spec.credentialsMountPath,
    subpath: spec.credentialsSubpath
  }));
  const agents = AGENT_SPECS.map((s) => s.kind);
  return { mounts, env: buildForwardedEnv(agents), agents };
}
function buildForwardedEnv(agents) {
  const env = {};
  if (agents.includes("opencode")) {
    env["OPENCODE_CONFIG_DIR"] = "/home/vscode/.local/share/opencode/config";
  }
  const forwardedKeys = /* @__PURE__ */ new Set([
    ...CLAUDE_FORWARDED_ENV_KEYS,
    ...CODEX_FORWARDED_ENV_KEYS,
    ...OPENCODE_FORWARDED_ENV_KEYS
  ]);
  for (const k of forwardedKeys) {
    const v = process.env[k];
    if (typeof v === "string" && v.length > 0) env[k] = v;
  }
  return env;
}
async function seedAgentVolumesIfFresh(backend, handle, opts = {}) {
  const wanted = new Set(opts.agents ?? AGENT_SPECS.map((s) => s.kind));
  const specs = AGENT_SPECS.filter((s) => wanted.has(s.kind));
  await Promise.all(specs.map((spec) => seedCredentialsOne(backend, handle, spec, opts)));
}
async function seedCredentialsOne(backend, handle, spec, opts) {
  const log = opts.onLog ?? (() => {
  });
  if (!opts.force) {
    const probe = await backend.exec(
      handle,
      `test -f ${spec.credentialsMountPath}/${SEED_MARKER}`
    );
    if (probe.exitCode === 0) {
      log(`${spec.kind}: credentials already seeded \u2014 mounting only`);
      return;
    }
  }
  log(`${spec.kind}: staging host credentials`);
  const staged = await spec.stageCredentials();
  for (const w of staged.warnings) log(w);
  try {
    if (staged.tarballPath === null) {
      log(`${spec.kind}: no credentials to seed`);
      return;
    }
    let tarSize = 0;
    try {
      const { statSync: statSync2 } = await import("fs");
      tarSize = statSync2(staged.tarballPath).size;
    } catch {
    }
    const sizeKB = (tarSize / 1024).toFixed(1);
    log(`${spec.kind}: uploading ${sizeKB} KB credentials tarball`);
    process.stderr.write(`[agent-creds] ${spec.kind}: uploading ${sizeKB} KB...
`);
    const t0 = Date.now();
    const remoteTar = `/tmp/agentbox-${spec.kind}-creds.tar.gz`;
    await backend.uploadFile(handle, staged.tarballPath, remoteTar);
    const upDt = ((Date.now() - t0) / 1e3).toFixed(1);
    process.stderr.write(`[agent-creds] ${spec.kind}: upload done in ${upDt}s
`);
    const stageDir = `/tmp/agentbox-creds-stage-${spec.kind}`;
    const extractCmd = `set -e; rm -rf ${stageDir}; mkdir -p ${stageDir}; tar -xzf ${remoteTar} -C ${stageDir}; cp -r ${stageDir}/. ${spec.credentialsMountPath}/; rm -rf ${stageDir}; date -u +%FT%TZ > ${spec.credentialsMountPath}/${SEED_MARKER}; rm -f ${remoteTar}`;
    const extract = await backend.exec(handle, extractCmd);
    if (extract.exitCode !== 0) {
      const msg = `${spec.kind}: credentials extract failed (exit ${String(extract.exitCode)}); agent falls back to interactive login. stdout: ${extract.stdout.slice(-200)} stderr: ${extract.stderr.slice(-200)}`;
      log(msg);
      process.stderr.write(`[agent-creds] ${msg}
`);
      return;
    }
    log(`${spec.kind}: credentials seeded \u2713`);
    process.stderr.write(`[agent-creds] ${spec.kind}: credentials seeded
`);
  } finally {
    await staged.cleanup();
  }
}
var OPENCODE_STATE_DIR = "/home/vscode/.local/state/opencode";
async function seedOpencodeModelState(backend, handle, opts = {}) {
  const log = opts.onLog ?? (() => {
  });
  const staged = await stageOpencodeStateForUpload();
  if (staged.tarballPath === null) {
    log("opencode: no host model selection to seed");
    return;
  }
  try {
    const remoteTar = "/tmp/agentbox-opencode-state.tar.gz";
    await backend.uploadFile(handle, staged.tarballPath, remoteTar);
    const res = await backend.exec(
      handle,
      `set -e; mkdir -p ${OPENCODE_STATE_DIR}; tar -xzf ${remoteTar} -C ${OPENCODE_STATE_DIR}; chown -R vscode:vscode ${OPENCODE_STATE_DIR} 2>/dev/null || true; rm -f ${remoteTar}`
    );
    if (res.exitCode !== 0) {
      log(
        `opencode: model-state seed failed (exit ${String(res.exitCode)}); box falls back to OpenCode's default model. stderr: ${res.stderr.slice(-200)}`
      );
      return;
    }
    log("opencode: model selection seeded \u2713");
  } finally {
    await staged.cleanup();
  }
}
function agentSpecsForCloud() {
  return AGENT_SPECS.map((s) => ({
    kind: s.kind,
    staticMountPath: s.staticMountPath,
    credentialsMountPath: s.credentialsMountPath,
    credentialsSubpath: s.credentialsSubpath
  }));
}
var EXTRACT_SPECS = [
  { kind: "claude", boxPath: "/home/vscode/.claude/.credentials.json", hostBackup: CREDENTIALS_BACKUP_FILE },
  { kind: "codex", boxPath: "/home/vscode/.codex/auth.json", hostBackup: CODEX_CREDENTIALS_BACKUP_FILE },
  {
    kind: "opencode",
    boxPath: "/home/vscode/.local/share/opencode/auth.json",
    hostBackup: OPENCODE_CREDENTIALS_BACKUP_FILE
  }
];
async function extractCloudAgentCredentials(backend, handle, opts = {}) {
  const log = opts.onLog ?? (() => {
  });
  const extracted = [];
  for (const spec of EXTRACT_SPECS) {
    const hostBackup = opts.backups?.[spec.kind] ?? spec.hostBackup;
    try {
      const r = await backend.exec(handle, `cat ${spec.boxPath} 2>/dev/null`, { noRetry: true });
      const text = r.stdout;
      if (r.exitCode !== 0 || !text || !isRealAgentCredential(spec.kind, text)) continue;
      await mkdir(dirname(hostBackup), { recursive: true });
      await writeFile(hostBackup, text, { mode: 384 });
      await chmod(hostBackup, 384).catch(() => {
      });
      extracted.push(spec.kind);
      log(`extracted ${spec.kind} login from box to ${hostBackup}`);
    } catch (err) {
      log(
        `WARN: ${spec.kind} credential extract failed (${err instanceof Error ? err.message : String(err)}) \u2014 skipping`
      );
    }
  }
  return extracted;
}
var CLOUD_CHECKPOINTS_ROOT = join(homedir(), ".agentbox", "cloud-checkpoints");
var CLOUD_SNAPSHOT_NAME_PREFIX = "agentbox-ckpt-";
function cloudSnapshotName(projectRoot, name) {
  const mnemonic = sanitizeMnemonic(basename(projectRoot));
  return `${CLOUD_SNAPSHOT_NAME_PREFIX}${hashProjectPath(projectRoot)}_${mnemonic}-${name}`;
}
function backendDir(backend, projectRoot) {
  return join(CLOUD_CHECKPOINTS_ROOT, backend, projectDirSegment(projectRoot));
}
function checkpointDir(backend, projectRoot, name) {
  return join(backendDir(backend, projectRoot), name);
}
async function readManifest(dir) {
  try {
    const raw = await readFile(join(dir, "manifest.json"), "utf8");
    const m = JSON.parse(raw);
    if (m.schema !== 1) return null;
    return m;
  } catch {
    return null;
  }
}
async function listCloudCheckpoints(projectRoot, backend) {
  const root = backendDir(backend, projectRoot);
  let entries;
  try {
    entries = (await readdir(root, { withFileTypes: true })).filter((e) => e.isDirectory()).map((e) => e.name);
  } catch {
    return [];
  }
  const out = [];
  for (const name of entries) {
    const dir = join(root, name);
    const manifest = await readManifest(dir);
    if (manifest) out.push({ name, dir, manifest });
  }
  out.sort((a, b) => a.manifest.createdAt.localeCompare(b.manifest.createdAt));
  return out;
}
async function resolveCloudCheckpoint(projectRoot, backend, ref) {
  const dir = checkpointDir(backend, projectRoot, ref);
  const manifest = await readManifest(dir);
  if (!manifest) return null;
  return { name: ref, dir, manifest };
}
async function writeCloudCheckpointManifest(projectRoot, backend, name, fields) {
  const dir = checkpointDir(backend, projectRoot, name);
  await mkdir2(dir, { recursive: true });
  const manifest = {
    schema: 1,
    name,
    backend,
    snapshotName: fields.snapshotName,
    sourceBoxId: fields.sourceBoxId,
    sourceBoxName: fields.sourceBoxName,
    createdAt: (/* @__PURE__ */ new Date()).toISOString()
  };
  await writeFile2(join(dir, "manifest.json"), JSON.stringify(manifest, null, 2) + "\n", "utf8");
  return { name, dir, manifest };
}
async function removeCloudCheckpointDir(projectRoot, backend, name) {
  const dir = checkpointDir(backend, projectRoot, name);
  const existed = await readManifest(dir) !== null;
  if (!existed) return false;
  await rm(dir, { recursive: true, force: true });
  return true;
}
async function probeCloudCheckpoint(backend, projectRoot, ref) {
  const found = await resolveCloudCheckpoint(projectRoot, backend.name, ref);
  if (!found) return { live: false, pruned: false };
  if (!backend.snapshotExists) return { live: true, pruned: false };
  const live = await backend.snapshotExists(found.manifest.snapshotName);
  if (live) return { live: true, pruned: false };
  await removeCloudCheckpointDir(projectRoot, backend.name, ref);
  return { live: false, pruned: true };
}
function isSnapshotGoneError(err) {
  if (err === null || typeof err !== "object") return false;
  const e = err;
  const status = e.response?.status ?? e.status;
  if (status === 410) return true;
  const parts = [
    typeof e.json?.error?.message === "string" ? e.json.error.message : "",
    typeof e.message === "string" ? e.message : ""
  ];
  const msg = parts.join(" ").toLowerCase();
  return /snapshot[^.]*\b(expired|deleted|gone|not[ -]?found)\b/.test(msg) || msg.includes("expired or deleted");
}
var WORKSPACE_DIR_DEFAULT = "/workspace";
var REMOTE_TAR_PATH = "/tmp/agentbox-envfiles.tar";
async function uploadEnvFiles(args) {
  const log = args.onLog ?? (() => {
  });
  if (args.files.length === 0) return { copied: 0 };
  const workspaceDir = args.workspaceDir ?? WORKSPACE_DIR_DEFAULT;
  const found = await execa("find", buildHostEnvFindArgs(args.files).slice(1), {
    cwd: args.workspacePath,
    reject: false
  });
  if (found.exitCode !== 0) {
    log(`env-file scan failed: ${String(found.stderr).slice(0, 300)}`);
    return { copied: 0 };
  }
  const list = String(found.stdout).split("\0").filter((p) => p.length > 0);
  if (list.length === 0) return { copied: 0 };
  const stage = await mkdtemp(join2(tmpdir(), "agentbox-envfiles-"));
  const localTar = join2(stage, "envfiles.tar");
  try {
    const packed = await execa(
      "tar",
      ["-C", args.workspacePath, "--null", "-T", "-", "-cf", localTar],
      { input: list.join("\0"), reject: false }
    );
    if (packed.exitCode !== 0) {
      log(`env-file tar pack failed: ${String(packed.stderr).slice(0, 300)}`);
      return { copied: 0 };
    }
    await writeFile3(join2(stage, ".marker"), "").catch(() => {
    });
    await args.backend.uploadFile(args.handle, localTar, REMOTE_TAR_PATH);
    const extract = await args.backend.exec(
      args.handle,
      `tar -xf ${REMOTE_TAR_PATH} -C ${workspaceDir} --no-same-permissions --no-same-owner -m && rm -f ${REMOTE_TAR_PATH}`
    );
    if (extract.exitCode !== 0) {
      log(
        `env-file extract failed (exit ${String(extract.exitCode)}); stdout: ${extract.stdout.slice(-200)} stderr: ${extract.stderr.slice(-200)}`
      );
      return { copied: 0 };
    }
  } finally {
    await rm2(stage, { recursive: true, force: true });
  }
  return { copied: list.length };
}
var BOX_HOME = "/home/vscode";
async function uploadCarryPaths(args) {
  const log = args.onLog ?? (() => {
  });
  if (args.entries.length === 0) {
    return { copied: 0, errors: [], applied: [] };
  }
  const stage = await mkdtemp2(join3(tmpdir2(), "agentbox-carry-"));
  const errors = [];
  const applied = [];
  let copied = 0;
  try {
    for (const [i, entry] of args.entries.entries()) {
      const where = `carry[${String(i)}] "${entry.rawSrc}"`;
      if (entry.kind === "missing") {
        log(`${where}: skipped (missing on host, optional)`);
        continue;
      }
      try {
        await uploadOneEntry({
          backend: args.backend,
          handle: args.handle,
          entry,
          stageDir: stage,
          index: i
        });
        copied += 1;
        applied.push({ src: entry.absSrc, dest: entry.absDest, bytes: entry.bytes ?? 0 });
      } catch (err) {
        const msg = err instanceof Error ? err.message : String(err);
        errors.push(`${where}: ${msg}`);
        log(`${where}: failed: ${msg}`);
      }
    }
  } finally {
    await rm3(stage, { recursive: true, force: true });
  }
  return { copied, errors, applied };
}
async function uploadOneEntry(args) {
  const { entry } = args;
  if (entry.kind === "missing") return;
  const boxDest = entry.absDest.startsWith("~/") ? `${BOX_HOME}/${entry.absDest.slice(2)}` : entry.absDest;
  const isDir = entry.kind === "dir";
  const parentDir = isDir ? boxDest : dirnameUnix(boxDest);
  const localTar = join3(args.stageDir, `carry-${String(args.index)}.tar`);
  const tarArgs = isDir ? ["-C", entry.absSrc, "-cf", localTar, "."] : ["-C", dirnameUnix(entry.absSrc), "-cf", localTar, basenameUnix(entry.absSrc)];
  const packed = await execa2("tar", tarArgs, { reject: false });
  if (packed.exitCode !== 0) {
    throw new Error(`tar pack failed: ${String(packed.stderr).slice(0, 300)}`);
  }
  const remoteTar = `/tmp/agentbox-carry-${String(args.index)}.tar`;
  await args.backend.uploadFile(args.handle, localTar, remoteTar);
  const mode = entry.mode !== void 0 ? entry.mode.toString(8).padStart(4, "0") : "";
  const uid = entry.user ?? 1e3;
  const fileBase = !isDir ? basenameUnix(entry.absSrc) : "";
  const destBase = !isDir ? basenameUnix(boxDest) : "";
  const renameNeeded = !isDir && fileBase !== destBase;
  const parts = [
    `mkdir -p ${shellQuote(parentDir)}`,
    isDir ? `tar -xf ${remoteTar} -C ${shellQuote(boxDest)} --no-same-permissions --no-same-owner -m` : `tar -xf ${remoteTar} -C ${shellQuote(parentDir)} --no-same-permissions --no-same-owner -m`
  ];
  if (renameNeeded) {
    parts.push(
      `mv ${shellQuote(`${parentDir}/${fileBase}`)} ${shellQuote(boxDest)}`
    );
  }
  if (mode) parts.push(`chmod -R ${mode} ${shellQuote(boxDest)}`);
  parts.push(`chown -R ${String(uid)}:${String(uid)} ${shellQuote(boxDest)}`);
  if (boxDest.startsWith(BOX_HOME + "/") && parentDir !== BOX_HOME) {
    parts.push(
      `parent=$(dirname ${shellQuote(boxDest)}); while [ "$parent" != "${BOX_HOME}" ] && [ "$parent" != "/" ]; do chown ${String(uid)}:${String(uid)} "$parent"; parent=$(dirname "$parent"); done`
    );
  }
  parts.push(`rm -f ${remoteTar}`);
  const cmd = parts.join(" && ");
  const execOpts = args.backend.name === "vercel" ? { user: "root" } : void 0;
  const res = await args.backend.exec(args.handle, cmd, execOpts);
  if (res.exitCode !== 0) {
    throw new Error(
      `in-box extract failed (exit ${String(res.exitCode)}): ${(res.stderr || res.stdout).slice(-300)}`
    );
  }
}
function dirnameUnix(p) {
  const i = p.lastIndexOf("/");
  if (i <= 0) return "/";
  return p.slice(0, i);
}
function basenameUnix(p) {
  const i = p.lastIndexOf("/");
  return i < 0 ? p : p.slice(i + 1);
}
function shellQuote(s) {
  return `'${s.replace(/'/g, `'\\''`)}'`;
}
async function readExposedServicePorts(workspacePath) {
  let text;
  try {
    text = await readFile2(join4(workspacePath, "agentbox.yaml"), "utf8");
  } catch {
    return [];
  }
  let doc;
  try {
    doc = parseYaml(text);
  } catch {
    return [];
  }
  if (!isPlainObject(doc)) return [];
  const services = doc["services"];
  if (!isPlainObject(services)) return [];
  const out = /* @__PURE__ */ new Set();
  for (const value of Object.values(services)) {
    if (!isPlainObject(value)) continue;
    const expose = value["expose"];
    if (!isPlainObject(expose)) continue;
    const port = expose["port"];
    if (typeof port === "number" && Number.isInteger(port) && port > 0 && port < 65536) {
      out.add(port);
    }
  }
  return [...out].sort((a, b) => a - b);
}
function isPlainObject(v) {
  return typeof v === "object" && v !== null && !Array.isArray(v);
}
function quoteShellArgv(argv) {
  return argv.map(quoteShellArg).join(" ");
}
function quoteShellArg(arg) {
  if (arg.length === 0) return "''";
  if (/^[A-Za-z0-9_@%+=:,./-]+$/.test(arg)) return arg;
  return "'" + arg.replace(/'/g, "'\\''") + "'";
}
function bashScript(body) {
  return `bash -c ${quoteShellArg(body)}`;
}
var REMOTE_UP_TAR = "/tmp/agentbox-cp-up.tar.gz";
var REMOTE_DOWN_TAR = "/tmp/agentbox-cp-down.tar.gz";
async function uploadToCloudBox(backend, handle, hostSrc, boxDst) {
  const srcAbs = hostResolve(hostSrc);
  if (!existsSync(srcAbs)) throw new Error(`source not found: ${hostSrc}`);
  const srcBasename = hostBasename(srcAbs);
  const srcParent = hostDirname(srcAbs);
  let boxParent;
  let finalName;
  if (boxDst.endsWith("/")) {
    boxParent = boxDst.replace(/\/+$/, "") || "/";
    finalName = srcBasename;
  } else {
    boxParent = posix.dirname(boxDst);
    finalName = posix.basename(boxDst);
  }
  const finalPath = boxParent === "/" ? `/${finalName}` : `${boxParent}/${finalName}`;
  const stage = await mkdtemp3(hostJoin(tmpdir3(), "agentbox-cp-up-"));
  const localTar = hostJoin(stage, "payload.tar.gz");
  try {
    await execa3("tar", ["-C", srcParent, "-czf", localTar, srcBasename], {
      env: { ...process.env, COPYFILE_DISABLE: "1" }
    });
    await backend.uploadFile(handle, localTar, REMOTE_UP_TAR);
    const initialPath = boxParent === "/" ? `/${srcBasename}` : `${boxParent}/${srcBasename}`;
    const renameStep = finalName !== srcBasename ? `$SUDO cp -f ${quoteShellArg(initialPath)} ${quoteShellArg(finalPath)} && $SUDO rm -f ${quoteShellArg(initialPath)}` : ": # no rename";
    const script = [
      `set -euo pipefail`,
      `if command -v sudo >/dev/null 2>&1; then SUDO='sudo -n'; else SUDO=''; fi`,
      `$SUDO mkdir -p ${quoteShellArg(boxParent)}`,
      // --no-same-permissions / --no-same-owner / -m: Daytona's S3-backed
      // FUSE volumes reject chmod/utime/chown; skipping them lets the extract
      // complete on a mounted-volume destination. Harmless no-op on the
      // sandbox's regular disk. Same flags as the credential-seed extract.
      `$SUDO tar -xzf ${quoteShellArg(REMOTE_UP_TAR)} -C ${quoteShellArg(boxParent)} --no-same-permissions --no-same-owner -m`,
      renameStep,
      // chown only the landed path — anything we mkdir'd through stays at
      // its existing ownership. Tolerate failure (chown bad on read-only mounts).
      `$SUDO chown -R "$(id -un):$(id -gn)" ${quoteShellArg(finalPath)} || true`,
      `rm -f ${quoteShellArg(REMOTE_UP_TAR)}`
    ].join("\n");
    const r = await backend.exec(handle, bashScript(script));
    if (r.exitCode !== 0) {
      throw new Error(`cloud upload extract failed: ${r.stderr || r.stdout}`);
    }
  } finally {
    await rm4(stage, { recursive: true, force: true });
  }
  return { finalPath };
}
async function pullCloudDirContents(backend, handle, boxSrcDir, hostDstDir) {
  const dstAbs = hostResolve(hostDstDir);
  mkdirSync(dstAbs, { recursive: true });
  const stage = await mkdtemp3(hostJoin(tmpdir3(), "agentbox-pull-"));
  const localTar = hostJoin(stage, "payload.tar.gz");
  try {
    const packScript = [
      `set -euo pipefail`,
      `cd ${quoteShellArg(boxSrcDir)}`,
      `tar -czf ${quoteShellArg(REMOTE_DOWN_TAR)} .`
    ].join("\n");
    const r = await backend.exec(handle, bashScript(packScript));
    if (r.exitCode !== 0) {
      throw new Error(`cloud workspace pack failed: ${r.stderr || r.stdout}`);
    }
    await backend.downloadFile(handle, REMOTE_DOWN_TAR, localTar);
    await execa3("tar", ["-xzf", localTar, "-C", dstAbs]);
    await backend.exec(handle, `rm -f ${quoteShellArg(REMOTE_DOWN_TAR)}`).catch(() => {
    });
  } finally {
    await rm4(stage, { recursive: true, force: true });
  }
  return { finalPath: dstAbs };
}
async function downloadFromCloudBox(backend, handle, boxSrc, hostDst) {
  const srcBasename = posix.basename(boxSrc);
  const srcParent = posix.dirname(boxSrc);
  const dstAbs = hostResolve(hostDst);
  let hostParent;
  let finalName;
  const dstExists = existsSync(dstAbs);
  if (hostDst.endsWith("/") || dstExists && statSync(dstAbs).isDirectory()) {
    hostParent = dstAbs;
    finalName = srcBasename;
  } else {
    hostParent = hostDirname(dstAbs);
    finalName = hostBasename(dstAbs);
  }
  mkdirSync(hostParent, { recursive: true });
  const finalPath = hostJoin(hostParent, finalName);
  const stage = await mkdtemp3(hostJoin(tmpdir3(), "agentbox-cp-down-"));
  const localTar = hostJoin(stage, "payload.tar.gz");
  try {
    const packScript = [
      `set -euo pipefail`,
      `cd ${quoteShellArg(srcParent)}`,
      `tar -czf ${quoteShellArg(REMOTE_DOWN_TAR)} ${quoteShellArg(srcBasename)}`
    ].join("\n");
    const r = await backend.exec(handle, bashScript(packScript));
    if (r.exitCode !== 0) {
      throw new Error(`cloud download pack failed: ${r.stderr || r.stdout}`);
    }
    await backend.downloadFile(handle, REMOTE_DOWN_TAR, localTar);
    await execa3("tar", ["-xzf", localTar, "-C", hostParent]);
    if (finalName !== srcBasename) {
      renameSync(hostJoin(hostParent, srcBasename), finalPath);
    }
    await backend.exec(handle, `rm -f ${quoteShellArg(REMOTE_DOWN_TAR)}`).catch(() => {
    });
  } finally {
    await rm4(stage, { recursive: true, force: true });
  }
  return { finalPath };
}
async function launchCloudCtlDaemon(args) {
  const env = [
    `AGENTBOX_BOX_ID=${quoteShellArgv([args.boxId])}`,
    `AGENTBOX_BOX_NAME=${quoteShellArgv([args.boxName])}`,
    `AGENTBOX_BOX_KIND=cloud`
  ];
  if (args.relayUrl) env.push(`AGENTBOX_RELAY_URL=${quoteShellArgv([args.relayUrl])}`);
  if (args.relayToken) env.push(`AGENTBOX_RELAY_TOKEN=${quoteShellArgv([args.relayToken])}`);
  if (args.bridgeToken) env.push(`AGENTBOX_BRIDGE_TOKEN=${quoteShellArgv([args.bridgeToken])}`);
  if (args.webProxyPort !== void 0)
    env.push(`AGENTBOX_WEB_PROXY_PORT=${quoteShellArgv([String(args.webProxyPort)])}`);
  const script = [
    `set -e`,
    `if command -v sudo >/dev/null 2>&1; then SUDO='sudo -n'; else SUDO=''; fi`,
    `$SUDO mkdir -p /run/agentbox /var/log/agentbox`,
    `$SUDO chown "$(id -un):$(id -gn)" /run/agentbox /var/log/agentbox`,
    `export ${env.join(" ")}`,
    `nohup /usr/local/bin/agentbox-ctl daemon >> /var/log/agentbox/ctl-daemon.log 2>&1 &`,
    `disown`,
    `echo started`
  ].join("\n");
  const r = await args.backend.exec(args.handle, bashScript(script));
  if (r.exitCode !== 0) {
    throw new Error(`agentbox-ctl daemon launch failed: ${r.stderr || r.stdout}`);
  }
}
async function launchCloudDockerdDaemon(args) {
  const timeoutMs = args.timeoutMs ?? 6e4;
  const startScript = [
    `set -euo pipefail`,
    `mkdir -p /var/log/agentbox`,
    `nohup sudo -n /usr/local/bin/agentbox-dockerd-start >> /var/log/agentbox/dockerd.log 2>&1 &`,
    `echo "spawned dockerd"`
  ].join("\n");
  const launch = await args.backend.exec(args.handle, bashScript(startScript));
  if (launch.exitCode !== 0) {
    return {
      up: false,
      reason: `dockerd launch failed: ${launch.stderr || launch.stdout}`
    };
  }
  const probeCmd = "[ -S /var/run/docker.sock ] && docker -H unix:///var/run/docker.sock info >/dev/null 2>&1";
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    const probe = await args.backend.exec(args.handle, probeCmd);
    if (probe.exitCode === 0) return { up: true };
    await new Promise((r) => setTimeout(r, 500));
  }
  return {
    up: false,
    reason: `dockerd did not become ready within ${String(timeoutMs)}ms`
  };
}
async function launchCloudVncDaemon(args) {
  const script = [
    `set -e`,
    `cd /home/vscode`,
    `export AGENTBOX_VNC_PASSWORD=${quoteShellArg(args.vncPassword)}`,
    `mkdir -p /var/log/agentbox 2>/dev/null || true`,
    `nohup /usr/local/bin/agentbox-vnc-start >> /var/log/agentbox/vnc-start.log 2>&1 &`,
    `disown`,
    // Match the host-side probe in packages/sandbox-docker/src/vnc.ts: poll for
    // ~5s, then give up. The script itself waits for Xvnc internally; this
    // outer probe confirms websockify's public port came up too.
    `for _ in $(seq 1 50); do`,
    `  if (echo > /dev/tcp/127.0.0.1/6080) 2>/dev/null; then echo ready; exit 0; fi`,
    `  sleep 0.1`,
    `done`,
    `echo "websockify did not bind 6080 within 5s" >&2`,
    `exit 1`
  ].join("\n");
  const r = await args.backend.exec(args.handle, bashScript(script));
  if (r.exitCode !== 0) {
    throw new Error(`agentbox-vnc-start failed: ${r.stderr || r.stdout}`);
  }
}
var WORKSPACE_DIR_DEFAULT2 = "/workspace";
async function seedCloudWorkspace(args) {
  const workspaceDir = args.workspaceDir ?? WORKSPACE_DIR_DEFAULT2;
  const log = args.onLog ?? (() => {
  });
  const repos = await detectGitRepos(args.workspacePath);
  const root = repos.find((r) => r.kind === "root");
  const nested = repos.filter((r) => r.kind === "nested");
  if (root) {
    log(
      nested.length > 0 ? `seeding /workspace from shallow git clone (+${String(nested.length)} nested repo${nested.length === 1 ? "" : "s"})` : "seeding /workspace from shallow git clone"
    );
    await seedFromGitClone({
      backend: args.backend,
      handle: args.handle,
      hostRepo: root.hostMainRepo,
      branch: args.branch,
      workspaceDir,
      bundleDepth: args.bundleDepth,
      fromBranch: args.fromBranch,
      useBranch: args.useBranch,
      onLog: log
    });
    for (const r of nested) {
      const sub = `${workspaceDir}/${r.relPathFromWorkspace}`;
      log(`seeding nested repo ${r.relPathFromWorkspace} from shallow git clone`);
      await seedFromGitClone({
        backend: args.backend,
        handle: args.handle,
        hostRepo: r.hostMainRepo,
        branch: args.branch,
        workspaceDir: sub,
        bundleDepth: args.bundleDepth,
        onLog: log
      });
    }
    return { fromGit: true, branch: args.branch };
  }
  log("seeding /workspace from workspace tarball (no git detected)");
  await seedFromTar({
    backend: args.backend,
    handle: args.handle,
    hostDir: args.workspacePath,
    workspaceDir
  });
  return { fromGit: false, branch: args.branch };
}
var STASH_CARRYOVER_REF = "refs/agentbox-carryover/stash";
var REMOTE_UNTRACKED_TAR = "/tmp/agentbox-carryover-untracked.tar.gz";
var DEFAULT_BUNDLE_DEPTH = 200;
var LARGE_BUNDLE_DEPTH = 100;
var LARGE_BUNDLE_THRESHOLD_BYTES = 20 * 1024 * 1024;
async function seedFromGitClone(args) {
  const log = args.onLog ?? (() => {
  });
  const stage = await mkdtemp4(join5(tmpdir4(), "agentbox-clone-"));
  const cloneDir = join5(stage, "clone");
  const tarPath = join5(stage, "workspace.tar.gz");
  const untrackedTarPath = join5(stage, "untracked.tar.gz");
  const stashSha = args.useBranch ? null : await safeStashCreate(args.hostRepo);
  const untrackedSize = args.useBranch ? 0 : await maybeBuildUntrackedTar(args.hostRepo, untrackedTarPath);
  let stashRefCreated = false;
  try {
    if (stashSha) {
      const ref = await execa4(
        "git",
        ["-C", args.hostRepo, "update-ref", STASH_CARRYOVER_REF, stashSha],
        { reject: false }
      );
      stashRefCreated = ref.exitCode === 0;
    }
    const configured = args.bundleDepth;
    const adaptive = configured === void 0;
    const initialDepth = adaptive ? DEFAULT_BUNDLE_DEPTH : configured === 0 ? null : configured;
    log(
      adaptive ? `clone: depth=${String(DEFAULT_BUNDLE_DEPTH)} (default, adaptive)` : initialDepth === null ? "clone: depth=full (configured)" : `clone: depth=${String(initialDepth)} (configured)`
    );
    const cloneBranch = args.useBranch ?? args.fromBranch;
    await runShallowClone(args.hostRepo, cloneDir, initialDepth, stashRefCreated, cloneBranch);
    await tarCloneDir(cloneDir, tarPath);
    if (adaptive && initialDepth !== null) {
      const size = await safeFileSize(tarPath);
      if (size > LARGE_BUNDLE_THRESHOLD_BYTES) {
        const mb = (size / (1024 * 1024)).toFixed(1);
        log(
          `clone tar exceeded ${String(LARGE_BUNDLE_THRESHOLD_BYTES / (1024 * 1024))} MB at depth ${String(DEFAULT_BUNDLE_DEPTH)} (${mb} MB), rebuilding at depth ${String(LARGE_BUNDLE_DEPTH)}`
        );
        await rm5(cloneDir, { recursive: true, force: true });
        await rm5(tarPath, { force: true });
        await runShallowClone(args.hostRepo, cloneDir, LARGE_BUNDLE_DEPTH, stashRefCreated, cloneBranch);
        await tarCloneDir(cloneDir, tarPath);
      }
    }
    const remoteUrl = await readOriginUrl(args.hostRepo);
    const remoteTar = "/tmp/agentbox-workspace.tar.gz";
    await args.backend.uploadFile(args.handle, tarPath, remoteTar);
    if (untrackedSize > 0) {
      await args.backend.uploadFile(args.handle, untrackedTarPath, REMOTE_UNTRACKED_TAR);
    }
    const setOrigin = remoteUrl ? `git -C ${quoteShellArgv([args.workspaceDir])} remote set-url origin ${quoteShellArgv([remoteUrl])}` : ": # no host origin to copy";
    const SUDO = `if command -v sudo >/dev/null 2>&1; then SUDO='sudo -n'; else SUDO=''; fi`;
    const carryOverSteps = stashSha ? [
      `if git -C ${quoteShellArgv([args.workspaceDir])} rev-parse --verify ${quoteShellArgv([`refs/remotes/origin/agentbox-carryover/stash`])} >/dev/null 2>&1; then git -C ${quoteShellArgv([args.workspaceDir])} stash apply ${quoteShellArgv([`refs/remotes/origin/agentbox-carryover/stash`])} || echo "agentbox: stash apply soft-failed; carry-over may be incomplete" >&2 ; git -C ${quoteShellArgv([args.workspaceDir])} update-ref -d ${quoteShellArgv([`refs/remotes/origin/agentbox-carryover/stash`])} || true ; fi`
    ] : [];
    if (untrackedSize > 0) {
      carryOverSteps.push(
        `if [ -f ${quoteShellArgv([REMOTE_UNTRACKED_TAR])} ]; then tar -C ${quoteShellArgv([args.workspaceDir])} -xzf ${quoteShellArgv([REMOTE_UNTRACKED_TAR])} && rm -f ${quoteShellArgv([REMOTE_UNTRACKED_TAR])} ; fi`
      );
    }
    const script = [
      `set -euo pipefail`,
      // Move out of any cwd we might inherit from Daytona's executeCommand
      // before we delete /workspace. The agentbox image bakes WORKDIR
      // /workspace; if the shell's cwd is /workspace when we `rm -rf` it,
      // the next process inherits a stale cwd FD and tar's children fail
      // with "Unable to read current working directory".
      `cd /tmp`,
      SUDO,
      // rm -rf only the directory we're about to extract into — for nested
      // repos this is just `/workspace/<rel>`, so the root clone (already
      // at `/workspace`) is preserved.
      `$SUDO rm -rf ${quoteShellArgv([args.workspaceDir])}`,
      `$SUDO mkdir -p ${quoteShellArgv([args.workspaceDir])}`,
      `$SUDO chown "$(id -un):$(id -gn)" ${quoteShellArgv([args.workspaceDir])}`,
      `tar -C ${quoteShellArgv([args.workspaceDir])} -xzf ${quoteShellArgv([remoteTar])}`,
      setOrigin,
      // reuse: the clone already landed on `<branch>` (pinned via `--branch`);
      // a plain checkout materializes the working tree without resetting the
      // ref. fork: `-B` (re)points `<branch>` at the clone HEAD.
      args.useBranch ? `git -C ${quoteShellArgv([args.workspaceDir])} checkout ${quoteShellArgv([args.branch])}` : `git -C ${quoteShellArgv([args.workspaceDir])} checkout -B ${quoteShellArgv([args.branch])}`,
      ...carryOverSteps,
      `rm -f ${quoteShellArgv([remoteTar])}`
    ].join("\n");
    const r = await args.backend.exec(args.handle, bashScript(script));
    if (r.exitCode !== 0) {
      throw new Error(`workspace seed (clone) failed: ${r.stderr || r.stdout}`);
    }
  } finally {
    if (stashRefCreated) {
      await execa4("git", ["-C", args.hostRepo, "update-ref", "-d", STASH_CARRYOVER_REF], {
        reject: false
      });
    }
    await rm5(stage, { recursive: true, force: true });
  }
}
async function runShallowClone(hostRepo, cloneDir, depth, includeStashRef, fromBranch) {
  const cloneArgs = ["clone", "--no-checkout", "--quiet"];
  if (depth !== null) cloneArgs.push(`--depth=${String(depth)}`);
  if (fromBranch) cloneArgs.push("--branch", fromBranch);
  cloneArgs.push(`file://${hostRepo}`, cloneDir);
  await execa4("git", cloneArgs);
  if (includeStashRef) {
    const fetchArgs = ["-C", cloneDir, "fetch", "--quiet"];
    if (depth !== null) fetchArgs.push(`--depth=${String(depth)}`);
    fetchArgs.push(
      `file://${hostRepo}`,
      `+${STASH_CARRYOVER_REF}:refs/remotes/origin/agentbox-carryover/stash`
    );
    await execa4("git", fetchArgs, { reject: false });
  }
}
async function tarCloneDir(cloneDir, outPath) {
  await execa4("tar", ["-C", cloneDir, "-czf", outPath, "."], {
    env: { ...process.env, COPYFILE_DISABLE: "1" }
  });
}
async function safeFileSize(path) {
  try {
    return (await stat(path)).size;
  } catch {
    return 0;
  }
}
async function safeStashCreate(hostRepo) {
  const r = await execa4("git", ["-C", hostRepo, "stash", "create"], { reject: false });
  if (r.exitCode !== 0) return null;
  const sha = r.stdout.trim();
  return sha.length > 0 ? sha : null;
}
async function maybeBuildUntrackedTar(hostRepo, outPath) {
  const list = await execa4(
    "git",
    ["-C", hostRepo, "ls-files", "--others", "--exclude-standard", "-z"],
    { reject: false }
  );
  if (list.exitCode !== 0 || list.stdout.length === 0) return 0;
  const tar = await execa4(
    "tar",
    ["-C", hostRepo, "--null", "-T", "-", "-czf", outPath],
    {
      input: list.stdout,
      env: { ...process.env, COPYFILE_DISABLE: "1" },
      reject: false
    }
  );
  if (tar.exitCode !== 0) return 0;
  try {
    const { stat: stat2 } = await import("fs/promises");
    const s = await stat2(outPath);
    return s.size;
  } catch {
    return 0;
  }
}
async function readOriginUrl(hostRepo) {
  const r = await execa4("git", ["-C", hostRepo, "remote", "get-url", "origin"], { reject: false });
  if (r.exitCode !== 0) return null;
  const out = (r.stdout ?? "").trim();
  return out.length > 0 ? out : null;
}
async function seedFromTar(args) {
  const stage = await mkdtemp4(join5(tmpdir4(), "agentbox-tar-"));
  const tarPath = join5(stage, "workspace.tar.gz");
  try {
    await execa4("tar", ["-C", args.hostDir, "-czf", tarPath, "."]);
    const remoteTar = "/tmp/agentbox-workspace.tar.gz";
    await args.backend.uploadFile(args.handle, tarPath, remoteTar);
    const SUDO = `if command -v sudo >/dev/null 2>&1; then SUDO='sudo -n'; else SUDO=''; fi`;
    const script = [
      `set -euo pipefail`,
      // Move out of any cwd we might inherit from Daytona's executeCommand
      // before we delete /workspace. The agentbox image bakes WORKDIR
      // /workspace; if the shell's cwd is /workspace when we `rm -rf` it,
      // the next process inherits a stale cwd FD and git-clone's child
      // (index-pack) fails with "Unable to read current working directory".
      `cd /tmp`,
      SUDO,
      `$SUDO rm -rf ${quoteShellArgv([args.workspaceDir])}`,
      `$SUDO mkdir -p ${quoteShellArgv([args.workspaceDir])}`,
      `$SUDO chown "$(id -un):$(id -gn)" ${quoteShellArgv([args.workspaceDir])}`,
      `tar -C ${quoteShellArgv([args.workspaceDir])} -xzf ${quoteShellArgv([remoteTar])}`,
      `rm -f ${quoteShellArgv([remoteTar])}`
    ].join("\n");
    const r = await args.backend.exec(args.handle, bashScript(script));
    if (r.exitCode !== 0) {
      throw new Error(`workspace seed (tar) failed: ${r.stderr || r.stdout}`);
    }
  } finally {
    await rm5(stage, { recursive: true, force: true });
  }
}
var CLOUD_WORKSPACE_DIR = "/workspace";
var CLOUD_WEB_PROXY_PORT = 80;
var CLOUD_VNC_PORT = 6080;
var DEFAULT_SIGNED_URL_TTL_SECONDS = 3600;
var FALLBACK_IMAGE = "agentbox/box:dev";
var DEFAULT_PORTLESS_PROXY_PORT = 1355;
function parsePortlessUrl(url) {
  try {
    const u = new URL(url);
    if (!u.hostname.endsWith(".localhost")) return void 0;
    const tls = u.protocol === "https:";
    const proxyPort = u.port ? Number.parseInt(u.port, 10) : tls ? 443 : 80;
    if (!Number.isFinite(proxyPort)) return void 0;
    return { proxyPort, tls };
  } catch {
    return void 0;
  }
}
function parseLoopbackPort(url) {
  try {
    const u = new URL(url);
    if (u.hostname !== "127.0.0.1" && u.hostname !== "localhost") return void 0;
    const port = Number.parseInt(u.port, 10);
    return Number.isFinite(port) ? port : void 0;
  } catch {
    return void 0;
  }
}
async function registerHostPortlessAlias(args) {
  const localPort = parseLoopbackPort(args.previewUrl);
  if (localPort === void 0) return void 0;
  const ok = await portlessAlias(args.alias, localPort);
  if (!ok) {
    args.onLog(
      `portless: ${args.label} alias not registered (portless CLI missing or not running) \u2014 host URL stays http://127.0.0.1:${String(localPort)}`
    );
    return void 0;
  }
  const url = await portlessGetUrl(args.alias);
  args.onLog(`portless alias ${url} -> 127.0.0.1:${String(localPort)}`);
  return url;
}
async function bootstrapPortlessForCloudBox(backend, handle, args) {
  const url = await registerHostPortlessAlias({
    alias: args.boxName,
    previewUrl: args.webPreviewUrl,
    label: "web",
    onLog: args.onLog
  });
  if (!url) return void 0;
  if (backend.startInBoxPortless) {
    const mode = parsePortlessUrl(url) ?? { proxyPort: DEFAULT_PORTLESS_PROXY_PORT, tls: false };
    try {
      await backend.startInBoxPortless(handle, {
        boxName: args.boxName,
        proxyPort: mode.proxyPort,
        tls: mode.tls,
        webPort: args.webPort
      });
      args.onLog(
        `portless: in-box mirror up on 127.0.0.1:${String(mode.proxyPort)} (${mode.tls ? "https" : "http"})`
      );
    } catch (err) {
      args.onLog(
        `portless: in-box mirror failed (continuing): ${err instanceof Error ? err.message : String(err)}`
      );
    }
  }
  return { alias: args.boxName, url };
}
function createCloudProvider(backend, opts = {}) {
  const providerName = backend.name;
  function handleFor(box) {
    const sandboxId = box.cloud?.sandboxId;
    if (!sandboxId) {
      throw new Error(`cloud box ${box.name} has no sandboxId \u2014 record is malformed`);
    }
    return { sandboxId };
  }
  function mintBox(req) {
    const id = generateBoxId();
    const name = req.name ?? `${basename2(req.workspacePath)}-${id}`;
    return {
      id,
      name,
      // --use-branch reuses the named branch directly; otherwise fork a fresh
      // per-box branch. The CLI validated `useBranch` exists host-side.
      branch: req.useBranch ?? `agentbox/${name}`
    };
  }
  async function probe(box) {
    try {
      const h = handleFor(box);
      const state = await backend.state(h);
      return state;
    } catch {
      return "missing";
    }
  }
  async function persistLastState(box, lastState) {
    if (!box.cloud) return;
    try {
      await recordBox({ ...box, cloud: { ...box.cloud, lastState } });
    } catch {
    }
  }
  async function reEnsureCloudBox(box, h) {
    const webPort = box.cloud?.webPort ?? backend.webProxyPort ?? CLOUD_WEB_PROXY_PORT;
    let webPreview;
    try {
      webPreview = await backend.previewUrl(h, webPort);
    } catch {
      const cached = box.cloud?.previewUrls?.[webPort];
      webPreview = cached ? { url: cached } : void 0;
    }
    const servicePreviews = {};
    try {
      const ports = await readExposedServicePorts(box.workspacePath);
      for (const port of ports) {
        if (port === webPort) continue;
        try {
          const p = await backend.previewUrl(h, port);
          servicePreviews[port] = p.url;
        } catch {
        }
      }
    } catch {
    }
    let relayPreview;
    try {
      relayPreview = await backend.previewUrl(h, 8788);
    } catch {
      relayPreview = box.cloud?.relayPreviewUrl ? { url: box.cloud.relayPreviewUrl, token: box.cloud.relayPreviewToken } : void 0;
    }
    const mergedPreviews = {
      ...box.cloud?.previewUrls ?? {},
      ...servicePreviews
    };
    if (webPreview !== void 0) mergedPreviews[webPort] = webPreview.url;
    let portlessAliasName = box.portlessAlias;
    let portlessUrlResolved = box.portlessUrl;
    if (box.portlessAlias && webPreview) {
      const r = await bootstrapPortlessForCloudBox(backend, h, {
        boxName: box.name,
        webPreviewUrl: webPreview.url,
        webPort,
        onLog: () => {
        }
      });
      if (r) {
        portlessAliasName = r.alias;
        portlessUrlResolved = r.url;
      }
    }
    let portlessVncAliasName = box.portlessVncAlias;
    let portlessVncUrlResolved = box.portlessVncUrl;
    if (box.portlessVncAlias && box.vncEnabled) {
      try {
        const vncPreview = await backend.previewUrl(h, CLOUD_VNC_PORT);
        const url = await registerHostPortlessAlias({
          alias: box.portlessVncAlias,
          previewUrl: vncPreview.url,
          label: "vnc",
          onLog: () => {
          }
        });
        if (url) {
          portlessVncAliasName = box.portlessVncAlias;
          portlessVncUrlResolved = url;
        }
      } catch {
      }
    }
    const next = {
      ...box,
      portlessAlias: portlessAliasName,
      portlessUrl: portlessUrlResolved,
      portlessVncAlias: portlessVncAliasName,
      portlessVncUrl: portlessVncUrlResolved,
      cloud: {
        ...box.cloud ?? { backend: providerName, sandboxId: h.sandboxId },
        webPort,
        previewUrls: Object.keys(mergedPreviews).length > 0 ? mergedPreviews : void 0,
        relayPreviewUrl: relayPreview?.url ?? box.cloud?.relayPreviewUrl,
        relayPreviewToken: relayPreview?.token ?? box.cloud?.relayPreviewToken,
        // reEnsureCloudBox only runs on a freshly-woken box (start/resume), so
        // the box is now running — persist it for the fast `agentbox list` path.
        lastState: "running"
      }
    };
    await recordBox(next);
    await launchCloudCtlDaemon({
      backend,
      handle: h,
      boxId: box.id,
      boxName: box.name,
      relayUrl: `http://127.0.0.1:${String(8788)}`,
      relayToken: box.relayToken ?? "",
      bridgeToken: box.cloud?.bridgeToken,
      webProxyPort: backend.webProxyPort
    });
    if (opts.launchDockerd !== false) {
      try {
        const dockerd = await launchCloudDockerdDaemon({ backend, handle: h, timeoutMs: 6e4 });
        if (!dockerd.up) {
        }
      } catch {
      }
    }
    if (box.vncEnabled && box.vncPassword) {
      try {
        await launchCloudVncDaemon({ backend, handle: h, vncPassword: box.vncPassword });
      } catch {
      }
    }
    if (relayPreview && box.relayToken && box.cloud?.bridgeToken) {
      try {
        await registerBoxWithRelay({
          boxId: box.id,
          token: box.relayToken,
          name: box.name,
          kind: "cloud",
          backend: backend.name,
          previewUrl: relayPreview.url,
          previewToken: relayPreview.token,
          bridgeToken: box.cloud.bridgeToken,
          createdAt: box.createdAt,
          projectIndex: box.projectIndex
        });
      } catch {
      }
    }
    return next;
  }
  return {
    name: providerName,
    async create(req) {
      const log = req.onLog ?? (() => {
      });
      const { id, name, branch } = mintBox(req);
      const image = opts.provisionImage ? await opts.provisionImage(req) : req.image ?? FALLBACK_IMAGE;
      const baseResources = opts.defaultResources ?? { cpu: 2, memory: 4, disk: 8 };
      const vcpuOverride = req.providerOptions?.["vcpus"];
      const resources = typeof vcpuOverride === "number" && vcpuOverride > 0 ? { ...baseResources, cpu: vcpuOverride } : baseResources;
      const timeoutOverride = req.providerOptions?.["timeoutMs"];
      const timeoutMs = typeof timeoutOverride === "number" && timeoutOverride > 0 ? timeoutOverride : void 0;
      const networkPolicyOpt = req.providerOptions?.["networkPolicy"];
      const networkPolicy = typeof networkPolicyOpt === "string" && networkPolicyOpt.trim() !== "" ? networkPolicyOpt.trim() : void 0;
      const relayToken = generateRelayToken();
      const bridgeToken = generateRelayToken();
      try {
        await ensureRelay({ onLog: log });
      } catch (err) {
        log(`relay ensure failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
      }
      let snapshotName;
      let resolvedCheckpointRef;
      if (req.checkpointRef && req.projectRoot) {
        const found = await resolveCloudCheckpoint(req.projectRoot, backend.name, req.checkpointRef);
        if (found) {
          snapshotName = found.manifest.snapshotName;
          resolvedCheckpointRef = found.name;
          log(`provisioning from cloud checkpoint '${found.name}' (snapshot ${snapshotName})`);
        } else {
          log(
            `cloud checkpoint '${req.checkpointRef}' not found for ${backend.name}; provisioning from base image`
          );
        }
      }
      const agentVolumes = await ensureAgentVolumesForCloud(backend, { onLog: log });
      const exposeServicePorts = await readExposedServicePorts(req.workspacePath);
      const provisionEnv = {
        AGENTBOX_BOX_ID: id,
        AGENTBOX_BOX_NAME: name,
        AGENTBOX_BOX_KIND: "cloud",
        // In-sandbox relay is on the box's loopback at the in-box port.
        // 8788 is distinct from the host relay's 8787 so a nested agentbox
        // run inside the box can claim :8787 without colliding.
        AGENTBOX_RELAY_URL: `http://127.0.0.1:${String(8788)}`,
        AGENTBOX_RELAY_TOKEN: relayToken,
        AGENTBOX_BRIDGE_TOKEN: bridgeToken,
        ...agentVolumes.env
      };
      const provisionFrom = async (snapshot) => {
        log(
          snapshot ? `provisioning ${providerName} sandbox from snapshot` : `provisioning ${providerName} sandbox`
        );
        return backend.provision({
          name,
          image,
          snapshot,
          resources,
          timeoutMs,
          exposePorts: exposeServicePorts,
          networkPolicy,
          env: provisionEnv,
          volumes: agentVolumes.mounts,
          onLog: log
        });
      };
      let handle;
      try {
        handle = await provisionFrom(snapshotName);
      } catch (err) {
        if (snapshotName && isSnapshotGoneError(err)) {
          log(
            `checkpoint snapshot '${resolvedCheckpointRef ?? snapshotName}' has expired or been deleted; starting a fresh box from the base image instead`
          );
          if (req.projectRoot && resolvedCheckpointRef) {
            try {
              await removeCloudCheckpointDir(req.projectRoot, backend.name, resolvedCheckpointRef);
            } catch {
            }
          }
          snapshotName = void 0;
          resolvedCheckpointRef = void 0;
          handle = await provisionFrom(void 0);
        } else {
          throw err;
        }
      }
      try {
        if (snapshotName) {
          log("skipping workspace seed \u2014 snapshot already contains /workspace");
        } else {
          await seedCloudWorkspace({
            backend,
            handle,
            workspacePath: req.workspacePath,
            branch,
            workspaceDir: CLOUD_WORKSPACE_DIR,
            bundleDepth: req.bundleDepth,
            fromBranch: req.fromBranch,
            useBranch: req.useBranch,
            onLog: log
          });
        }
        if (agentVolumes.agents.length > 0) {
          await seedAgentVolumesIfFresh(backend, handle, {
            agents: agentVolumes.agents,
            hostWorkspace: req.workspacePath,
            onLog: log
          });
        }
        await seedOpencodeModelState(backend, handle, { onLog: log });
        if (req.envFilesToImport && req.envFilesToImport.length > 0) {
          const { copied } = await uploadEnvFiles({
            backend,
            handle,
            workspacePath: req.workspacePath,
            files: req.envFilesToImport,
            workspaceDir: CLOUD_WORKSPACE_DIR,
            onLog: log
          });
          if (copied > 0) log(`copied ${String(copied)} env/config file(s) into /workspace`);
        }
        let carrySummary;
        if (req.carry && req.carry.length > 0) {
          log(`carry: copying ${String(req.carry.length)} host path(s) into the box`);
          const result = await uploadCarryPaths({
            backend,
            handle,
            entries: req.carry,
            onLog: log
          });
          log(`carry: copied ${String(result.copied)}/${String(req.carry.length)} entry/entries`);
          for (const err of result.errors) log(`carry: ${err}`);
          if (result.applied.length > 0) {
            carrySummary = { count: result.applied.length, entries: result.applied };
          }
        }
        log("launching agentbox-ctl daemon");
        await launchCloudCtlDaemon({
          backend,
          handle,
          boxId: id,
          boxName: name,
          relayUrl: `http://127.0.0.1:${String(8788)}`,
          relayToken,
          bridgeToken,
          webProxyPort: backend.webProxyPort
        });
        if (opts.launchDockerd !== false) {
          log("launching in-box dockerd");
          try {
            const dockerd = await launchCloudDockerdDaemon({ backend, handle, timeoutMs: 6e4 });
            if (!dockerd.up) log(`dockerd did not become ready (continuing): ${dockerd.reason ?? "unknown"}`);
          } catch (err) {
            log(`dockerd daemon launch failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
          }
        }
        const vncEnabled = req.vnc?.enabled !== false;
        const vncPassword = vncEnabled ? generateVncPassword() : void 0;
        if (vncEnabled && vncPassword) {
          log("launching VNC stack (Xvnc + websockify + noVNC)");
          try {
            await launchCloudVncDaemon({ backend, handle, vncPassword });
          } catch (err) {
            log(
              `VNC daemon launch failed (continuing): ${err instanceof Error ? err.message : String(err)}`
            );
          }
        }
        const wp = backend.webProxyPort ?? CLOUD_WEB_PROXY_PORT;
        let webPreview;
        try {
          webPreview = await backend.previewUrl(handle, wp);
        } catch {
          webPreview = void 0;
        }
        const portlessOpt = req.providerOptions?.["portless"] ?? true;
        let portlessAliasName;
        let portlessUrlResolved;
        if (portlessOpt && webPreview) {
          const r = await bootstrapPortlessForCloudBox(backend, handle, {
            boxName: name,
            webPreviewUrl: webPreview.url,
            webPort: wp,
            onLog: log
          });
          if (r) {
            portlessAliasName = r.alias;
            portlessUrlResolved = r.url;
          }
        }
        let vncPreview;
        if (portlessOpt && vncEnabled) {
          try {
            vncPreview = await backend.previewUrl(handle, CLOUD_VNC_PORT);
          } catch {
            vncPreview = void 0;
          }
        }
        let portlessVncAliasName;
        let portlessVncUrlResolved;
        if (portlessOpt && vncPreview) {
          const vncAlias = `vnc-${name}`;
          const url = await registerHostPortlessAlias({
            alias: vncAlias,
            previewUrl: vncPreview.url,
            label: "vnc",
            onLog: log
          });
          if (url) {
            portlessVncAliasName = vncAlias;
            portlessVncUrlResolved = url;
          }
        }
        const servicePorts = exposeServicePorts;
        const servicePreviews = {};
        for (const port of servicePorts) {
          if (port === wp) continue;
          try {
            const p = await backend.previewUrl(handle, port);
            servicePreviews[port] = p.url;
          } catch {
          }
        }
        let relayPreview;
        try {
          relayPreview = await backend.previewUrl(handle, 8788);
        } catch {
          relayPreview = void 0;
        }
        const state = await readState();
        const projectIndex = req.projectRoot ? allocateProjectIndex(state, req.projectRoot) : void 0;
        if (relayPreview) {
          try {
            await registerBoxWithRelay({
              boxId: id,
              token: relayToken,
              name,
              projectIndex,
              kind: "cloud",
              backend: backend.name,
              previewUrl: relayPreview.url,
              previewToken: relayPreview.token,
              bridgeToken,
              createdAt: (/* @__PURE__ */ new Date()).toISOString()
            });
          } catch (err) {
            log(
              `register with host relay failed (continuing): ${err instanceof Error ? err.message : String(err)}`
            );
          }
        }
        const record = {
          id,
          name,
          provider: providerName,
          // `container` carries the sandbox id with a `cloud:` prefix —
          // unique within state, never collides with a real docker
          // container, and grepping for `agentbox-cloud-*` (the old
          // synthetic value) finds nothing now. `image` mirrors the
          // resolved cloud image so `BoxRecord.image: string` stays
          // required without docker-internal readers seeing `undefined`.
          container: `cloud:${handle.sandboxId}`,
          image,
          workspacePath: req.workspacePath,
          projectRoot: req.projectRoot,
          projectIndex,
          relayToken,
          withPlaywright: req.withPlaywright,
          withEnv: req.withEnv,
          carry: carrySummary,
          portlessAlias: portlessAliasName,
          portlessUrl: portlessUrlResolved,
          portlessVncAlias: portlessVncAliasName,
          portlessVncUrl: portlessVncUrlResolved,
          vncEnabled,
          vncPassword,
          vncContainerPort: vncEnabled ? CLOUD_VNC_PORT : void 0,
          resourceLimits: req.limits ? {
            memoryBytes: req.limits.memoryBytes ?? void 0,
            cpus: req.limits.cpus ?? void 0,
            pidsLimit: req.limits.pidsLimit ?? void 0,
            disk: req.limits.disk ?? void 0
          } : void 0,
          cloud: {
            backend: backend.name,
            sandboxId: handle.sandboxId,
            image,
            webPort: wp,
            previewUrls: (() => {
              const m = { ...servicePreviews };
              if (webPreview) m[wp] = webPreview.url;
              return Object.keys(m).length > 0 ? m : void 0;
            })(),
            relayPreviewUrl: relayPreview?.url,
            relayPreviewToken: relayPreview?.token,
            bridgeToken,
            snapshotRef: resolvedCheckpointRef,
            lastState: "running"
          },
          createdAt: (/* @__PURE__ */ new Date()).toISOString()
        };
        await recordBox(record);
        return { record, imageBuilt: false };
      } catch (err) {
        try {
          await backend.destroy(handle);
        } catch {
        }
        throw err;
      }
    },
    async start(box) {
      const h = handleFor(box);
      await backend.start(h);
      return reEnsureCloudBox(box, h);
    },
    async pause(box) {
      await backend.pause(handleFor(box));
      await persistLastState(box, "paused");
    },
    async resume(box) {
      const h = handleFor(box);
      await backend.resume(h);
      await reEnsureCloudBox(box, h);
    },
    async stop(box) {
      await backend.stop(handleFor(box));
      await persistLastState(box, "paused");
    },
    async destroy(box) {
      try {
        await backend.destroy(handleFor(box));
      } catch (err) {
        const msg = err instanceof Error ? err.message : String(err);
        if (!/not.?found|missing/i.test(msg)) throw err;
      }
      if (box.portlessAlias) {
        try {
          await portlessUnalias(box.portlessAlias);
        } catch {
        }
      }
      if (box.portlessVncAlias) {
        try {
          await portlessUnalias(box.portlessVncAlias);
        } catch {
        }
      }
      try {
        await forgetBoxFromRelay(box.id);
      } catch {
      }
      await removeBoxRecord(box.id);
    },
    async probeState(box) {
      return probe(box);
    },
    async inspect(box) {
      const state = await probe(box);
      const webPort = box.cloud?.webPort ?? backend.webProxyPort ?? CLOUD_WEB_PROXY_PORT;
      const portlessWebUrl = box.portlessAlias !== void 0 ? box.portlessUrl ?? `https://${box.portlessAlias}.localhost` : void 0;
      const cachedWebUrl = box.cloud?.previewUrls?.[webPort];
      const webUrl = portlessWebUrl ?? cachedWebUrl;
      const endpoints = [];
      if (webUrl) {
        endpoints.push({
          kind: "web",
          name: "web",
          containerPort: webPort,
          url: webUrl,
          reachable: true
        });
      }
      for (const [portStr, url] of Object.entries(box.cloud?.previewUrls ?? {})) {
        const port = Number.parseInt(portStr, 10);
        if (!Number.isFinite(port) || port === webPort) continue;
        endpoints.push({
          kind: "web",
          name: `service-${String(port)}`,
          containerPort: port,
          url,
          reachable: true
        });
      }
      return {
        record: box,
        state,
        endpoints: {
          domain: webUrl ? new URL(webUrl).host : "",
          domainIsOrb: false,
          endpoints
        },
        raw: void 0
      };
    },
    async exec(box, argv, opts2) {
      const r = await backend.exec(handleFor(box), quoteShellArgv(argv), {
        cwd: opts2?.cwd,
        env: opts2?.env,
        user: opts2?.user
      });
      return { exitCode: r.exitCode, stdout: r.stdout, stderr: r.stderr };
    },
    async buildAttach(box, kind, opts2) {
      if (!backend.attachArgv) {
        throw new Error(
          `cloud backend '${backend.name}' does not implement attachArgv \u2014 interactive attach not supported`
        );
      }
      const handle = handleFor(box);
      const baseArgv = await backend.attachArgv(handle);
      const inner = renderInnerCommand(kind, opts2);
      const argv = opts2?.detached ? [...baseArgv.slice(1), inner] : [...baseArgv.slice(1), "-t", inner];
      const fullArgv = [baseArgv[0], ...argv];
      const cleanup = backend.revokeAttachToken ? async () => {
        await backend.revokeAttachToken(handle, baseArgv);
      } : void 0;
      return { argv: fullArgv, cleanup };
    },
    async uploadPath(box, hostSrc, boxDst) {
      return uploadToCloudBox(backend, handleFor(box), hostSrc, boxDst);
    },
    async downloadPath(box, boxSrc, hostDst) {
      return downloadFromCloudBox(backend, handleFor(box), boxSrc, hostDst);
    },
    async downloadDirContents(box, boxSrc, hostDst) {
      return pullCloudDirContents(backend, handleFor(box), boxSrc, hostDst);
    },
    async resolveUrl(box, opts2) {
      const h = handleFor(box);
      const kind = opts2?.kind ?? "web";
      if (!opts2?.loopback) {
        if (kind === "web" && box.portlessAlias) {
          return box.portlessUrl ?? `https://${box.portlessAlias}.localhost`;
        }
        if (kind === "vnc" && box.portlessVncAlias) {
          return box.portlessVncUrl ?? `https://${box.portlessVncAlias}.localhost`;
        }
      }
      const port = kind === "vnc" ? CLOUD_VNC_PORT : box.cloud?.webPort ?? backend.webProxyPort ?? CLOUD_WEB_PROXY_PORT;
      if (backend.signedPreviewUrl) {
        const ttl = opts2?.ttl ?? DEFAULT_SIGNED_URL_TTL_SECONDS;
        try {
          const signed = await backend.signedPreviewUrl(h, port, ttl);
          return signed.url;
        } catch (err) {
          if (kind === "web") {
            const fallbackPort = await firstExposedServicePort(box);
            if (fallbackPort !== void 0 && fallbackPort !== port) {
              const signed = await backend.signedPreviewUrl(h, fallbackPort, ttl);
              return signed.url;
            }
          }
          throw err;
        }
      }
      const p = await backend.previewUrl(h, port);
      throw new Error(
        `cloud backend '${backend.name}' does not support signed preview URLs; the standard URL (${p.url}) requires a header token (e.g. x-daytona-preview-token: ${p.token ?? "<unset>"}) that browsers can't attach from a click. Use a programmatic client or wait for backend support.`
      );
    },
    // Cloud checkpoint capability. Backends without `createSnapshot` get a
    // capability stub whose methods throw — the CLI's `agentbox checkpoint
    // create` then surfaces a clean "not supported" error rather than a
    // silent no-op.
    checkpoint: makeCloudCheckpoint(backend),
    // Extract the box's agent login(s) back to the host (~/.agentbox) so the
    // next box inherits the login. Lives on the base cloud provider (not inside
    // `checkpoint.create`) so it works even for providers that override the
    // whole `checkpoint` capability (vercel). The CLI calls this on
    // `checkpoint create --set-default`, while the box is guaranteed running.
    async extractAgentCredentials(box) {
      if (!box.cloud?.sandboxId) return [];
      return extractCloudAgentCredentials(backend, { sandboxId: box.cloud.sandboxId });
    }
    // stats is provider-optional; cloud backends without a metrics API just
    // omit it. Backends that have one can decorate the returned provider.
  };
}
var RESERVED_CLOUD_PORTS = /* @__PURE__ */ new Set([CLOUD_WEB_PROXY_PORT, CLOUD_VNC_PORT, 8788]);
async function firstExposedServicePort(box) {
  const reserved = (p) => RESERVED_CLOUD_PORTS.has(p) || p === box.cloud?.webPort;
  const fromRecord = Object.keys(box.cloud?.previewUrls ?? {}).map(Number).filter((p) => Number.isInteger(p) && !reserved(p));
  if (fromRecord.length > 0) return Math.min(...fromRecord);
  try {
    const fromYaml = (await readExposedServicePorts(box.workspacePath)).filter((p) => !reserved(p));
    if (fromYaml.length > 0) return Math.min(...fromYaml);
  } catch {
  }
  return void 0;
}
function makeCloudCheckpoint(backend) {
  return {
    async create(box, name) {
      if (!backend.createSnapshot) {
        throw new Error(
          `cloud backend '${backend.name}' doesn't support snapshots \u2014 \`agentbox checkpoint\` unavailable`
        );
      }
      if (!box.projectRoot) {
        throw new Error(
          `cloud checkpoint requires the box to have a project root (run \`agentbox checkpoint\` from inside the project)`
        );
      }
      if (!box.cloud?.sandboxId) {
        throw new Error(`cloud box ${box.name} has no sandboxId \u2014 record is malformed`);
      }
      const snapshotName = cloudSnapshotName(box.projectRoot, name);
      await backend.createSnapshot({ sandboxId: box.cloud.sandboxId }, snapshotName);
      const info = await writeCloudCheckpointManifest(box.projectRoot, backend.name, name, {
        snapshotName,
        sourceBoxId: box.id,
        sourceBoxName: box.name
      });
      return { ref: info.name };
    },
    async list(projectRoot) {
      const entries = await listCloudCheckpoints(projectRoot, backend.name);
      return entries.map((e) => ({ ref: e.name, createdAt: e.manifest.createdAt }));
    },
    async remove(projectRoot, ref) {
      const entry = await resolveCloudCheckpoint(projectRoot, backend.name, ref);
      if (!entry) return;
      if (backend.deleteSnapshot) {
        try {
          await backend.deleteSnapshot(entry.manifest.snapshotName);
        } catch {
        }
      }
      await removeCloudCheckpointDir(projectRoot, backend.name, ref);
    }
  };
}
function renderInnerCommand(kind, opts) {
  const sessionName = opts?.sessionName ?? defaultSessionName(kind);
  const fallback = opts?.command ?? defaultCommand(kind, opts);
  if (kind === "logs") {
    return fallback;
  }
  if (opts?.noTmux) {
    return fallback;
  }
  const sessionQ = shellSingle(sessionName);
  const cwdQ = shellSingle(CLOUD_WORKSPACE_DIR);
  const fallbackQ = shellSingle(fallback);
  const configSnippet = buildTmuxConfigShellSnippet(sessionName);
  const lines = [
    `command -v tmux >/dev/null || { echo "tmux not installed in sandbox"; exit 127; }`,
    `tmux has-session -t ${sessionQ} 2>/dev/null || tmux new-session -d -c ${cwdQ} -s ${sessionQ} ${fallbackQ}`,
    configSnippet
  ];
  if (opts?.detached) return lines.join("; ");
  return [...lines, `exec tmux attach -t ${sessionQ}`].join("; ");
}
function defaultSessionName(kind) {
  switch (kind) {
    case "shell":
      return "shell";
    case "agent":
      return "agent";
    case "logs":
      return "logs";
  }
}
function defaultCommand(kind, opts) {
  switch (kind) {
    case "shell":
      return "bash -l";
    case "agent":
      return "bash -l";
    case "logs": {
      if (!opts?.service) {
        return 'echo "no service specified \u2014 set BuildAttachOptions.service"';
      }
      const tail = opts.tail !== void 0 ? String(opts.tail) : "200";
      const args = [`--tail ${shellSingle(tail)}`];
      if (opts.follow !== false) args.push("--follow");
      return `/usr/local/bin/agentbox-ctl logs ${shellSingle(opts.service)} ${args.join(" ")}`;
    }
  }
}
function shellSingle(s) {
  return "'" + s.replace(/'/g, "'\\''") + "'";
}

export {
  ensureAgentVolumesForCloud,
  seedAgentVolumesIfFresh,
  agentSpecsForCloud,
  listCloudCheckpoints,
  resolveCloudCheckpoint,
  writeCloudCheckpointManifest,
  removeCloudCheckpointDir,
  probeCloudCheckpoint,
  createCloudProvider,
  renderInnerCommand
};
//# sourceMappingURL=chunk-MXXXKJYS.js.map