@tablation/crew 0.126.10 → 0.126.11

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 +43 -25
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -6353,7 +6353,7 @@ function attentionProblems(items, already) {
6353
6353
  }
6354
6354
 
6355
6355
  // src/sandbox-image.ts
6356
- import { createHash as createHash6 } from "crypto";
6356
+ import { createHash as createHash7 } from "crypto";
6357
6357
  import { spawn as spawn5 } from "child_process";
6358
6358
  import { execFileSync as execFileSync8 } from "child_process";
6359
6359
  import { existsSync as existsSync30, mkdirSync as mkdirSync19, readFileSync as readFileSync27, renameSync as renameSync3, writeFileSync as writeFileSync20, rmSync as rmSync15 } from "fs";
@@ -6363,7 +6363,7 @@ import { tmpdir as tmpdir3 } from "os";
6363
6363
 
6364
6364
  // src/passenger-containers.ts
6365
6365
  import { execFileSync as execFileSync7 } from "child_process";
6366
- import { createHash as createHash5 } from "crypto";
6366
+ import { createHash as createHash6 } from "crypto";
6367
6367
 
6368
6368
  // src/sandbox-cache.ts
6369
6369
  import { execFile as execFile2 } from "child_process";
@@ -6383,7 +6383,7 @@ import { readFileSync as readFileSync25, existsSync as existsSync26, statSync as
6383
6383
  import { StringDecoder } from "string_decoder";
6384
6384
  import { finished } from "stream/promises";
6385
6385
  import { join as join29, dirname as dirname14, basename as basename9 } from "path";
6386
- import { createHash as createHash4 } from "crypto";
6386
+ import { createHash as createHash5 } from "crypto";
6387
6387
 
6388
6388
  // src/state.ts
6389
6389
  import { readFileSync as readFileSync19, writeFileSync as writeFileSync14, existsSync as existsSync19, mkdirSync as mkdirSync13, rmSync as rmSync10, statSync as statSync7, readdirSync as readdirSync5 } from "fs";
@@ -10682,6 +10682,7 @@ function skillMarkerWarnings(promptsDir, personaPrompts) {
10682
10682
  // src/runner.ts
10683
10683
  import { spawn as spawn3, execFile, execFileSync as execFileSync6 } from "child_process";
10684
10684
  import { mkdtempSync, mkdirSync as mkdirSync17, writeFileSync as writeFileSync18, rmSync as rmSync14 } from "fs";
10685
+ import { createHash as createHash4 } from "crypto";
10685
10686
  import { tmpdir as tmpdir2 } from "os";
10686
10687
  import { basename as basename8, dirname as dirname13, join as join28 } from "path";
10687
10688
  import { promisify } from "util";
@@ -10777,8 +10778,9 @@ function shQuote2(s) {
10777
10778
  return `'${s.replace(/'/g, `'\\''`)}'`;
10778
10779
  }
10779
10780
  function sandboxName(plan, now = Date.now()) {
10780
- const base = [plan.route, plan.role, plan.ticket ?? ""].join("-").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
10781
- return `crew-${base.slice(0, 36)}-${now.toString(36)}`.replace(/-+/g, "-");
10781
+ const h = createHash4("sha256").update([plan.route, plan.role, plan.ticket ?? ""].join("\0")).digest();
10782
+ const tag = (h.readUInt32BE(0) % 36 ** 6).toString(36).padStart(6, "0");
10783
+ return `crew-${tag}${now.toString(36).slice(-8).padStart(8, "0")}`;
10782
10784
  }
10783
10785
  var SandboxRunner = class {
10784
10786
  kind = "sandbox";
@@ -10941,7 +10943,8 @@ function runnerFor(kind, sandbox) {
10941
10943
  function runnerOfSidecar(sc) {
10942
10944
  return sc.runner === "sandbox" ? new SandboxRunner(sc.sandboxBin ? { bin: sc.sandboxBin } : {}) : new HostRunner();
10943
10945
  }
10944
- function checkSandboxRunner(cfg = {}, run3 = (b, a) => execFileSync6(b, a, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], timeout: 15e3 })) {
10946
+ var PROBE_CREATE_TIMEOUT_MS = 12e4;
10947
+ function checkSandboxRunner(cfg = {}, run3 = (b, a, t) => execFileSync6(b, a, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], timeout: t ?? 15e3 })) {
10945
10948
  const bin = cfg.bin ?? DEFAULT_SANDBOX_CONFIG.bin;
10946
10949
  let version;
10947
10950
  try {
@@ -10958,6 +10961,21 @@ function checkSandboxRunner(cfg = {}, run3 = (b, a) => execFileSync6(b, a, { enc
10958
10961
  detail: `${version}: the gateway does not answer (${(err3.stderr || err3.message).trim().split("\n").filter(Boolean).slice(0, 2).join(" / ")}). Start it; on Docker Desktop its docker section needs supervisor_network_mode = "bridge", and allow_driver_config = true for the cache volume mount.`
10959
10962
  };
10960
10963
  }
10964
+ const probe = sandboxName({ route: "doctor", role: "dev", ticket: void 0 });
10965
+ try {
10966
+ run3(bin, ["sandbox", "create", "--name", probe, "--detach", "--", "sleep", "60"], PROBE_CREATE_TIMEOUT_MS);
10967
+ } catch (e) {
10968
+ const err3 = e;
10969
+ if (err3.code === "ETIMEDOUT" || err3.killed) {
10970
+ return { ok: false, detail: `${version}: creating a probe sandbox named ${probe} timed out after ${PROBE_CREATE_TIMEOUT_MS / 1e3} s; the gateway may still be pulling its images on a first create, so run crew doctor again` };
10971
+ }
10972
+ return { ok: false, detail: `${version}: the gateway refused a probe sandbox named ${probe} (${(err3.stderr || err3.message).trim().split("\n").filter(Boolean).slice(0, 2).join(" / ")})` };
10973
+ } finally {
10974
+ try {
10975
+ run3(bin, ["sandbox", "delete", probe]);
10976
+ } catch {
10977
+ }
10978
+ }
10961
10979
  return { ok: true, detail: version };
10962
10980
  }
10963
10981
 
@@ -11144,7 +11162,7 @@ function planAgentRun(o) {
11144
11162
  brief: expanded.text,
11145
11163
  digest
11146
11164
  });
11147
- const promptSha = createHash4("sha256").update(expanded.text).digest("hex");
11165
+ const promptSha = createHash5("sha256").update(expanded.text).digest("hex");
11148
11166
  const streamsDir = join29(o.stateDir, "streams");
11149
11167
  const base = `${routeLabel}-${o.role}-${o.cycle}${o.runId ? `-${o.runId}` : ""}`;
11150
11168
  const seat = resolveSeat(o.ship, o.route, o.role, o.agentPersona ?? (o.agentModel ? { model: o.agentModel } : {}), o.repo);
@@ -12097,8 +12115,8 @@ async function mintMissingSeatKeys(route2, o) {
12097
12115
  const resolved = route2.resolved;
12098
12116
  const doFetch = o.fetchImpl ?? fetch;
12099
12117
  const targets = [
12100
- ...SEAT_KEY_ROLES.filter((r) => resolved.seats[r]).map((role) => ({ role, agentId: seatAgentId(route2, role) })),
12101
- ...resolved.releaseSeat ? [{ role: "release", agentId: resolved.releaseAgentId }] : []
12118
+ ...SEAT_KEY_ROLES.filter((r) => resolved.seats[r]).map((role) => ({ role, agentId: seatAgentId(route2, role), actorRecordId: resolved.seats[role] })),
12119
+ ...resolved.releaseSeat ? [{ role: "release", agentId: resolved.releaseAgentId, actorRecordId: resolved.releaseSeat }] : []
12102
12120
  ];
12103
12121
  let store;
12104
12122
  try {
@@ -12127,7 +12145,7 @@ async function mintMissingSeatKeys(route2, o) {
12127
12145
  return targets.map(({ role, agentId }) => agentId ? { role, action: "failed", detail } : { role, action: "no_agent" });
12128
12146
  }
12129
12147
  }
12130
- for (const { role, agentId } of targets) {
12148
+ for (const { role, agentId, actorRecordId } of targets) {
12131
12149
  if (!agentId) {
12132
12150
  out.push({ role, action: "no_agent" });
12133
12151
  continue;
@@ -12149,7 +12167,7 @@ async function mintMissingSeatKeys(route2, o) {
12149
12167
  "Content-Type": "application/json",
12150
12168
  "User-Agent": o.userAgent ?? "Mozilla/5.0 TablationCrewAgent/1.0"
12151
12169
  },
12152
- body: JSON.stringify({ name: `crew ${o.shipName ?? "ship"} ${role}` })
12170
+ body: JSON.stringify({ name: `crew ${o.shipName ?? "ship"} ${role}`, ...actorRecordId ? { actorRecordId } : {} })
12153
12171
  });
12154
12172
  if (res.status === 403) {
12155
12173
  out.push({ role, action: "forbidden" });
@@ -12220,8 +12238,8 @@ async function revokeSeatKeys(route2, o) {
12220
12238
  const resolved = route2.resolved;
12221
12239
  const doFetch = o.fetchImpl ?? fetch;
12222
12240
  const targets = [
12223
- ...SEAT_KEY_ROLES.filter((r) => resolved.seats[r]).map((role) => ({ role, agentId: seatAgentId(route2, role) })),
12224
- ...resolved.releaseSeat ? [{ role: "release", agentId: resolved.releaseAgentId }] : []
12241
+ ...SEAT_KEY_ROLES.filter((r) => resolved.seats[r]).map((role) => ({ role, agentId: seatAgentId(route2, role), actorRecordId: resolved.seats[role] })),
12242
+ ...resolved.releaseSeat ? [{ role: "release", agentId: resolved.releaseAgentId, actorRecordId: resolved.releaseSeat }] : []
12225
12243
  ];
12226
12244
  let store;
12227
12245
  try {
@@ -12751,12 +12769,12 @@ function containerNameFor(workspaceId) {
12751
12769
  return `crew-passenger-${workspaceId}`;
12752
12770
  }
12753
12771
  function portFor(workspaceId, base = 28765, span = 1e3) {
12754
- const digest = createHash5("sha256").update(workspaceId).digest();
12772
+ const digest = createHash6("sha256").update(workspaceId).digest();
12755
12773
  return base + digest.readUInt32BE(0) % span;
12756
12774
  }
12757
12775
  function mountsDigest(mounts, image) {
12758
12776
  const sorted2 = [...mounts].sort((a, b) => a.containerPath.localeCompare(b.containerPath));
12759
- return createHash5("sha256").update(JSON.stringify({ mounts: sorted2, image })).digest("hex").slice(0, 16);
12777
+ return createHash6("sha256").update(JSON.stringify({ mounts: sorted2, image })).digest("hex").slice(0, 16);
12760
12778
  }
12761
12779
  function planContainers(cfg) {
12762
12780
  const byWorkspace = /* @__PURE__ */ new Map();
@@ -12959,7 +12977,7 @@ echo "password=$CREW_FORGE_TOKEN"
12959
12977
  `;
12960
12978
  var MCP_CONFIG = `${JSON.stringify({ mcpServers: {} }, null, 2)}
12961
12979
  `;
12962
- var hash = (parts) => createHash6("sha256").update(JSON.stringify(parts)).digest("hex").slice(0, 12);
12980
+ var hash = (parts) => createHash7("sha256").update(JSON.stringify(parts)).digest("hex").slice(0, 12);
12963
12981
  var slug = (s) => s.toLowerCase().replace(/[^a-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
12964
12982
  var run2 = (cmd) => `RUN ["/bin/bash", "-c", ${JSON.stringify(`set -euo pipefail; ${cmd}`)}]`;
12965
12983
  var CREW_ENV = {
@@ -14384,13 +14402,13 @@ import { hostname as hostname3 } from "os";
14384
14402
 
14385
14403
  // src/machine-id.ts
14386
14404
  import { execFileSync as execFileSync10 } from "child_process";
14387
- import { createHash as createHash7 } from "crypto";
14405
+ import { createHash as createHash8 } from "crypto";
14388
14406
  import { existsSync as existsSync33, mkdirSync as mkdirSync24, readFileSync as readFileSync32, writeFileSync as writeFileSync25 } from "fs";
14389
14407
  import { dirname as dirname19, join as join37 } from "path";
14390
14408
  function machineIdPathFor(stateDir) {
14391
14409
  return join37(stateDir, "machine-id");
14392
14410
  }
14393
- var sha256 = (s) => createHash7("sha256").update(s).digest("hex");
14411
+ var sha256 = (s) => createHash8("sha256").update(s).digest("hex");
14394
14412
  function readRawMachineId(platform2 = process.platform) {
14395
14413
  try {
14396
14414
  if (platform2 === "darwin") {
@@ -20572,7 +20590,7 @@ async function runAgentsSync(target, o) {
20572
20590
  }
20573
20591
 
20574
20592
  // src/logbook.ts
20575
- import { createHash as createHash8 } from "crypto";
20593
+ import { createHash as createHash9 } from "crypto";
20576
20594
  import { TablationClient as TablationClient4 } from "@tablation/client";
20577
20595
  var LogbookError = class extends Error {
20578
20596
  };
@@ -20658,7 +20676,7 @@ async function showLogEntry(route2, entryId, opts = {}) {
20658
20676
  };
20659
20677
  }
20660
20678
  const prompt = appendAdditions(match.prompt ?? "", match.prompt_additions);
20661
- const actualSha = createHash8("sha256").update(prompt).digest("hex");
20679
+ const actualSha = createHash9("sha256").update(prompt).digest("hex");
20662
20680
  const exact = !!entry.prompt_sha && actualSha === entry.prompt_sha;
20663
20681
  return {
20664
20682
  entry,
@@ -22240,7 +22258,7 @@ function shipIdentityJson(s) {
22240
22258
  }
22241
22259
 
22242
22260
  // src/mcp-endpoint-registry.ts
22243
- import { createHash as createHash9 } from "crypto";
22261
+ import { createHash as createHash10 } from "crypto";
22244
22262
  function endpointsUrl(api, workspaceId, id) {
22245
22263
  const base = `${api.baseUrl.replace(/\/+$/, "")}/api/workspaces/${workspaceId}/mcp-endpoints`;
22246
22264
  return id ? `${base}/${id}` : base;
@@ -22310,7 +22328,7 @@ async function probeEndpointAccess(api, workspaceId) {
22310
22328
  }
22311
22329
  var REGISTER_MCP_ENDPOINTS_HINT = "give this key's role the REGISTER_MCP_ENDPOINTS capability, e.g. via the group that holds the Crew project role";
22312
22330
  function registrationKey(url, mcpSecret, controlUrl) {
22313
- return createHash9("sha256").update(`${url}
22331
+ return createHash10("sha256").update(`${url}
22314
22332
  ${mcpSecret ?? ""}
22315
22333
  ${controlUrl ?? ""}`).digest("hex").slice(0, 16);
22316
22334
  }
@@ -23693,7 +23711,7 @@ async function buildEnvironment(route2, ship, ticket) {
23693
23711
  }
23694
23712
 
23695
23713
  // src/control-api.ts
23696
- import { createHash as createHash10 } from "crypto";
23714
+ import { createHash as createHash11 } from "crypto";
23697
23715
  import {
23698
23716
  chmodSync as chmodSync4,
23699
23717
  closeSync as closeSync6,
@@ -23953,7 +23971,7 @@ var ControlAuth = class {
23953
23971
  if (!token) return "unauthorized";
23954
23972
  for (const k of this.o.shipKeys()) if (k && secretsMatch(token, k)) return "ok";
23955
23973
  const now = (this.o.now ?? Date.now)();
23956
- const id = createHash10("sha256").update(token).digest("hex");
23974
+ const id = createHash11("sha256").update(token).digest("hex");
23957
23975
  const hit = this.cache.get(id);
23958
23976
  if (hit && now - hit.at < (this.o.cacheMs ?? 6e4)) return hit.verdict;
23959
23977
  const verdict = await this.ask(token);
@@ -23974,7 +23992,7 @@ var ControlAuth = class {
23974
23992
  for (const k of this.o.shipKeys()) if (k && secretsMatch(token, k)) return "ok";
23975
23993
  for (const k of this.o.workspaceSecrets?.(workspaceId) ?? []) if (k && secretsMatch(token, k)) return "ok";
23976
23994
  const now = (this.o.now ?? Date.now)();
23977
- const id = `${workspaceId}:${createHash10("sha256").update(token).digest("hex")}`;
23995
+ const id = `${workspaceId}:${createHash11("sha256").update(token).digest("hex")}`;
23978
23996
  const hit = this.cache.get(id);
23979
23997
  if (hit && now - hit.at < (this.o.cacheMs ?? 6e4)) return hit.verdict;
23980
23998
  const verdict = await this.ask(token, [workspaceId]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tablation/crew",
3
- "version": "0.126.10",
3
+ "version": "0.126.11",
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",