@mastra/e2b 0.11.0-alpha.0 → 0.11.0-alpha.2

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/index.js CHANGED
@@ -550,7 +550,7 @@ var E2BProcessManager = class extends SandboxProcessManager {
550
550
  handle = new E2BProcessHandle(await e2b.commands.run(command, {
551
551
  background: true,
552
552
  stdin: true,
553
- cwd: options.cwd,
553
+ cwd: options.cwd ?? this.sandbox.workingDirectory,
554
554
  envs,
555
555
  timeoutMs: options.timeout,
556
556
  onStdout: (data) => handle.emitStdout(data),
@@ -1562,7 +1562,7 @@ var E2BSandbox = class E2BSandbox extends MastraSandbox {
1562
1562
  * need `git fetch` + checkout of their actual ref plus setup drift, instead
1563
1563
  * of a cold clone + full install.
1564
1564
  *
1565
- * There is exactly ONE template per (repo, setup command, workdir): the
1565
+ * There is exactly ONE template per (repo, setup command, repoDir): the
1566
1566
  * template name is a deterministic `mastra-repo-<hash>` over those inputs,
1567
1567
  * and the commit sha rides as a docker-style TAG on that name
1568
1568
  * (`mastra-repo-<hash>:sha-<sha>`). A moved default branch produces a new
@@ -1642,7 +1642,8 @@ function repoTemplateName(identity) {
1642
1642
  identity.setupCommand ?? null,
1643
1643
  identity.buildEnv ? Object.entries(identity.buildEnv).sort(([a], [b]) => a.localeCompare(b)) : null,
1644
1644
  identity.cpuCount ?? 2,
1645
- identity.memoryMB ?? 1024
1645
+ identity.memoryMB ?? 1024,
1646
+ ...identity.workingDirectory !== void 0 ? [identity.workingDirectory] : []
1646
1647
  ];
1647
1648
  const hash = createHash("sha256").update(JSON.stringify(config)).digest("hex").slice(0, 8);
1648
1649
  const { owner, repo } = parseCloneUrl(cloneUrl);
@@ -1698,10 +1699,11 @@ async function resolveSpecAtHead(options) {
1698
1699
  spec: buildRepoTemplateSpec({
1699
1700
  cloneUrl,
1700
1701
  ...sha ? { sha } : {},
1701
- ...options.setupCommand ? { setupCommand: options.setupCommand } : {},
1702
+ ...normalizeSetupCommands(options.setupCommand).length > 0 ? { setupCommand: options.setupCommand } : {},
1702
1703
  ...buildEnv ? { buildEnv } : {},
1703
1704
  ...options.cpuCount !== void 0 ? { cpuCount: options.cpuCount } : {},
1704
- ...options.memoryMB !== void 0 ? { memoryMB: options.memoryMB } : {}
1705
+ ...options.memoryMB !== void 0 ? { memoryMB: options.memoryMB } : {},
1706
+ ...options.workingDirectory !== void 0 ? { workingDirectory: trimTrailingSlashes(assertWorkingDirectory(options.workingDirectory)) } : {}
1705
1707
  }, token),
1706
1708
  ...sha ? { sha } : {}
1707
1709
  };
@@ -1739,7 +1741,7 @@ async function refreshRepoTemplate(options, connection) {
1739
1741
  }
1740
1742
  /**
1741
1743
  * The clone URL is the only untrusted input that reaches a build command,
1742
- * so it is checked before it can be interpolated into one. The workdir is
1744
+ * so it is checked before it can be interpolated into one. The repoDir is
1743
1745
  * derived from it rather than supplied, so it needs no separate guard.
1744
1746
  */
1745
1747
  function assertCloneUrl(cloneUrl) {
@@ -1756,18 +1758,21 @@ function gitAuthFlag() {
1756
1758
  return `-c http.extraheader="AUTHORIZATION: basic $(printf 'x-access-token:%s' "$${BUILD_TOKEN_ENV}" | base64 -w0)"`;
1757
1759
  }
1758
1760
  function buildRepoTemplateSpec(identity, token) {
1759
- const { sha, setupCommand, buildEnv } = identity;
1761
+ const { sha, setupCommand, buildEnv, workingDirectory } = identity;
1760
1762
  const cloneUrl = normalizeCloneUrl(identity.cloneUrl);
1761
- const workdir = defaultWorkdir(cloneUrl);
1763
+ const repoDir = repoDirName(cloneUrl);
1762
1764
  const auth = token ? `${gitAuthFlag()} ` : "";
1763
- const steps = [`git ${auth}clone ${cloneUrl} "${workdir}"`];
1764
- if (sha) steps.push(`git -C "${workdir}" ${auth}fetch origin ${sha}`, `git -C "${workdir}" checkout ${sha}`);
1765
- if (setupCommand) steps.push(`cd "${workdir}" && ${setupCommand}`);
1766
1765
  let template = createDefaultMountableTemplate().template;
1767
1766
  const env = { ...buildEnv };
1768
1767
  if (token) env[BUILD_TOKEN_ENV] = token;
1769
1768
  if (Object.keys(env).length > 0) template = template.setEnvs(env);
1770
- template = template.runCmd(steps);
1769
+ if (workingDirectory) {
1770
+ const dir = trimTrailingSlashes(workingDirectory);
1771
+ template = template.runCmd(`mkdir -p "${dir}"`).setWorkdir(dir);
1772
+ }
1773
+ template = template.runCmd(`git ${auth}clone ${cloneUrl} "${repoDir}"`);
1774
+ if (sha) template = template.runCmd(`git -C "${repoDir}" ${auth}fetch origin ${sha}`).runCmd(`git -C "${repoDir}" checkout ${sha}`);
1775
+ for (const command of normalizeSetupCommands(setupCommand)) template = template.runCmd(`cd "${repoDir}" && ${command}`);
1771
1776
  return {
1772
1777
  ref: repoTemplateRef(identity),
1773
1778
  template,
@@ -1834,9 +1839,23 @@ function parseCloneUrl(cloneUrl) {
1834
1839
  repo
1835
1840
  };
1836
1841
  }
1837
- function defaultWorkdir(cloneUrl) {
1842
+ /** Normalize setup commands and drop blank entries that would produce invalid shell steps. */
1843
+ function normalizeSetupCommands(setupCommand) {
1844
+ return (setupCommand === void 0 ? [] : Array.isArray(setupCommand) ? setupCommand : [setupCommand]).filter((command) => command.trim() !== "");
1845
+ }
1846
+ function repoDirName(cloneUrl) {
1838
1847
  const { repo } = parseCloneUrl(cloneUrl);
1839
- return `$HOME/${repo.replace(/[^\w.-]/g, "-").replace(/^\.+/, "") || "repo"}`;
1848
+ return repo.replace(/[^\w.-]/g, "-").replace(/^\.+/, "") || "repo";
1849
+ }
1850
+ function trimTrailingSlashes(path) {
1851
+ let end = path.length;
1852
+ while (end > 1 && path[end - 1] === "/") end--;
1853
+ return path.slice(0, end);
1854
+ }
1855
+ /** Validate a literal absolute path before embedding it in shell build steps. */
1856
+ function assertWorkingDirectory(dir) {
1857
+ if (!(/^\/[A-Za-z0-9._/-]*$/.test(dir) && !dir.split("/").includes(".."))) throw new Error(`Repo template workingDirectory must be an absolute path of plain path characters (got ${JSON.stringify(dir)}); ~ and $HOME are not expanded.`);
1858
+ return dir;
1840
1859
  }
1841
1860
  //#endregion
1842
1861
  //#region src/provider.ts