@tablation/crew 0.112.0 → 0.113.0

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.
Files changed (2) hide show
  1. package/dist/cli.js +30 -10
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -11784,7 +11784,13 @@ function syncAllPassengerCheckouts(cfg) {
11784
11784
 
11785
11785
  // src/sandbox-image.ts
11786
11786
  var SANDBOX_BASE_IMAGE = "nvcr.io/nvidia/base/ubuntu:24.04";
11787
- var SANDBOX_HARNESS_VERSION = "0.1.6";
11787
+ var SANDBOX_OPENSHELL_VERSION = "0.1.6";
11788
+ var SANDBOX_CLAUDE_VERSION = "2.1.309";
11789
+ var SANDBOX_CLAUDE_DIST = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases";
11790
+ var SANDBOX_CLAUDE_SHA256 = {
11791
+ x86_64: { platform: "linux-x64", sha256: "4d704a8aecbe038affa3000f498ae17c1b4f753add8facb8764120affc99b658" },
11792
+ aarch64: { platform: "linux-arm64", sha256: "9796dd26899337f687739a0b39a7353b639f062a3436a7b941fcf19a1b757a9b" }
11793
+ };
11788
11794
  var SANDBOX_UID = 1e3;
11789
11795
  var CREW_PREFIX = "/opt/crew";
11790
11796
  var SANDBOX_RETRY_AFTER_MS = 60 * 60 * 1e3;
@@ -11808,15 +11814,28 @@ var CREW_ENV = {
11808
11814
  XDG_CACHE_HOME: `${CREW_PREFIX}/cache`,
11809
11815
  npm_config_cache: `${CREW_PREFIX}/cache/npm`,
11810
11816
  npm_config_store_dir: `${CREW_PREFIX}/pnpm-store`,
11811
- PNPM_HOME: `${CREW_PREFIX}/pnpm`
11817
+ PNPM_HOME: `${CREW_PREFIX}/pnpm`,
11818
+ // A run cannot reach the download host, so an in-run update attempt is only noise.
11819
+ DISABLE_AUTOUPDATER: "1"
11812
11820
  };
11821
+ function claudeInstallCommand() {
11822
+ const cases = Object.entries(SANDBOX_CLAUDE_SHA256).map(([arch, { platform: platform2, sha256: sha2562 }]) => `${arch}) p=${platform2}; sum=${sha2562};;`).join(" ");
11823
+ return [
11824
+ `case "$(uname -m)" in ${cases} *) echo "no pinned Claude Code binary for $(uname -m)" >&2; exit 1;; esac`,
11825
+ `mkdir -p ${CREW_PREFIX}/bin`,
11826
+ `curl -fsSL --retry 3 -o ${CREW_PREFIX}/bin/claude "${SANDBOX_CLAUDE_DIST}/${SANDBOX_CLAUDE_VERSION}/$p/claude"`,
11827
+ `echo "$sum ${CREW_PREFIX}/bin/claude" | sha256sum -c -`,
11828
+ `chmod 0755 ${CREW_PREFIX}/bin/claude`,
11829
+ `${CREW_PREFIX}/bin/claude --version | grep -F "${SANDBOX_CLAUDE_VERSION}"`
11830
+ ].join("; ");
11831
+ }
11813
11832
  function baseLayer() {
11814
11833
  const dockerfile = [
11815
11834
  `FROM ${SANDBOX_BASE_IMAGE}`,
11816
- `LABEL io.crew.sandbox.layer="base" io.crew.sandbox.harness="${SANDBOX_HARNESS_VERSION}"`,
11835
+ `LABEL io.crew.sandbox.layer="base" io.crew.sandbox.openshell="${SANDBOX_OPENSHELL_VERSION}"`,
11817
11836
  ""
11818
11837
  ].join("\n");
11819
- return { name: "base", tag: `crew-sandbox-base:${hash({ SANDBOX_BASE_IMAGE, SANDBOX_HARNESS_VERSION })}`, dockerfile, files: {} };
11838
+ return { name: "base", tag: `crew-sandbox-base:${hash({ SANDBOX_BASE_IMAGE, SANDBOX_OPENSHELL_VERSION })}`, dockerfile, files: {} };
11820
11839
  }
11821
11840
  function crewLayer(base) {
11822
11841
  const files = { "credential-helper": CREDENTIAL_HELPER, "mcp.json": MCP_CONFIG };
@@ -11827,10 +11846,11 @@ function crewLayer(base) {
11827
11846
  run2("apt-get update && apt-get install -y --no-install-recommends ca-certificates curl git && rm -rf /var/lib/apt/lists/*"),
11828
11847
  `COPY credential-helper ${CREW_PREFIX}/bin/credential-helper`,
11829
11848
  `COPY mcp.json ${CREW_PREFIX}/mcp/mcp.json`,
11849
+ run2(claudeInstallCommand()),
11830
11850
  run2(`chmod 0755 ${CREW_PREFIX}/bin/credential-helper && git config --system credential.helper ${CREW_PREFIX}/bin/credential-helper`),
11831
11851
  run2(`mkdir -p ${CREW_PREFIX}/cache ${CREW_PREFIX}/pnpm-store ${CREW_PREFIX}/pnpm /sandbox && chown -R ${SANDBOX_UID}:${SANDBOX_UID} ${CREW_PREFIX} /sandbox`),
11832
11852
  `ENV ${env} PATH=${CREW_PREFIX}/pnpm:${CREW_PREFIX}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`,
11833
- `LABEL io.crew.sandbox.layer="crew"`,
11853
+ `LABEL io.crew.sandbox.layer="crew" io.crew.sandbox.claude="${SANDBOX_CLAUDE_VERSION}"`,
11834
11854
  ""
11835
11855
  ].join("\n");
11836
11856
  return { name: "crew", tag: `crew-sandbox-crew:${hash({ base: base.tag, dockerfile, files })}`, dockerfile, files };
@@ -11891,7 +11911,7 @@ function planSandbox(repo, decl, warm = {}) {
11891
11911
  const base = baseLayer();
11892
11912
  const crew = crewLayer(base);
11893
11913
  const layer = repoLayer(repo, decl, crew, warm);
11894
- return { repo, tag: layer.tag, layers: [base, crew, layer] };
11914
+ return { repo, tag: layer.tag, claude: SANDBOX_CLAUDE_VERSION, layers: [base, crew, layer] };
11895
11915
  }
11896
11916
  var sandboxStatePath = (stateDir) => join26(stateDir, "sandbox-images.json");
11897
11917
  function readSandboxState(stateDir) {
@@ -11916,8 +11936,8 @@ function sandboxImageStatus(state, plan) {
11916
11936
  return { status: "failed", detail: `last build of ${plan.tag} failed at ${s.failure.at}; log ${s.failure.logPath}${current ? `; running ${current.tag}` : ""}` };
11917
11937
  }
11918
11938
  if (!current) return { status: "missing", detail: `no image built yet (wants ${plan.tag}); run \`crew sandbox build\`` };
11919
- if (current.tag !== plan.tag) return { status: "stale", detail: `running ${current.tag}, declaration now builds ${plan.tag}` };
11920
- return { status: "ok", detail: `${current.tag} built ${current.builtAt}` };
11939
+ if (current.tag !== plan.tag) return { status: "stale", detail: `running ${current.tag} (claude ${current.claude ?? "unknown"}), declaration now builds ${plan.tag} (claude ${plan.claude})` };
11940
+ return { status: "ok", detail: `${current.tag} built ${current.builtAt}, claude ${current.claude ?? "unknown"}` };
11921
11941
  }
11922
11942
  var spawnBuildRunner = (engine = "docker") => (args, logPath) => new Promise((resolve7) => {
11923
11943
  const child = spawn4(engine, args, { stdio: ["ignore", "pipe", "pipe"] });
@@ -11980,7 +12000,7 @@ async function buildSandboxImage(plan, deps) {
11980
12000
  rmSync13(ctx, { recursive: true, force: true });
11981
12001
  }
11982
12002
  }
11983
- const tags = [{ tag: plan.tag, builtAt: now().toISOString() }, ...entry.tags.filter((t) => t.tag !== plan.tag)];
12003
+ const tags = [{ tag: plan.tag, builtAt: now().toISOString(), claude: plan.claude }, ...entry.tags.filter((t) => t.tag !== plan.tag)];
11984
12004
  const dropped = tags.slice(KEEP_TAGS);
11985
12005
  state[plan.repo] = { tags: tags.slice(0, KEEP_TAGS) };
11986
12006
  writeSandboxState(deps.stateDir, state);
@@ -26683,7 +26703,7 @@ Signed in as ${result.identity.email} \u2014 minted an API key in workspace "${r
26683
26703
  `);
26684
26704
  for (const t of r.tags) {
26685
26705
  const ageH = Math.max(0, Math.round((Date.now() - Date.parse(t.builtAt)) / 36e5));
26686
- process.stdout.write(` ${t.tag} built ${t.builtAt} (${ageH}h ago)
26706
+ process.stdout.write(` ${t.tag} built ${t.builtAt} (${ageH}h ago), claude ${t.claude ?? "unknown"}
26687
26707
  `);
26688
26708
  }
26689
26709
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tablation/crew",
3
- "version": "0.112.0",
3
+ "version": "0.113.0",
4
4
  "description": "A standing team of headless agents that picks work off a Tablation board, does it on a machine you control, and reports back.",
5
5
  "type": "module",
6
6
  "license": "MIT",