@tablation/crew 0.47.1 → 0.47.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/cli.js +106 -70
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { resolve as resolve4, dirname as dirname12, join as
|
|
4
|
+
import { resolve as resolve4, dirname as dirname12, join as join24, basename as basename9 } from "path";
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
6
|
import { hostname as hostname2, homedir as homedir8 } from "os";
|
|
7
7
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
@@ -4030,9 +4030,11 @@ import {
|
|
|
4030
4030
|
statSync as statSync4,
|
|
4031
4031
|
unlinkSync as unlinkSync2,
|
|
4032
4032
|
readFileSync as readFileSync9,
|
|
4033
|
-
writeFileSync as writeFileSync6
|
|
4033
|
+
writeFileSync as writeFileSync6,
|
|
4034
|
+
readdirSync as readdirSync3,
|
|
4035
|
+
rmSync as rmSync6
|
|
4034
4036
|
} from "fs";
|
|
4035
|
-
import { dirname as dirname5, basename as basename4 } from "path";
|
|
4037
|
+
import { dirname as dirname5, basename as basename4, join as join10 } from "path";
|
|
4036
4038
|
var GitError = class extends Error {
|
|
4037
4039
|
};
|
|
4038
4040
|
function streamText(x) {
|
|
@@ -4367,12 +4369,36 @@ function recoverStrandedReleaseCheckouts(cwd) {
|
|
|
4367
4369
|
if (line.startsWith("worktree ")) path = line.slice("worktree ".length);
|
|
4368
4370
|
else if (line.startsWith("branch refs/heads/crew/release-") && path) {
|
|
4369
4371
|
gitOk(cwd, ["worktree", "remove", "--force", path]);
|
|
4372
|
+
const root = dirname5(path);
|
|
4373
|
+
if (basename4(root).startsWith("crew-release-")) rmSync6(root, { recursive: true, force: true });
|
|
4370
4374
|
}
|
|
4371
4375
|
}
|
|
4372
4376
|
const stranded = (gitOk(cwd, ["for-each-ref", "--format=%(refname:short)", "refs/heads/crew/release-*"]) ?? "").split("\n").filter(Boolean);
|
|
4373
4377
|
for (const b of stranded) gitOk(cwd, ["branch", "-q", "-D", b]);
|
|
4374
4378
|
return stranded;
|
|
4375
4379
|
}
|
|
4380
|
+
function sweepStaleReleaseRoots(tmp, now = Date.now(), maxAgeMs = 60 * 60 * 1e3) {
|
|
4381
|
+
const removed = [];
|
|
4382
|
+
let names;
|
|
4383
|
+
try {
|
|
4384
|
+
names = readdirSync3(tmp);
|
|
4385
|
+
} catch {
|
|
4386
|
+
return removed;
|
|
4387
|
+
}
|
|
4388
|
+
for (const name of names) {
|
|
4389
|
+
if (!name.startsWith("crew-release-")) continue;
|
|
4390
|
+
const root = join10(tmp, name);
|
|
4391
|
+
try {
|
|
4392
|
+
const st = statSync4(root);
|
|
4393
|
+
if (!st.isDirectory() || now - st.mtimeMs < maxAgeMs) continue;
|
|
4394
|
+
if (existsSync9(join10(root, "checkout"))) continue;
|
|
4395
|
+
rmSync6(root, { recursive: true, force: true });
|
|
4396
|
+
removed.push(name);
|
|
4397
|
+
} catch {
|
|
4398
|
+
}
|
|
4399
|
+
}
|
|
4400
|
+
return removed;
|
|
4401
|
+
}
|
|
4376
4402
|
function pushBranch(cwd, remote, branch, dst = branch) {
|
|
4377
4403
|
git(cwd, ["push", remote, `${branch}:${dst}`]);
|
|
4378
4404
|
}
|
|
@@ -6268,7 +6294,7 @@ function materializeBranchForTicket(dir, cfg, t, role) {
|
|
|
6268
6294
|
|
|
6269
6295
|
// src/poll.ts
|
|
6270
6296
|
import { writeFileSync as writeFileSync7 } from "fs";
|
|
6271
|
-
import { join as
|
|
6297
|
+
import { join as join11 } from "path";
|
|
6272
6298
|
|
|
6273
6299
|
// src/stalled.ts
|
|
6274
6300
|
var STALLED_AFTER_CYCLES = 30;
|
|
@@ -6545,7 +6571,7 @@ async function decideCycle(o) {
|
|
|
6545
6571
|
}
|
|
6546
6572
|
return decision;
|
|
6547
6573
|
}
|
|
6548
|
-
var digestPath = (stateDir, route, role) =>
|
|
6574
|
+
var digestPath = (stateDir, route, role) => join11(stateDir, `digest-${route}-${role}.md`);
|
|
6549
6575
|
function writeDigest(o, d, role, stateDir) {
|
|
6550
6576
|
const me = o.route.resolved?.seats[role];
|
|
6551
6577
|
if (!me) return false;
|
|
@@ -6993,7 +7019,7 @@ var alreadyReported = (ticket, g, events) => events.some((e) => e.record_id ===
|
|
|
6993
7019
|
import { spawn as spawn2 } from "child_process";
|
|
6994
7020
|
import { readFileSync as readFileSync12, existsSync as existsSync12, statSync as statSync5, mkdirSync as mkdirSync6, writeFileSync as writeFileSync8, createWriteStream } from "fs";
|
|
6995
7021
|
import { finished } from "stream/promises";
|
|
6996
|
-
import { join as
|
|
7022
|
+
import { join as join14, dirname as dirname6 } from "path";
|
|
6997
7023
|
import { createHash as createHash2 } from "crypto";
|
|
6998
7024
|
|
|
6999
7025
|
// src/environment.ts
|
|
@@ -7408,14 +7434,14 @@ function expandSkillMarkers(text, lookup, opts = {}) {
|
|
|
7408
7434
|
}
|
|
7409
7435
|
|
|
7410
7436
|
// src/skills.ts
|
|
7411
|
-
import { readFileSync as readFileSync11, readdirSync as
|
|
7412
|
-
import { join as
|
|
7437
|
+
import { readFileSync as readFileSync11, readdirSync as readdirSync4, existsSync as existsSync11 } from "fs";
|
|
7438
|
+
import { join as join13 } from "path";
|
|
7413
7439
|
import { parse as parseYaml } from "yaml";
|
|
7414
7440
|
import { TablationClient as TablationClient3, StaleWriteError as StaleWriteError8, TablationApiError as TablationApiError2 } from "@tablation/client";
|
|
7415
7441
|
|
|
7416
7442
|
// src/agents.ts
|
|
7417
7443
|
import { readFileSync as readFileSync10, existsSync as existsSync10 } from "fs";
|
|
7418
|
-
import { join as
|
|
7444
|
+
import { join as join12 } from "path";
|
|
7419
7445
|
import { TablationClient as TablationClient2, StaleWriteError as StaleWriteError7, TablationApiError } from "@tablation/client";
|
|
7420
7446
|
var PERSONA_NAME = {
|
|
7421
7447
|
dev: "Developer",
|
|
@@ -7429,10 +7455,10 @@ var CREW_AGENT_COLUMN = "agent_id";
|
|
|
7429
7455
|
var AgentsSyncError = class extends Error {
|
|
7430
7456
|
};
|
|
7431
7457
|
function personaDefaultPrompt(promptsDir, role) {
|
|
7432
|
-
const briefPath =
|
|
7458
|
+
const briefPath = join12(promptsDir, "personas", `lane-${role}.md`);
|
|
7433
7459
|
if (!existsSync10(briefPath)) throw new AgentsSyncError(`no brief at ${briefPath}`);
|
|
7434
7460
|
if (SELF_CONTAINED_ROLES.has(role)) return readFileSync10(briefPath, "utf8");
|
|
7435
|
-
const commonPath =
|
|
7461
|
+
const commonPath = join12(promptsDir, "personas", "common.md");
|
|
7436
7462
|
if (!existsSync10(commonPath)) return readFileSync10(briefPath, "utf8");
|
|
7437
7463
|
return `${readFileSync10(commonPath, "utf8")}${readFileSync10(briefPath, "utf8")}`;
|
|
7438
7464
|
}
|
|
@@ -7812,9 +7838,9 @@ function parseSkillFile(path) {
|
|
|
7812
7838
|
return { name: meta.name, description: meta.description, prompt: body, file: path };
|
|
7813
7839
|
}
|
|
7814
7840
|
function listLocalSkills(promptsDir) {
|
|
7815
|
-
const dir =
|
|
7841
|
+
const dir = join13(promptsDir, "skills");
|
|
7816
7842
|
if (!existsSync11(dir)) return [];
|
|
7817
|
-
return
|
|
7843
|
+
return readdirSync4(dir).filter((f) => f.endsWith(".md")).map((f) => parseSkillFile(join13(dir, f)));
|
|
7818
7844
|
}
|
|
7819
7845
|
async function syncSkills(route, opts) {
|
|
7820
7846
|
if (!route.resolved) {
|
|
@@ -8047,15 +8073,15 @@ var AgentError = class extends Error {
|
|
|
8047
8073
|
var AgentSpawnError = class extends AgentError {
|
|
8048
8074
|
};
|
|
8049
8075
|
function planAgentRun(o) {
|
|
8050
|
-
const briefPath =
|
|
8076
|
+
const briefPath = join14(o.route.promptsDir, "personas", `lane-${o.role}.md`);
|
|
8051
8077
|
if (!existsSync12(briefPath)) {
|
|
8052
8078
|
throw new AgentError(`no brief at ${briefPath} \u2014 refusing to run an unscoped session`);
|
|
8053
8079
|
}
|
|
8054
|
-
const commonPath =
|
|
8080
|
+
const commonPath = join14(o.route.promptsDir, "personas", "common.md");
|
|
8055
8081
|
const usesCommon = !SELF_CONTAINED_ROLES.has(o.role) && existsSync12(commonPath);
|
|
8056
8082
|
const now = o.now ?? (() => Date.now());
|
|
8057
8083
|
const routeLabel = routeSlug(o.route.route);
|
|
8058
|
-
const digestPath2 =
|
|
8084
|
+
const digestPath2 = join14(o.stateDir, `digest-${routeLabel}-${o.role}.md`);
|
|
8059
8085
|
let digest;
|
|
8060
8086
|
let ageSeconds;
|
|
8061
8087
|
if (existsSync12(digestPath2)) {
|
|
@@ -8085,7 +8111,7 @@ function planAgentRun(o) {
|
|
|
8085
8111
|
digest
|
|
8086
8112
|
});
|
|
8087
8113
|
const promptSha = createHash2("sha256").update(expanded.text).digest("hex");
|
|
8088
|
-
const streamsDir =
|
|
8114
|
+
const streamsDir = join14(o.stateDir, "streams");
|
|
8089
8115
|
const base = `${routeLabel}-${o.role}-${o.cycle}`;
|
|
8090
8116
|
const seat = resolveSeat(o.ship, o.route, o.role, o.agentPersona ?? (o.agentModel ? { model: o.agentModel } : {}), o.repo);
|
|
8091
8117
|
const { toolchain, model } = seat;
|
|
@@ -8141,8 +8167,8 @@ function planAgentRun(o) {
|
|
|
8141
8167
|
digestAttached: digest !== void 0,
|
|
8142
8168
|
digestAgeSeconds: ageSeconds,
|
|
8143
8169
|
model,
|
|
8144
|
-
streamPath:
|
|
8145
|
-
eventsPath:
|
|
8170
|
+
streamPath: join14(streamsDir, `${base}.jsonl`),
|
|
8171
|
+
eventsPath: join14(streamsDir, `${base}.events.jsonl`),
|
|
8146
8172
|
ticket: o.ticket,
|
|
8147
8173
|
agentLog,
|
|
8148
8174
|
promptVersion: o.route.resolved?.agentPersonas?.[o.role]?.historyId,
|
|
@@ -8349,12 +8375,12 @@ function spawnAgent(plan, emit) {
|
|
|
8349
8375
|
|
|
8350
8376
|
// src/run-worktree.ts
|
|
8351
8377
|
import { existsSync as existsSync14 } from "fs";
|
|
8352
|
-
import { dirname as dirname7, join as
|
|
8378
|
+
import { dirname as dirname7, join as join16 } from "path";
|
|
8353
8379
|
|
|
8354
8380
|
// src/ports.ts
|
|
8355
8381
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
8356
8382
|
import { existsSync as existsSync13 } from "fs";
|
|
8357
|
-
import { join as
|
|
8383
|
+
import { join as join15 } from "path";
|
|
8358
8384
|
var run = (cmd, args) => {
|
|
8359
8385
|
try {
|
|
8360
8386
|
return execFileSync2(cmd, args, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
|
|
@@ -8399,7 +8425,7 @@ function ticketForPort(port, s = DEFAULT_PORTS) {
|
|
|
8399
8425
|
}
|
|
8400
8426
|
function worktreeExists(parent, prefix, n) {
|
|
8401
8427
|
for (const name of [`${prefix}${n}`, `${prefix}${String(n).padStart(3, "0")}`]) {
|
|
8402
|
-
if (existsSync13(
|
|
8428
|
+
if (existsSync13(join15(parent, name, ".git"))) return true;
|
|
8403
8429
|
}
|
|
8404
8430
|
return false;
|
|
8405
8431
|
}
|
|
@@ -8487,7 +8513,7 @@ function planRunWorktree(dir, cfg, t, role) {
|
|
|
8487
8513
|
if (countCommits(existing.path, `${baseRef}..HEAD`) > 0) return { action: "leave-unpushed", path: existing.path, branch };
|
|
8488
8514
|
return { action: "recut", path: existing.path, branch, base: baseRef };
|
|
8489
8515
|
}
|
|
8490
|
-
const path =
|
|
8516
|
+
const path = join16(dirname7(dir), worktreeForTicket(dir, cfg, t, role));
|
|
8491
8517
|
if (located?.where === "remote" || located && hasRemote && remoteBranchExists(dir, remote, located.branch)) {
|
|
8492
8518
|
return { action: "cut-remote", path, branch: located.branch };
|
|
8493
8519
|
}
|
|
@@ -8695,7 +8721,7 @@ async function retireRunWorktree(tracker, dir, cfg, t, role, seatId, shipName2,
|
|
|
8695
8721
|
}
|
|
8696
8722
|
|
|
8697
8723
|
// src/connect-wizard.ts
|
|
8698
|
-
import { delimiter, dirname as dirname8, join as
|
|
8724
|
+
import { delimiter, dirname as dirname8, join as join17 } from "path";
|
|
8699
8725
|
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync15, mkdirSync as mkdirSync7, writeFileSync as writeFileSync9 } from "fs";
|
|
8700
8726
|
import { stringify } from "yaml";
|
|
8701
8727
|
var HOST_PASSENGERS_DOCS_URL = "https://crew.tablation.dev/host-passengers";
|
|
@@ -8718,7 +8744,7 @@ function defaultIsExecutable(p) {
|
|
|
8718
8744
|
function findOnPath2(name, pathEnv, isExecutable = defaultIsExecutable) {
|
|
8719
8745
|
for (const dir of pathEnv.split(delimiter)) {
|
|
8720
8746
|
if (!dir) continue;
|
|
8721
|
-
const candidate =
|
|
8747
|
+
const candidate = join17(dir, name);
|
|
8722
8748
|
if (isExecutable(candidate)) return candidate;
|
|
8723
8749
|
}
|
|
8724
8750
|
return void 0;
|
|
@@ -8813,8 +8839,8 @@ Wrote ${o.configPath}.
|
|
|
8813
8839
|
}
|
|
8814
8840
|
|
|
8815
8841
|
// src/release-run.ts
|
|
8816
|
-
import { readFileSync as readFileSync13, writeFileSync as writeFileSync10, existsSync as existsSync16, copyFileSync, mkdirSync as mkdirSync8, mkdtempSync, rmSync as
|
|
8817
|
-
import { dirname as dirname9, join as
|
|
8842
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync10, existsSync as existsSync16, copyFileSync, mkdirSync as mkdirSync8, mkdtempSync, rmSync as rmSync7 } from "fs";
|
|
8843
|
+
import { dirname as dirname9, join as join18 } from "path";
|
|
8818
8844
|
import { tmpdir as tmpdir2 } from "os";
|
|
8819
8845
|
|
|
8820
8846
|
// src/release.ts
|
|
@@ -9472,7 +9498,7 @@ async function bump(o, size) {
|
|
|
9472
9498
|
}
|
|
9473
9499
|
return printed;
|
|
9474
9500
|
}
|
|
9475
|
-
const files = o.repo.release.versionFiles.map((f) =>
|
|
9501
|
+
const files = o.repo.release.versionFiles.map((f) => join18(o.cwd, f));
|
|
9476
9502
|
const first = files[0];
|
|
9477
9503
|
if (!existsSync16(first)) {
|
|
9478
9504
|
o.emit.error(`no ${o.repo.release.versionFiles[0]} to read a version from`);
|
|
@@ -9504,7 +9530,7 @@ async function bump(o, size) {
|
|
|
9504
9530
|
function writeChangelog(o, version, entries) {
|
|
9505
9531
|
const file = o.repo.release.changelog;
|
|
9506
9532
|
if (!file || entries.length === 0) return;
|
|
9507
|
-
const path =
|
|
9533
|
+
const path = join18(o.cwd, file);
|
|
9508
9534
|
const section = renderChangelogSection(version, (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), entries);
|
|
9509
9535
|
if (o.dryRun) {
|
|
9510
9536
|
o.emit.emit(`would prepend ${entries.length} entr(ies) to ${file}`);
|
|
@@ -9589,17 +9615,25 @@ async function confirmLastRelease(o, decision) {
|
|
|
9589
9615
|
if (!confirmed) o.emit.warn(`${decision.lastTag} is still not confirmed live \u2014 tickets stay verified`);
|
|
9590
9616
|
return { confirmed, version };
|
|
9591
9617
|
}
|
|
9618
|
+
function closeReleaseCheckout(cwd, root, dir, branch, run2 = gitOk) {
|
|
9619
|
+
try {
|
|
9620
|
+
run2(cwd, ["worktree", "remove", "--force", dir]);
|
|
9621
|
+
} finally {
|
|
9622
|
+
try {
|
|
9623
|
+
rmSync7(root, { recursive: true, force: true });
|
|
9624
|
+
} finally {
|
|
9625
|
+
run2(cwd, ["worktree", "prune"]);
|
|
9626
|
+
run2(cwd, ["branch", "-D", branch]);
|
|
9627
|
+
}
|
|
9628
|
+
}
|
|
9629
|
+
}
|
|
9592
9630
|
function openReleaseCheckout(o) {
|
|
9593
9631
|
const { remote, base } = o.repo.branch;
|
|
9594
9632
|
const branch = `crew/release-${Date.now()}`;
|
|
9595
|
-
const root = mkdtempSync(
|
|
9596
|
-
const dir =
|
|
9597
|
-
|
|
9598
|
-
|
|
9599
|
-
rmSync6(root, { recursive: true, force: true });
|
|
9600
|
-
gitOk(o.cwd, ["worktree", "prune"]);
|
|
9601
|
-
gitOk(o.cwd, ["branch", "-D", branch]);
|
|
9602
|
-
};
|
|
9633
|
+
const root = mkdtempSync(join18(tmpdir2(), "crew-release-"));
|
|
9634
|
+
const dir = join18(root, "checkout");
|
|
9635
|
+
o.emit.emit(`release checkout: ${dir}`, { step: "release" });
|
|
9636
|
+
const close = () => closeReleaseCheckout(o.cwd, root, dir, branch);
|
|
9603
9637
|
try {
|
|
9604
9638
|
git(o.cwd, ["worktree", "add", "-q", "-b", branch, dir, `${remote}/${base}`]);
|
|
9605
9639
|
} catch (e) {
|
|
@@ -9607,10 +9641,10 @@ function openReleaseCheckout(o) {
|
|
|
9607
9641
|
throw e;
|
|
9608
9642
|
}
|
|
9609
9643
|
for (const f of o.repo.worktrees.copy) {
|
|
9610
|
-
const src =
|
|
9644
|
+
const src = join18(o.cwd, f);
|
|
9611
9645
|
if (!existsSync16(src)) continue;
|
|
9612
|
-
mkdirSync8(dirname9(
|
|
9613
|
-
copyFileSync(src,
|
|
9646
|
+
mkdirSync8(dirname9(join18(dir, f)), { recursive: true });
|
|
9647
|
+
copyFileSync(src, join18(dir, f));
|
|
9614
9648
|
}
|
|
9615
9649
|
return { dir, branch, close };
|
|
9616
9650
|
}
|
|
@@ -9689,6 +9723,8 @@ async function runRelease(o) {
|
|
|
9689
9723
|
let checkout;
|
|
9690
9724
|
const stranded = recoverStrandedReleaseCheckouts(o.cwd);
|
|
9691
9725
|
if (stranded.length > 0) o.emit.warn(scoped(`dropped release checkout(s) stranded by a crash: ${stranded.join(", ")}`));
|
|
9726
|
+
const swept = sweepStaleReleaseRoots(tmpdir2());
|
|
9727
|
+
if (swept.length > 0) o.emit.emit(scoped(`removed ${swept.length} stale crew-release-* temp dir(s)`), { step: "release" });
|
|
9692
9728
|
try {
|
|
9693
9729
|
checkout = openReleaseCheckout(o);
|
|
9694
9730
|
} catch (e) {
|
|
@@ -11451,14 +11487,14 @@ function applyRemoteBranchCleanup(cwd, remote, branches2, dryRun, log) {
|
|
|
11451
11487
|
}
|
|
11452
11488
|
|
|
11453
11489
|
// src/stream-sweep.ts
|
|
11454
|
-
import { existsSync as existsSync19, readdirSync as
|
|
11455
|
-
import { join as
|
|
11490
|
+
import { existsSync as existsSync19, readdirSync as readdirSync5, rmSync as rmSync8, statSync as statSync7 } from "fs";
|
|
11491
|
+
import { join as join19 } from "path";
|
|
11456
11492
|
var DAY_MS2 = 24 * 60 * 60 * 1e3;
|
|
11457
11493
|
function planStreamSweep(stateDir, retentionDays, now = Date.now()) {
|
|
11458
|
-
const dir =
|
|
11494
|
+
const dir = join19(stateDir, "streams");
|
|
11459
11495
|
if (!existsSync19(dir)) return [];
|
|
11460
11496
|
const cutoff = now - retentionDays * DAY_MS2;
|
|
11461
|
-
return
|
|
11497
|
+
return readdirSync5(dir).map((name) => join19(dir, name)).filter((path) => {
|
|
11462
11498
|
try {
|
|
11463
11499
|
return statSync7(path).mtimeMs < cutoff;
|
|
11464
11500
|
} catch {
|
|
@@ -11474,7 +11510,7 @@ function applyStreamSweep(paths, dryRun, log) {
|
|
|
11474
11510
|
continue;
|
|
11475
11511
|
}
|
|
11476
11512
|
try {
|
|
11477
|
-
|
|
11513
|
+
rmSync8(path, { force: true });
|
|
11478
11514
|
removed++;
|
|
11479
11515
|
log.emit(`removed stream artifact ${path}`, { step: "worktree" });
|
|
11480
11516
|
} catch (e) {
|
|
@@ -11486,7 +11522,7 @@ function applyStreamSweep(paths, dryRun, log) {
|
|
|
11486
11522
|
function planEventsSweep(stateDir, retentionDays, now = Date.now()) {
|
|
11487
11523
|
if (!existsSync19(stateDir)) return [];
|
|
11488
11524
|
const cutoff = now - retentionDays * DAY_MS2;
|
|
11489
|
-
return
|
|
11525
|
+
return readdirSync5(stateDir).filter((name) => ROTATED_EVENTS_RE.test(name)).map((name) => join19(stateDir, name)).filter((path) => {
|
|
11490
11526
|
try {
|
|
11491
11527
|
return statSync7(path).mtimeMs < cutoff;
|
|
11492
11528
|
} catch {
|
|
@@ -11503,11 +11539,11 @@ import { dirname as dirOf, resolve as resolvePath } from "path";
|
|
|
11503
11539
|
// src/ssh-keys.ts
|
|
11504
11540
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
11505
11541
|
import { existsSync as existsSync20, mkdirSync as mkdirSync9, readFileSync as readFileSync14, chmodSync } from "fs";
|
|
11506
|
-
import { dirname as dirname11, join as
|
|
11542
|
+
import { dirname as dirname11, join as join20 } from "path";
|
|
11507
11543
|
var SshKeyError = class extends Error {
|
|
11508
11544
|
};
|
|
11509
11545
|
function shipSshKeyPathFor(stateDir) {
|
|
11510
|
-
return
|
|
11546
|
+
return join20(stateDir, "ssh", "id_ed25519");
|
|
11511
11547
|
}
|
|
11512
11548
|
function ensureShipSshKeypair(stateDir) {
|
|
11513
11549
|
const privateKeyPath = shipSshKeyPathFor(stateDir);
|
|
@@ -11752,9 +11788,9 @@ function syncAllPassengerCheckouts(cfg) {
|
|
|
11752
11788
|
|
|
11753
11789
|
// src/tunnel.ts
|
|
11754
11790
|
import { spawn as spawn3 } from "child_process";
|
|
11755
|
-
import { existsSync as existsSync21, mkdirSync as mkdirSync10, readFileSync as readFileSync15, writeFileSync as writeFileSync11, unlinkSync as unlinkSync3, readdirSync as
|
|
11791
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync10, readFileSync as readFileSync15, writeFileSync as writeFileSync11, unlinkSync as unlinkSync3, readdirSync as readdirSync6 } from "fs";
|
|
11756
11792
|
import { randomInt } from "crypto";
|
|
11757
|
-
import { join as
|
|
11793
|
+
import { join as join21 } from "path";
|
|
11758
11794
|
var DEFAULT_SPAWN_OPTIONS = { stdio: "ignore", detached: true };
|
|
11759
11795
|
var defaultSpawn = (cmd, args) => spawn3(cmd, args, DEFAULT_SPAWN_OPTIONS);
|
|
11760
11796
|
var SLUG_ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
@@ -11821,7 +11857,7 @@ function startTunnel(opts) {
|
|
|
11821
11857
|
};
|
|
11822
11858
|
}
|
|
11823
11859
|
function tunnelStatePath(stateDir, workspaceId) {
|
|
11824
|
-
return
|
|
11860
|
+
return join21(stateDir, "passengers", `${workspaceId}.json`);
|
|
11825
11861
|
}
|
|
11826
11862
|
function readPersistedTunnel(stateDir, workspaceId) {
|
|
11827
11863
|
const path = tunnelStatePath(stateDir, workspaceId);
|
|
@@ -11834,7 +11870,7 @@ function readPersistedTunnel(stateDir, workspaceId) {
|
|
|
11834
11870
|
}
|
|
11835
11871
|
function writePersistedTunnel(stateDir, state) {
|
|
11836
11872
|
const path = tunnelStatePath(stateDir, state.workspaceId);
|
|
11837
|
-
mkdirSync10(
|
|
11873
|
+
mkdirSync10(join21(stateDir, "passengers"), { recursive: true });
|
|
11838
11874
|
writeFileSync11(path, `${JSON.stringify(state, null, 2)}
|
|
11839
11875
|
`);
|
|
11840
11876
|
}
|
|
@@ -11932,9 +11968,9 @@ function syncPassengerTunnels(plans, relayHost, relayPort, privateKeyPath, state
|
|
|
11932
11968
|
}
|
|
11933
11969
|
}
|
|
11934
11970
|
function readAllPersistedWorkspaceIds(stateDir) {
|
|
11935
|
-
const dir =
|
|
11971
|
+
const dir = join21(stateDir, "passengers");
|
|
11936
11972
|
if (!existsSync21(dir)) return [];
|
|
11937
|
-
return
|
|
11973
|
+
return readdirSync6(dir).filter((f) => f.endsWith(".json") && !f.endsWith("-sync.json")).map((f) => f.slice(0, -".json".length));
|
|
11938
11974
|
}
|
|
11939
11975
|
|
|
11940
11976
|
// src/mcp-endpoint-registry.ts
|
|
@@ -12054,8 +12090,8 @@ async function unregisterEndpoint(workspaceId, info, d) {
|
|
|
12054
12090
|
import { createServer as createHttpServer } from "http";
|
|
12055
12091
|
import { spawn as spawn4 } from "child_process";
|
|
12056
12092
|
import { randomBytes } from "crypto";
|
|
12057
|
-
import { existsSync as existsSync22, mkdirSync as mkdirSync11, readFileSync as readFileSync16, writeFileSync as writeFileSync12, unlinkSync as unlinkSync4, readdirSync as
|
|
12058
|
-
import { join as
|
|
12093
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync11, readFileSync as readFileSync16, writeFileSync as writeFileSync12, unlinkSync as unlinkSync4, readdirSync as readdirSync7 } from "fs";
|
|
12094
|
+
import { join as join22 } from "path";
|
|
12059
12095
|
|
|
12060
12096
|
// src/secret-compare.ts
|
|
12061
12097
|
import { timingSafeEqual } from "crypto";
|
|
@@ -12144,7 +12180,7 @@ var defaultSpawn2 = (cmd, args, env) => {
|
|
|
12144
12180
|
return child;
|
|
12145
12181
|
};
|
|
12146
12182
|
function syncDaemonStatePath(stateDir, workspaceId) {
|
|
12147
|
-
return
|
|
12183
|
+
return join22(stateDir, "passengers", `${workspaceId}-sync.json`);
|
|
12148
12184
|
}
|
|
12149
12185
|
function readPersistedSyncDaemon(stateDir, workspaceId) {
|
|
12150
12186
|
const path = syncDaemonStatePath(stateDir, workspaceId);
|
|
@@ -12157,7 +12193,7 @@ function readPersistedSyncDaemon(stateDir, workspaceId) {
|
|
|
12157
12193
|
}
|
|
12158
12194
|
function writePersistedSyncDaemon(stateDir, state) {
|
|
12159
12195
|
const path = syncDaemonStatePath(stateDir, state.workspaceId);
|
|
12160
|
-
mkdirSync11(
|
|
12196
|
+
mkdirSync11(join22(stateDir, "passengers"), { recursive: true });
|
|
12161
12197
|
writeFileSync12(path, `${JSON.stringify(state, null, 2)}
|
|
12162
12198
|
`);
|
|
12163
12199
|
}
|
|
@@ -12178,10 +12214,10 @@ function waitForExit(pid, alive, timeoutMs = 5e3) {
|
|
|
12178
12214
|
}
|
|
12179
12215
|
}
|
|
12180
12216
|
function readAllPersistedSyncWorkspaceIds(stateDir) {
|
|
12181
|
-
const dir =
|
|
12217
|
+
const dir = join22(stateDir, "passengers");
|
|
12182
12218
|
if (!existsSync22(dir)) return [];
|
|
12183
12219
|
const suffix = "-sync.json";
|
|
12184
|
-
return
|
|
12220
|
+
return readdirSync7(dir).filter((f) => f.endsWith(suffix)).map((f) => f.slice(0, -suffix.length));
|
|
12185
12221
|
}
|
|
12186
12222
|
function syncPassengerSyncDaemons(plans, cfg, stateDir, deps = {}) {
|
|
12187
12223
|
const alive = deps.isPidAlive ?? isPidAlive;
|
|
@@ -12236,8 +12272,8 @@ function syncPassengerSyncDaemons(plans, cfg, stateDir, deps = {}) {
|
|
|
12236
12272
|
}
|
|
12237
12273
|
|
|
12238
12274
|
// src/daemon.ts
|
|
12239
|
-
import { existsSync as existsSync23, mkdirSync as mkdirSync12, readFileSync as readFileSync17, readdirSync as
|
|
12240
|
-
import { join as
|
|
12275
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync12, readFileSync as readFileSync17, readdirSync as readdirSync8, rmSync as rmSync9, statSync as statSync8, writeFileSync as writeFileSync13 } from "fs";
|
|
12276
|
+
import { join as join23 } from "path";
|
|
12241
12277
|
var DEFAULT_FLOOR_MS = 5e3;
|
|
12242
12278
|
var DEFAULT_CEILING_MS = INTERVAL_SECONDS * 1e3;
|
|
12243
12279
|
var defaultSleep = (ms2) => new Promise((resolve5) => setTimeout(resolve5, ms2));
|
|
@@ -12275,8 +12311,8 @@ function latestMtime(path) {
|
|
|
12275
12311
|
if (stat.isFile()) return stat.mtimeMs;
|
|
12276
12312
|
if (!stat.isDirectory()) return 0;
|
|
12277
12313
|
let latest = stat.mtimeMs;
|
|
12278
|
-
for (const entry of
|
|
12279
|
-
latest = Math.max(latest, latestMtime(
|
|
12314
|
+
for (const entry of readdirSync8(path, { withFileTypes: true })) {
|
|
12315
|
+
latest = Math.max(latest, latestMtime(join23(path, entry.name)));
|
|
12280
12316
|
}
|
|
12281
12317
|
return latest;
|
|
12282
12318
|
}
|
|
@@ -12288,14 +12324,14 @@ function makeStaleChecker(paths, opts = {}) {
|
|
|
12288
12324
|
return () => computeTreeSignature(paths) !== initial || opts.reloadSentinel !== void 0 && existsSync23(opts.reloadSentinel);
|
|
12289
12325
|
}
|
|
12290
12326
|
function reloadSentinelFor(stateDir) {
|
|
12291
|
-
return
|
|
12327
|
+
return join23(stateDir, "reload-requested");
|
|
12292
12328
|
}
|
|
12293
12329
|
function daemonStampFor(stateDir) {
|
|
12294
|
-
return
|
|
12330
|
+
return join23(stateDir, "daemon.started");
|
|
12295
12331
|
}
|
|
12296
12332
|
function noteDaemonStarted(stateDir, now = Date.now()) {
|
|
12297
12333
|
mkdirSync12(stateDir, { recursive: true });
|
|
12298
|
-
|
|
12334
|
+
rmSync9(reloadSentinelFor(stateDir), { force: true });
|
|
12299
12335
|
writeFileSync13(daemonStampFor(stateDir), `${JSON.stringify({ pid: process.pid, startedAt: now })}
|
|
12300
12336
|
`);
|
|
12301
12337
|
}
|
|
@@ -13115,7 +13151,7 @@ if (command === "passenger-sync-daemon") {
|
|
|
13115
13151
|
}
|
|
13116
13152
|
if (host === "linux" && hasSystemd) {
|
|
13117
13153
|
const label = labelFor(CREW_HOME, "run");
|
|
13118
|
-
const staleTimer =
|
|
13154
|
+
const staleTimer = join24(homedir8(), ".config", "systemd", "user", `${label}.timer`);
|
|
13119
13155
|
if (existsSync24(staleTimer)) {
|
|
13120
13156
|
process.stdout.write(
|
|
13121
13157
|
`removing stale run timer from before the persistent-service cutover: ${staleTimer}${dryRun ? " (dry run)" : ""}
|
|
@@ -14123,7 +14159,7 @@ ${changed2.map((c) => ` - ${c}
|
|
|
14123
14159
|
process.exit(1);
|
|
14124
14160
|
}
|
|
14125
14161
|
requireArmed("run the daemon loop");
|
|
14126
|
-
const watchPaths = isCompiledBinary(import.meta.url) ? [process.execPath] : [
|
|
14162
|
+
const watchPaths = isCompiledBinary(import.meta.url) ? [process.execPath] : [join24(CREW_HOME, "src"), join24(CREW_HOME, "dist"), join24(CREW_HOME, "bin")];
|
|
14127
14163
|
const configPaths = daemonConfigPaths(cfg);
|
|
14128
14164
|
watchPaths.push(...configPaths);
|
|
14129
14165
|
noteDaemonStarted(cfg.ship.stateDir);
|
|
@@ -14803,7 +14839,7 @@ Signed in as ${result.identity.email} \u2014 minted an API key in workspace "${r
|
|
|
14803
14839
|
const keyPersisted = keychainBacked || apiKeyFile !== void 0;
|
|
14804
14840
|
const wizard = firstRun;
|
|
14805
14841
|
const writeFirstRun = wizard !== void 0 && !dryRun && keyPersisted;
|
|
14806
|
-
const routeDir = value("dir") ?? (writeFirstRun ?
|
|
14842
|
+
const routeDir = value("dir") ?? (writeFirstRun ? join24(DEFAULT_REPOS_BASE_PATH, found.workspaceSlug) : void 0);
|
|
14807
14843
|
const routeBlock = renderConnection(
|
|
14808
14844
|
found,
|
|
14809
14845
|
route2,
|
package/package.json
CHANGED