@tablation/crew 0.126.1 → 0.126.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 +114 -78
- package/dist/sandbox-intel-bridge.cjs +29 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -794,7 +794,7 @@ function shellInitScript(shell) {
|
|
|
794
794
|
|
|
795
795
|
// src/config.ts
|
|
796
796
|
import { readFileSync as readFileSync15, existsSync as existsSync15 } from "fs";
|
|
797
|
-
import { resolve as resolve2, dirname as
|
|
797
|
+
import { resolve as resolve2, dirname as dirname8, isAbsolute as isAbsolute2, join as join17, basename as basename4 } from "path";
|
|
798
798
|
import { homedir as homedir6, tmpdir } from "os";
|
|
799
799
|
import { parse as parse2 } from "yaml";
|
|
800
800
|
|
|
@@ -2661,7 +2661,7 @@ function explain(ship, required) {
|
|
|
2661
2661
|
|
|
2662
2662
|
// src/repo-config.ts
|
|
2663
2663
|
import { readFileSync as readFileSync14, existsSync as existsSync14 } from "fs";
|
|
2664
|
-
import { join as join16, basename as basename3 } from "path";
|
|
2664
|
+
import { join as join16, basename as basename3, dirname as dirname7 } from "path";
|
|
2665
2665
|
import { parse } from "yaml";
|
|
2666
2666
|
|
|
2667
2667
|
// src/sandbox-policy.ts
|
|
@@ -2863,6 +2863,19 @@ var SPEC_VERSION = 1;
|
|
|
2863
2863
|
var REPO_CONFIG_FILENAMES = [".crew.yaml", ".crew.yml", ".crew.json"];
|
|
2864
2864
|
var RepoConfigError = class extends Error {
|
|
2865
2865
|
};
|
|
2866
|
+
function versionFileProblem(name, text2) {
|
|
2867
|
+
const remedy = `a version file that is not a JSON object with a string "version" needs hooks.bump instead of release.versionFiles (docs/REPO_SPEC.md)`;
|
|
2868
|
+
let doc;
|
|
2869
|
+
try {
|
|
2870
|
+
doc = JSON.parse(text2);
|
|
2871
|
+
} catch {
|
|
2872
|
+
return `release.versionFiles entry "${name}" is not a JSON document \u2014 ${remedy}`;
|
|
2873
|
+
}
|
|
2874
|
+
if (!doc || typeof doc !== "object" || Array.isArray(doc) || typeof doc.version !== "string") {
|
|
2875
|
+
return `release.versionFiles entry "${name}" has no string "version" field \u2014 ${remedy}`;
|
|
2876
|
+
}
|
|
2877
|
+
return null;
|
|
2878
|
+
}
|
|
2866
2879
|
var HOOK_NAMES = [
|
|
2867
2880
|
"test",
|
|
2868
2881
|
"build",
|
|
@@ -3197,6 +3210,22 @@ function parseRepoConfig(text2, file) {
|
|
|
3197
3210
|
if (versionFiles.length === 0) {
|
|
3198
3211
|
throw new RepoConfigError(`${file}: release.versionFiles cannot be empty`);
|
|
3199
3212
|
}
|
|
3213
|
+
if (versionFilesGiven) {
|
|
3214
|
+
for (const name of versionFiles) {
|
|
3215
|
+
const path = join16(dirname7(file), name);
|
|
3216
|
+
if (!existsSync14(path)) continue;
|
|
3217
|
+
let text3;
|
|
3218
|
+
try {
|
|
3219
|
+
text3 = readFileSync14(path, "utf8");
|
|
3220
|
+
} catch (e) {
|
|
3221
|
+
throw new RepoConfigError(
|
|
3222
|
+
`${file}: release.versionFiles entry "${name}" cannot be read (${e.code ?? "read error"})`
|
|
3223
|
+
);
|
|
3224
|
+
}
|
|
3225
|
+
const problem = versionFileProblem(name, text3);
|
|
3226
|
+
if (problem) throw new RepoConfigError(`${file}: ${problem}`);
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3200
3229
|
const inspectorRaw = raw.periscope?.inspector;
|
|
3201
3230
|
if (inspectorRaw !== void 0 && inspectorRaw !== "proxy" && inspectorRaw !== "repo") {
|
|
3202
3231
|
throw new RepoConfigError(`${file}: periscope.inspector must be "proxy" or "repo"`);
|
|
@@ -3898,7 +3927,7 @@ function loadConfig(crewHome, configFile, opts = {}) {
|
|
|
3898
3927
|
` + configSearchPath(crewHome).map((c) => ` - ${c}`).join("\n") + `
|
|
3899
3928
|
|
|
3900
3929
|
Create the first of those:
|
|
3901
|
-
mkdir -p ${
|
|
3930
|
+
mkdir -p ${dirname8(defaultConfigPath())} && cp ${join17(crewHome, "crew.example.yaml")} ${defaultConfigPath()}`
|
|
3902
3931
|
);
|
|
3903
3932
|
}
|
|
3904
3933
|
let raw;
|
|
@@ -3908,7 +3937,7 @@ Create the first of those:
|
|
|
3908
3937
|
throw new ConfigError(`${file}: not valid YAML \u2014 ${e.message}`);
|
|
3909
3938
|
}
|
|
3910
3939
|
if (!raw || typeof raw !== "object") throw new ConfigError(`${file} is empty or not a mapping`);
|
|
3911
|
-
const base =
|
|
3940
|
+
const base = dirname8(file);
|
|
3912
3941
|
const missing = new Missing();
|
|
3913
3942
|
rejectUnknownKeys(raw, /* @__PURE__ */ new Set(["ship", "routes"]), "top-level", file);
|
|
3914
3943
|
const shipRaw = raw.ship ?? {};
|
|
@@ -4275,7 +4304,7 @@ function locateDir(cfg, dir, commonDirOf) {
|
|
|
4275
4304
|
const direct = find(target);
|
|
4276
4305
|
if (direct) return direct;
|
|
4277
4306
|
const common = commonDirOf?.(target);
|
|
4278
|
-
return common ? find(
|
|
4307
|
+
return common ? find(dirname8(resolve2(target, common))) : void 0;
|
|
4279
4308
|
}
|
|
4280
4309
|
function findRoute(cfg, route2) {
|
|
4281
4310
|
if (!route2) {
|
|
@@ -4717,7 +4746,7 @@ function recoveredFailureHeadlines(o, route2) {
|
|
|
4717
4746
|
}
|
|
4718
4747
|
|
|
4719
4748
|
// src/install.ts
|
|
4720
|
-
import { dirname as
|
|
4749
|
+
import { dirname as dirname9, join as join18, extname } from "path";
|
|
4721
4750
|
import { homedir as homedir7, userInfo } from "os";
|
|
4722
4751
|
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync16, mkdirSync as mkdirSync11, readdirSync as readdirSync3, readFileSync as readFileSync16, statSync as statSync5, writeFileSync as writeFileSync12, unlinkSync, realpathSync } from "fs";
|
|
4723
4752
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
@@ -4762,7 +4791,7 @@ function schedulerLogFor(crewLog, job) {
|
|
|
4762
4791
|
return `${stem}.${suffix}${ext || ".log"}`;
|
|
4763
4792
|
}
|
|
4764
4793
|
function pathFor(ship) {
|
|
4765
|
-
const nodeBinDir =
|
|
4794
|
+
const nodeBinDir = dirname9(process.execPath);
|
|
4766
4795
|
const parts = [nodeBinDir];
|
|
4767
4796
|
if (ship.extraPath) parts.push(ship.extraPath);
|
|
4768
4797
|
parts.push("/usr/bin", "/bin", "/usr/sbin", "/sbin");
|
|
@@ -4784,7 +4813,7 @@ function dockerPathProblem(ship, shellPath = process.env.PATH ?? "") {
|
|
|
4784
4813
|
const schedulerPath = pathFor(ship);
|
|
4785
4814
|
if (findOnPath("docker", schedulerPath)) return void 0;
|
|
4786
4815
|
const inShell = findOnPath("docker", shellPath);
|
|
4787
|
-
return inShell ? `\`docker\` is not on the scheduler PATH (${schedulerPath}) but is at ${inShell} in your shell; add ${
|
|
4816
|
+
return inShell ? `\`docker\` is not on the scheduler PATH (${schedulerPath}) but is at ${inShell} in your shell; add ${dirname9(inShell)} to ship.extraPath in crew.yaml and run \`crew install\`` : `\`docker\` is not on the scheduler PATH (${schedulerPath}) or your shell PATH; install Docker, then add its directory to ship.extraPath in crew.yaml and run \`crew install\``;
|
|
4788
4817
|
}
|
|
4789
4818
|
var USER_INSTALL = { root: false, user: "" };
|
|
4790
4819
|
function installContext(env = process.env) {
|
|
@@ -5079,7 +5108,7 @@ async function applyInstall(plan, crewHome, dryRun, log) {
|
|
|
5079
5108
|
}
|
|
5080
5109
|
const before = existsSync16(path) ? readFileSync16(path, "utf8") : null;
|
|
5081
5110
|
if (before !== plan.unitContent[path]) changed2 = true;
|
|
5082
|
-
mkdirSync11(
|
|
5111
|
+
mkdirSync11(dirname9(path), { recursive: true });
|
|
5083
5112
|
writeFileSync12(path, plan.unitContent[path]);
|
|
5084
5113
|
log.emit(`wrote ${path}`);
|
|
5085
5114
|
}
|
|
@@ -5308,7 +5337,7 @@ import {
|
|
|
5308
5337
|
readdirSync as readdirSync4,
|
|
5309
5338
|
rmSync as rmSync9
|
|
5310
5339
|
} from "fs";
|
|
5311
|
-
import { dirname as
|
|
5340
|
+
import { dirname as dirname10, basename as basename5, join as join19 } from "path";
|
|
5312
5341
|
var GitError = class extends Error {
|
|
5313
5342
|
};
|
|
5314
5343
|
function streamText(x) {
|
|
@@ -5688,7 +5717,7 @@ function recoverStrandedReleaseCheckouts(cwd) {
|
|
|
5688
5717
|
if (line.startsWith("worktree ")) path = line.slice("worktree ".length);
|
|
5689
5718
|
else if (line.startsWith("branch refs/heads/crew/release-") && path) {
|
|
5690
5719
|
gitOk(cwd, ["worktree", "remove", "--force", path]);
|
|
5691
|
-
const root =
|
|
5720
|
+
const root = dirname10(path);
|
|
5692
5721
|
if (basename5(root).startsWith("crew-release-")) rmSync9(root, { recursive: true, force: true });
|
|
5693
5722
|
}
|
|
5694
5723
|
}
|
|
@@ -5768,7 +5797,7 @@ function ensureRepoCheckout(dir, remote, opts = {}) {
|
|
|
5768
5797
|
`${dir} does not exist and this repo has no discovered remote to clone from \u2014 re-run \`crew connect\`, or check out the repository yourself and point \`repos:\` at it`
|
|
5769
5798
|
);
|
|
5770
5799
|
}
|
|
5771
|
-
mkdirSync12(
|
|
5800
|
+
mkdirSync12(dirname10(dir), { recursive: true });
|
|
5772
5801
|
const url = cloneUrlFor(remote, opts);
|
|
5773
5802
|
try {
|
|
5774
5803
|
execFileSync5("git", ["clone", url, dir], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
|
|
@@ -5793,7 +5822,7 @@ function sleepSync(ms3) {
|
|
|
5793
5822
|
}
|
|
5794
5823
|
function acquireCheckoutLock(dir, timeoutMs = 3e4) {
|
|
5795
5824
|
const lockPath = checkoutLockPath(dir);
|
|
5796
|
-
mkdirSync12(
|
|
5825
|
+
mkdirSync12(dirname10(lockPath), { recursive: true });
|
|
5797
5826
|
const deadline = Date.now() + timeoutMs;
|
|
5798
5827
|
for (; ; ) {
|
|
5799
5828
|
try {
|
|
@@ -6305,7 +6334,7 @@ import { createHash as createHash6 } from "crypto";
|
|
|
6305
6334
|
import { spawn as spawn5 } from "child_process";
|
|
6306
6335
|
import { execFileSync as execFileSync8 } from "child_process";
|
|
6307
6336
|
import { existsSync as existsSync30, mkdirSync as mkdirSync19, readFileSync as readFileSync27, renameSync as renameSync3, writeFileSync as writeFileSync20, rmSync as rmSync15 } from "fs";
|
|
6308
|
-
import { dirname as
|
|
6337
|
+
import { dirname as dirname15, join as join32 } from "path";
|
|
6309
6338
|
import { fileURLToPath } from "url";
|
|
6310
6339
|
import { tmpdir as tmpdir3 } from "os";
|
|
6311
6340
|
|
|
@@ -6330,7 +6359,7 @@ import { spawnSync as spawnSync6 } from "child_process";
|
|
|
6330
6359
|
import { readFileSync as readFileSync25, existsSync as existsSync26, statSync as statSync8, mkdirSync as mkdirSync18, writeFileSync as writeFileSync19, createWriteStream, openSync as openSync4, closeSync as closeSync4, readSync } from "fs";
|
|
6331
6360
|
import { StringDecoder } from "string_decoder";
|
|
6332
6361
|
import { finished } from "stream/promises";
|
|
6333
|
-
import { join as join29, dirname as
|
|
6362
|
+
import { join as join29, dirname as dirname14, basename as basename9 } from "path";
|
|
6334
6363
|
import { createHash as createHash4 } from "crypto";
|
|
6335
6364
|
|
|
6336
6365
|
// src/state.ts
|
|
@@ -7235,7 +7264,7 @@ function renderEnvironment(i) {
|
|
|
7235
7264
|
|
|
7236
7265
|
// src/intel-bridge.ts
|
|
7237
7266
|
import { existsSync as existsSync20, mkdirSync as mkdirSync14, readFileSync as readFileSync20, rmSync as rmSync11, writeFileSync as writeFileSync15 } from "fs";
|
|
7238
|
-
import { dirname as
|
|
7267
|
+
import { dirname as dirname11, join as join22 } from "path";
|
|
7239
7268
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
7240
7269
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
7241
7270
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -7255,7 +7284,7 @@ function intelDir(stateDir, route2, ticket) {
|
|
|
7255
7284
|
}
|
|
7256
7285
|
var attachFilePath = (stateDir, route2, ticket) => join22(intelDir(stateDir, route2, ticket), "url");
|
|
7257
7286
|
function writeAttachFile(file, url) {
|
|
7258
|
-
mkdirSync14(
|
|
7287
|
+
mkdirSync14(dirname11(file), { recursive: true });
|
|
7259
7288
|
writeFileSync15(file, `${url}
|
|
7260
7289
|
`);
|
|
7261
7290
|
}
|
|
@@ -9300,7 +9329,7 @@ function holdWarnings(tickets, ships, contract, humanHolds, now = Date.now()) {
|
|
|
9300
9329
|
|
|
9301
9330
|
// src/run-worktree.ts
|
|
9302
9331
|
import { existsSync as existsSync22 } from "fs";
|
|
9303
|
-
import { dirname as
|
|
9332
|
+
import { dirname as dirname12, join as join24 } from "path";
|
|
9304
9333
|
var describeRunWorktreePlan = (p) => {
|
|
9305
9334
|
switch (p.action) {
|
|
9306
9335
|
case "cut-remote":
|
|
@@ -9357,7 +9386,7 @@ function planRunWorktree(dir, cfg, t, role, opts = {}) {
|
|
|
9357
9386
|
if (countCommits(existing.path, `${baseRef}..HEAD`) > 0) return { action: "leave-unpushed", path: existing.path, branch };
|
|
9358
9387
|
return { action: "recut", path: existing.path, branch, base: baseRef };
|
|
9359
9388
|
}
|
|
9360
|
-
const path = join24(
|
|
9389
|
+
const path = join24(dirname12(dir), worktreeForTicket(dir, cfg, t, role));
|
|
9361
9390
|
if (located?.where === "remote" || located && hasRemote && remoteBranchExists(dir, remote, located.branch)) {
|
|
9362
9391
|
return { action: "cut-remote", path, branch: located.branch };
|
|
9363
9392
|
}
|
|
@@ -10631,7 +10660,7 @@ function skillMarkerWarnings(promptsDir, personaPrompts) {
|
|
|
10631
10660
|
import { spawn as spawn3, execFile, execFileSync as execFileSync6 } from "child_process";
|
|
10632
10661
|
import { mkdtempSync, mkdirSync as mkdirSync17, writeFileSync as writeFileSync18, rmSync as rmSync14 } from "fs";
|
|
10633
10662
|
import { tmpdir as tmpdir2 } from "os";
|
|
10634
|
-
import { basename as basename8, dirname as
|
|
10663
|
+
import { basename as basename8, dirname as dirname13, join as join28 } from "path";
|
|
10635
10664
|
import { promisify } from "util";
|
|
10636
10665
|
|
|
10637
10666
|
// src/run-limit.ts
|
|
@@ -10760,7 +10789,7 @@ var SandboxRunner = class {
|
|
|
10760
10789
|
throw new Error(`cannot generate the sandbox policy: ${e.message}`);
|
|
10761
10790
|
}
|
|
10762
10791
|
policyFile = policyPathFor(plan.streamPath);
|
|
10763
|
-
mkdirSync17(
|
|
10792
|
+
mkdirSync17(dirname13(policyFile), { recursive: true });
|
|
10764
10793
|
writeFileSync18(policyFile, generated.yaml, { mode: 384 });
|
|
10765
10794
|
}
|
|
10766
10795
|
const create2 = ["sandbox", "create", "--name", name, "--detach"];
|
|
@@ -11022,7 +11051,7 @@ function codeBridgeFor(o, harness) {
|
|
|
11022
11051
|
"--clone",
|
|
11023
11052
|
o.ship.sandbox?.workDir ?? DEFAULT_SANDBOX_WORKDIR,
|
|
11024
11053
|
"--state-dir",
|
|
11025
|
-
|
|
11054
|
+
dirname14(SANDBOX_INTEL_DIR),
|
|
11026
11055
|
"--ticket",
|
|
11027
11056
|
number,
|
|
11028
11057
|
...seed ? ["--seed-cache", seed] : []
|
|
@@ -11036,7 +11065,7 @@ function codeBridgeFor(o, harness) {
|
|
|
11036
11065
|
bridge.files = [{ path: bridge.settingsFile, content: text2 }];
|
|
11037
11066
|
} else {
|
|
11038
11067
|
const file = join29(intelDir(o.stateDir, o.route.route, number), "gemini-settings.json");
|
|
11039
|
-
mkdirSync18(
|
|
11068
|
+
mkdirSync18(dirname14(file), { recursive: true });
|
|
11040
11069
|
writeFileSync19(file, text2);
|
|
11041
11070
|
bridge.settingsFile = file;
|
|
11042
11071
|
}
|
|
@@ -11259,7 +11288,7 @@ async function killForDeadline(kill, pid, emit, role, ticket, spawnedAt, limitMi
|
|
|
11259
11288
|
var withoutKey = ({ apiKey: _apiKey, ...rest }) => rest;
|
|
11260
11289
|
function openSink(path) {
|
|
11261
11290
|
try {
|
|
11262
|
-
mkdirSync18(
|
|
11291
|
+
mkdirSync18(dirname14(path), { recursive: true });
|
|
11263
11292
|
return createWriteStream(path, { flags: "a" });
|
|
11264
11293
|
} catch {
|
|
11265
11294
|
return void 0;
|
|
@@ -11611,7 +11640,7 @@ function spawnAgent(plan, emit, hintMoved) {
|
|
|
11611
11640
|
const id = identityOf(plan, adapter.harness);
|
|
11612
11641
|
let streamFd;
|
|
11613
11642
|
try {
|
|
11614
|
-
mkdirSync18(
|
|
11643
|
+
mkdirSync18(dirname14(plan.streamPath), { recursive: true });
|
|
11615
11644
|
streamFd = openSync4(plan.streamPath, "a");
|
|
11616
11645
|
} catch (e) {
|
|
11617
11646
|
void endSink(eventsSink);
|
|
@@ -12830,7 +12859,7 @@ var SANDBOX_UID = 1e3;
|
|
|
12830
12859
|
var CREW_PREFIX = "/opt/crew";
|
|
12831
12860
|
var SANDBOX_BRIDGE_PATH = `${CREW_PREFIX}/bin/intel-bridge`;
|
|
12832
12861
|
function readBridgeBundle() {
|
|
12833
|
-
const here =
|
|
12862
|
+
const here = dirname15(fileURLToPath(import.meta.url));
|
|
12834
12863
|
for (const p of [join32(here, "sandbox-intel-bridge.cjs"), join32(here, "..", "dist", "sandbox-intel-bridge.cjs")]) {
|
|
12835
12864
|
if (existsSync30(p)) return readFileSync27(p, "utf8");
|
|
12836
12865
|
}
|
|
@@ -13055,7 +13084,7 @@ async function buildSandboxImage(plan, deps) {
|
|
|
13055
13084
|
try {
|
|
13056
13085
|
writeFileSync20(join32(ctx, "Dockerfile"), layer.dockerfile);
|
|
13057
13086
|
for (const [name, content] of Object.entries(layer.files)) {
|
|
13058
|
-
mkdirSync19(
|
|
13087
|
+
mkdirSync19(dirname15(join32(ctx, name)), { recursive: true });
|
|
13059
13088
|
writeFileSync20(join32(ctx, name), content);
|
|
13060
13089
|
}
|
|
13061
13090
|
const code = await deps.run(["build", "--tag", layer.tag, "--file", join32(ctx, "Dockerfile"), ctx], logPath);
|
|
@@ -13468,7 +13497,7 @@ function doctorSelftestLines(stored, toolchains) {
|
|
|
13468
13497
|
}
|
|
13469
13498
|
|
|
13470
13499
|
// src/cli.ts
|
|
13471
|
-
import { resolve as resolve7, dirname as
|
|
13500
|
+
import { resolve as resolve7, dirname as dirname34, join as join55, basename as basename16 } from "path";
|
|
13472
13501
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
13473
13502
|
import { hostname as hostname4, homedir as homedir11 } from "os";
|
|
13474
13503
|
import { spawnSync as spawnSync11 } from "child_process";
|
|
@@ -13667,7 +13696,7 @@ function rosterMarkdown(roster, meId) {
|
|
|
13667
13696
|
|
|
13668
13697
|
// src/connect-resume.ts
|
|
13669
13698
|
import { mkdirSync as mkdirSync21, readFileSync as readFileSync29, rmSync as rmSync17, writeFileSync as writeFileSync22 } from "fs";
|
|
13670
|
-
import { dirname as
|
|
13699
|
+
import { dirname as dirname16, join as join34 } from "path";
|
|
13671
13700
|
function lastSessionFile(stateDir) {
|
|
13672
13701
|
return join34(stateDir, "connect-session.json");
|
|
13673
13702
|
}
|
|
@@ -13687,7 +13716,7 @@ function readPointers(stateDir) {
|
|
|
13687
13716
|
}
|
|
13688
13717
|
function writePointers(stateDir, pointers) {
|
|
13689
13718
|
const file = lastSessionFile(stateDir);
|
|
13690
|
-
mkdirSync21(
|
|
13719
|
+
mkdirSync21(dirname16(file), { recursive: true });
|
|
13691
13720
|
writeFileSync22(file, `${JSON.stringify(pointers, null, 2)}
|
|
13692
13721
|
`, { mode: 384 });
|
|
13693
13722
|
}
|
|
@@ -13774,7 +13803,7 @@ async function signOutSessions(o) {
|
|
|
13774
13803
|
|
|
13775
13804
|
// src/reset.ts
|
|
13776
13805
|
import { existsSync as existsSync32, mkdirSync as mkdirSync22, readFileSync as readFileSync30, readdirSync as readdirSync12, rmSync as rmSync18, statSync as statSync10, writeFileSync as writeFileSync23 } from "fs";
|
|
13777
|
-
import { dirname as
|
|
13806
|
+
import { dirname as dirname17, join as join35 } from "path";
|
|
13778
13807
|
import { hostFromUrl as hostFromUrl3 } from "@tablation/client";
|
|
13779
13808
|
function clonedCheckoutsFile(stateDir) {
|
|
13780
13809
|
return join35(stateDir, "cloned-checkouts.json");
|
|
@@ -13791,7 +13820,7 @@ function recordClonedCheckout(stateDir, dir) {
|
|
|
13791
13820
|
const known = readClonedCheckouts(stateDir);
|
|
13792
13821
|
if (known.includes(dir)) return;
|
|
13793
13822
|
const file = clonedCheckoutsFile(stateDir);
|
|
13794
|
-
mkdirSync22(
|
|
13823
|
+
mkdirSync22(dirname17(file), { recursive: true });
|
|
13795
13824
|
writeFileSync23(file, `${JSON.stringify([...known, dir], null, 2)}
|
|
13796
13825
|
`);
|
|
13797
13826
|
}
|
|
@@ -13974,7 +14003,7 @@ async function runDeprovision(o, fx, deps) {
|
|
|
13974
14003
|
// src/pool-member.ts
|
|
13975
14004
|
import { mkdirSync as mkdirSync23, readFileSync as readFileSync31, renameSync as renameSync4, writeFileSync as writeFileSync24 } from "fs";
|
|
13976
14005
|
import { homedir as homedir8 } from "os";
|
|
13977
|
-
import { dirname as
|
|
14006
|
+
import { dirname as dirname18, join as join36 } from "path";
|
|
13978
14007
|
var POOL_EXIT = { ok: 0, failed: 1, credential: 2 };
|
|
13979
14008
|
function backoffMs(attempt) {
|
|
13980
14009
|
return Math.min(6e4, 5e3 * 2 ** Math.max(0, attempt));
|
|
@@ -14218,7 +14247,7 @@ function fileMemberStore(dir) {
|
|
|
14218
14247
|
}
|
|
14219
14248
|
},
|
|
14220
14249
|
write(f) {
|
|
14221
|
-
mkdirSync23(
|
|
14250
|
+
mkdirSync23(dirname18(file), { recursive: true, mode: 448 });
|
|
14222
14251
|
const tmp = `${file}.tmp`;
|
|
14223
14252
|
writeFileSync24(tmp, `${JSON.stringify(f)}
|
|
14224
14253
|
`, { mode: 384 });
|
|
@@ -14279,7 +14308,7 @@ import { hostname as hostname3 } from "os";
|
|
|
14279
14308
|
import { execFileSync as execFileSync10 } from "child_process";
|
|
14280
14309
|
import { createHash as createHash7 } from "crypto";
|
|
14281
14310
|
import { existsSync as existsSync33, mkdirSync as mkdirSync24, readFileSync as readFileSync32, writeFileSync as writeFileSync25 } from "fs";
|
|
14282
|
-
import { dirname as
|
|
14311
|
+
import { dirname as dirname19, join as join37 } from "path";
|
|
14283
14312
|
function machineIdPathFor(stateDir) {
|
|
14284
14313
|
return join37(stateDir, "machine-id");
|
|
14285
14314
|
}
|
|
@@ -14313,7 +14342,7 @@ function ensureMachineId(stateDir, opts = {}) {
|
|
|
14313
14342
|
const raw = (opts.read ?? readRawMachineId)();
|
|
14314
14343
|
if (!raw) return void 0;
|
|
14315
14344
|
const hashed = sha256(raw);
|
|
14316
|
-
mkdirSync24(
|
|
14345
|
+
mkdirSync24(dirname19(path), { recursive: true });
|
|
14317
14346
|
writeFileSync25(path, `${hashed}
|
|
14318
14347
|
`, { mode: 384 });
|
|
14319
14348
|
return hashed;
|
|
@@ -16594,7 +16623,7 @@ async function resolveOne(tracker, t, seat, approvedStatus, buildingStatus, affi
|
|
|
16594
16623
|
|
|
16595
16624
|
// src/repo-refresh.ts
|
|
16596
16625
|
import { existsSync as existsSync37, mkdirSync as mkdirSync26, readFileSync as readFileSync35, writeFileSync as writeFileSync29 } from "fs";
|
|
16597
|
-
import { dirname as
|
|
16626
|
+
import { dirname as dirname21 } from "path";
|
|
16598
16627
|
var REFRESH_COOLDOWN_MS = 2 * 6e4;
|
|
16599
16628
|
var UNSERVABLE_PASSES_BEFORE_ATTENTION = 3;
|
|
16600
16629
|
var lastAsked = /* @__PURE__ */ new Map();
|
|
@@ -16626,7 +16655,7 @@ function persistRepoRows(stateDir, routeName, rows) {
|
|
|
16626
16655
|
if (!existsSync37(path)) return;
|
|
16627
16656
|
const raw = JSON.parse(readFileSync35(path, "utf8"));
|
|
16628
16657
|
applyRepoRows(raw, rows);
|
|
16629
|
-
mkdirSync26(
|
|
16658
|
+
mkdirSync26(dirname21(path), { recursive: true });
|
|
16630
16659
|
writeFileSync29(path, `${JSON.stringify(raw, null, 2)}
|
|
16631
16660
|
`);
|
|
16632
16661
|
}
|
|
@@ -17077,7 +17106,7 @@ Ship ${shipName2} found: ${problem}. The release refuses to squash a ref nobody
|
|
|
17077
17106
|
var localRefSkipReported = (ticket, problem, events) => events.some((e) => e.record_id === ticket.id && e.event_type === "local_ref_skip" && (e.message ?? "").includes(problem));
|
|
17078
17107
|
|
|
17079
17108
|
// src/connect-wizard.ts
|
|
17080
|
-
import { delimiter, dirname as
|
|
17109
|
+
import { delimiter, dirname as dirname22, join as join41 } from "path";
|
|
17081
17110
|
import { accessSync as accessSync3, constants as constants3, existsSync as existsSync38, mkdirSync as mkdirSync27, writeFileSync as writeFileSync30 } from "fs";
|
|
17082
17111
|
import { stringify as stringify3 } from "yaml";
|
|
17083
17112
|
var HOST_PASSENGERS_DOCS_URL = "https://crew.tablation.dev/host-passengers";
|
|
@@ -17126,9 +17155,9 @@ async function runWizard(p, env) {
|
|
|
17126
17155
|
if (entered && isExec(entered)) agentBin = entered;
|
|
17127
17156
|
else p.say(entered ? `${entered} is not an executable file.` : "A path is required.");
|
|
17128
17157
|
}
|
|
17129
|
-
const nodeDir =
|
|
17158
|
+
const nodeDir = dirname22(env.nodePath);
|
|
17130
17159
|
const pnpmPath = findOnPath2("pnpm", env.pathEnv, isExec);
|
|
17131
|
-
const baseDirs = [nodeDir, pnpmPath ?
|
|
17160
|
+
const baseDirs = [nodeDir, pnpmPath ? dirname22(pnpmPath) : void 0];
|
|
17132
17161
|
p.say(
|
|
17133
17162
|
`
|
|
17134
17163
|
Host Passengers lets this machine run the agent sessions that other people's
|
|
@@ -17139,7 +17168,7 @@ Tablation workspaces ask for, in a container. More: ${HOST_PASSENGERS_DOCS_URL}`
|
|
|
17139
17168
|
p.say("Docker is not available here, so nothing will be hosted until it is. Your answer is recorded anyway.");
|
|
17140
17169
|
}
|
|
17141
17170
|
const dockerPath = hostPassengers ? findOnPath2("docker", env.pathEnv, isExec) : void 0;
|
|
17142
|
-
const extraPath = deriveExtraPath([...baseDirs, dockerPath ?
|
|
17171
|
+
const extraPath = deriveExtraPath([...baseDirs, dockerPath ? dirname22(dockerPath) : void 0]);
|
|
17143
17172
|
if (extraPath) {
|
|
17144
17173
|
p.say(`Hooks will get ${extraPath} on their PATH (where node, pnpm${dockerPath ? " and docker" : ""} live).`);
|
|
17145
17174
|
}
|
|
@@ -17161,7 +17190,7 @@ routes:
|
|
|
17161
17190
|
${routeBlock}`;
|
|
17162
17191
|
}
|
|
17163
17192
|
function writeNewConfig(path, text2) {
|
|
17164
|
-
mkdirSync27(
|
|
17193
|
+
mkdirSync27(dirname22(path), { recursive: true });
|
|
17165
17194
|
try {
|
|
17166
17195
|
writeFileSync30(path, text2, { mode: 384, flag: "wx" });
|
|
17167
17196
|
return true;
|
|
@@ -17197,7 +17226,7 @@ Wrote ${o.configPath}.
|
|
|
17197
17226
|
// src/connect-json.ts
|
|
17198
17227
|
import { accessSync as accessSync4, constants as constants4 } from "fs";
|
|
17199
17228
|
import { homedir as homedir10 } from "os";
|
|
17200
|
-
import { dirname as
|
|
17229
|
+
import { dirname as dirname23, join as join42 } from "path";
|
|
17201
17230
|
import { delimiter as delimiter2 } from "path";
|
|
17202
17231
|
var CHOICE_EXIT_CODE = 3;
|
|
17203
17232
|
function createEmitter(json2, write) {
|
|
@@ -17263,7 +17292,7 @@ function flagWizardAnswers(f, env) {
|
|
|
17263
17292
|
const agentBin = f.agentBin ?? found?.bin;
|
|
17264
17293
|
const pnpmPath = findOnPath2("pnpm", env.pathEnv, isExec);
|
|
17265
17294
|
const dockerPath = f.hostPassengers ? findOnPath2("docker", env.pathEnv, isExec) : void 0;
|
|
17266
|
-
const extraPath = f.extraPath ?? deriveExtraPath([
|
|
17295
|
+
const extraPath = f.extraPath ?? deriveExtraPath([dirname23(env.nodePath), pnpmPath ? dirname23(pnpmPath) : void 0, dockerPath ? dirname23(dockerPath) : void 0]);
|
|
17267
17296
|
return {
|
|
17268
17297
|
answers: {
|
|
17269
17298
|
name: f.shipName?.trim() || env.hostname,
|
|
@@ -17278,7 +17307,7 @@ function flagWizardAnswers(f, env) {
|
|
|
17278
17307
|
|
|
17279
17308
|
// src/release-run.ts
|
|
17280
17309
|
import { readFileSync as readFileSync36, writeFileSync as writeFileSync31, existsSync as existsSync39, copyFileSync, mkdirSync as mkdirSync28, mkdtempSync as mkdtempSync3, rmSync as rmSync19 } from "fs";
|
|
17281
|
-
import { dirname as
|
|
17310
|
+
import { dirname as dirname24, join as join43 } from "path";
|
|
17282
17311
|
import { tmpdir as tmpdir5 } from "os";
|
|
17283
17312
|
|
|
17284
17313
|
// src/release.ts
|
|
@@ -18025,7 +18054,13 @@ async function bump(o, size) {
|
|
|
18025
18054
|
o.emit.error(`no ${o.repo.release.versionFiles[0]} to read a version from`);
|
|
18026
18055
|
return null;
|
|
18027
18056
|
}
|
|
18028
|
-
const
|
|
18057
|
+
const firstText = readFileSync36(first, "utf8");
|
|
18058
|
+
const problem = versionFileProblem(o.repo.release.versionFiles[0], firstText);
|
|
18059
|
+
if (problem) {
|
|
18060
|
+
o.emit.error(problem);
|
|
18061
|
+
return null;
|
|
18062
|
+
}
|
|
18063
|
+
const current = JSON.parse(firstText).version;
|
|
18029
18064
|
if (!current) {
|
|
18030
18065
|
o.emit.error(`no version field in ${o.repo.release.versionFiles[0]}`);
|
|
18031
18066
|
return null;
|
|
@@ -18164,7 +18199,7 @@ function openReleaseCheckout(o) {
|
|
|
18164
18199
|
for (const f of o.repo.worktrees.copy) {
|
|
18165
18200
|
const src = join43(o.cwd, f);
|
|
18166
18201
|
if (!existsSync39(src)) continue;
|
|
18167
|
-
mkdirSync28(
|
|
18202
|
+
mkdirSync28(dirname24(join43(dir, f)), { recursive: true });
|
|
18168
18203
|
copyFileSync(src, join43(dir, f));
|
|
18169
18204
|
}
|
|
18170
18205
|
return { dir, branch, close };
|
|
@@ -19504,7 +19539,7 @@ function nextRoles(decision, ran) {
|
|
|
19504
19539
|
|
|
19505
19540
|
// src/ship-name.ts
|
|
19506
19541
|
import { existsSync as existsSync41, mkdirSync as mkdirSync29, readFileSync as readFileSync37, renameSync as renameSync5, writeFileSync as writeFileSync32 } from "fs";
|
|
19507
|
-
import { dirname as
|
|
19542
|
+
import { dirname as dirname25 } from "path";
|
|
19508
19543
|
import { parseDocument as parseDocument5 } from "yaml";
|
|
19509
19544
|
var ShipNameError = class extends Error {
|
|
19510
19545
|
};
|
|
@@ -19583,7 +19618,7 @@ function writeSyncedName(resolvedFile, name) {
|
|
|
19583
19618
|
}
|
|
19584
19619
|
if (raw.shipName === name) return;
|
|
19585
19620
|
raw.shipName = name;
|
|
19586
|
-
mkdirSync29(
|
|
19621
|
+
mkdirSync29(dirname25(resolvedFile), { recursive: true });
|
|
19587
19622
|
const tmp = `${resolvedFile}.tmp${process.pid}`;
|
|
19588
19623
|
writeFileSync32(tmp, `${JSON.stringify(raw, null, 2)}
|
|
19589
19624
|
`);
|
|
@@ -20277,7 +20312,7 @@ function describeCapability(i) {
|
|
|
20277
20312
|
|
|
20278
20313
|
// src/agents-sync-run.ts
|
|
20279
20314
|
import { existsSync as existsSync42, mkdirSync as mkdirSync30, readFileSync as readFileSync38, writeFileSync as writeFileSync33 } from "fs";
|
|
20280
|
-
import { dirname as
|
|
20315
|
+
import { dirname as dirname26 } from "path";
|
|
20281
20316
|
async function runAgentsSync(target, o) {
|
|
20282
20317
|
const dryRun = o.dryRun ?? false;
|
|
20283
20318
|
const force = o.force ?? false;
|
|
@@ -20314,7 +20349,7 @@ async function runAgentsSync(target, o) {
|
|
|
20314
20349
|
raw.agentPersonas = personaResult.agentPersonas;
|
|
20315
20350
|
if (skillResult) raw.agentSkills = skillResult.agentSkills;
|
|
20316
20351
|
if (personaResult.releaseAgentId) raw.releaseAgentId = personaResult.releaseAgentId;
|
|
20317
|
-
mkdirSync30(
|
|
20352
|
+
mkdirSync30(dirname26(resolvedPath), { recursive: true });
|
|
20318
20353
|
writeFileSync33(resolvedPath, `${JSON.stringify(raw, null, 2)}
|
|
20319
20354
|
`);
|
|
20320
20355
|
if (target.resolved) {
|
|
@@ -20937,7 +20972,7 @@ ${run3.err}` });
|
|
|
20937
20972
|
}
|
|
20938
20973
|
|
|
20939
20974
|
// src/sample-ticket.ts
|
|
20940
|
-
import { basename as basename12, dirname as
|
|
20975
|
+
import { basename as basename12, dirname as dirname27, join as join44 } from "path";
|
|
20941
20976
|
var SAMPLE_REPO = "crew-sample";
|
|
20942
20977
|
var SAMPLE_REMOTE = `local/${SAMPLE_REPO}`;
|
|
20943
20978
|
var SAMPLE_MARKER = "sample: true";
|
|
@@ -20960,7 +20995,7 @@ has something safe to work on: its test and build hooks always pass, it has no
|
|
|
20960
20995
|
remote, and \`crew sample-ticket --remove\` deletes it.
|
|
20961
20996
|
`;
|
|
20962
20997
|
function sampleDir(existing, reposBase, workspace) {
|
|
20963
|
-
if (existing.length > 0) return join44(
|
|
20998
|
+
if (existing.length > 0) return join44(dirname27(existing[0]), SAMPLE_REPO);
|
|
20964
20999
|
return join44(reposBase, workspace, SAMPLE_REPO);
|
|
20965
21000
|
}
|
|
20966
21001
|
var SAMPLE_TITLE = "Sample: add a documented `greet` function with a test";
|
|
@@ -21006,7 +21041,7 @@ function planSampleTicket(i) {
|
|
|
21006
21041
|
|
|
21007
21042
|
// src/worktree-sweep.ts
|
|
21008
21043
|
import { existsSync as existsSync43, readFileSync as readFileSync40, readdirSync as readdirSync14 } from "fs";
|
|
21009
|
-
import { basename as basename13, dirname as
|
|
21044
|
+
import { basename as basename13, dirname as dirname28, join as join45, resolve as resolve5 } from "path";
|
|
21010
21045
|
function planWorktreeSweep(target, tickets, contract) {
|
|
21011
21046
|
const terminal = new Set(contract.statuses.resolved.filter((s) => s !== contract.statuses.verified));
|
|
21012
21047
|
const verified = contract.statuses.verified;
|
|
@@ -21070,7 +21105,7 @@ function worktreeTicketNumbers(target) {
|
|
|
21070
21105
|
return [...nums];
|
|
21071
21106
|
}
|
|
21072
21107
|
function siblingWorktreeDirs(target) {
|
|
21073
|
-
const parent =
|
|
21108
|
+
const parent = dirname28(target.dir.replace(/[/\\]+$/, ""));
|
|
21074
21109
|
const stem = `${basename13(target.dir.replace(/[/\\]+$/, ""))}-`;
|
|
21075
21110
|
const registered = new Set(worktrees(target.dir).map((w) => resolve5(w.path)));
|
|
21076
21111
|
let names;
|
|
@@ -21922,7 +21957,7 @@ import { dirname as dirOf2, resolve as resolvePath } from "path";
|
|
|
21922
21957
|
// src/ssh-keys.ts
|
|
21923
21958
|
import { execFileSync as execFileSync13 } from "child_process";
|
|
21924
21959
|
import { existsSync as existsSync46, mkdirSync as mkdirSync32, readFileSync as readFileSync42, chmodSync as chmodSync3 } from "fs";
|
|
21925
|
-
import { dirname as
|
|
21960
|
+
import { dirname as dirname29, join as join49 } from "path";
|
|
21926
21961
|
var SshKeyError = class extends Error {
|
|
21927
21962
|
};
|
|
21928
21963
|
function shipSshKeyPathFor(stateDir) {
|
|
@@ -21932,7 +21967,7 @@ function ensureShipSshKeypair(stateDir) {
|
|
|
21932
21967
|
const privateKeyPath = shipSshKeyPathFor(stateDir);
|
|
21933
21968
|
const publicKeyPath = `${privateKeyPath}.pub`;
|
|
21934
21969
|
if (!existsSync46(privateKeyPath)) {
|
|
21935
|
-
mkdirSync32(
|
|
21970
|
+
mkdirSync32(dirname29(privateKeyPath), { recursive: true });
|
|
21936
21971
|
try {
|
|
21937
21972
|
execFileSync13("ssh-keygen", [
|
|
21938
21973
|
"-t",
|
|
@@ -22124,7 +22159,7 @@ import { join as join50 } from "path";
|
|
|
22124
22159
|
|
|
22125
22160
|
// src/passenger-mirror.ts
|
|
22126
22161
|
import { mkdirSync as mkdirSync33 } from "fs";
|
|
22127
|
-
import { dirname as
|
|
22162
|
+
import { dirname as dirname30 } from "path";
|
|
22128
22163
|
function mirrorRepoOf(spec) {
|
|
22129
22164
|
const fromOrigin = spec.originUrl ? parseRemote(spec.originUrl) : null;
|
|
22130
22165
|
if (fromOrigin) return fromOrigin;
|
|
@@ -22142,7 +22177,7 @@ async function materializeMirrorCheckouts(specs, cacheFor = (s) => new SandboxCa
|
|
|
22142
22177
|
continue;
|
|
22143
22178
|
}
|
|
22144
22179
|
try {
|
|
22145
|
-
const parent =
|
|
22180
|
+
const parent = dirname30(spec.dir);
|
|
22146
22181
|
mkdirSync33(parent, { recursive: true });
|
|
22147
22182
|
mkdirSync33(spec.dir, { recursive: true });
|
|
22148
22183
|
const r = await cacheFor(spec).materialize(repo, spec.base, parent, spec.name);
|
|
@@ -22348,7 +22383,7 @@ import { createServer, request as httpRequest } from "http";
|
|
|
22348
22383
|
import { request as httpsRequest } from "https";
|
|
22349
22384
|
import { connect as netConnect } from "net";
|
|
22350
22385
|
import { connect as tlsConnect } from "tls";
|
|
22351
|
-
import { dirname as
|
|
22386
|
+
import { dirname as dirname31, isAbsolute as isAbsolute4 } from "path";
|
|
22352
22387
|
import { brotliDecompressSync, gunzipSync, inflateSync } from "zlib";
|
|
22353
22388
|
|
|
22354
22389
|
// src/periscope-inspector.ts
|
|
@@ -22462,7 +22497,7 @@ function parsePointedBody(raw) {
|
|
|
22462
22497
|
return entry;
|
|
22463
22498
|
}
|
|
22464
22499
|
function appendPointed(file, entry, now = /* @__PURE__ */ new Date()) {
|
|
22465
|
-
mkdirSync35(
|
|
22500
|
+
mkdirSync35(dirname31(file), { recursive: true });
|
|
22466
22501
|
appendFileSync3(file, `${JSON.stringify({ ...entry, at: now.toISOString() })}
|
|
22467
22502
|
`);
|
|
22468
22503
|
}
|
|
@@ -23480,7 +23515,7 @@ import {
|
|
|
23480
23515
|
} from "fs";
|
|
23481
23516
|
import { createConnection } from "net";
|
|
23482
23517
|
import { createServer as createServer2 } from "http";
|
|
23483
|
-
import { basename as basename14, dirname as
|
|
23518
|
+
import { basename as basename14, dirname as dirname32, join as join52 } from "path";
|
|
23484
23519
|
import { execFile as execFile3, spawn as spawn12 } from "child_process";
|
|
23485
23520
|
|
|
23486
23521
|
// src/periscope-control.ts
|
|
@@ -23796,7 +23831,7 @@ function candidates(live, rotated) {
|
|
|
23796
23831
|
const out = [live];
|
|
23797
23832
|
if (!rotated) return out;
|
|
23798
23833
|
try {
|
|
23799
|
-
for (const n of readdirSync18(
|
|
23834
|
+
for (const n of readdirSync18(dirname32(live))) if (ROTATED_EVENTS_RE.test(n)) out.push(join52(dirname32(live), n));
|
|
23800
23835
|
} catch {
|
|
23801
23836
|
}
|
|
23802
23837
|
return out;
|
|
@@ -23956,7 +23991,7 @@ async function tailReply(path, q2, rotated, abort) {
|
|
|
23956
23991
|
const deadline = Date.now() + Math.min(wait, MAX_WAIT_SECONDS) * 1e3;
|
|
23957
23992
|
let r = readTail(path, { after, tail: tail3, rotated });
|
|
23958
23993
|
while (after && !r.lines.length && !r.reset && Date.now() < deadline && !abort.aborted) {
|
|
23959
|
-
await waitForChange(
|
|
23994
|
+
await waitForChange(dirname32(path), deadline - Date.now(), abort);
|
|
23960
23995
|
r = readTail(path, { after: r.cursor, rotated });
|
|
23961
23996
|
}
|
|
23962
23997
|
return reply2(200, r);
|
|
@@ -24146,7 +24181,7 @@ function crewJson(args, timeoutMs = 6e4) {
|
|
|
24146
24181
|
|
|
24147
24182
|
// src/periscope-mcp.ts
|
|
24148
24183
|
import { lstat, mkdir, readdir, readFile, readlink, realpath, rm, stat, writeFile } from "fs/promises";
|
|
24149
|
-
import { basename as basename15, dirname as
|
|
24184
|
+
import { basename as basename15, dirname as dirname33, isAbsolute as isAbsolute5, join as join54, relative as relative2, resolve as resolve6, sep } from "path";
|
|
24150
24185
|
import { z } from "zod";
|
|
24151
24186
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
24152
24187
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
@@ -24284,10 +24319,10 @@ async function realAncestor(p) {
|
|
|
24284
24319
|
}
|
|
24285
24320
|
if (isLink) {
|
|
24286
24321
|
if (++hops > 40) throw new PathRefusal(`too many symbolic links resolving ${p}`);
|
|
24287
|
-
cur = resolve6(
|
|
24322
|
+
cur = resolve6(dirname33(cur), await readlink(cur));
|
|
24288
24323
|
continue;
|
|
24289
24324
|
}
|
|
24290
|
-
const parent =
|
|
24325
|
+
const parent = dirname33(cur);
|
|
24291
24326
|
if (parent === cur) throw new PathRefusal(`cannot resolve ${p}`);
|
|
24292
24327
|
tail3.push(basename15(cur));
|
|
24293
24328
|
cur = parent;
|
|
@@ -24398,7 +24433,7 @@ function createPeriscopeMcpServer(d, sc) {
|
|
|
24398
24433
|
if (Buffer.byteLength(content) > MAX_WRITE_BYTES) return text(`content exceeds ${MAX_WRITE_BYTES} bytes`, true);
|
|
24399
24434
|
const abs = await inTree(path);
|
|
24400
24435
|
if (abs === await realpath(root)) return text("path must name a file", true);
|
|
24401
|
-
await mkdir(
|
|
24436
|
+
await mkdir(dirname33(abs), { recursive: true });
|
|
24402
24437
|
await inTree(path);
|
|
24403
24438
|
await writeFile(abs, content);
|
|
24404
24439
|
return text(`Wrote ${Buffer.byteLength(content)} bytes to ${await rel(abs)}`);
|
|
@@ -24438,7 +24473,7 @@ function createPeriscopeMcpServer(d, sc) {
|
|
|
24438
24473
|
inputSchema: { path: z.string() },
|
|
24439
24474
|
annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: false }
|
|
24440
24475
|
}, async ({ path }) => {
|
|
24441
|
-
const parent = await inTree(
|
|
24476
|
+
const parent = await inTree(dirname33(path) === "" ? "." : dirname33(path));
|
|
24442
24477
|
const abs = join54(parent, basename15(path));
|
|
24443
24478
|
if (basename15(path) === ".git" || abs === parent) return text("path must name a file", true);
|
|
24444
24479
|
const st = await lstat(abs).catch(() => void 0);
|
|
@@ -24560,7 +24595,7 @@ function findPeriscope(sidecars, segment) {
|
|
|
24560
24595
|
}
|
|
24561
24596
|
|
|
24562
24597
|
// src/cli.ts
|
|
24563
|
-
var CREW_HOME = isCompiledBinary(import.meta.url) ?
|
|
24598
|
+
var CREW_HOME = isCompiledBinary(import.meta.url) ? dirname34(process.execPath) : resolve7(dirname34(fileURLToPath2(import.meta.url)), "..");
|
|
24564
24599
|
var RELEASE_LOCK_TTL_MS = 20 * 60 * 1e3;
|
|
24565
24600
|
var CYCLE_SECONDS2 = 120;
|
|
24566
24601
|
var STALE_CYCLES = 3;
|
|
@@ -27109,7 +27144,7 @@ ${cu.tail.trimEnd()}
|
|
|
27109
27144
|
const found = cfg.routes.find((r) => r.route === routeArg);
|
|
27110
27145
|
if (!found) throw new ReposError(`no route "${routeArg}" in the config (have: ${cfg.routes.map((r) => r.route).join(", ") || "none"})`);
|
|
27111
27146
|
const named2 = value("route") ? void 0 : positional[3];
|
|
27112
|
-
const dir = named2 ? repoDirOf(configText,
|
|
27147
|
+
const dir = named2 ? repoDirOf(configText, dirname34(cfg.configFile), found.route, named2) : resolvePath(positional[value("route") ? 2 : 3] ?? ".");
|
|
27113
27148
|
const target = reposOf(found).find((t) => resolvePath(t.dir) === dir || t.name === named2);
|
|
27114
27149
|
const o = target ? found.repoOverrides[target.name] : void 0;
|
|
27115
27150
|
runReposCheck(dir, {
|
|
@@ -27133,7 +27168,7 @@ ${cu.tail.trimEnd()}
|
|
|
27133
27168
|
if (sub === "hooks") {
|
|
27134
27169
|
try {
|
|
27135
27170
|
const a = parseHooksArgs(positional.slice(2), routeNamesOf(configText));
|
|
27136
|
-
const dir = repoDirOf(configText,
|
|
27171
|
+
const dir = repoDirOf(configText, dirname34(cfg.configFile), a.route, a.name);
|
|
27137
27172
|
if (!existsSync51(dir)) throw new ReposError(`${dir} does not exist on disk`);
|
|
27138
27173
|
const files = { exists: (r) => existsSync51(resolvePath(dir, r)), list: (r) => {
|
|
27139
27174
|
try {
|
|
@@ -27300,7 +27335,7 @@ ${cu.tail.trimEnd()}
|
|
|
27300
27335
|
}
|
|
27301
27336
|
const originOf = (dir) => gitOk(dir, ["remote", "get-url", "origin"]) ?? void 0;
|
|
27302
27337
|
const text2 = configText;
|
|
27303
|
-
const base =
|
|
27338
|
+
const base = dirname34(cfg.configFile);
|
|
27304
27339
|
const isCheckout = (d) => existsSync51(`${d}/.git`);
|
|
27305
27340
|
try {
|
|
27306
27341
|
if (sub === "list") {
|
|
@@ -27315,7 +27350,8 @@ ${cu.tail.trimEnd()}
|
|
|
27315
27350
|
isCheckout,
|
|
27316
27351
|
repoHasHooks: (d) => REPO_CONFIG_FILENAMES.some((f) => {
|
|
27317
27352
|
try {
|
|
27318
|
-
|
|
27353
|
+
const path = resolvePath(d, f);
|
|
27354
|
+
return Object.keys(parseRepoConfig(readFileSync46(path, "utf8"), path).hooks).length > 0;
|
|
27319
27355
|
} catch {
|
|
27320
27356
|
return false;
|
|
27321
27357
|
}
|
|
@@ -27978,7 +28014,7 @@ Signed in as ${result.identity.email} \u2014 minted an API key in workspace "${r
|
|
|
27978
28014
|
process.stderr.write(`(dry run) would write resolved ids to ${resolvedPath}
|
|
27979
28015
|
`);
|
|
27980
28016
|
} else {
|
|
27981
|
-
mkdirSync38(
|
|
28017
|
+
mkdirSync38(dirname34(resolvedPath), { recursive: true });
|
|
27982
28018
|
if (hadPreviousFile) copyFileSync2(resolvedPath, `${resolvedPath}.bak`);
|
|
27983
28019
|
const tmpPath = `${resolvedPath}.tmp${process.pid}`;
|
|
27984
28020
|
writeFileSync38(tmpPath, `${JSON.stringify(resolved, null, 2)}
|
|
@@ -28027,7 +28063,7 @@ Signed in as ${result.identity.email} \u2014 minted an API key in workspace "${r
|
|
|
28027
28063
|
process.stderr.write(`(dry run) would write the minted API key to ${apiKeyFile}
|
|
28028
28064
|
`);
|
|
28029
28065
|
} else {
|
|
28030
|
-
mkdirSync38(
|
|
28066
|
+
mkdirSync38(dirname34(apiKeyFile), { recursive: true });
|
|
28031
28067
|
writeFileSync38(apiKeyFile, `${apiKeyVar}=${apiKey}
|
|
28032
28068
|
`, { mode: 384 });
|
|
28033
28069
|
process.stderr.write(`API key written to ${apiKeyFile}
|
|
@@ -29500,7 +29536,7 @@ ${where.join("\n")}`);
|
|
|
29500
29536
|
if (!route2.resolved) fail2(`route ${route2.route} is not connected \u2014 run \`crew connect\` first`);
|
|
29501
29537
|
const tracker = new Tracker(route2, cfg.ship);
|
|
29502
29538
|
const configText = readFileSync46(cfg.configFile, "utf8");
|
|
29503
|
-
const cfgBase =
|
|
29539
|
+
const cfgBase = dirname34(cfg.configFile);
|
|
29504
29540
|
const configured2 = configuredRepos(configText, route2.route, cfgBase);
|
|
29505
29541
|
const dir = configured2.find((r) => r.name === SAMPLE_REPO)?.dir ?? sampleDir(configured2.map((r) => r.dir), route2.reposBasePath, route2.route.split("/")[0]);
|
|
29506
29542
|
const resolvedFile = resolvedPathFor(cfg.ship.stateDir, route2.route);
|
|
@@ -24682,6 +24682,19 @@ var SPEC_VERSION = 1;
|
|
|
24682
24682
|
var REPO_CONFIG_FILENAMES = [".crew.yaml", ".crew.yml", ".crew.json"];
|
|
24683
24683
|
var RepoConfigError = class extends Error {
|
|
24684
24684
|
};
|
|
24685
|
+
function versionFileProblem(name, text) {
|
|
24686
|
+
const remedy = `a version file that is not a JSON object with a string "version" needs hooks.bump instead of release.versionFiles (docs/REPO_SPEC.md)`;
|
|
24687
|
+
let doc;
|
|
24688
|
+
try {
|
|
24689
|
+
doc = JSON.parse(text);
|
|
24690
|
+
} catch {
|
|
24691
|
+
return `release.versionFiles entry "${name}" is not a JSON document \u2014 ${remedy}`;
|
|
24692
|
+
}
|
|
24693
|
+
if (!doc || typeof doc !== "object" || Array.isArray(doc) || typeof doc.version !== "string") {
|
|
24694
|
+
return `release.versionFiles entry "${name}" has no string "version" field \u2014 ${remedy}`;
|
|
24695
|
+
}
|
|
24696
|
+
return null;
|
|
24697
|
+
}
|
|
24685
24698
|
var HOOK_NAMES = [
|
|
24686
24699
|
"test",
|
|
24687
24700
|
"build",
|
|
@@ -25015,6 +25028,22 @@ function parseRepoConfig(text, file) {
|
|
|
25015
25028
|
if (versionFiles.length === 0) {
|
|
25016
25029
|
throw new RepoConfigError(`${file}: release.versionFiles cannot be empty`);
|
|
25017
25030
|
}
|
|
25031
|
+
if (versionFilesGiven) {
|
|
25032
|
+
for (const name of versionFiles) {
|
|
25033
|
+
const path = (0, import_node_path6.join)((0, import_node_path6.dirname)(file), name);
|
|
25034
|
+
if (!(0, import_node_fs5.existsSync)(path)) continue;
|
|
25035
|
+
let text2;
|
|
25036
|
+
try {
|
|
25037
|
+
text2 = (0, import_node_fs5.readFileSync)(path, "utf8");
|
|
25038
|
+
} catch (e) {
|
|
25039
|
+
throw new RepoConfigError(
|
|
25040
|
+
`${file}: release.versionFiles entry "${name}" cannot be read (${e.code ?? "read error"})`
|
|
25041
|
+
);
|
|
25042
|
+
}
|
|
25043
|
+
const problem = versionFileProblem(name, text2);
|
|
25044
|
+
if (problem) throw new RepoConfigError(`${file}: ${problem}`);
|
|
25045
|
+
}
|
|
25046
|
+
}
|
|
25018
25047
|
const inspectorRaw = raw.periscope?.inspector;
|
|
25019
25048
|
if (inspectorRaw !== void 0 && inspectorRaw !== "proxy" && inspectorRaw !== "repo") {
|
|
25020
25049
|
throw new RepoConfigError(`${file}: periscope.inspector must be "proxy" or "repo"`);
|
package/package.json
CHANGED