@tablation/crew 0.127.0 → 0.127.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 +271 -111
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -6356,7 +6356,7 @@ function attentionProblems(items, already) {
|
|
|
6356
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
|
-
import { existsSync as existsSync30, mkdirSync as mkdirSync19, readFileSync as
|
|
6359
|
+
import { existsSync as existsSync30, mkdirSync as mkdirSync19, readFileSync as readFileSync28, renameSync as renameSync3, writeFileSync as writeFileSync20, rmSync as rmSync15 } from "fs";
|
|
6360
6360
|
import { dirname as dirname15, join as join32 } from "path";
|
|
6361
6361
|
import { fileURLToPath } from "url";
|
|
6362
6362
|
import { tmpdir as tmpdir3 } from "os";
|
|
@@ -6374,12 +6374,12 @@ import { spawnSync as spawnSync7 } from "child_process";
|
|
|
6374
6374
|
import { existsSync as existsSync29, readdirSync as readdirSync11 } from "fs";
|
|
6375
6375
|
|
|
6376
6376
|
// src/interrupted.ts
|
|
6377
|
-
import { existsSync as existsSync27, readdirSync as readdirSync9, readFileSync as
|
|
6377
|
+
import { existsSync as existsSync27, readdirSync as readdirSync9, readFileSync as readFileSync27 } from "fs";
|
|
6378
6378
|
import { join as join30 } from "path";
|
|
6379
6379
|
|
|
6380
6380
|
// src/agent.ts
|
|
6381
6381
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
6382
|
-
import { readFileSync as
|
|
6382
|
+
import { readFileSync as readFileSync26, existsSync as existsSync26, statSync as statSync8, mkdirSync as mkdirSync18, writeFileSync as writeFileSync19, createWriteStream, openSync as openSync4, closeSync as closeSync4, readSync } from "fs";
|
|
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";
|
|
@@ -6887,6 +6887,97 @@ var State = class _State {
|
|
|
6887
6887
|
}
|
|
6888
6888
|
};
|
|
6889
6889
|
|
|
6890
|
+
// src/signed-out.ts
|
|
6891
|
+
import { readFileSync as readFileSync20 } from "fs";
|
|
6892
|
+
var SIGNED_OUT_PATTERN = /not logged in|please run \/?login|\/login|invalid api key|failed to authenticate|oauth session expired|could not be refreshed|reauthentication is needed|application default credentials/i;
|
|
6893
|
+
function authModeOf(spec, hostEnv = process.env) {
|
|
6894
|
+
const env = { ...hostEnv, ...spec.env };
|
|
6895
|
+
const on = (v) => !!v && v !== "0" && v.toLowerCase() !== "false";
|
|
6896
|
+
if (spec.auth === "subscription") return "login";
|
|
6897
|
+
if (on(env.CLAUDE_CODE_USE_VERTEX)) return "vertex";
|
|
6898
|
+
if (env.ANTHROPIC_API_KEY) return "api-key";
|
|
6899
|
+
return "login";
|
|
6900
|
+
}
|
|
6901
|
+
var SIGNED_OUT_REMEDY = {
|
|
6902
|
+
vertex: "run `gcloud auth application-default login` on this Mac",
|
|
6903
|
+
"api-key": "check the API key the toolchain uses (ANTHROPIC_API_KEY) is valid and unrevoked",
|
|
6904
|
+
login: "run `claude` in a terminal on this Mac and `/login`"
|
|
6905
|
+
};
|
|
6906
|
+
function signedOutMessage(toolchain, mode) {
|
|
6907
|
+
return `toolchain ${toolchain} is signed out \u2014 its runs end at the harness's sign-out error. To fix: ${SIGNED_OUT_REMEDY[mode]}`;
|
|
6908
|
+
}
|
|
6909
|
+
var signedOutKey = (toolchain) => `signed_out:${toolchain}`;
|
|
6910
|
+
function signedOutItem(toolchain, mode, nowIso = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
6911
|
+
return { kind: "signed_out", key: signedOutKey(toolchain), since: nowIso, message: signedOutMessage(toolchain, mode) };
|
|
6912
|
+
}
|
|
6913
|
+
var textOf = (v) => typeof v === "string" ? v : JSON.stringify(v ?? "");
|
|
6914
|
+
function eventsShowSignedOut(events) {
|
|
6915
|
+
let assistantTurns = 0;
|
|
6916
|
+
let toolUse = false;
|
|
6917
|
+
let onlyTurnSignedOut = false;
|
|
6918
|
+
for (const ev of events) {
|
|
6919
|
+
if (typeof ev !== "object" || ev === null) continue;
|
|
6920
|
+
const e = ev;
|
|
6921
|
+
if (e.type === "result") {
|
|
6922
|
+
if (e.is_error === true && SIGNED_OUT_PATTERN.test(textOf(e.result))) return true;
|
|
6923
|
+
} else if (e.type === "assistant") {
|
|
6924
|
+
assistantTurns++;
|
|
6925
|
+
const content = Array.isArray(e.message?.content) ? e.message.content : [];
|
|
6926
|
+
if (content.some((b) => b?.type === "tool_use")) toolUse = true;
|
|
6927
|
+
if (SIGNED_OUT_PATTERN.test(textOf(e.message))) {
|
|
6928
|
+
if (e.isApiErrorMessage === true || e.error !== void 0) return true;
|
|
6929
|
+
onlyTurnSignedOut = true;
|
|
6930
|
+
}
|
|
6931
|
+
}
|
|
6932
|
+
}
|
|
6933
|
+
return assistantTurns === 1 && onlyTurnSignedOut && !toolUse;
|
|
6934
|
+
}
|
|
6935
|
+
function streamShowsSignedOut(streamPath) {
|
|
6936
|
+
let raw;
|
|
6937
|
+
try {
|
|
6938
|
+
raw = readFileSync20(streamPath, "utf8");
|
|
6939
|
+
} catch {
|
|
6940
|
+
return false;
|
|
6941
|
+
}
|
|
6942
|
+
if (!SIGNED_OUT_PATTERN.test(raw)) return false;
|
|
6943
|
+
const events = [];
|
|
6944
|
+
for (const line of raw.split("\n")) {
|
|
6945
|
+
if (!line.trim()) continue;
|
|
6946
|
+
try {
|
|
6947
|
+
events.push(JSON.parse(line));
|
|
6948
|
+
} catch {
|
|
6949
|
+
}
|
|
6950
|
+
}
|
|
6951
|
+
return eventsShowSignedOut(events);
|
|
6952
|
+
}
|
|
6953
|
+
function streamShowsRealTurn(streamPath) {
|
|
6954
|
+
let raw;
|
|
6955
|
+
try {
|
|
6956
|
+
raw = readFileSync20(streamPath, "utf8");
|
|
6957
|
+
} catch {
|
|
6958
|
+
return false;
|
|
6959
|
+
}
|
|
6960
|
+
return raw.split("\n").some((line) => {
|
|
6961
|
+
if (!line.includes('"assistant"')) return false;
|
|
6962
|
+
try {
|
|
6963
|
+
const e = JSON.parse(line);
|
|
6964
|
+
return e.type === "assistant" && e.isApiErrorMessage !== true && e.error === void 0 && !SIGNED_OUT_PATTERN.test(textOf(e.message));
|
|
6965
|
+
} catch {
|
|
6966
|
+
return false;
|
|
6967
|
+
}
|
|
6968
|
+
});
|
|
6969
|
+
}
|
|
6970
|
+
var SignedOutError = class extends Error {
|
|
6971
|
+
toolchain;
|
|
6972
|
+
mode;
|
|
6973
|
+
constructor(toolchain, mode) {
|
|
6974
|
+
super(signedOutMessage(toolchain, mode));
|
|
6975
|
+
this.toolchain = toolchain;
|
|
6976
|
+
this.mode = mode;
|
|
6977
|
+
}
|
|
6978
|
+
};
|
|
6979
|
+
var SIGNED_OUT_PAUSE_MS = 15 * 60 * 1e3;
|
|
6980
|
+
|
|
6890
6981
|
// src/environment.ts
|
|
6891
6982
|
import { basename as basename6 } from "path";
|
|
6892
6983
|
|
|
@@ -7286,7 +7377,7 @@ function renderEnvironment(i) {
|
|
|
7286
7377
|
}
|
|
7287
7378
|
|
|
7288
7379
|
// src/intel-bridge.ts
|
|
7289
|
-
import { existsSync as existsSync20, mkdirSync as mkdirSync14, readFileSync as
|
|
7380
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync14, readFileSync as readFileSync21, rmSync as rmSync11, writeFileSync as writeFileSync15 } from "fs";
|
|
7290
7381
|
import { dirname as dirname11, join as join22 } from "path";
|
|
7291
7382
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
7292
7383
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
@@ -7313,7 +7404,7 @@ function writeAttachFile(file, url) {
|
|
|
7313
7404
|
}
|
|
7314
7405
|
function readAttachFile(file) {
|
|
7315
7406
|
try {
|
|
7316
|
-
const url =
|
|
7407
|
+
const url = readFileSync21(file, "utf8").trim();
|
|
7317
7408
|
return /^https?:\/\/\S+$/i.test(url) ? url : void 0;
|
|
7318
7409
|
} catch {
|
|
7319
7410
|
return void 0;
|
|
@@ -7692,7 +7783,7 @@ var BeforeFirstEditTracker = class {
|
|
|
7692
7783
|
};
|
|
7693
7784
|
|
|
7694
7785
|
// src/agent-log.ts
|
|
7695
|
-
import { existsSync as existsSync21, mkdirSync as mkdirSync15, readdirSync as readdirSync6, readFileSync as
|
|
7786
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync15, readdirSync as readdirSync6, readFileSync as readFileSync22, rmSync as rmSync12, writeFileSync as writeFileSync16 } from "fs";
|
|
7696
7787
|
import { join as join23 } from "path";
|
|
7697
7788
|
|
|
7698
7789
|
// src/pending-backoff.ts
|
|
@@ -7909,7 +8000,7 @@ async function replayQueuedAgentRuns(stateDir, route2, keyFor, log, now = /* @__
|
|
|
7909
8000
|
const path = join23(dir, f);
|
|
7910
8001
|
let q2;
|
|
7911
8002
|
try {
|
|
7912
|
-
q2 = JSON.parse(
|
|
8003
|
+
q2 = JSON.parse(readFileSync22(path, "utf8"));
|
|
7913
8004
|
} catch {
|
|
7914
8005
|
continue;
|
|
7915
8006
|
}
|
|
@@ -7962,7 +8053,7 @@ async function replayQueuedTicketCounters(stateDir, route2, keyFor, log, now = /
|
|
|
7962
8053
|
const path = join23(dir, f);
|
|
7963
8054
|
let q2;
|
|
7964
8055
|
try {
|
|
7965
|
-
q2 = JSON.parse(
|
|
8056
|
+
q2 = JSON.parse(readFileSync22(path, "utf8"));
|
|
7966
8057
|
} catch {
|
|
7967
8058
|
continue;
|
|
7968
8059
|
}
|
|
@@ -8184,7 +8275,7 @@ var HandoffTranscriptTracker = class {
|
|
|
8184
8275
|
};
|
|
8185
8276
|
|
|
8186
8277
|
// src/pending-handoff.ts
|
|
8187
|
-
import { existsSync as existsSync23, mkdirSync as mkdirSync16, readdirSync as readdirSync7, readFileSync as
|
|
8278
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync16, readdirSync as readdirSync7, readFileSync as readFileSync23, rmSync as rmSync13, writeFileSync as writeFileSync17 } from "fs";
|
|
8188
8279
|
import { join as join25 } from "path";
|
|
8189
8280
|
|
|
8190
8281
|
// src/ticket-branch.ts
|
|
@@ -9879,7 +9970,7 @@ function listPendingHandoffs(stateDir, route2) {
|
|
|
9879
9970
|
const out = [];
|
|
9880
9971
|
for (const f of readdirSync7(dir).filter((n) => n.endsWith(".json")).sort()) {
|
|
9881
9972
|
try {
|
|
9882
|
-
const rec = JSON.parse(
|
|
9973
|
+
const rec = JSON.parse(readFileSync23(join25(dir, f), "utf8"));
|
|
9883
9974
|
if (rec.version === 1 && rec.ticketRecordId && (!route2 || rec.route === route2)) out.push(rec);
|
|
9884
9975
|
} catch {
|
|
9885
9976
|
}
|
|
@@ -9997,7 +10088,7 @@ function expandSkillMarkers(text2, lookup2, opts = {}) {
|
|
|
9997
10088
|
}
|
|
9998
10089
|
|
|
9999
10090
|
// src/skills.ts
|
|
10000
|
-
import { readFileSync as
|
|
10091
|
+
import { readFileSync as readFileSync25, readdirSync as readdirSync8, existsSync as existsSync25 } from "fs";
|
|
10001
10092
|
import { join as join27 } from "path";
|
|
10002
10093
|
import { parse as parseYaml } from "yaml";
|
|
10003
10094
|
import { TablationClient as TablationClient3, StaleWriteError as StaleWriteError3, TablationApiError as TablationApiError2 } from "@tablation/client";
|
|
@@ -10014,7 +10105,7 @@ ${additions}`;
|
|
|
10014
10105
|
}
|
|
10015
10106
|
|
|
10016
10107
|
// src/agents.ts
|
|
10017
|
-
import { readFileSync as
|
|
10108
|
+
import { readFileSync as readFileSync24, existsSync as existsSync24 } from "fs";
|
|
10018
10109
|
import { join as join26 } from "path";
|
|
10019
10110
|
import { TablationClient as TablationClient2, StaleWriteError as StaleWriteError2, TablationApiError } from "@tablation/client";
|
|
10020
10111
|
var PERSONA_NAME = {
|
|
@@ -10031,10 +10122,10 @@ var AgentsSyncError = class extends Error {
|
|
|
10031
10122
|
function personaDefaultPrompt(promptsDir, role) {
|
|
10032
10123
|
const briefPath = join26(promptsDir, "personas", `lane-${role}.md`);
|
|
10033
10124
|
if (!existsSync24(briefPath)) throw new AgentsSyncError(`no brief at ${briefPath}`);
|
|
10034
|
-
if (SELF_CONTAINED_ROLES.has(role)) return
|
|
10125
|
+
if (SELF_CONTAINED_ROLES.has(role)) return readFileSync24(briefPath, "utf8");
|
|
10035
10126
|
const commonPath = join26(promptsDir, "personas", "common.md");
|
|
10036
|
-
if (!existsSync24(commonPath)) return
|
|
10037
|
-
return `${
|
|
10127
|
+
if (!existsSync24(commonPath)) return readFileSync24(briefPath, "utf8");
|
|
10128
|
+
return `${readFileSync24(commonPath, "utf8")}${readFileSync24(briefPath, "utf8")}`;
|
|
10038
10129
|
}
|
|
10039
10130
|
async function resolveAgentId(route2, role, opts) {
|
|
10040
10131
|
const cached = route2.resolved?.agentPersonas?.[role]?.agentId;
|
|
@@ -10481,7 +10572,7 @@ function describeCrewLink(o) {
|
|
|
10481
10572
|
var SkillSyncError = class extends Error {
|
|
10482
10573
|
};
|
|
10483
10574
|
function parseSkillFile(path) {
|
|
10484
|
-
const text2 =
|
|
10575
|
+
const text2 = readFileSync25(path, "utf8");
|
|
10485
10576
|
const match = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/.exec(text2);
|
|
10486
10577
|
if (!match) throw new SkillSyncError(`${path}: missing YAML frontmatter (expected a leading --- block)`);
|
|
10487
10578
|
const frontmatter = match[1];
|
|
@@ -11061,7 +11152,7 @@ var ALLOWANCE_REFUSAL_MARKER = "AI_ALLOWANCE_EXCEEDED";
|
|
|
11061
11152
|
function streamShowsAllowanceRefusal(streamPath) {
|
|
11062
11153
|
let raw;
|
|
11063
11154
|
try {
|
|
11064
|
-
raw =
|
|
11155
|
+
raw = readFileSync26(streamPath, "utf8");
|
|
11065
11156
|
} catch {
|
|
11066
11157
|
return false;
|
|
11067
11158
|
}
|
|
@@ -11147,10 +11238,10 @@ function planAgentRun(o) {
|
|
|
11147
11238
|
let ageSeconds;
|
|
11148
11239
|
if (existsSync26(digestPath2)) {
|
|
11149
11240
|
ageSeconds = Math.floor((now() - statSync8(digestPath2).mtimeMs) / 1e3);
|
|
11150
|
-
if (ageSeconds <= DIGEST_MAX_AGE_SECONDS) digest =
|
|
11241
|
+
if (ageSeconds <= DIGEST_MAX_AGE_SECONDS) digest = readFileSync26(digestPath2, "utf8");
|
|
11151
11242
|
}
|
|
11152
|
-
const common = usesCommon ?
|
|
11153
|
-
const brief =
|
|
11243
|
+
const common = usesCommon ? readFileSync26(commonPath, "utf8") : "";
|
|
11244
|
+
const brief = readFileSync26(briefPath, "utf8");
|
|
11154
11245
|
const effectiveCommon = o.divergedPrompt ? "" : common;
|
|
11155
11246
|
const effectiveBrief = appendAdditions(o.divergedPrompt ?? brief, o.personaAdditions);
|
|
11156
11247
|
const localSkills = new Map(listLocalSkills(o.route.promptsDir).map((s) => [s.name, s.prompt]));
|
|
@@ -11239,6 +11330,7 @@ function planAgentRun(o) {
|
|
|
11239
11330
|
toolchain: toolchain.name,
|
|
11240
11331
|
harness: toolchain.harness,
|
|
11241
11332
|
workspaceAuth: toolchain.auth === "workspace",
|
|
11333
|
+
authMode: authModeOf(toolchain),
|
|
11242
11334
|
provider: toolchainProvider(toolchain),
|
|
11243
11335
|
maxRunMinutes: resolveMaxRunMinutes(o.route.maxRunMinutes, toolchain.maxRunMinutes),
|
|
11244
11336
|
...o.ship.runner === "sandbox" ? {
|
|
@@ -11305,7 +11397,7 @@ function describePlan(p) {
|
|
|
11305
11397
|
var pidPathFor = (streamPath) => `${streamPath}.pid`;
|
|
11306
11398
|
function readRunSidecar(streamPath) {
|
|
11307
11399
|
try {
|
|
11308
|
-
const sc = JSON.parse(
|
|
11400
|
+
const sc = JSON.parse(readFileSync26(pidPathFor(streamPath), "utf8"));
|
|
11309
11401
|
return typeof sc.pid === "number" && typeof sc.spawnedAt === "string" && typeof sc.role === "string" ? sc : null;
|
|
11310
11402
|
} catch {
|
|
11311
11403
|
return null;
|
|
@@ -11620,10 +11712,11 @@ async function finishRun(id, obs, emit, startedAt, end, agentLogKey, hintMoved)
|
|
|
11620
11712
|
...result?.costUsd !== void 0 ? { totalCostUsd: result.costUsd } : {}
|
|
11621
11713
|
}
|
|
11622
11714
|
});
|
|
11715
|
+
const signedOut = !end.interrupted && streamShowsSignedOut(id.streamPath);
|
|
11623
11716
|
if (id.agentLog && agentLogKey) {
|
|
11624
11717
|
const report = {
|
|
11625
11718
|
ticketReference: attributedTicket,
|
|
11626
|
-
outcome: end.interrupted ? "interrupted" : end.code === 0 || end.code === null && obs.sawResult ? "success" : "error",
|
|
11719
|
+
outcome: end.interrupted ? "interrupted" : signedOut ? "error" : end.code === 0 || end.code === null && obs.sawResult ? "success" : "error",
|
|
11627
11720
|
startedAt,
|
|
11628
11721
|
finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11629
11722
|
cycles: obs.cycles,
|
|
@@ -11878,7 +11971,7 @@ function runFinished(streamPath) {
|
|
|
11878
11971
|
const path = `${streamPath}.meta.json`;
|
|
11879
11972
|
if (!existsSync27(path)) return false;
|
|
11880
11973
|
try {
|
|
11881
|
-
return JSON.parse(
|
|
11974
|
+
return JSON.parse(readFileSync27(path, "utf8")).running !== true;
|
|
11882
11975
|
} catch {
|
|
11883
11976
|
return true;
|
|
11884
11977
|
}
|
|
@@ -12969,7 +13062,7 @@ var SANDBOX_BRIDGE_PATH = `${CREW_PREFIX}/bin/intel-bridge`;
|
|
|
12969
13062
|
function readBridgeBundle() {
|
|
12970
13063
|
const here = dirname15(fileURLToPath(import.meta.url));
|
|
12971
13064
|
for (const p of [join32(here, "sandbox-intel-bridge.cjs"), join32(here, "..", "dist", "sandbox-intel-bridge.cjs")]) {
|
|
12972
|
-
if (existsSync30(p)) return
|
|
13065
|
+
if (existsSync30(p)) return readFileSync28(p, "utf8");
|
|
12973
13066
|
}
|
|
12974
13067
|
return void 0;
|
|
12975
13068
|
}
|
|
@@ -13121,7 +13214,7 @@ var shipSandboxRef = () => ({ name: SHIP_SANDBOX_KEY, decl: { packages: [], setu
|
|
|
13121
13214
|
var sandboxStatePath = (stateDir) => join32(stateDir, "sandbox-images.json");
|
|
13122
13215
|
function readSandboxState(stateDir) {
|
|
13123
13216
|
try {
|
|
13124
|
-
const v = JSON.parse(
|
|
13217
|
+
const v = JSON.parse(readFileSync28(sandboxStatePath(stateDir), "utf8"));
|
|
13125
13218
|
return v && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
13126
13219
|
} catch {
|
|
13127
13220
|
return {};
|
|
@@ -13253,7 +13346,7 @@ async function sandboxBuildTick(repos, deps, force = false) {
|
|
|
13253
13346
|
}
|
|
13254
13347
|
|
|
13255
13348
|
// src/doctor-checks.ts
|
|
13256
|
-
import { execFileSync as execFileSync9 } from "child_process";
|
|
13349
|
+
import { execFileSync as execFileSync9, spawnSync as spawnSync8 } from "child_process";
|
|
13257
13350
|
var PROBE_BRANCH = "crew-probe-branch";
|
|
13258
13351
|
var realGit = (cwd, args, env) => {
|
|
13259
13352
|
execFileSync9("git", args, { cwd, env, stdio: ["ignore", "pipe", "pipe"], timeout: 3e4 });
|
|
@@ -13386,10 +13479,25 @@ function managedRuntimeWarnings(kind, ship) {
|
|
|
13386
13479
|
}
|
|
13387
13480
|
return out;
|
|
13388
13481
|
}
|
|
13482
|
+
var MANAGED_GIT_EMAIL = "crew@tablation.dev";
|
|
13483
|
+
function readGlobalGitIdentity() {
|
|
13484
|
+
const get2 = (key) => {
|
|
13485
|
+
const res = spawnSync8("git", ["config", "--global", "--get", key], { encoding: "utf8" });
|
|
13486
|
+
const v = (res.stdout ?? "").trim();
|
|
13487
|
+
return res.status === 0 && v ? v : null;
|
|
13488
|
+
};
|
|
13489
|
+
return { name: get2("user.name"), email: get2("user.email") };
|
|
13490
|
+
}
|
|
13491
|
+
function managedGitIdentityWarnings(kind, identity) {
|
|
13492
|
+
if (kind !== "managed_instance" && kind !== "pooled_instance" && kind !== "pooled") return [];
|
|
13493
|
+
const missing = [identity.name ? "" : "user.name", identity.email ? "" : "user.email"].filter(Boolean);
|
|
13494
|
+
if (missing.length === 0) return [];
|
|
13495
|
+
return [`git ${missing.join(" and ")} not set for this user on a ${kind} ship; every commit crew makes here fails with "Committer identity unknown" (re-run \`crew provision\`, or \`git config --global user.name <ship name>\` and \`user.email ${MANAGED_GIT_EMAIL}\`)`];
|
|
13496
|
+
}
|
|
13389
13497
|
|
|
13390
13498
|
// src/selftest.ts
|
|
13391
13499
|
import { spawn as spawn6 } from "child_process";
|
|
13392
|
-
import { existsSync as existsSync31, mkdirSync as mkdirSync20, mkdtempSync as mkdtempSync2, readFileSync as
|
|
13500
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync20, mkdtempSync as mkdtempSync2, readFileSync as readFileSync29, rmSync as rmSync16, writeFileSync as writeFileSync21 } from "fs";
|
|
13393
13501
|
import { tmpdir as tmpdir4 } from "os";
|
|
13394
13502
|
import { join as join33 } from "path";
|
|
13395
13503
|
var SELFTEST_TIMEOUT_MS = 12e4;
|
|
@@ -13523,6 +13631,11 @@ ${seen.texts.join("\n")}`)) {
|
|
|
13523
13631
|
return fail2("mcp-unavailable", "the tracker MCP tool was not available to the session");
|
|
13524
13632
|
}
|
|
13525
13633
|
const answered = seen.texts.length > 0 || seen.finalText;
|
|
13634
|
+
if (SIGNED_OUT_PATTERN.test(`${run3.stderr}
|
|
13635
|
+
${seen.finalText ?? ""}
|
|
13636
|
+
${seen.texts.join("\n")}`)) {
|
|
13637
|
+
return { failure: "login-missing", detail: signedOutMessage(spec.name, authModeOf(spec)) };
|
|
13638
|
+
}
|
|
13526
13639
|
if (!answered || LOGIN.test(run3.stderr) || LOGIN.test(seen.finalText ?? "")) {
|
|
13527
13640
|
return fail2("login-missing", `\`${bin}\` exited${run3.code !== null ? ` (${run3.code})` : ""} before answering; the vendor login is probably missing`);
|
|
13528
13641
|
}
|
|
@@ -13589,7 +13702,7 @@ var fileFor2 = (stateDir) => join33(stateDir, "selftest.json");
|
|
|
13589
13702
|
function readSelftest(stateDir) {
|
|
13590
13703
|
try {
|
|
13591
13704
|
const p = fileFor2(stateDir);
|
|
13592
|
-
return existsSync31(p) ? JSON.parse(
|
|
13705
|
+
return existsSync31(p) ? JSON.parse(readFileSync29(p, "utf8")) : {};
|
|
13593
13706
|
} catch {
|
|
13594
13707
|
return {};
|
|
13595
13708
|
}
|
|
@@ -13613,7 +13726,7 @@ function doctorSelftestLines(stored, toolchains) {
|
|
|
13613
13726
|
import { resolve as resolve7, dirname as dirname34, join as join56, basename as basename16 } from "path";
|
|
13614
13727
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
13615
13728
|
import { hostname as hostname5, homedir as homedir11 } from "os";
|
|
13616
|
-
import { spawnSync as
|
|
13729
|
+
import { spawnSync as spawnSync12 } from "child_process";
|
|
13617
13730
|
import { parse as parseYaml2 } from "yaml";
|
|
13618
13731
|
|
|
13619
13732
|
// src/argv.ts
|
|
@@ -13808,14 +13921,14 @@ function rosterMarkdown(roster, meId) {
|
|
|
13808
13921
|
}
|
|
13809
13922
|
|
|
13810
13923
|
// src/connect-resume.ts
|
|
13811
|
-
import { mkdirSync as mkdirSync21, readFileSync as
|
|
13924
|
+
import { mkdirSync as mkdirSync21, readFileSync as readFileSync30, rmSync as rmSync17, writeFileSync as writeFileSync22 } from "fs";
|
|
13812
13925
|
import { dirname as dirname16, join as join34 } from "path";
|
|
13813
13926
|
function lastSessionFile(stateDir) {
|
|
13814
13927
|
return join34(stateDir, "connect-session.json");
|
|
13815
13928
|
}
|
|
13816
13929
|
function readPointers(stateDir) {
|
|
13817
13930
|
try {
|
|
13818
|
-
const parsed = JSON.parse(
|
|
13931
|
+
const parsed = JSON.parse(readFileSync30(lastSessionFile(stateDir), "utf8"));
|
|
13819
13932
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
13820
13933
|
const out = {};
|
|
13821
13934
|
for (const [host, v] of Object.entries(parsed)) {
|
|
@@ -13915,7 +14028,7 @@ async function signOutSessions(o) {
|
|
|
13915
14028
|
}
|
|
13916
14029
|
|
|
13917
14030
|
// src/reset.ts
|
|
13918
|
-
import { existsSync as existsSync32, mkdirSync as mkdirSync22, readFileSync as
|
|
14031
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync22, readFileSync as readFileSync31, readdirSync as readdirSync12, rmSync as rmSync18, statSync as statSync10, writeFileSync as writeFileSync23 } from "fs";
|
|
13919
14032
|
import { dirname as dirname17, join as join35 } from "path";
|
|
13920
14033
|
import { hostFromUrl as hostFromUrl3 } from "@tablation/client";
|
|
13921
14034
|
function clonedCheckoutsFile(stateDir) {
|
|
@@ -13923,7 +14036,7 @@ function clonedCheckoutsFile(stateDir) {
|
|
|
13923
14036
|
}
|
|
13924
14037
|
function readClonedCheckouts(stateDir) {
|
|
13925
14038
|
try {
|
|
13926
|
-
const parsed = JSON.parse(
|
|
14039
|
+
const parsed = JSON.parse(readFileSync31(clonedCheckoutsFile(stateDir), "utf8"));
|
|
13927
14040
|
return Array.isArray(parsed) ? parsed.filter((d) => typeof d === "string") : [];
|
|
13928
14041
|
} catch {
|
|
13929
14042
|
return [];
|
|
@@ -14114,7 +14227,7 @@ async function runDeprovision(o, fx, deps) {
|
|
|
14114
14227
|
}
|
|
14115
14228
|
|
|
14116
14229
|
// src/pool-member.ts
|
|
14117
|
-
import { mkdirSync as mkdirSync23, readFileSync as
|
|
14230
|
+
import { mkdirSync as mkdirSync23, readFileSync as readFileSync32, renameSync as renameSync4, writeFileSync as writeFileSync24 } from "fs";
|
|
14118
14231
|
import { homedir as homedir8 } from "os";
|
|
14119
14232
|
import { dirname as dirname18, join as join36 } from "path";
|
|
14120
14233
|
var POOL_EXIT = { ok: 0, failed: 1, credential: 2 };
|
|
@@ -14354,7 +14467,7 @@ function fileMemberStore(dir) {
|
|
|
14354
14467
|
return {
|
|
14355
14468
|
read() {
|
|
14356
14469
|
try {
|
|
14357
|
-
return JSON.parse(
|
|
14470
|
+
return JSON.parse(readFileSync32(file, "utf8"));
|
|
14358
14471
|
} catch {
|
|
14359
14472
|
return {};
|
|
14360
14473
|
}
|
|
@@ -14420,7 +14533,7 @@ import { hostname as hostname3 } from "os";
|
|
|
14420
14533
|
// src/machine-id.ts
|
|
14421
14534
|
import { execFileSync as execFileSync10 } from "child_process";
|
|
14422
14535
|
import { createHash as createHash8 } from "crypto";
|
|
14423
|
-
import { existsSync as existsSync33, mkdirSync as mkdirSync24, readFileSync as
|
|
14536
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync24, readFileSync as readFileSync33, writeFileSync as writeFileSync25 } from "fs";
|
|
14424
14537
|
import { dirname as dirname19, join as join37 } from "path";
|
|
14425
14538
|
function machineIdPathFor(stateDir) {
|
|
14426
14539
|
return join37(stateDir, "machine-id");
|
|
@@ -14437,7 +14550,7 @@ function readRawMachineId(platform2 = process.platform) {
|
|
|
14437
14550
|
}
|
|
14438
14551
|
for (const p of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
14439
14552
|
if (existsSync33(p)) {
|
|
14440
|
-
const id =
|
|
14553
|
+
const id = readFileSync33(p, "utf8").trim();
|
|
14441
14554
|
if (id) return id;
|
|
14442
14555
|
}
|
|
14443
14556
|
}
|
|
@@ -14449,7 +14562,7 @@ function ensureMachineId(stateDir, opts = {}) {
|
|
|
14449
14562
|
if (opts.override?.trim()) return sha256(opts.override.trim());
|
|
14450
14563
|
const path = machineIdPathFor(stateDir);
|
|
14451
14564
|
if (existsSync33(path)) {
|
|
14452
|
-
const cached =
|
|
14565
|
+
const cached = readFileSync33(path, "utf8").trim();
|
|
14453
14566
|
if (/^[0-9a-f]{64}$/.test(cached)) return cached;
|
|
14454
14567
|
}
|
|
14455
14568
|
const raw = (opts.read ?? readRawMachineId)();
|
|
@@ -14468,8 +14581,8 @@ function matchShipRows(ships, shipName2, machineId) {
|
|
|
14468
14581
|
}
|
|
14469
14582
|
|
|
14470
14583
|
// src/provision.ts
|
|
14471
|
-
import { spawnSync as
|
|
14472
|
-
import { existsSync as existsSync34, readFileSync as
|
|
14584
|
+
import { spawnSync as spawnSync9 } from "child_process";
|
|
14585
|
+
import { existsSync as existsSync34, readFileSync as readFileSync34, writeFileSync as writeFileSync26 } from "fs";
|
|
14473
14586
|
import { hostname as hostname2 } from "os";
|
|
14474
14587
|
import { parseDocument as parseDocument3, isMap as isMap2, isScalar } from "yaml";
|
|
14475
14588
|
|
|
@@ -14916,6 +15029,11 @@ async function runProvision(o, deps, write, human) {
|
|
|
14916
15029
|
emit("connect", `set ${key}`, { setting: key });
|
|
14917
15030
|
}
|
|
14918
15031
|
}
|
|
15032
|
+
if (isManagedShipKind(o.shipKind)) {
|
|
15033
|
+
summary.gitIdentity = deps.ensureGitIdentity(shipName2, MANAGED_GIT_EMAIL);
|
|
15034
|
+
if (summary.gitIdentity === "set") summary.changed = true;
|
|
15035
|
+
emit("git_identity", `git identity: ${summary.gitIdentity}`, { action: summary.gitIdentity });
|
|
15036
|
+
}
|
|
14919
15037
|
for (const host of o.forgeHosts) {
|
|
14920
15038
|
const token = o.tokens[host];
|
|
14921
15039
|
const stored = deps.storedToken(host);
|
|
@@ -15072,7 +15190,7 @@ function realProvisionDeps(crewHome) {
|
|
|
15072
15190
|
const env = { ...process.env, ...o.env };
|
|
15073
15191
|
delete env.CREW_FORGE_TOKEN;
|
|
15074
15192
|
for (const k of Object.keys(env)) if (k.startsWith("CREW_CONNECT_KEY_")) delete env[k];
|
|
15075
|
-
const res =
|
|
15193
|
+
const res = spawnSync9(bin, [...pre, ...args], { cwd: crewHome, encoding: "utf8", env, input: o.input, maxBuffer: 64 * 1024 * 1024 });
|
|
15076
15194
|
return { status: res.status ?? 1, stdout: res.stdout ?? "", stderr: `${res.stderr ?? ""}${res.error ? String(res.error) : ""}` };
|
|
15077
15195
|
};
|
|
15078
15196
|
const configFile = () => {
|
|
@@ -15085,7 +15203,7 @@ function realProvisionDeps(crewHome) {
|
|
|
15085
15203
|
enableRoute(route2) {
|
|
15086
15204
|
const file = configFile();
|
|
15087
15205
|
if (!file) return false;
|
|
15088
|
-
const text2 =
|
|
15206
|
+
const text2 = readFileSync34(file, "utf8");
|
|
15089
15207
|
const doc = parseDocument3(text2);
|
|
15090
15208
|
const routes = doc.get("routes");
|
|
15091
15209
|
const entry = routes?.items?.find((r) => r.get("route") === route2);
|
|
@@ -15111,7 +15229,7 @@ function realProvisionDeps(crewHome) {
|
|
|
15111
15229
|
continue;
|
|
15112
15230
|
}
|
|
15113
15231
|
for (const p of plan.unitPaths) {
|
|
15114
|
-
if (!existsSync34(p) ||
|
|
15232
|
+
if (!existsSync34(p) || readFileSync34(p, "utf8") !== plan.unitContent[p]) unitsStale = true;
|
|
15115
15233
|
}
|
|
15116
15234
|
}
|
|
15117
15235
|
const label = labelFor(crewHome, "run");
|
|
@@ -15120,22 +15238,22 @@ function realProvisionDeps(crewHome) {
|
|
|
15120
15238
|
if (mechanism === "systemd") {
|
|
15121
15239
|
const system = ctx.root || existsSync34(systemUnitPathFor(label));
|
|
15122
15240
|
const ctl = system ? ["systemctl"] : ["systemctl", "--user"];
|
|
15123
|
-
running =
|
|
15241
|
+
running = spawnSync9(ctl[0], [...ctl.slice(1), "is-active", "--quiet", `${label}.service`]).status === 0;
|
|
15124
15242
|
if (!system) {
|
|
15125
|
-
const out =
|
|
15243
|
+
const out = spawnSync9("loginctl", ["show-user", ctx.user, "-p", "Linger"], { encoding: "utf8" });
|
|
15126
15244
|
lingering = /Linger=yes/.test(out.stdout ?? "");
|
|
15127
15245
|
}
|
|
15128
15246
|
} else if (mechanism === "cron") {
|
|
15129
15247
|
running = true;
|
|
15130
15248
|
} else if (mechanism === "launchd") {
|
|
15131
|
-
running =
|
|
15249
|
+
running = spawnSync9("launchctl", ["list", label]).status === 0;
|
|
15132
15250
|
}
|
|
15133
15251
|
return { mechanism, unitsStale, running, lingering };
|
|
15134
15252
|
},
|
|
15135
15253
|
setShipSetting(key, value2) {
|
|
15136
15254
|
const file = configFile();
|
|
15137
15255
|
if (!file) return false;
|
|
15138
|
-
const doc = parseDocument3(
|
|
15256
|
+
const doc = parseDocument3(readFileSync34(file, "utf8"));
|
|
15139
15257
|
if (doc.getIn(["ship", key]) === value2) return false;
|
|
15140
15258
|
doc.setIn(["ship", key], value2);
|
|
15141
15259
|
writeFileSync26(file, doc.toString());
|
|
@@ -15144,11 +15262,22 @@ function realProvisionDeps(crewHome) {
|
|
|
15144
15262
|
applyManagedDefaults() {
|
|
15145
15263
|
const file = configFile();
|
|
15146
15264
|
if (!file) return [];
|
|
15147
|
-
const doc = parseDocument3(
|
|
15265
|
+
const doc = parseDocument3(readFileSync34(file, "utf8"));
|
|
15148
15266
|
const wrote = applyManagedDefaultsToDoc(doc);
|
|
15149
15267
|
if (wrote.length) writeFileSync26(file, doc.toString());
|
|
15150
15268
|
return wrote;
|
|
15151
15269
|
},
|
|
15270
|
+
ensureGitIdentity(name, email) {
|
|
15271
|
+
const have = readGlobalGitIdentity();
|
|
15272
|
+
let wrote = false;
|
|
15273
|
+
for (const [key, value2] of [["user.name", have.name ? null : name], ["user.email", have.email ? null : email]]) {
|
|
15274
|
+
if (value2 === null) continue;
|
|
15275
|
+
const res = spawnSync9("git", ["config", "--global", key, value2], { encoding: "utf8" });
|
|
15276
|
+
if (res.status !== 0) throw new Error(`git config --global ${key}: ${(res.stderr ?? "").trim() || `exited ${res.status}`}`);
|
|
15277
|
+
wrote = true;
|
|
15278
|
+
}
|
|
15279
|
+
return wrote ? "set" : "kept";
|
|
15280
|
+
},
|
|
15152
15281
|
storedToken(host) {
|
|
15153
15282
|
const res = spawnCrew(["credential", "get"], { input: `protocol=https
|
|
15154
15283
|
host=${host}
|
|
@@ -15163,7 +15292,7 @@ host=${host}
|
|
|
15163
15292
|
|
|
15164
15293
|
// src/tunnel.ts
|
|
15165
15294
|
import { spawn as spawn7 } from "child_process";
|
|
15166
|
-
import { existsSync as existsSync35, mkdirSync as mkdirSync25, readFileSync as
|
|
15295
|
+
import { existsSync as existsSync35, mkdirSync as mkdirSync25, readFileSync as readFileSync35, writeFileSync as writeFileSync27, unlinkSync as unlinkSync3, readdirSync as readdirSync13 } from "fs";
|
|
15167
15296
|
import { randomInt } from "crypto";
|
|
15168
15297
|
import { join as join39 } from "path";
|
|
15169
15298
|
var DEFAULT_SPAWN_OPTIONS = { stdio: "ignore", detached: true };
|
|
@@ -15249,7 +15378,7 @@ function readPersistedTunnel(stateDir, workspaceId) {
|
|
|
15249
15378
|
const path = tunnelStatePath(stateDir, workspaceId);
|
|
15250
15379
|
if (!existsSync35(path)) return void 0;
|
|
15251
15380
|
try {
|
|
15252
|
-
return JSON.parse(
|
|
15381
|
+
return JSON.parse(readFileSync35(path, "utf8"));
|
|
15253
15382
|
} catch {
|
|
15254
15383
|
return void 0;
|
|
15255
15384
|
}
|
|
@@ -16794,7 +16923,7 @@ async function resolveOne(tracker, t, seat, approvedStatus, buildingStatus, affi
|
|
|
16794
16923
|
}
|
|
16795
16924
|
|
|
16796
16925
|
// src/repo-refresh.ts
|
|
16797
|
-
import { existsSync as existsSync37, mkdirSync as mkdirSync26, readFileSync as
|
|
16926
|
+
import { existsSync as existsSync37, mkdirSync as mkdirSync26, readFileSync as readFileSync36, writeFileSync as writeFileSync29 } from "fs";
|
|
16798
16927
|
import { dirname as dirname21 } from "path";
|
|
16799
16928
|
var REFRESH_COOLDOWN_MS = 2 * 6e4;
|
|
16800
16929
|
var UNSERVABLE_PASSES_BEFORE_ATTENTION = 3;
|
|
@@ -16825,7 +16954,7 @@ function applyRepoRows(resolved, rows) {
|
|
|
16825
16954
|
function persistRepoRows(stateDir, routeName, rows) {
|
|
16826
16955
|
const path = resolvedPathFor(stateDir, routeName);
|
|
16827
16956
|
if (!existsSync37(path)) return;
|
|
16828
|
-
const raw = JSON.parse(
|
|
16957
|
+
const raw = JSON.parse(readFileSync36(path, "utf8"));
|
|
16829
16958
|
applyRepoRows(raw, rows);
|
|
16830
16959
|
mkdirSync26(dirname21(path), { recursive: true });
|
|
16831
16960
|
writeFileSync29(path, `${JSON.stringify(raw, null, 2)}
|
|
@@ -17478,7 +17607,7 @@ function flagWizardAnswers(f, env) {
|
|
|
17478
17607
|
}
|
|
17479
17608
|
|
|
17480
17609
|
// src/release-run.ts
|
|
17481
|
-
import { readFileSync as
|
|
17610
|
+
import { readFileSync as readFileSync37, writeFileSync as writeFileSync31, existsSync as existsSync39, copyFileSync, mkdirSync as mkdirSync28, mkdtempSync as mkdtempSync3, rmSync as rmSync19 } from "fs";
|
|
17482
17611
|
import { dirname as dirname24, join as join43 } from "path";
|
|
17483
17612
|
import { tmpdir as tmpdir5, hostname as hostname4 } from "os";
|
|
17484
17613
|
|
|
@@ -18255,7 +18384,7 @@ async function bump(o, size) {
|
|
|
18255
18384
|
o.emit.error(`no ${o.repo.release.versionFiles[0]} to read a version from`);
|
|
18256
18385
|
return null;
|
|
18257
18386
|
}
|
|
18258
|
-
const firstText =
|
|
18387
|
+
const firstText = readFileSync37(first, "utf8");
|
|
18259
18388
|
const problem = versionFileProblem(o.repo.release.versionFiles[0], firstText);
|
|
18260
18389
|
if (problem) {
|
|
18261
18390
|
o.emit.error(problem);
|
|
@@ -18274,7 +18403,7 @@ async function bump(o, size) {
|
|
|
18274
18403
|
return version;
|
|
18275
18404
|
}
|
|
18276
18405
|
for (const f of files) {
|
|
18277
|
-
const src =
|
|
18406
|
+
const src = readFileSync37(f, "utf8");
|
|
18278
18407
|
const out = src.replace(/("version"\s*:\s*")[^"]*(")/, `$1${version}$2`);
|
|
18279
18408
|
if (out === src) {
|
|
18280
18409
|
o.emit.error(`no version field in ${f}`);
|
|
@@ -18293,7 +18422,7 @@ function writeChangelog(o, version, entries) {
|
|
|
18293
18422
|
o.emit.emit(`would prepend ${entries.length} entr(ies) to ${file}`);
|
|
18294
18423
|
return;
|
|
18295
18424
|
}
|
|
18296
|
-
const existing = existsSync39(path) ?
|
|
18425
|
+
const existing = existsSync39(path) ? readFileSync37(path, "utf8") : "# Changelog\n";
|
|
18297
18426
|
writeFileSync31(path, insertChangelogSection(existing, section));
|
|
18298
18427
|
}
|
|
18299
18428
|
async function confirm(o, expected) {
|
|
@@ -19810,7 +19939,7 @@ function nextRoles(decision, ran) {
|
|
|
19810
19939
|
}
|
|
19811
19940
|
|
|
19812
19941
|
// src/ship-name.ts
|
|
19813
|
-
import { existsSync as existsSync42, mkdirSync as mkdirSync30, readFileSync as
|
|
19942
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync30, readFileSync as readFileSync38, renameSync as renameSync5, writeFileSync as writeFileSync32 } from "fs";
|
|
19814
19943
|
import { dirname as dirname26 } from "path";
|
|
19815
19944
|
import { parseDocument as parseDocument5 } from "yaml";
|
|
19816
19945
|
var ShipNameError = class extends Error {
|
|
@@ -19874,7 +20003,7 @@ async function syncRouteName(i) {
|
|
|
19874
20003
|
function readSyncedName(resolvedFile) {
|
|
19875
20004
|
if (!existsSync42(resolvedFile)) return void 0;
|
|
19876
20005
|
try {
|
|
19877
|
-
const v = JSON.parse(
|
|
20006
|
+
const v = JSON.parse(readFileSync38(resolvedFile, "utf8")).shipName;
|
|
19878
20007
|
return typeof v === "string" ? v : void 0;
|
|
19879
20008
|
} catch {
|
|
19880
20009
|
return void 0;
|
|
@@ -19884,7 +20013,7 @@ function writeSyncedName(resolvedFile, name) {
|
|
|
19884
20013
|
if (!existsSync42(resolvedFile)) return;
|
|
19885
20014
|
let raw;
|
|
19886
20015
|
try {
|
|
19887
|
-
raw = JSON.parse(
|
|
20016
|
+
raw = JSON.parse(readFileSync38(resolvedFile, "utf8"));
|
|
19888
20017
|
} catch {
|
|
19889
20018
|
return;
|
|
19890
20019
|
}
|
|
@@ -19899,7 +20028,7 @@ function writeSyncedName(resolvedFile, name) {
|
|
|
19899
20028
|
async function reconcileShipName(i) {
|
|
19900
20029
|
let local = i.ship.name;
|
|
19901
20030
|
try {
|
|
19902
|
-
local = shipNameOfYaml(
|
|
20031
|
+
local = shipNameOfYaml(readFileSync38(i.configFile, "utf8")) ?? local;
|
|
19903
20032
|
} catch {
|
|
19904
20033
|
}
|
|
19905
20034
|
const resolvedFile = resolvedPathFor(i.stateDir, i.route);
|
|
@@ -19923,7 +20052,7 @@ async function reconcileShipName(i) {
|
|
|
19923
20052
|
}
|
|
19924
20053
|
if (result.status !== "ok") return result;
|
|
19925
20054
|
if (result.action === "adopt" || result.action === "row-wins") {
|
|
19926
|
-
const text2 =
|
|
20055
|
+
const text2 = readFileSync38(i.configFile, "utf8");
|
|
19927
20056
|
writeFileSync32(i.configFile, setShipNameInYaml(text2, result.name));
|
|
19928
20057
|
i.ship.name = result.name;
|
|
19929
20058
|
if (result.action === "row-wins") {
|
|
@@ -20583,7 +20712,7 @@ function describeCapability(i) {
|
|
|
20583
20712
|
}
|
|
20584
20713
|
|
|
20585
20714
|
// src/agents-sync-run.ts
|
|
20586
|
-
import { existsSync as existsSync43, mkdirSync as mkdirSync31, readFileSync as
|
|
20715
|
+
import { existsSync as existsSync43, mkdirSync as mkdirSync31, readFileSync as readFileSync39, writeFileSync as writeFileSync33 } from "fs";
|
|
20587
20716
|
import { dirname as dirname27 } from "path";
|
|
20588
20717
|
async function runAgentsSync(target, o) {
|
|
20589
20718
|
const dryRun = o.dryRun ?? false;
|
|
@@ -20617,7 +20746,7 @@ async function runAgentsSync(target, o) {
|
|
|
20617
20746
|
for (const s of skillResult?.outcomes ?? []) o.say(describeSkillSyncOutcome(s));
|
|
20618
20747
|
if (!dryRun) {
|
|
20619
20748
|
const resolvedPath = resolvedPathFor(o.stateDir, target.route);
|
|
20620
|
-
const raw = existsSync43(resolvedPath) ? JSON.parse(
|
|
20749
|
+
const raw = existsSync43(resolvedPath) ? JSON.parse(readFileSync39(resolvedPath, "utf8")) : {};
|
|
20621
20750
|
raw.agentPersonas = personaResult.agentPersonas;
|
|
20622
20751
|
if (skillResult) raw.agentSkills = skillResult.agentSkills;
|
|
20623
20752
|
if (personaResult.releaseAgentId) raw.releaseAgentId = personaResult.releaseAgentId;
|
|
@@ -20738,8 +20867,8 @@ async function showLogEntry(route2, entryId, opts = {}) {
|
|
|
20738
20867
|
}
|
|
20739
20868
|
|
|
20740
20869
|
// src/repos-check.ts
|
|
20741
|
-
import { spawnSync as
|
|
20742
|
-
import { readFileSync as
|
|
20870
|
+
import { spawnSync as spawnSync11 } from "child_process";
|
|
20871
|
+
import { readFileSync as readFileSync40 } from "fs";
|
|
20743
20872
|
import { basename as basename11 } from "path";
|
|
20744
20873
|
var POSIX_SHELL = /^(?:ba|z|da|k|a|mk)?sh$|^fish$/;
|
|
20745
20874
|
function checkHookSyntax(script, shell) {
|
|
@@ -20747,10 +20876,10 @@ function checkHookSyntax(script, shell) {
|
|
|
20747
20876
|
const name = basename11(spec.bin).replace(/\.exe$/i, "").toLowerCase();
|
|
20748
20877
|
let run3;
|
|
20749
20878
|
if (POSIX_SHELL.test(name)) {
|
|
20750
|
-
run3 =
|
|
20879
|
+
run3 = spawnSync11(spec.bin, ["-n"], { input: script, encoding: "utf8" });
|
|
20751
20880
|
} else if (/^(pwsh|powershell)$/.test(name)) {
|
|
20752
20881
|
const parse3 = "$e=$null;[void][System.Management.Automation.Language.Parser]::ParseInput($env:CREW_CHECK_SCRIPT,[ref]$null,[ref]$e);if($e){$e|ForEach-Object{[Console]::Error.WriteLine($_.Message)};exit 1}";
|
|
20753
|
-
run3 =
|
|
20882
|
+
run3 = spawnSync11(spec.bin, ["-NoProfile", "-NonInteractive", "-Command", parse3], {
|
|
20754
20883
|
encoding: "utf8",
|
|
20755
20884
|
env: { ...process.env, CREW_CHECK_SCRIPT: script }
|
|
20756
20885
|
});
|
|
@@ -20780,7 +20909,7 @@ function checkRepoSpec(dir, opts = {}) {
|
|
|
20780
20909
|
}
|
|
20781
20910
|
let parsed;
|
|
20782
20911
|
try {
|
|
20783
|
-
parsed = parseRepoConfig(
|
|
20912
|
+
parsed = parseRepoConfig(readFileSync40(file, "utf8"), file);
|
|
20784
20913
|
} catch (e) {
|
|
20785
20914
|
if (!(e instanceof RepoConfigError)) throw e;
|
|
20786
20915
|
return { ...empty, file, error: e.message, exitCode: 1 };
|
|
@@ -21312,7 +21441,7 @@ function planSampleTicket(i) {
|
|
|
21312
21441
|
}
|
|
21313
21442
|
|
|
21314
21443
|
// src/worktree-sweep.ts
|
|
21315
|
-
import { existsSync as existsSync44, readFileSync as
|
|
21444
|
+
import { existsSync as existsSync44, readFileSync as readFileSync41, readdirSync as readdirSync14 } from "fs";
|
|
21316
21445
|
import { basename as basename13, dirname as dirname29, join as join45, resolve as resolve5 } from "path";
|
|
21317
21446
|
function planWorktreeSweep(target, tickets, contract) {
|
|
21318
21447
|
const terminal = new Set(contract.statuses.resolved.filter((s) => s !== contract.statuses.verified));
|
|
@@ -21493,7 +21622,7 @@ function isHandBackMerge(path, base) {
|
|
|
21493
21622
|
if (!msgPath) return false;
|
|
21494
21623
|
let first;
|
|
21495
21624
|
try {
|
|
21496
|
-
first =
|
|
21625
|
+
first = readFileSync41(resolve5(path, msgPath), "utf8").split("\n")[0] ?? "";
|
|
21497
21626
|
} catch {
|
|
21498
21627
|
return false;
|
|
21499
21628
|
}
|
|
@@ -21643,11 +21772,11 @@ function planEventsSweep(stateDir, retentionDays, now = Date.now()) {
|
|
|
21643
21772
|
}
|
|
21644
21773
|
|
|
21645
21774
|
// src/cli.ts
|
|
21646
|
-
import { realpathSync as realpathSync3, readFileSync as
|
|
21775
|
+
import { realpathSync as realpathSync3, readFileSync as readFileSync47, existsSync as existsSync52, mkdirSync as mkdirSync38, writeFileSync as writeFileSync38, rmSync as rmSync25, unlinkSync as unlinkSync5, copyFileSync as copyFileSync2, renameSync as renameSync6, statSync as statSync16, readdirSync as readdirSync20 } from "fs";
|
|
21647
21776
|
import { createInterface } from "readline/promises";
|
|
21648
21777
|
|
|
21649
21778
|
// src/periscope-cmd.ts
|
|
21650
|
-
import { existsSync as existsSync46, mkdirSync as mkdirSync32, readFileSync as
|
|
21779
|
+
import { existsSync as existsSync46, mkdirSync as mkdirSync32, readFileSync as readFileSync42, rmSync as rmSync21, writeFileSync as writeFileSync34 } from "fs";
|
|
21651
21780
|
import { join as join47 } from "path";
|
|
21652
21781
|
var PeriscopeError = class extends Error {
|
|
21653
21782
|
};
|
|
@@ -21673,7 +21802,7 @@ function writePeriscopePrior(stateDir, ticketRecordId, prior) {
|
|
|
21673
21802
|
function readPeriscopePrior(stateDir, ticketRecordId) {
|
|
21674
21803
|
try {
|
|
21675
21804
|
const p = priorPath(stateDir, ticketRecordId);
|
|
21676
|
-
return existsSync46(p) ? JSON.parse(
|
|
21805
|
+
return existsSync46(p) ? JSON.parse(readFileSync42(p, "utf8")) : void 0;
|
|
21677
21806
|
} catch {
|
|
21678
21807
|
return void 0;
|
|
21679
21808
|
}
|
|
@@ -22228,7 +22357,7 @@ import { dirname as dirOf2, resolve as resolvePath } from "path";
|
|
|
22228
22357
|
|
|
22229
22358
|
// src/ssh-keys.ts
|
|
22230
22359
|
import { execFileSync as execFileSync13 } from "child_process";
|
|
22231
|
-
import { existsSync as existsSync47, mkdirSync as mkdirSync33, readFileSync as
|
|
22360
|
+
import { existsSync as existsSync47, mkdirSync as mkdirSync33, readFileSync as readFileSync43, chmodSync as chmodSync3 } from "fs";
|
|
22232
22361
|
import { dirname as dirname30, join as join49 } from "path";
|
|
22233
22362
|
var SshKeyError = class extends Error {
|
|
22234
22363
|
};
|
|
@@ -22262,7 +22391,7 @@ function ensureShipSshKeypair(stateDir) {
|
|
|
22262
22391
|
if (!existsSync47(publicKeyPath)) {
|
|
22263
22392
|
throw new SshKeyError(`${privateKeyPath} exists but ${publicKeyPath} does not \u2014 regenerate or restore it`);
|
|
22264
22393
|
}
|
|
22265
|
-
const publicKey =
|
|
22394
|
+
const publicKey = readFileSync43(publicKeyPath, "utf8").trim();
|
|
22266
22395
|
return { privateKeyPath, publicKeyPath, publicKey };
|
|
22267
22396
|
}
|
|
22268
22397
|
function sshKeygenAvailable() {
|
|
@@ -22426,7 +22555,7 @@ async function unregisterEndpoint(workspaceId, info, d) {
|
|
|
22426
22555
|
import { createServer as createHttpServer } from "http";
|
|
22427
22556
|
import { spawn as spawn9 } from "child_process";
|
|
22428
22557
|
import { randomBytes } from "crypto";
|
|
22429
|
-
import { existsSync as existsSync48, mkdirSync as mkdirSync34, readFileSync as
|
|
22558
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync34, readFileSync as readFileSync44, writeFileSync as writeFileSync35, unlinkSync as unlinkSync4, readdirSync as readdirSync16 } from "fs";
|
|
22430
22559
|
import { join as join50 } from "path";
|
|
22431
22560
|
|
|
22432
22561
|
// src/secret-compare.ts
|
|
@@ -22526,7 +22655,7 @@ function readPersistedSyncDaemon(stateDir, workspaceId) {
|
|
|
22526
22655
|
const path = syncDaemonStatePath(stateDir, workspaceId);
|
|
22527
22656
|
if (!existsSync48(path)) return void 0;
|
|
22528
22657
|
try {
|
|
22529
|
-
return JSON.parse(
|
|
22658
|
+
return JSON.parse(readFileSync44(path, "utf8"));
|
|
22530
22659
|
} catch {
|
|
22531
22660
|
return void 0;
|
|
22532
22661
|
}
|
|
@@ -23075,7 +23204,7 @@ function contractFixers(dir, baseRef, tickets, locate) {
|
|
|
23075
23204
|
}
|
|
23076
23205
|
|
|
23077
23206
|
// src/daemon.ts
|
|
23078
|
-
import { existsSync as existsSync49, mkdirSync as mkdirSync36, readFileSync as
|
|
23207
|
+
import { existsSync as existsSync49, mkdirSync as mkdirSync36, readFileSync as readFileSync45, readdirSync as readdirSync17, rmSync as rmSync22, statSync as statSync14, writeFileSync as writeFileSync36 } from "fs";
|
|
23079
23208
|
import { join as join52 } from "path";
|
|
23080
23209
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
23081
23210
|
var DEFAULT_FLOOR_MS = 5e3;
|
|
@@ -23196,7 +23325,7 @@ function noteDaemonStarted(stateDir, now = Date.now()) {
|
|
|
23196
23325
|
}
|
|
23197
23326
|
function readDaemonStarted(stateDir) {
|
|
23198
23327
|
try {
|
|
23199
|
-
const v = JSON.parse(
|
|
23328
|
+
const v = JSON.parse(readFileSync45(daemonStampFor(stateDir), "utf8")).startedAt;
|
|
23200
23329
|
return typeof v === "number" ? v : null;
|
|
23201
23330
|
} catch {
|
|
23202
23331
|
return null;
|
|
@@ -23379,6 +23508,12 @@ async function runOnePassUnguarded(o) {
|
|
|
23379
23508
|
clearShipAttention(o.state, workspaceAllowanceKey(role));
|
|
23380
23509
|
}).catch(async (e) => {
|
|
23381
23510
|
const message = e.message;
|
|
23511
|
+
if (e instanceof SignedOutError) {
|
|
23512
|
+
breaker.pause(role, SIGNED_OUT_PAUSE_MS);
|
|
23513
|
+
emit.warn(`${role} paused: ${message}`, { step: "agent", role });
|
|
23514
|
+
await raiseShipAttention({ state: o.state, emit, route: o.route, ship: o.ship }, signedOutItem(e.toolchain, e.mode));
|
|
23515
|
+
return;
|
|
23516
|
+
}
|
|
23382
23517
|
if (e instanceof WorkspaceAllowanceExhausted) {
|
|
23383
23518
|
breaker.pause(role, ALLOWANCE_PAUSE_MS);
|
|
23384
23519
|
emit.warn(`${role} paused: ${message}`, { step: "agent", role });
|
|
@@ -23720,6 +23855,7 @@ async function runRoleAgentLocked(role, decision, ctx, hooks, held) {
|
|
|
23720
23855
|
if (plan.workspaceAuth && streamShowsAllowanceRefusal(plan.streamPath)) {
|
|
23721
23856
|
throw new WorkspaceAllowanceExhausted("the inference endpoint refused the run: the workspace is past its AI allowance");
|
|
23722
23857
|
}
|
|
23858
|
+
await settleSignOut(plan, tracker, ctx.state, workingId, emit);
|
|
23723
23859
|
}
|
|
23724
23860
|
} finally {
|
|
23725
23861
|
await settleRunEnd({
|
|
@@ -23756,6 +23892,26 @@ async function buildEnvironment(route2, ship, ticket) {
|
|
|
23756
23892
|
const attachments = await tracker.attachmentsProbe().catch(() => null);
|
|
23757
23893
|
return renderEnvironment({ route: route2, userAgent: ship.userAgent, repos: await withRepoMaps(repos, ship.mapTokenBudget, ship.shell), contract, sourceTicket: ticket, authorship, attachments, shipName: ship.name, ...sandboxEnv(ship) });
|
|
23758
23894
|
}
|
|
23895
|
+
async function settleSignOut(plan, tracker, state, ticketId, emit) {
|
|
23896
|
+
const toolchain = plan.toolchain;
|
|
23897
|
+
if (!toolchain) return;
|
|
23898
|
+
if (!streamShowsSignedOut(plan.streamPath)) {
|
|
23899
|
+
if (streamShowsRealTurn(plan.streamPath)) clearShipAttention(state, signedOutKey(toolchain));
|
|
23900
|
+
return;
|
|
23901
|
+
}
|
|
23902
|
+
if (ticketId) {
|
|
23903
|
+
try {
|
|
23904
|
+
const affinity = await tracker.claimAffinity();
|
|
23905
|
+
const current = await tracker.ticket(ticketId);
|
|
23906
|
+
if (affinity && current[affinity.column] === affinity.shipId) {
|
|
23907
|
+
await tracker.updateTicket(ticketId, { [affinity.column]: null }, current.updated_at);
|
|
23908
|
+
}
|
|
23909
|
+
} catch (e) {
|
|
23910
|
+
emit.warn(`could not release the ticket hold after a sign-out: ${e.message}`, { step: "agent" });
|
|
23911
|
+
}
|
|
23912
|
+
}
|
|
23913
|
+
throw new SignedOutError(toolchain, plan.authMode ?? "login");
|
|
23914
|
+
}
|
|
23759
23915
|
|
|
23760
23916
|
// src/control-api.ts
|
|
23761
23917
|
import { createHash as createHash11 } from "crypto";
|
|
@@ -24446,7 +24602,7 @@ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/
|
|
|
24446
24602
|
|
|
24447
24603
|
// src/periscope-endpoints.ts
|
|
24448
24604
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
24449
|
-
import { chmodSync as chmodSync5, existsSync as existsSync51, mkdirSync as mkdirSync37, readdirSync as readdirSync19, readFileSync as
|
|
24605
|
+
import { chmodSync as chmodSync5, existsSync as existsSync51, mkdirSync as mkdirSync37, readdirSync as readdirSync19, readFileSync as readFileSync46, rmSync as rmSync24, writeFileSync as writeFileSync37 } from "fs";
|
|
24450
24606
|
import { join as join54 } from "path";
|
|
24451
24607
|
var secretDir = (stateDir) => join54(stateDir, "periscope-mcp");
|
|
24452
24608
|
var secretFile = (stateDir, id) => join54(secretDir(stateDir), `${id}.json`);
|
|
@@ -24463,7 +24619,7 @@ function mintPeriscopeSecret(stateDir, ticketRecordId) {
|
|
|
24463
24619
|
}
|
|
24464
24620
|
function readPeriscopeSecret(stateDir, ticketRecordId) {
|
|
24465
24621
|
try {
|
|
24466
|
-
const v = JSON.parse(
|
|
24622
|
+
const v = JSON.parse(readFileSync46(secretFile(stateDir, ticketRecordId), "utf8"));
|
|
24467
24623
|
return typeof v.secret === "string" && v.secret ? v.secret : void 0;
|
|
24468
24624
|
} catch {
|
|
24469
24625
|
return void 0;
|
|
@@ -24474,7 +24630,7 @@ function removePeriscopeSecret(stateDir, ticketRecordId) {
|
|
|
24474
24630
|
}
|
|
24475
24631
|
function readPeriscopeEndpoint(stateDir, ticketRecordId) {
|
|
24476
24632
|
try {
|
|
24477
|
-
return JSON.parse(
|
|
24633
|
+
return JSON.parse(readFileSync46(endpointFile(stateDir, ticketRecordId), "utf8"));
|
|
24478
24634
|
} catch {
|
|
24479
24635
|
return void 0;
|
|
24480
24636
|
}
|
|
@@ -25223,7 +25379,7 @@ if (command === "provision") {
|
|
|
25223
25379
|
process.exit(outcome.code);
|
|
25224
25380
|
}
|
|
25225
25381
|
if (command === "pool-member") {
|
|
25226
|
-
const pool = poolConfigFrom(argv, process.env, () =>
|
|
25382
|
+
const pool = poolConfigFrom(argv, process.env, () => readFileSync47(0, "utf8"));
|
|
25227
25383
|
if (typeof pool === "string") {
|
|
25228
25384
|
process.stderr.write(`crew pool-member: ${pool}
|
|
25229
25385
|
`);
|
|
@@ -25487,7 +25643,7 @@ if (command === "passenger-sync-daemon") {
|
|
|
25487
25643
|
throw e;
|
|
25488
25644
|
}
|
|
25489
25645
|
if (command === "credential") {
|
|
25490
|
-
const r = runCredential(positional[1],
|
|
25646
|
+
const r = runCredential(positional[1], readFileSync47(0, "utf8"), cfg.ship.forges, cfg.ship.stateDir);
|
|
25491
25647
|
process.stdout.write(r.out);
|
|
25492
25648
|
process.stderr.write(r.err);
|
|
25493
25649
|
process.exit(r.code);
|
|
@@ -25499,9 +25655,9 @@ if (command === "passenger-sync-daemon") {
|
|
|
25499
25655
|
forges: cfg.ship.forges,
|
|
25500
25656
|
stateDir: cfg.ship.stateDir,
|
|
25501
25657
|
configFile: cfg.configFile,
|
|
25502
|
-
readFile: (p) =>
|
|
25658
|
+
readFile: (p) => readFileSync47(p, "utf8"),
|
|
25503
25659
|
writeFile: (p, t) => writeFileSync38(p, t),
|
|
25504
|
-
stdin: () =>
|
|
25660
|
+
stdin: () => readFileSync47(0, "utf8"),
|
|
25505
25661
|
env: process.env
|
|
25506
25662
|
}
|
|
25507
25663
|
);
|
|
@@ -25831,7 +25987,7 @@ if (command === "passenger-sync-daemon") {
|
|
|
25831
25987
|
`
|
|
25832
25988
|
);
|
|
25833
25989
|
if (!dryRun) {
|
|
25834
|
-
|
|
25990
|
+
spawnSync12("systemctl", ["--user", "disable", "--now", `${label}.timer`], { cwd: CREW_HOME });
|
|
25835
25991
|
try {
|
|
25836
25992
|
unlinkSync5(staleTimer);
|
|
25837
25993
|
} catch {
|
|
@@ -25882,7 +26038,7 @@ if (command === "passenger-sync-daemon") {
|
|
|
25882
26038
|
async function doctorFix(o) {
|
|
25883
26039
|
const routes = await Promise.all(routesInScope(cfg.routes, named).map((c) => gatherHealth({ route: c.route, enabled: c.enabled, hasRepos: reposOf(c).length > 0 }, () => routeProblems(c))));
|
|
25884
26040
|
const unitExists = (p) => existsSync52(p);
|
|
25885
|
-
const crontab = o.host === "linux" ?
|
|
26041
|
+
const crontab = o.host === "linux" ? spawnSync12("crontab", ["-l"], { encoding: "utf8" }).stdout ?? "" : "";
|
|
25886
26042
|
const schedulerAbsent = o.host !== "windows" ? !schedulerInstalled(planInstall(cfg.ship, CREW_HOME, o.host, detectSystemd(), "run", installContext()), unitExists, crontab) : true;
|
|
25887
26043
|
const plan = planFix({ routes, schedulerAbsent, host: o.host });
|
|
25888
26044
|
for (const n of plan.notes) process.stdout.write(`fix: ${n}
|
|
@@ -25898,7 +26054,7 @@ if (command === "passenger-sync-daemon") {
|
|
|
25898
26054
|
for (const a of plan.actions) {
|
|
25899
26055
|
if (a.kind === "enable") {
|
|
25900
26056
|
if (prompter && !await prompter.confirm(`Route ${a.route} passes every check \u2014 set enabled: true in ${cfg.configFile}?`, false)) continue;
|
|
25901
|
-
writeFileSync38(cfg.configFile, planEnable(
|
|
26057
|
+
writeFileSync38(cfg.configFile, planEnable(readFileSync47(cfg.configFile, "utf8"), a.route));
|
|
25902
26058
|
enabledSound.add(a.route);
|
|
25903
26059
|
changed2.push(`enabled route ${a.route} in ${cfg.configFile}`);
|
|
25904
26060
|
} else {
|
|
@@ -27053,7 +27209,7 @@ ${cu.tail.trimEnd()}
|
|
|
27053
27209
|
}
|
|
27054
27210
|
let failed = false;
|
|
27055
27211
|
for (const cmd2 of commands) {
|
|
27056
|
-
const res2 =
|
|
27212
|
+
const res2 = spawnSync12(cmd2[0], cmd2.slice(1), { cwd: CREW_HOME, encoding: "utf8" });
|
|
27057
27213
|
if (res2.stdout) process.stdout.write(res2.stdout);
|
|
27058
27214
|
if (res2.stderr) process.stderr.write(res2.stderr);
|
|
27059
27215
|
if (cmd2 === control.startCommand && (res2.error || res2.status !== 0)) {
|
|
@@ -27071,7 +27227,7 @@ ${cu.tail.trimEnd()}
|
|
|
27071
27227
|
`);
|
|
27072
27228
|
break;
|
|
27073
27229
|
}
|
|
27074
|
-
const res =
|
|
27230
|
+
const res = spawnSync12(cmd[0], cmd.slice(1), { cwd: CREW_HOME, encoding: "utf8" });
|
|
27075
27231
|
if (res.stdout) process.stdout.write(res.stdout);
|
|
27076
27232
|
if (res.stderr) process.stderr.write(res.stderr);
|
|
27077
27233
|
if (daemonSub !== "status" && (res.error || res.status !== 0)) {
|
|
@@ -27399,7 +27555,7 @@ ${cu.tail.trimEnd()}
|
|
|
27399
27555
|
`);
|
|
27400
27556
|
if (!dryRun) {
|
|
27401
27557
|
const resolvedPath = resolvedPathFor(cfg.ship.stateDir, target.route);
|
|
27402
|
-
const raw = existsSync52(resolvedPath) ? JSON.parse(
|
|
27558
|
+
const raw = existsSync52(resolvedPath) ? JSON.parse(readFileSync47(resolvedPath, "utf8")) : {};
|
|
27403
27559
|
raw.agentSkills = result.agentSkills;
|
|
27404
27560
|
mkdirSync38(dirOf2(resolvedPath), { recursive: true });
|
|
27405
27561
|
writeFileSync38(resolvedPath, `${JSON.stringify(raw, null, 2)}
|
|
@@ -27425,7 +27581,7 @@ ${cu.tail.trimEnd()}
|
|
|
27425
27581
|
throw e;
|
|
27426
27582
|
}
|
|
27427
27583
|
const oldName = cfg.ship.name;
|
|
27428
|
-
writeFileSync38(cfg.configFile, setShipNameInYaml(
|
|
27584
|
+
writeFileSync38(cfg.configFile, setShipNameInYaml(readFileSync47(cfg.configFile, "utf8"), newName));
|
|
27429
27585
|
cfg.ship.name = newName;
|
|
27430
27586
|
let renameMachineId;
|
|
27431
27587
|
try {
|
|
@@ -27472,7 +27628,7 @@ ${cu.tail.trimEnd()}
|
|
|
27472
27628
|
process.exit(2);
|
|
27473
27629
|
};
|
|
27474
27630
|
if (sub !== "add" && sub !== "list" && sub !== "clone" && sub !== "hooks" && sub !== "check") usage2();
|
|
27475
|
-
const configText =
|
|
27631
|
+
const configText = readFileSync47(cfg.configFile, "utf8");
|
|
27476
27632
|
if (sub === "check") {
|
|
27477
27633
|
try {
|
|
27478
27634
|
const routeArg = value("route") ?? positional[2];
|
|
@@ -27513,7 +27669,7 @@ ${cu.tail.trimEnd()}
|
|
|
27513
27669
|
}
|
|
27514
27670
|
}, read: (r) => {
|
|
27515
27671
|
try {
|
|
27516
|
-
return
|
|
27672
|
+
return readFileSync47(resolvePath(dir, r), "utf8");
|
|
27517
27673
|
} catch {
|
|
27518
27674
|
return void 0;
|
|
27519
27675
|
}
|
|
@@ -27664,7 +27820,7 @@ ${cu.tail.trimEnd()}
|
|
|
27664
27820
|
let resolvedRemotes;
|
|
27665
27821
|
if (existsSync52(resolvedFile)) {
|
|
27666
27822
|
try {
|
|
27667
|
-
resolvedRemotes = JSON.parse(
|
|
27823
|
+
resolvedRemotes = JSON.parse(readFileSync47(resolvedFile, "utf8"));
|
|
27668
27824
|
} catch {
|
|
27669
27825
|
}
|
|
27670
27826
|
}
|
|
@@ -27686,7 +27842,7 @@ ${cu.tail.trimEnd()}
|
|
|
27686
27842
|
repoHasHooks: (d) => REPO_CONFIG_FILENAMES.some((f) => {
|
|
27687
27843
|
try {
|
|
27688
27844
|
const path = resolvePath(d, f);
|
|
27689
|
-
return Object.keys(parseRepoConfig(
|
|
27845
|
+
return Object.keys(parseRepoConfig(readFileSync47(path, "utf8"), path).hooks).length > 0;
|
|
27690
27846
|
} catch {
|
|
27691
27847
|
return false;
|
|
27692
27848
|
}
|
|
@@ -27795,7 +27951,7 @@ ${cu.tail.trimEnd()}
|
|
|
27795
27951
|
process.stdout.write(`created Repos row ${String(rowPayload.name)} (${String(rowPayload.remote)}) ${created.id}
|
|
27796
27952
|
`);
|
|
27797
27953
|
if (existsSync52(resolvedFile)) {
|
|
27798
|
-
const raw = JSON.parse(
|
|
27954
|
+
const raw = JSON.parse(readFileSync47(resolvedFile, "utf8"));
|
|
27799
27955
|
raw.repoNames = { ...raw.repoNames, [created.id]: String(rowPayload.name) };
|
|
27800
27956
|
raw.repoRemotes = { ...raw.repoRemotes, [created.id]: String(rowPayload.remote) };
|
|
27801
27957
|
writeFileSync38(resolvedFile, `${JSON.stringify(raw, null, 2)}
|
|
@@ -28173,7 +28329,7 @@ Signed in as ${result.identity.email} \u2014 minted an API key in workspace "${r
|
|
|
28173
28329
|
process.exit(2);
|
|
28174
28330
|
}
|
|
28175
28331
|
if (found.shipNameAdopted && !dryRun) {
|
|
28176
|
-
writeFileSync38(cfg.configFile, setShipNameInYaml(
|
|
28332
|
+
writeFileSync38(cfg.configFile, setShipNameInYaml(readFileSync47(cfg.configFile, "utf8"), found.shipNameAdopted));
|
|
28177
28333
|
cfg.ship.name = found.shipNameAdopted;
|
|
28178
28334
|
}
|
|
28179
28335
|
if (found.shipRow) {
|
|
@@ -28219,7 +28375,7 @@ Signed in as ${result.identity.email} \u2014 minted an API key in workspace "${r
|
|
|
28219
28375
|
const hadPreviousFile = existsSync52(resolvedPath);
|
|
28220
28376
|
if (hadPreviousFile) {
|
|
28221
28377
|
try {
|
|
28222
|
-
previous = JSON.parse(
|
|
28378
|
+
previous = JSON.parse(readFileSync47(resolvedPath, "utf8"));
|
|
28223
28379
|
} catch {
|
|
28224
28380
|
}
|
|
28225
28381
|
}
|
|
@@ -29528,7 +29684,7 @@ ${where.join("\n")}`);
|
|
|
29528
29684
|
process.stdout.write(upOutput(res, terminal));
|
|
29529
29685
|
const opener = openerFor(process.platform);
|
|
29530
29686
|
if (opener && shouldOpen({ open: flag("open"), noOpen: flag("no-open"), json: jsonP, terminal })) {
|
|
29531
|
-
const r =
|
|
29687
|
+
const r = spawnSync12(opener, [res.url], { stdio: "ignore" });
|
|
29532
29688
|
if (r.error || r.status !== 0) process.stderr.write(`crew periscope: could not open ${res.url} with ${opener}
|
|
29533
29689
|
`);
|
|
29534
29690
|
}
|
|
@@ -29729,7 +29885,7 @@ ${where.join("\n")}`);
|
|
|
29729
29885
|
};
|
|
29730
29886
|
const droppedRoutes = [];
|
|
29731
29887
|
try {
|
|
29732
|
-
const rawCfg = parseYaml2(
|
|
29888
|
+
const rawCfg = parseYaml2(readFileSync47(cfg.configFile, "utf8"));
|
|
29733
29889
|
for (const r of rawCfg?.routes ?? []) {
|
|
29734
29890
|
if (typeof r?.route !== "string" || cfg.routes.some((x) => x.route === r.route)) continue;
|
|
29735
29891
|
try {
|
|
@@ -29776,7 +29932,7 @@ ${where.join("\n")}`);
|
|
|
29776
29932
|
}
|
|
29777
29933
|
const host = hostPlatform();
|
|
29778
29934
|
const control = host === "windows" ? null : planDaemonControl(CREW_HOME, host, detectSystemd());
|
|
29779
|
-
const unitStatus = control?.statusCommand ?
|
|
29935
|
+
const unitStatus = control?.statusCommand ? spawnSync12(control.statusCommand[0], control.statusCommand.slice(1), { cwd: CREW_HOME, encoding: "utf8" }) : null;
|
|
29780
29936
|
const unitRunning = unitStatus !== null && !unitStatus.error && unitStatus.status === 0;
|
|
29781
29937
|
if (!unitRunning) {
|
|
29782
29938
|
process.stdout.write("crew reload: no daemon unit is running \u2014 nothing to reload (the next run reads crew.yaml fresh)\n");
|
|
@@ -29790,7 +29946,7 @@ ${where.join("\n")}`);
|
|
|
29790
29946
|
);
|
|
29791
29947
|
if (flag("now") && control?.stopCommand && control.startCommand) {
|
|
29792
29948
|
for (const cmd of [control.stopCommand, control.startCommand]) {
|
|
29793
|
-
const res =
|
|
29949
|
+
const res = spawnSync12(cmd[0], cmd.slice(1), { cwd: CREW_HOME, encoding: "utf8" });
|
|
29794
29950
|
if (cmd === control.startCommand && (res.error || res.status !== 0)) {
|
|
29795
29951
|
process.stderr.write(`crew reload: ${cmd.join(" ")} exited ${res.status ?? "error"}
|
|
29796
29952
|
`);
|
|
@@ -29848,7 +30004,7 @@ ${where.join("\n")}`);
|
|
|
29848
30004
|
}
|
|
29849
30005
|
case "log": {
|
|
29850
30006
|
try {
|
|
29851
|
-
const text2 =
|
|
30007
|
+
const text2 = readFileSync47(cfg.ship.logFile, "utf8").split("\n");
|
|
29852
30008
|
process.stdout.write(`${text2.slice(-(Number(value("tail")) || 40)).join("\n")}
|
|
29853
30009
|
`);
|
|
29854
30010
|
} catch {
|
|
@@ -29871,7 +30027,7 @@ ${where.join("\n")}`);
|
|
|
29871
30027
|
};
|
|
29872
30028
|
if (!route2.resolved) fail2(`route ${route2.route} is not connected \u2014 run \`crew connect\` first`);
|
|
29873
30029
|
const tracker = new Tracker(route2, cfg.ship);
|
|
29874
|
-
const configText =
|
|
30030
|
+
const configText = readFileSync47(cfg.configFile, "utf8");
|
|
29875
30031
|
const cfgBase = dirname34(cfg.configFile);
|
|
29876
30032
|
const configured2 = configuredRepos(configText, route2.route, cfgBase);
|
|
29877
30033
|
const dir = configured2.find((r) => r.name === SAMPLE_REPO)?.dir ?? sampleDir(configured2.map((r) => r.dir), route2.reposBasePath, route2.route.split("/")[0]);
|
|
@@ -29909,7 +30065,7 @@ ${where.join("\n")}`);
|
|
|
29909
30065
|
if (row) {
|
|
29910
30066
|
await tracker.deleteRepoRow(row.id);
|
|
29911
30067
|
if (existsSync52(resolvedFile)) {
|
|
29912
|
-
const raw = JSON.parse(
|
|
30068
|
+
const raw = JSON.parse(readFileSync47(resolvedFile, "utf8"));
|
|
29913
30069
|
if (raw.repoNames) delete raw.repoNames[row.id];
|
|
29914
30070
|
if (raw.repoRemotes) delete raw.repoRemotes[row.id];
|
|
29915
30071
|
writeFileSync38(resolvedFile, `${JSON.stringify(raw, null, 2)}
|
|
@@ -29932,7 +30088,7 @@ ${where.join("\n")}`);
|
|
|
29932
30088
|
writeFileSync38(join56(dir, "README.md"), SAMPLE_README);
|
|
29933
30089
|
writeFileSync38(join56(dir, ".crew.yaml"), SAMPLE_CREW_YAML);
|
|
29934
30090
|
const g = (...a) => {
|
|
29935
|
-
const r =
|
|
30091
|
+
const r = spawnSync12("git", a, { cwd: dir, encoding: "utf8" });
|
|
29936
30092
|
if (r.status !== 0) fail2(`git ${a[0]} failed in ${dir}: ${(r.stderr || r.stdout).trim()}`);
|
|
29937
30093
|
};
|
|
29938
30094
|
g("init", "-b", "main");
|
|
@@ -29949,7 +30105,7 @@ ${where.join("\n")}`);
|
|
|
29949
30105
|
});
|
|
29950
30106
|
repoId = (await tracker.createRepoRow(payload)).id;
|
|
29951
30107
|
if (existsSync52(resolvedFile)) {
|
|
29952
|
-
const raw = JSON.parse(
|
|
30108
|
+
const raw = JSON.parse(readFileSync47(resolvedFile, "utf8"));
|
|
29953
30109
|
raw.repoNames = { ...raw.repoNames, [repoId]: SAMPLE_REPO };
|
|
29954
30110
|
raw.repoRemotes = { ...raw.repoRemotes, [repoId]: SAMPLE_REMOTE };
|
|
29955
30111
|
writeFileSync38(resolvedFile, `${JSON.stringify(raw, null, 2)}
|
|
@@ -30364,7 +30520,9 @@ watermark: ${state.watermark()}
|
|
|
30364
30520
|
}
|
|
30365
30521
|
for (const message of roleCapWarnings(cfg.ship)) problems.push({ severity: "note", kind: "role_cap_above_ship_cap", message });
|
|
30366
30522
|
if (!flag("offline")) {
|
|
30367
|
-
|
|
30523
|
+
const shipKind = await doctorShipKind(route2, cfg.ship);
|
|
30524
|
+
for (const message of managedRuntimeWarnings(shipKind, cfg.ship)) problems.push({ severity: "attention", kind: "managed_runtime_default", message });
|
|
30525
|
+
for (const message of managedGitIdentityWarnings(shipKind, readGlobalGitIdentity())) problems.push({ severity: "attention", kind: "managed_git_identity", message });
|
|
30368
30526
|
}
|
|
30369
30527
|
for (const t of rejectedTunnels(cfg.ship.stateDir)) {
|
|
30370
30528
|
problems.push({ severity: "attention", kind: TUNNEL_REJECTED_KEY, message: tunnelRejectedMessage(t.workspaceId, t.quickExits), remedy: "rotate the slug with `crew rotate-passenger-url`" });
|
|
@@ -30421,7 +30579,7 @@ routes: ${cfg.routes.map((c) => c.route).join(", ")}
|
|
|
30421
30579
|
const unitPlan = planInstall(cfg.ship, CREW_HOME, host, detectSystemd(), "run", installContext());
|
|
30422
30580
|
const abandons = unitAbandonsAgents(unitPlan, (p) => {
|
|
30423
30581
|
try {
|
|
30424
|
-
return
|
|
30582
|
+
return readFileSync47(p, "utf8");
|
|
30425
30583
|
} catch {
|
|
30426
30584
|
return null;
|
|
30427
30585
|
}
|
|
@@ -30615,6 +30773,8 @@ crew manifest: ${seats2.length ? seats2.map((c) => c.name).join(", ") : "non
|
|
|
30615
30773
|
`
|
|
30616
30774
|
);
|
|
30617
30775
|
for (const w of managedRuntimeWarnings(row.kind, cfg.ship)) process.stdout.write(`managed runtime: WARN ${w}
|
|
30776
|
+
`);
|
|
30777
|
+
for (const w of managedGitIdentityWarnings(row.kind, readGlobalGitIdentity())) process.stdout.write(`managed git: WARN ${w}
|
|
30618
30778
|
`);
|
|
30619
30779
|
}
|
|
30620
30780
|
}
|
package/package.json
CHANGED