@tablation/crew 0.127.1 → 0.127.3
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 +244 -98
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -6215,7 +6215,8 @@ async function raiseShipAttention(o, item) {
|
|
|
6215
6215
|
const previous = store.previous();
|
|
6216
6216
|
const next = upsert(previous, item);
|
|
6217
6217
|
store.persist(next);
|
|
6218
|
-
|
|
6218
|
+
const changed2 = item.kind === "sandbox_cache" && previous.some((i) => i.key === item.key && i.message !== item.message);
|
|
6219
|
+
if (transitions(previous, next).length === 0 && !changed2) return false;
|
|
6219
6220
|
announce(o.emit, item);
|
|
6220
6221
|
if (o.route && o.ship) {
|
|
6221
6222
|
await notify(o.route, o.ship, { level: "warn", headline: item.message }, o.emit);
|
|
@@ -6356,7 +6357,7 @@ function attentionProblems(items, already) {
|
|
|
6356
6357
|
import { createHash as createHash7 } from "crypto";
|
|
6357
6358
|
import { spawn as spawn5 } from "child_process";
|
|
6358
6359
|
import { execFileSync as execFileSync8 } from "child_process";
|
|
6359
|
-
import { existsSync as existsSync30, mkdirSync as mkdirSync19, readFileSync as
|
|
6360
|
+
import { existsSync as existsSync30, mkdirSync as mkdirSync19, readFileSync as readFileSync28, renameSync as renameSync3, writeFileSync as writeFileSync20, rmSync as rmSync15 } from "fs";
|
|
6360
6361
|
import { dirname as dirname15, join as join32 } from "path";
|
|
6361
6362
|
import { fileURLToPath } from "url";
|
|
6362
6363
|
import { tmpdir as tmpdir3 } from "os";
|
|
@@ -6374,12 +6375,12 @@ import { spawnSync as spawnSync7 } from "child_process";
|
|
|
6374
6375
|
import { existsSync as existsSync29, readdirSync as readdirSync11 } from "fs";
|
|
6375
6376
|
|
|
6376
6377
|
// src/interrupted.ts
|
|
6377
|
-
import { existsSync as existsSync27, readdirSync as readdirSync9, readFileSync as
|
|
6378
|
+
import { existsSync as existsSync27, readdirSync as readdirSync9, readFileSync as readFileSync27 } from "fs";
|
|
6378
6379
|
import { join as join30 } from "path";
|
|
6379
6380
|
|
|
6380
6381
|
// src/agent.ts
|
|
6381
6382
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
6382
|
-
import { readFileSync as
|
|
6383
|
+
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
6384
|
import { StringDecoder } from "string_decoder";
|
|
6384
6385
|
import { finished } from "stream/promises";
|
|
6385
6386
|
import { join as join29, dirname as dirname14, basename as basename9 } from "path";
|
|
@@ -6887,6 +6888,97 @@ var State = class _State {
|
|
|
6887
6888
|
}
|
|
6888
6889
|
};
|
|
6889
6890
|
|
|
6891
|
+
// src/signed-out.ts
|
|
6892
|
+
import { readFileSync as readFileSync20 } from "fs";
|
|
6893
|
+
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;
|
|
6894
|
+
function authModeOf(spec, hostEnv = process.env) {
|
|
6895
|
+
const env = { ...hostEnv, ...spec.env };
|
|
6896
|
+
const on = (v) => !!v && v !== "0" && v.toLowerCase() !== "false";
|
|
6897
|
+
if (spec.auth === "subscription") return "login";
|
|
6898
|
+
if (on(env.CLAUDE_CODE_USE_VERTEX)) return "vertex";
|
|
6899
|
+
if (env.ANTHROPIC_API_KEY) return "api-key";
|
|
6900
|
+
return "login";
|
|
6901
|
+
}
|
|
6902
|
+
var SIGNED_OUT_REMEDY = {
|
|
6903
|
+
vertex: "run `gcloud auth application-default login` on this Mac",
|
|
6904
|
+
"api-key": "check the API key the toolchain uses (ANTHROPIC_API_KEY) is valid and unrevoked",
|
|
6905
|
+
login: "run `claude` in a terminal on this Mac and `/login`"
|
|
6906
|
+
};
|
|
6907
|
+
function signedOutMessage(toolchain, mode) {
|
|
6908
|
+
return `toolchain ${toolchain} is signed out \u2014 its runs end at the harness's sign-out error. To fix: ${SIGNED_OUT_REMEDY[mode]}`;
|
|
6909
|
+
}
|
|
6910
|
+
var signedOutKey = (toolchain) => `signed_out:${toolchain}`;
|
|
6911
|
+
function signedOutItem(toolchain, mode, nowIso = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
6912
|
+
return { kind: "signed_out", key: signedOutKey(toolchain), since: nowIso, message: signedOutMessage(toolchain, mode) };
|
|
6913
|
+
}
|
|
6914
|
+
var textOf = (v) => typeof v === "string" ? v : JSON.stringify(v ?? "");
|
|
6915
|
+
function eventsShowSignedOut(events) {
|
|
6916
|
+
let assistantTurns = 0;
|
|
6917
|
+
let toolUse = false;
|
|
6918
|
+
let onlyTurnSignedOut = false;
|
|
6919
|
+
for (const ev of events) {
|
|
6920
|
+
if (typeof ev !== "object" || ev === null) continue;
|
|
6921
|
+
const e = ev;
|
|
6922
|
+
if (e.type === "result") {
|
|
6923
|
+
if (e.is_error === true && SIGNED_OUT_PATTERN.test(textOf(e.result))) return true;
|
|
6924
|
+
} else if (e.type === "assistant") {
|
|
6925
|
+
assistantTurns++;
|
|
6926
|
+
const content = Array.isArray(e.message?.content) ? e.message.content : [];
|
|
6927
|
+
if (content.some((b) => b?.type === "tool_use")) toolUse = true;
|
|
6928
|
+
if (SIGNED_OUT_PATTERN.test(textOf(e.message))) {
|
|
6929
|
+
if (e.isApiErrorMessage === true || e.error !== void 0) return true;
|
|
6930
|
+
onlyTurnSignedOut = true;
|
|
6931
|
+
}
|
|
6932
|
+
}
|
|
6933
|
+
}
|
|
6934
|
+
return assistantTurns === 1 && onlyTurnSignedOut && !toolUse;
|
|
6935
|
+
}
|
|
6936
|
+
function streamShowsSignedOut(streamPath) {
|
|
6937
|
+
let raw;
|
|
6938
|
+
try {
|
|
6939
|
+
raw = readFileSync20(streamPath, "utf8");
|
|
6940
|
+
} catch {
|
|
6941
|
+
return false;
|
|
6942
|
+
}
|
|
6943
|
+
if (!SIGNED_OUT_PATTERN.test(raw)) return false;
|
|
6944
|
+
const events = [];
|
|
6945
|
+
for (const line of raw.split("\n")) {
|
|
6946
|
+
if (!line.trim()) continue;
|
|
6947
|
+
try {
|
|
6948
|
+
events.push(JSON.parse(line));
|
|
6949
|
+
} catch {
|
|
6950
|
+
}
|
|
6951
|
+
}
|
|
6952
|
+
return eventsShowSignedOut(events);
|
|
6953
|
+
}
|
|
6954
|
+
function streamShowsRealTurn(streamPath) {
|
|
6955
|
+
let raw;
|
|
6956
|
+
try {
|
|
6957
|
+
raw = readFileSync20(streamPath, "utf8");
|
|
6958
|
+
} catch {
|
|
6959
|
+
return false;
|
|
6960
|
+
}
|
|
6961
|
+
return raw.split("\n").some((line) => {
|
|
6962
|
+
if (!line.includes('"assistant"')) return false;
|
|
6963
|
+
try {
|
|
6964
|
+
const e = JSON.parse(line);
|
|
6965
|
+
return e.type === "assistant" && e.isApiErrorMessage !== true && e.error === void 0 && !SIGNED_OUT_PATTERN.test(textOf(e.message));
|
|
6966
|
+
} catch {
|
|
6967
|
+
return false;
|
|
6968
|
+
}
|
|
6969
|
+
});
|
|
6970
|
+
}
|
|
6971
|
+
var SignedOutError = class extends Error {
|
|
6972
|
+
toolchain;
|
|
6973
|
+
mode;
|
|
6974
|
+
constructor(toolchain, mode) {
|
|
6975
|
+
super(signedOutMessage(toolchain, mode));
|
|
6976
|
+
this.toolchain = toolchain;
|
|
6977
|
+
this.mode = mode;
|
|
6978
|
+
}
|
|
6979
|
+
};
|
|
6980
|
+
var SIGNED_OUT_PAUSE_MS = 15 * 60 * 1e3;
|
|
6981
|
+
|
|
6890
6982
|
// src/environment.ts
|
|
6891
6983
|
import { basename as basename6 } from "path";
|
|
6892
6984
|
|
|
@@ -7286,7 +7378,7 @@ function renderEnvironment(i) {
|
|
|
7286
7378
|
}
|
|
7287
7379
|
|
|
7288
7380
|
// src/intel-bridge.ts
|
|
7289
|
-
import { existsSync as existsSync20, mkdirSync as mkdirSync14, readFileSync as
|
|
7381
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync14, readFileSync as readFileSync21, rmSync as rmSync11, writeFileSync as writeFileSync15 } from "fs";
|
|
7290
7382
|
import { dirname as dirname11, join as join22 } from "path";
|
|
7291
7383
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
7292
7384
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
@@ -7313,7 +7405,7 @@ function writeAttachFile(file, url) {
|
|
|
7313
7405
|
}
|
|
7314
7406
|
function readAttachFile(file) {
|
|
7315
7407
|
try {
|
|
7316
|
-
const url =
|
|
7408
|
+
const url = readFileSync21(file, "utf8").trim();
|
|
7317
7409
|
return /^https?:\/\/\S+$/i.test(url) ? url : void 0;
|
|
7318
7410
|
} catch {
|
|
7319
7411
|
return void 0;
|
|
@@ -7692,7 +7784,7 @@ var BeforeFirstEditTracker = class {
|
|
|
7692
7784
|
};
|
|
7693
7785
|
|
|
7694
7786
|
// src/agent-log.ts
|
|
7695
|
-
import { existsSync as existsSync21, mkdirSync as mkdirSync15, readdirSync as readdirSync6, readFileSync as
|
|
7787
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync15, readdirSync as readdirSync6, readFileSync as readFileSync22, rmSync as rmSync12, writeFileSync as writeFileSync16 } from "fs";
|
|
7696
7788
|
import { join as join23 } from "path";
|
|
7697
7789
|
|
|
7698
7790
|
// src/pending-backoff.ts
|
|
@@ -7909,7 +8001,7 @@ async function replayQueuedAgentRuns(stateDir, route2, keyFor, log, now = /* @__
|
|
|
7909
8001
|
const path = join23(dir, f);
|
|
7910
8002
|
let q2;
|
|
7911
8003
|
try {
|
|
7912
|
-
q2 = JSON.parse(
|
|
8004
|
+
q2 = JSON.parse(readFileSync22(path, "utf8"));
|
|
7913
8005
|
} catch {
|
|
7914
8006
|
continue;
|
|
7915
8007
|
}
|
|
@@ -7962,7 +8054,7 @@ async function replayQueuedTicketCounters(stateDir, route2, keyFor, log, now = /
|
|
|
7962
8054
|
const path = join23(dir, f);
|
|
7963
8055
|
let q2;
|
|
7964
8056
|
try {
|
|
7965
|
-
q2 = JSON.parse(
|
|
8057
|
+
q2 = JSON.parse(readFileSync22(path, "utf8"));
|
|
7966
8058
|
} catch {
|
|
7967
8059
|
continue;
|
|
7968
8060
|
}
|
|
@@ -8184,7 +8276,7 @@ var HandoffTranscriptTracker = class {
|
|
|
8184
8276
|
};
|
|
8185
8277
|
|
|
8186
8278
|
// src/pending-handoff.ts
|
|
8187
|
-
import { existsSync as existsSync23, mkdirSync as mkdirSync16, readdirSync as readdirSync7, readFileSync as
|
|
8279
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync16, readdirSync as readdirSync7, readFileSync as readFileSync23, rmSync as rmSync13, writeFileSync as writeFileSync17 } from "fs";
|
|
8188
8280
|
import { join as join25 } from "path";
|
|
8189
8281
|
|
|
8190
8282
|
// src/ticket-branch.ts
|
|
@@ -9879,7 +9971,7 @@ function listPendingHandoffs(stateDir, route2) {
|
|
|
9879
9971
|
const out = [];
|
|
9880
9972
|
for (const f of readdirSync7(dir).filter((n) => n.endsWith(".json")).sort()) {
|
|
9881
9973
|
try {
|
|
9882
|
-
const rec = JSON.parse(
|
|
9974
|
+
const rec = JSON.parse(readFileSync23(join25(dir, f), "utf8"));
|
|
9883
9975
|
if (rec.version === 1 && rec.ticketRecordId && (!route2 || rec.route === route2)) out.push(rec);
|
|
9884
9976
|
} catch {
|
|
9885
9977
|
}
|
|
@@ -9997,7 +10089,7 @@ function expandSkillMarkers(text2, lookup2, opts = {}) {
|
|
|
9997
10089
|
}
|
|
9998
10090
|
|
|
9999
10091
|
// src/skills.ts
|
|
10000
|
-
import { readFileSync as
|
|
10092
|
+
import { readFileSync as readFileSync25, readdirSync as readdirSync8, existsSync as existsSync25 } from "fs";
|
|
10001
10093
|
import { join as join27 } from "path";
|
|
10002
10094
|
import { parse as parseYaml } from "yaml";
|
|
10003
10095
|
import { TablationClient as TablationClient3, StaleWriteError as StaleWriteError3, TablationApiError as TablationApiError2 } from "@tablation/client";
|
|
@@ -10014,7 +10106,7 @@ ${additions}`;
|
|
|
10014
10106
|
}
|
|
10015
10107
|
|
|
10016
10108
|
// src/agents.ts
|
|
10017
|
-
import { readFileSync as
|
|
10109
|
+
import { readFileSync as readFileSync24, existsSync as existsSync24 } from "fs";
|
|
10018
10110
|
import { join as join26 } from "path";
|
|
10019
10111
|
import { TablationClient as TablationClient2, StaleWriteError as StaleWriteError2, TablationApiError } from "@tablation/client";
|
|
10020
10112
|
var PERSONA_NAME = {
|
|
@@ -10031,10 +10123,10 @@ var AgentsSyncError = class extends Error {
|
|
|
10031
10123
|
function personaDefaultPrompt(promptsDir, role) {
|
|
10032
10124
|
const briefPath = join26(promptsDir, "personas", `lane-${role}.md`);
|
|
10033
10125
|
if (!existsSync24(briefPath)) throw new AgentsSyncError(`no brief at ${briefPath}`);
|
|
10034
|
-
if (SELF_CONTAINED_ROLES.has(role)) return
|
|
10126
|
+
if (SELF_CONTAINED_ROLES.has(role)) return readFileSync24(briefPath, "utf8");
|
|
10035
10127
|
const commonPath = join26(promptsDir, "personas", "common.md");
|
|
10036
|
-
if (!existsSync24(commonPath)) return
|
|
10037
|
-
return `${
|
|
10128
|
+
if (!existsSync24(commonPath)) return readFileSync24(briefPath, "utf8");
|
|
10129
|
+
return `${readFileSync24(commonPath, "utf8")}${readFileSync24(briefPath, "utf8")}`;
|
|
10038
10130
|
}
|
|
10039
10131
|
async function resolveAgentId(route2, role, opts) {
|
|
10040
10132
|
const cached = route2.resolved?.agentPersonas?.[role]?.agentId;
|
|
@@ -10481,7 +10573,7 @@ function describeCrewLink(o) {
|
|
|
10481
10573
|
var SkillSyncError = class extends Error {
|
|
10482
10574
|
};
|
|
10483
10575
|
function parseSkillFile(path) {
|
|
10484
|
-
const text2 =
|
|
10576
|
+
const text2 = readFileSync25(path, "utf8");
|
|
10485
10577
|
const match = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/.exec(text2);
|
|
10486
10578
|
if (!match) throw new SkillSyncError(`${path}: missing YAML frontmatter (expected a leading --- block)`);
|
|
10487
10579
|
const frontmatter = match[1];
|
|
@@ -11061,7 +11153,7 @@ var ALLOWANCE_REFUSAL_MARKER = "AI_ALLOWANCE_EXCEEDED";
|
|
|
11061
11153
|
function streamShowsAllowanceRefusal(streamPath) {
|
|
11062
11154
|
let raw;
|
|
11063
11155
|
try {
|
|
11064
|
-
raw =
|
|
11156
|
+
raw = readFileSync26(streamPath, "utf8");
|
|
11065
11157
|
} catch {
|
|
11066
11158
|
return false;
|
|
11067
11159
|
}
|
|
@@ -11147,10 +11239,10 @@ function planAgentRun(o) {
|
|
|
11147
11239
|
let ageSeconds;
|
|
11148
11240
|
if (existsSync26(digestPath2)) {
|
|
11149
11241
|
ageSeconds = Math.floor((now() - statSync8(digestPath2).mtimeMs) / 1e3);
|
|
11150
|
-
if (ageSeconds <= DIGEST_MAX_AGE_SECONDS) digest =
|
|
11242
|
+
if (ageSeconds <= DIGEST_MAX_AGE_SECONDS) digest = readFileSync26(digestPath2, "utf8");
|
|
11151
11243
|
}
|
|
11152
|
-
const common = usesCommon ?
|
|
11153
|
-
const brief =
|
|
11244
|
+
const common = usesCommon ? readFileSync26(commonPath, "utf8") : "";
|
|
11245
|
+
const brief = readFileSync26(briefPath, "utf8");
|
|
11154
11246
|
const effectiveCommon = o.divergedPrompt ? "" : common;
|
|
11155
11247
|
const effectiveBrief = appendAdditions(o.divergedPrompt ?? brief, o.personaAdditions);
|
|
11156
11248
|
const localSkills = new Map(listLocalSkills(o.route.promptsDir).map((s) => [s.name, s.prompt]));
|
|
@@ -11239,6 +11331,7 @@ function planAgentRun(o) {
|
|
|
11239
11331
|
toolchain: toolchain.name,
|
|
11240
11332
|
harness: toolchain.harness,
|
|
11241
11333
|
workspaceAuth: toolchain.auth === "workspace",
|
|
11334
|
+
authMode: authModeOf(toolchain),
|
|
11242
11335
|
provider: toolchainProvider(toolchain),
|
|
11243
11336
|
maxRunMinutes: resolveMaxRunMinutes(o.route.maxRunMinutes, toolchain.maxRunMinutes),
|
|
11244
11337
|
...o.ship.runner === "sandbox" ? {
|
|
@@ -11305,7 +11398,7 @@ function describePlan(p) {
|
|
|
11305
11398
|
var pidPathFor = (streamPath) => `${streamPath}.pid`;
|
|
11306
11399
|
function readRunSidecar(streamPath) {
|
|
11307
11400
|
try {
|
|
11308
|
-
const sc = JSON.parse(
|
|
11401
|
+
const sc = JSON.parse(readFileSync26(pidPathFor(streamPath), "utf8"));
|
|
11309
11402
|
return typeof sc.pid === "number" && typeof sc.spawnedAt === "string" && typeof sc.role === "string" ? sc : null;
|
|
11310
11403
|
} catch {
|
|
11311
11404
|
return null;
|
|
@@ -11620,10 +11713,11 @@ async function finishRun(id, obs, emit, startedAt, end, agentLogKey, hintMoved)
|
|
|
11620
11713
|
...result?.costUsd !== void 0 ? { totalCostUsd: result.costUsd } : {}
|
|
11621
11714
|
}
|
|
11622
11715
|
});
|
|
11716
|
+
const signedOut = !end.interrupted && streamShowsSignedOut(id.streamPath);
|
|
11623
11717
|
if (id.agentLog && agentLogKey) {
|
|
11624
11718
|
const report = {
|
|
11625
11719
|
ticketReference: attributedTicket,
|
|
11626
|
-
outcome: end.interrupted ? "interrupted" : end.code === 0 || end.code === null && obs.sawResult ? "success" : "error",
|
|
11720
|
+
outcome: end.interrupted ? "interrupted" : signedOut ? "error" : end.code === 0 || end.code === null && obs.sawResult ? "success" : "error",
|
|
11627
11721
|
startedAt,
|
|
11628
11722
|
finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11629
11723
|
cycles: obs.cycles,
|
|
@@ -11878,7 +11972,7 @@ function runFinished(streamPath) {
|
|
|
11878
11972
|
const path = `${streamPath}.meta.json`;
|
|
11879
11973
|
if (!existsSync27(path)) return false;
|
|
11880
11974
|
try {
|
|
11881
|
-
return JSON.parse(
|
|
11975
|
+
return JSON.parse(readFileSync27(path, "utf8")).running !== true;
|
|
11882
11976
|
} catch {
|
|
11883
11977
|
return true;
|
|
11884
11978
|
}
|
|
@@ -12611,7 +12705,7 @@ var SandboxCache = class {
|
|
|
12611
12705
|
try {
|
|
12612
12706
|
await this.helper(this.s.helperImage, REFRESH_SCRIPT, [mirrorRelPath(r), forgeDescriptorFor(r.host).httpsUrl(r.host, r.path)], env);
|
|
12613
12707
|
} catch (e) {
|
|
12614
|
-
out.push({ repo: r, ok: false, detail: describe(e) });
|
|
12708
|
+
out.push({ repo: r, ok: false, detail: r.token ? describe(e) : `no readable forge token for ${r.host} (see \`crew forge list\`); ${describe(e)}` });
|
|
12615
12709
|
continue;
|
|
12616
12710
|
}
|
|
12617
12711
|
if (this.s.depsCommand && this.s.depsImage) {
|
|
@@ -12715,6 +12809,10 @@ function cacheSettingsOf(cfg) {
|
|
|
12715
12809
|
};
|
|
12716
12810
|
}
|
|
12717
12811
|
var sandboxCacheKey = (volume, r) => `sandbox_cache:${volume}:${r.host}/${r.path}`;
|
|
12812
|
+
function unmirroredRepos(served, mirrors) {
|
|
12813
|
+
const have = new Set(mirrors.map((m) => `${m.repo.host}/${m.repo.path}`));
|
|
12814
|
+
return served.map((r) => `${r.host}/${r.path}`).filter((k, i, a) => !have.has(k) && a.indexOf(k) === i);
|
|
12815
|
+
}
|
|
12718
12816
|
var CACHE_REFRESH_INTERVAL_MS = 6e4;
|
|
12719
12817
|
function makeCachePass(o) {
|
|
12720
12818
|
const now = o.now ?? Date.now;
|
|
@@ -12737,7 +12835,7 @@ function makeCachePass(o) {
|
|
|
12737
12835
|
for (const out of all) {
|
|
12738
12836
|
const key = sandboxCacheKey(o.volume, out.repo);
|
|
12739
12837
|
if (out.ok) o.ok(key);
|
|
12740
|
-
else await o.fail(key, `sandbox cache: ${out.repo.host}/${out.repo.path} did not refresh (${out.detail}); runs use the previous mirror. Resumes automatically when a later pass refreshes it
|
|
12838
|
+
else await o.fail(key, `sandbox cache: ${out.repo.host}/${out.repo.path} did not refresh (${out.detail}); runs use the previous mirror. Resumes automatically when a later pass refreshes it`, new Date(now()).toISOString());
|
|
12741
12839
|
}
|
|
12742
12840
|
return all;
|
|
12743
12841
|
};
|
|
@@ -12969,7 +13067,7 @@ var SANDBOX_BRIDGE_PATH = `${CREW_PREFIX}/bin/intel-bridge`;
|
|
|
12969
13067
|
function readBridgeBundle() {
|
|
12970
13068
|
const here = dirname15(fileURLToPath(import.meta.url));
|
|
12971
13069
|
for (const p of [join32(here, "sandbox-intel-bridge.cjs"), join32(here, "..", "dist", "sandbox-intel-bridge.cjs")]) {
|
|
12972
|
-
if (existsSync30(p)) return
|
|
13070
|
+
if (existsSync30(p)) return readFileSync28(p, "utf8");
|
|
12973
13071
|
}
|
|
12974
13072
|
return void 0;
|
|
12975
13073
|
}
|
|
@@ -13121,7 +13219,7 @@ var shipSandboxRef = () => ({ name: SHIP_SANDBOX_KEY, decl: { packages: [], setu
|
|
|
13121
13219
|
var sandboxStatePath = (stateDir) => join32(stateDir, "sandbox-images.json");
|
|
13122
13220
|
function readSandboxState(stateDir) {
|
|
13123
13221
|
try {
|
|
13124
|
-
const v = JSON.parse(
|
|
13222
|
+
const v = JSON.parse(readFileSync28(sandboxStatePath(stateDir), "utf8"));
|
|
13125
13223
|
return v && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
13126
13224
|
} catch {
|
|
13127
13225
|
return {};
|
|
@@ -13404,7 +13502,7 @@ function managedGitIdentityWarnings(kind, identity) {
|
|
|
13404
13502
|
|
|
13405
13503
|
// src/selftest.ts
|
|
13406
13504
|
import { spawn as spawn6 } from "child_process";
|
|
13407
|
-
import { existsSync as existsSync31, mkdirSync as mkdirSync20, mkdtempSync as mkdtempSync2, readFileSync as
|
|
13505
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync20, mkdtempSync as mkdtempSync2, readFileSync as readFileSync29, rmSync as rmSync16, writeFileSync as writeFileSync21 } from "fs";
|
|
13408
13506
|
import { tmpdir as tmpdir4 } from "os";
|
|
13409
13507
|
import { join as join33 } from "path";
|
|
13410
13508
|
var SELFTEST_TIMEOUT_MS = 12e4;
|
|
@@ -13538,6 +13636,11 @@ ${seen.texts.join("\n")}`)) {
|
|
|
13538
13636
|
return fail2("mcp-unavailable", "the tracker MCP tool was not available to the session");
|
|
13539
13637
|
}
|
|
13540
13638
|
const answered = seen.texts.length > 0 || seen.finalText;
|
|
13639
|
+
if (SIGNED_OUT_PATTERN.test(`${run3.stderr}
|
|
13640
|
+
${seen.finalText ?? ""}
|
|
13641
|
+
${seen.texts.join("\n")}`)) {
|
|
13642
|
+
return { failure: "login-missing", detail: signedOutMessage(spec.name, authModeOf(spec)) };
|
|
13643
|
+
}
|
|
13541
13644
|
if (!answered || LOGIN.test(run3.stderr) || LOGIN.test(seen.finalText ?? "")) {
|
|
13542
13645
|
return fail2("login-missing", `\`${bin}\` exited${run3.code !== null ? ` (${run3.code})` : ""} before answering; the vendor login is probably missing`);
|
|
13543
13646
|
}
|
|
@@ -13604,7 +13707,7 @@ var fileFor2 = (stateDir) => join33(stateDir, "selftest.json");
|
|
|
13604
13707
|
function readSelftest(stateDir) {
|
|
13605
13708
|
try {
|
|
13606
13709
|
const p = fileFor2(stateDir);
|
|
13607
|
-
return existsSync31(p) ? JSON.parse(
|
|
13710
|
+
return existsSync31(p) ? JSON.parse(readFileSync29(p, "utf8")) : {};
|
|
13608
13711
|
} catch {
|
|
13609
13712
|
return {};
|
|
13610
13713
|
}
|
|
@@ -13823,14 +13926,14 @@ function rosterMarkdown(roster, meId) {
|
|
|
13823
13926
|
}
|
|
13824
13927
|
|
|
13825
13928
|
// src/connect-resume.ts
|
|
13826
|
-
import { mkdirSync as mkdirSync21, readFileSync as
|
|
13929
|
+
import { mkdirSync as mkdirSync21, readFileSync as readFileSync30, rmSync as rmSync17, writeFileSync as writeFileSync22 } from "fs";
|
|
13827
13930
|
import { dirname as dirname16, join as join34 } from "path";
|
|
13828
13931
|
function lastSessionFile(stateDir) {
|
|
13829
13932
|
return join34(stateDir, "connect-session.json");
|
|
13830
13933
|
}
|
|
13831
13934
|
function readPointers(stateDir) {
|
|
13832
13935
|
try {
|
|
13833
|
-
const parsed = JSON.parse(
|
|
13936
|
+
const parsed = JSON.parse(readFileSync30(lastSessionFile(stateDir), "utf8"));
|
|
13834
13937
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
13835
13938
|
const out = {};
|
|
13836
13939
|
for (const [host, v] of Object.entries(parsed)) {
|
|
@@ -13930,7 +14033,7 @@ async function signOutSessions(o) {
|
|
|
13930
14033
|
}
|
|
13931
14034
|
|
|
13932
14035
|
// src/reset.ts
|
|
13933
|
-
import { existsSync as existsSync32, mkdirSync as mkdirSync22, readFileSync as
|
|
14036
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync22, readFileSync as readFileSync31, readdirSync as readdirSync12, rmSync as rmSync18, statSync as statSync10, writeFileSync as writeFileSync23 } from "fs";
|
|
13934
14037
|
import { dirname as dirname17, join as join35 } from "path";
|
|
13935
14038
|
import { hostFromUrl as hostFromUrl3 } from "@tablation/client";
|
|
13936
14039
|
function clonedCheckoutsFile(stateDir) {
|
|
@@ -13938,7 +14041,7 @@ function clonedCheckoutsFile(stateDir) {
|
|
|
13938
14041
|
}
|
|
13939
14042
|
function readClonedCheckouts(stateDir) {
|
|
13940
14043
|
try {
|
|
13941
|
-
const parsed = JSON.parse(
|
|
14044
|
+
const parsed = JSON.parse(readFileSync31(clonedCheckoutsFile(stateDir), "utf8"));
|
|
13942
14045
|
return Array.isArray(parsed) ? parsed.filter((d) => typeof d === "string") : [];
|
|
13943
14046
|
} catch {
|
|
13944
14047
|
return [];
|
|
@@ -14129,7 +14232,7 @@ async function runDeprovision(o, fx, deps) {
|
|
|
14129
14232
|
}
|
|
14130
14233
|
|
|
14131
14234
|
// src/pool-member.ts
|
|
14132
|
-
import { mkdirSync as mkdirSync23, readFileSync as
|
|
14235
|
+
import { mkdirSync as mkdirSync23, readFileSync as readFileSync32, renameSync as renameSync4, writeFileSync as writeFileSync24 } from "fs";
|
|
14133
14236
|
import { homedir as homedir8 } from "os";
|
|
14134
14237
|
import { dirname as dirname18, join as join36 } from "path";
|
|
14135
14238
|
var POOL_EXIT = { ok: 0, failed: 1, credential: 2 };
|
|
@@ -14369,7 +14472,7 @@ function fileMemberStore(dir) {
|
|
|
14369
14472
|
return {
|
|
14370
14473
|
read() {
|
|
14371
14474
|
try {
|
|
14372
|
-
return JSON.parse(
|
|
14475
|
+
return JSON.parse(readFileSync32(file, "utf8"));
|
|
14373
14476
|
} catch {
|
|
14374
14477
|
return {};
|
|
14375
14478
|
}
|
|
@@ -14435,7 +14538,7 @@ import { hostname as hostname3 } from "os";
|
|
|
14435
14538
|
// src/machine-id.ts
|
|
14436
14539
|
import { execFileSync as execFileSync10 } from "child_process";
|
|
14437
14540
|
import { createHash as createHash8 } from "crypto";
|
|
14438
|
-
import { existsSync as existsSync33, mkdirSync as mkdirSync24, readFileSync as
|
|
14541
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync24, readFileSync as readFileSync33, writeFileSync as writeFileSync25 } from "fs";
|
|
14439
14542
|
import { dirname as dirname19, join as join37 } from "path";
|
|
14440
14543
|
function machineIdPathFor(stateDir) {
|
|
14441
14544
|
return join37(stateDir, "machine-id");
|
|
@@ -14452,7 +14555,7 @@ function readRawMachineId(platform2 = process.platform) {
|
|
|
14452
14555
|
}
|
|
14453
14556
|
for (const p of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
14454
14557
|
if (existsSync33(p)) {
|
|
14455
|
-
const id =
|
|
14558
|
+
const id = readFileSync33(p, "utf8").trim();
|
|
14456
14559
|
if (id) return id;
|
|
14457
14560
|
}
|
|
14458
14561
|
}
|
|
@@ -14464,7 +14567,7 @@ function ensureMachineId(stateDir, opts = {}) {
|
|
|
14464
14567
|
if (opts.override?.trim()) return sha256(opts.override.trim());
|
|
14465
14568
|
const path = machineIdPathFor(stateDir);
|
|
14466
14569
|
if (existsSync33(path)) {
|
|
14467
|
-
const cached =
|
|
14570
|
+
const cached = readFileSync33(path, "utf8").trim();
|
|
14468
14571
|
if (/^[0-9a-f]{64}$/.test(cached)) return cached;
|
|
14469
14572
|
}
|
|
14470
14573
|
const raw = (opts.read ?? readRawMachineId)();
|
|
@@ -14484,7 +14587,7 @@ function matchShipRows(ships, shipName2, machineId) {
|
|
|
14484
14587
|
|
|
14485
14588
|
// src/provision.ts
|
|
14486
14589
|
import { spawnSync as spawnSync9 } from "child_process";
|
|
14487
|
-
import { existsSync as existsSync34, readFileSync as
|
|
14590
|
+
import { existsSync as existsSync34, readFileSync as readFileSync34, writeFileSync as writeFileSync26 } from "fs";
|
|
14488
14591
|
import { hostname as hostname2 } from "os";
|
|
14489
14592
|
import { parseDocument as parseDocument3, isMap as isMap2, isScalar } from "yaml";
|
|
14490
14593
|
|
|
@@ -15105,7 +15208,7 @@ function realProvisionDeps(crewHome) {
|
|
|
15105
15208
|
enableRoute(route2) {
|
|
15106
15209
|
const file = configFile();
|
|
15107
15210
|
if (!file) return false;
|
|
15108
|
-
const text2 =
|
|
15211
|
+
const text2 = readFileSync34(file, "utf8");
|
|
15109
15212
|
const doc = parseDocument3(text2);
|
|
15110
15213
|
const routes = doc.get("routes");
|
|
15111
15214
|
const entry = routes?.items?.find((r) => r.get("route") === route2);
|
|
@@ -15131,7 +15234,7 @@ function realProvisionDeps(crewHome) {
|
|
|
15131
15234
|
continue;
|
|
15132
15235
|
}
|
|
15133
15236
|
for (const p of plan.unitPaths) {
|
|
15134
|
-
if (!existsSync34(p) ||
|
|
15237
|
+
if (!existsSync34(p) || readFileSync34(p, "utf8") !== plan.unitContent[p]) unitsStale = true;
|
|
15135
15238
|
}
|
|
15136
15239
|
}
|
|
15137
15240
|
const label = labelFor(crewHome, "run");
|
|
@@ -15155,7 +15258,7 @@ function realProvisionDeps(crewHome) {
|
|
|
15155
15258
|
setShipSetting(key, value2) {
|
|
15156
15259
|
const file = configFile();
|
|
15157
15260
|
if (!file) return false;
|
|
15158
|
-
const doc = parseDocument3(
|
|
15261
|
+
const doc = parseDocument3(readFileSync34(file, "utf8"));
|
|
15159
15262
|
if (doc.getIn(["ship", key]) === value2) return false;
|
|
15160
15263
|
doc.setIn(["ship", key], value2);
|
|
15161
15264
|
writeFileSync26(file, doc.toString());
|
|
@@ -15164,7 +15267,7 @@ function realProvisionDeps(crewHome) {
|
|
|
15164
15267
|
applyManagedDefaults() {
|
|
15165
15268
|
const file = configFile();
|
|
15166
15269
|
if (!file) return [];
|
|
15167
|
-
const doc = parseDocument3(
|
|
15270
|
+
const doc = parseDocument3(readFileSync34(file, "utf8"));
|
|
15168
15271
|
const wrote = applyManagedDefaultsToDoc(doc);
|
|
15169
15272
|
if (wrote.length) writeFileSync26(file, doc.toString());
|
|
15170
15273
|
return wrote;
|
|
@@ -15194,7 +15297,7 @@ host=${host}
|
|
|
15194
15297
|
|
|
15195
15298
|
// src/tunnel.ts
|
|
15196
15299
|
import { spawn as spawn7 } from "child_process";
|
|
15197
|
-
import { existsSync as existsSync35, mkdirSync as mkdirSync25, readFileSync as
|
|
15300
|
+
import { existsSync as existsSync35, mkdirSync as mkdirSync25, readFileSync as readFileSync35, writeFileSync as writeFileSync27, unlinkSync as unlinkSync3, readdirSync as readdirSync13 } from "fs";
|
|
15198
15301
|
import { randomInt } from "crypto";
|
|
15199
15302
|
import { join as join39 } from "path";
|
|
15200
15303
|
var DEFAULT_SPAWN_OPTIONS = { stdio: "ignore", detached: true };
|
|
@@ -15280,7 +15383,7 @@ function readPersistedTunnel(stateDir, workspaceId) {
|
|
|
15280
15383
|
const path = tunnelStatePath(stateDir, workspaceId);
|
|
15281
15384
|
if (!existsSync35(path)) return void 0;
|
|
15282
15385
|
try {
|
|
15283
|
-
return JSON.parse(
|
|
15386
|
+
return JSON.parse(readFileSync35(path, "utf8"));
|
|
15284
15387
|
} catch {
|
|
15285
15388
|
return void 0;
|
|
15286
15389
|
}
|
|
@@ -16825,7 +16928,7 @@ async function resolveOne(tracker, t, seat, approvedStatus, buildingStatus, affi
|
|
|
16825
16928
|
}
|
|
16826
16929
|
|
|
16827
16930
|
// src/repo-refresh.ts
|
|
16828
|
-
import { existsSync as existsSync37, mkdirSync as mkdirSync26, readFileSync as
|
|
16931
|
+
import { existsSync as existsSync37, mkdirSync as mkdirSync26, readFileSync as readFileSync36, writeFileSync as writeFileSync29 } from "fs";
|
|
16829
16932
|
import { dirname as dirname21 } from "path";
|
|
16830
16933
|
var REFRESH_COOLDOWN_MS = 2 * 6e4;
|
|
16831
16934
|
var UNSERVABLE_PASSES_BEFORE_ATTENTION = 3;
|
|
@@ -16856,7 +16959,7 @@ function applyRepoRows(resolved, rows) {
|
|
|
16856
16959
|
function persistRepoRows(stateDir, routeName, rows) {
|
|
16857
16960
|
const path = resolvedPathFor(stateDir, routeName);
|
|
16858
16961
|
if (!existsSync37(path)) return;
|
|
16859
|
-
const raw = JSON.parse(
|
|
16962
|
+
const raw = JSON.parse(readFileSync36(path, "utf8"));
|
|
16860
16963
|
applyRepoRows(raw, rows);
|
|
16861
16964
|
mkdirSync26(dirname21(path), { recursive: true });
|
|
16862
16965
|
writeFileSync29(path, `${JSON.stringify(raw, null, 2)}
|
|
@@ -17509,7 +17612,7 @@ function flagWizardAnswers(f, env) {
|
|
|
17509
17612
|
}
|
|
17510
17613
|
|
|
17511
17614
|
// src/release-run.ts
|
|
17512
|
-
import { readFileSync as
|
|
17615
|
+
import { readFileSync as readFileSync37, writeFileSync as writeFileSync31, existsSync as existsSync39, copyFileSync, mkdirSync as mkdirSync28, mkdtempSync as mkdtempSync3, rmSync as rmSync19 } from "fs";
|
|
17513
17616
|
import { dirname as dirname24, join as join43 } from "path";
|
|
17514
17617
|
import { tmpdir as tmpdir5, hostname as hostname4 } from "os";
|
|
17515
17618
|
|
|
@@ -18286,7 +18389,7 @@ async function bump(o, size) {
|
|
|
18286
18389
|
o.emit.error(`no ${o.repo.release.versionFiles[0]} to read a version from`);
|
|
18287
18390
|
return null;
|
|
18288
18391
|
}
|
|
18289
|
-
const firstText =
|
|
18392
|
+
const firstText = readFileSync37(first, "utf8");
|
|
18290
18393
|
const problem = versionFileProblem(o.repo.release.versionFiles[0], firstText);
|
|
18291
18394
|
if (problem) {
|
|
18292
18395
|
o.emit.error(problem);
|
|
@@ -18305,7 +18408,7 @@ async function bump(o, size) {
|
|
|
18305
18408
|
return version;
|
|
18306
18409
|
}
|
|
18307
18410
|
for (const f of files) {
|
|
18308
|
-
const src =
|
|
18411
|
+
const src = readFileSync37(f, "utf8");
|
|
18309
18412
|
const out = src.replace(/("version"\s*:\s*")[^"]*(")/, `$1${version}$2`);
|
|
18310
18413
|
if (out === src) {
|
|
18311
18414
|
o.emit.error(`no version field in ${f}`);
|
|
@@ -18324,7 +18427,7 @@ function writeChangelog(o, version, entries) {
|
|
|
18324
18427
|
o.emit.emit(`would prepend ${entries.length} entr(ies) to ${file}`);
|
|
18325
18428
|
return;
|
|
18326
18429
|
}
|
|
18327
|
-
const existing = existsSync39(path) ?
|
|
18430
|
+
const existing = existsSync39(path) ? readFileSync37(path, "utf8") : "# Changelog\n";
|
|
18328
18431
|
writeFileSync31(path, insertChangelogSection(existing, section));
|
|
18329
18432
|
}
|
|
18330
18433
|
async function confirm(o, expected) {
|
|
@@ -19238,6 +19341,7 @@ function runForge(a, io) {
|
|
|
19238
19341
|
const tok = sourceFromArgs(a);
|
|
19239
19342
|
if (typeof tok === "string") return fail2(tok);
|
|
19240
19343
|
const doc = parseDocument4(io.readFile(io.configFile));
|
|
19344
|
+
doc.setIn(["ship", "forges", host, "username"], forgeDescriptorFor(host).credentialUsername);
|
|
19241
19345
|
doc.setIn(["ship", "forges", host, "token"], tok);
|
|
19242
19346
|
io.writeFile(io.configFile, doc.toString());
|
|
19243
19347
|
io.forges = { ...io.forges ?? {}, [host]: { username: forgeDescriptorFor(host).credentialUsername, token: tok } };
|
|
@@ -19841,7 +19945,7 @@ function nextRoles(decision, ran) {
|
|
|
19841
19945
|
}
|
|
19842
19946
|
|
|
19843
19947
|
// src/ship-name.ts
|
|
19844
|
-
import { existsSync as existsSync42, mkdirSync as mkdirSync30, readFileSync as
|
|
19948
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync30, readFileSync as readFileSync38, renameSync as renameSync5, writeFileSync as writeFileSync32 } from "fs";
|
|
19845
19949
|
import { dirname as dirname26 } from "path";
|
|
19846
19950
|
import { parseDocument as parseDocument5 } from "yaml";
|
|
19847
19951
|
var ShipNameError = class extends Error {
|
|
@@ -19905,7 +20009,7 @@ async function syncRouteName(i) {
|
|
|
19905
20009
|
function readSyncedName(resolvedFile) {
|
|
19906
20010
|
if (!existsSync42(resolvedFile)) return void 0;
|
|
19907
20011
|
try {
|
|
19908
|
-
const v = JSON.parse(
|
|
20012
|
+
const v = JSON.parse(readFileSync38(resolvedFile, "utf8")).shipName;
|
|
19909
20013
|
return typeof v === "string" ? v : void 0;
|
|
19910
20014
|
} catch {
|
|
19911
20015
|
return void 0;
|
|
@@ -19915,7 +20019,7 @@ function writeSyncedName(resolvedFile, name) {
|
|
|
19915
20019
|
if (!existsSync42(resolvedFile)) return;
|
|
19916
20020
|
let raw;
|
|
19917
20021
|
try {
|
|
19918
|
-
raw = JSON.parse(
|
|
20022
|
+
raw = JSON.parse(readFileSync38(resolvedFile, "utf8"));
|
|
19919
20023
|
} catch {
|
|
19920
20024
|
return;
|
|
19921
20025
|
}
|
|
@@ -19930,7 +20034,7 @@ function writeSyncedName(resolvedFile, name) {
|
|
|
19930
20034
|
async function reconcileShipName(i) {
|
|
19931
20035
|
let local = i.ship.name;
|
|
19932
20036
|
try {
|
|
19933
|
-
local = shipNameOfYaml(
|
|
20037
|
+
local = shipNameOfYaml(readFileSync38(i.configFile, "utf8")) ?? local;
|
|
19934
20038
|
} catch {
|
|
19935
20039
|
}
|
|
19936
20040
|
const resolvedFile = resolvedPathFor(i.stateDir, i.route);
|
|
@@ -19954,7 +20058,7 @@ async function reconcileShipName(i) {
|
|
|
19954
20058
|
}
|
|
19955
20059
|
if (result.status !== "ok") return result;
|
|
19956
20060
|
if (result.action === "adopt" || result.action === "row-wins") {
|
|
19957
|
-
const text2 =
|
|
20061
|
+
const text2 = readFileSync38(i.configFile, "utf8");
|
|
19958
20062
|
writeFileSync32(i.configFile, setShipNameInYaml(text2, result.name));
|
|
19959
20063
|
i.ship.name = result.name;
|
|
19960
20064
|
if (result.action === "row-wins") {
|
|
@@ -20614,7 +20718,7 @@ function describeCapability(i) {
|
|
|
20614
20718
|
}
|
|
20615
20719
|
|
|
20616
20720
|
// src/agents-sync-run.ts
|
|
20617
|
-
import { existsSync as existsSync43, mkdirSync as mkdirSync31, readFileSync as
|
|
20721
|
+
import { existsSync as existsSync43, mkdirSync as mkdirSync31, readFileSync as readFileSync39, writeFileSync as writeFileSync33 } from "fs";
|
|
20618
20722
|
import { dirname as dirname27 } from "path";
|
|
20619
20723
|
async function runAgentsSync(target, o) {
|
|
20620
20724
|
const dryRun = o.dryRun ?? false;
|
|
@@ -20648,7 +20752,7 @@ async function runAgentsSync(target, o) {
|
|
|
20648
20752
|
for (const s of skillResult?.outcomes ?? []) o.say(describeSkillSyncOutcome(s));
|
|
20649
20753
|
if (!dryRun) {
|
|
20650
20754
|
const resolvedPath = resolvedPathFor(o.stateDir, target.route);
|
|
20651
|
-
const raw = existsSync43(resolvedPath) ? JSON.parse(
|
|
20755
|
+
const raw = existsSync43(resolvedPath) ? JSON.parse(readFileSync39(resolvedPath, "utf8")) : {};
|
|
20652
20756
|
raw.agentPersonas = personaResult.agentPersonas;
|
|
20653
20757
|
if (skillResult) raw.agentSkills = skillResult.agentSkills;
|
|
20654
20758
|
if (personaResult.releaseAgentId) raw.releaseAgentId = personaResult.releaseAgentId;
|
|
@@ -20770,7 +20874,7 @@ async function showLogEntry(route2, entryId, opts = {}) {
|
|
|
20770
20874
|
|
|
20771
20875
|
// src/repos-check.ts
|
|
20772
20876
|
import { spawnSync as spawnSync11 } from "child_process";
|
|
20773
|
-
import { readFileSync as
|
|
20877
|
+
import { readFileSync as readFileSync40 } from "fs";
|
|
20774
20878
|
import { basename as basename11 } from "path";
|
|
20775
20879
|
var POSIX_SHELL = /^(?:ba|z|da|k|a|mk)?sh$|^fish$/;
|
|
20776
20880
|
function checkHookSyntax(script, shell) {
|
|
@@ -20811,7 +20915,7 @@ function checkRepoSpec(dir, opts = {}) {
|
|
|
20811
20915
|
}
|
|
20812
20916
|
let parsed;
|
|
20813
20917
|
try {
|
|
20814
|
-
parsed = parseRepoConfig(
|
|
20918
|
+
parsed = parseRepoConfig(readFileSync40(file, "utf8"), file);
|
|
20815
20919
|
} catch (e) {
|
|
20816
20920
|
if (!(e instanceof RepoConfigError)) throw e;
|
|
20817
20921
|
return { ...empty, file, error: e.message, exitCode: 1 };
|
|
@@ -21343,7 +21447,7 @@ function planSampleTicket(i) {
|
|
|
21343
21447
|
}
|
|
21344
21448
|
|
|
21345
21449
|
// src/worktree-sweep.ts
|
|
21346
|
-
import { existsSync as existsSync44, readFileSync as
|
|
21450
|
+
import { existsSync as existsSync44, readFileSync as readFileSync41, readdirSync as readdirSync14 } from "fs";
|
|
21347
21451
|
import { basename as basename13, dirname as dirname29, join as join45, resolve as resolve5 } from "path";
|
|
21348
21452
|
function planWorktreeSweep(target, tickets, contract) {
|
|
21349
21453
|
const terminal = new Set(contract.statuses.resolved.filter((s) => s !== contract.statuses.verified));
|
|
@@ -21524,7 +21628,7 @@ function isHandBackMerge(path, base) {
|
|
|
21524
21628
|
if (!msgPath) return false;
|
|
21525
21629
|
let first;
|
|
21526
21630
|
try {
|
|
21527
|
-
first =
|
|
21631
|
+
first = readFileSync41(resolve5(path, msgPath), "utf8").split("\n")[0] ?? "";
|
|
21528
21632
|
} catch {
|
|
21529
21633
|
return false;
|
|
21530
21634
|
}
|
|
@@ -21674,11 +21778,11 @@ function planEventsSweep(stateDir, retentionDays, now = Date.now()) {
|
|
|
21674
21778
|
}
|
|
21675
21779
|
|
|
21676
21780
|
// src/cli.ts
|
|
21677
|
-
import { realpathSync as realpathSync3, readFileSync as
|
|
21781
|
+
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";
|
|
21678
21782
|
import { createInterface } from "readline/promises";
|
|
21679
21783
|
|
|
21680
21784
|
// src/periscope-cmd.ts
|
|
21681
|
-
import { existsSync as existsSync46, mkdirSync as mkdirSync32, readFileSync as
|
|
21785
|
+
import { existsSync as existsSync46, mkdirSync as mkdirSync32, readFileSync as readFileSync42, rmSync as rmSync21, writeFileSync as writeFileSync34 } from "fs";
|
|
21682
21786
|
import { join as join47 } from "path";
|
|
21683
21787
|
var PeriscopeError = class extends Error {
|
|
21684
21788
|
};
|
|
@@ -21704,7 +21808,7 @@ function writePeriscopePrior(stateDir, ticketRecordId, prior) {
|
|
|
21704
21808
|
function readPeriscopePrior(stateDir, ticketRecordId) {
|
|
21705
21809
|
try {
|
|
21706
21810
|
const p = priorPath(stateDir, ticketRecordId);
|
|
21707
|
-
return existsSync46(p) ? JSON.parse(
|
|
21811
|
+
return existsSync46(p) ? JSON.parse(readFileSync42(p, "utf8")) : void 0;
|
|
21708
21812
|
} catch {
|
|
21709
21813
|
return void 0;
|
|
21710
21814
|
}
|
|
@@ -22259,7 +22363,7 @@ import { dirname as dirOf2, resolve as resolvePath } from "path";
|
|
|
22259
22363
|
|
|
22260
22364
|
// src/ssh-keys.ts
|
|
22261
22365
|
import { execFileSync as execFileSync13 } from "child_process";
|
|
22262
|
-
import { existsSync as existsSync47, mkdirSync as mkdirSync33, readFileSync as
|
|
22366
|
+
import { existsSync as existsSync47, mkdirSync as mkdirSync33, readFileSync as readFileSync43, chmodSync as chmodSync3 } from "fs";
|
|
22263
22367
|
import { dirname as dirname30, join as join49 } from "path";
|
|
22264
22368
|
var SshKeyError = class extends Error {
|
|
22265
22369
|
};
|
|
@@ -22293,7 +22397,7 @@ function ensureShipSshKeypair(stateDir) {
|
|
|
22293
22397
|
if (!existsSync47(publicKeyPath)) {
|
|
22294
22398
|
throw new SshKeyError(`${privateKeyPath} exists but ${publicKeyPath} does not \u2014 regenerate or restore it`);
|
|
22295
22399
|
}
|
|
22296
|
-
const publicKey =
|
|
22400
|
+
const publicKey = readFileSync43(publicKeyPath, "utf8").trim();
|
|
22297
22401
|
return { privateKeyPath, publicKeyPath, publicKey };
|
|
22298
22402
|
}
|
|
22299
22403
|
function sshKeygenAvailable() {
|
|
@@ -22457,7 +22561,7 @@ async function unregisterEndpoint(workspaceId, info, d) {
|
|
|
22457
22561
|
import { createServer as createHttpServer } from "http";
|
|
22458
22562
|
import { spawn as spawn9 } from "child_process";
|
|
22459
22563
|
import { randomBytes } from "crypto";
|
|
22460
|
-
import { existsSync as existsSync48, mkdirSync as mkdirSync34, readFileSync as
|
|
22564
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync34, readFileSync as readFileSync44, writeFileSync as writeFileSync35, unlinkSync as unlinkSync4, readdirSync as readdirSync16 } from "fs";
|
|
22461
22565
|
import { join as join50 } from "path";
|
|
22462
22566
|
|
|
22463
22567
|
// src/secret-compare.ts
|
|
@@ -22557,7 +22661,7 @@ function readPersistedSyncDaemon(stateDir, workspaceId) {
|
|
|
22557
22661
|
const path = syncDaemonStatePath(stateDir, workspaceId);
|
|
22558
22662
|
if (!existsSync48(path)) return void 0;
|
|
22559
22663
|
try {
|
|
22560
|
-
return JSON.parse(
|
|
22664
|
+
return JSON.parse(readFileSync44(path, "utf8"));
|
|
22561
22665
|
} catch {
|
|
22562
22666
|
return void 0;
|
|
22563
22667
|
}
|
|
@@ -23106,7 +23210,7 @@ function contractFixers(dir, baseRef, tickets, locate) {
|
|
|
23106
23210
|
}
|
|
23107
23211
|
|
|
23108
23212
|
// src/daemon.ts
|
|
23109
|
-
import { existsSync as existsSync49, mkdirSync as mkdirSync36, readFileSync as
|
|
23213
|
+
import { existsSync as existsSync49, mkdirSync as mkdirSync36, readFileSync as readFileSync45, readdirSync as readdirSync17, rmSync as rmSync22, statSync as statSync14, writeFileSync as writeFileSync36 } from "fs";
|
|
23110
23214
|
import { join as join52 } from "path";
|
|
23111
23215
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
23112
23216
|
var DEFAULT_FLOOR_MS = 5e3;
|
|
@@ -23227,7 +23331,7 @@ function noteDaemonStarted(stateDir, now = Date.now()) {
|
|
|
23227
23331
|
}
|
|
23228
23332
|
function readDaemonStarted(stateDir) {
|
|
23229
23333
|
try {
|
|
23230
|
-
const v = JSON.parse(
|
|
23334
|
+
const v = JSON.parse(readFileSync45(daemonStampFor(stateDir), "utf8")).startedAt;
|
|
23231
23335
|
return typeof v === "number" ? v : null;
|
|
23232
23336
|
} catch {
|
|
23233
23337
|
return null;
|
|
@@ -23410,6 +23514,12 @@ async function runOnePassUnguarded(o) {
|
|
|
23410
23514
|
clearShipAttention(o.state, workspaceAllowanceKey(role));
|
|
23411
23515
|
}).catch(async (e) => {
|
|
23412
23516
|
const message = e.message;
|
|
23517
|
+
if (e instanceof SignedOutError) {
|
|
23518
|
+
breaker.pause(role, SIGNED_OUT_PAUSE_MS);
|
|
23519
|
+
emit.warn(`${role} paused: ${message}`, { step: "agent", role });
|
|
23520
|
+
await raiseShipAttention({ state: o.state, emit, route: o.route, ship: o.ship }, signedOutItem(e.toolchain, e.mode));
|
|
23521
|
+
return;
|
|
23522
|
+
}
|
|
23413
23523
|
if (e instanceof WorkspaceAllowanceExhausted) {
|
|
23414
23524
|
breaker.pause(role, ALLOWANCE_PAUSE_MS);
|
|
23415
23525
|
emit.warn(`${role} paused: ${message}`, { step: "agent", role });
|
|
@@ -23751,6 +23861,7 @@ async function runRoleAgentLocked(role, decision, ctx, hooks, held) {
|
|
|
23751
23861
|
if (plan.workspaceAuth && streamShowsAllowanceRefusal(plan.streamPath)) {
|
|
23752
23862
|
throw new WorkspaceAllowanceExhausted("the inference endpoint refused the run: the workspace is past its AI allowance");
|
|
23753
23863
|
}
|
|
23864
|
+
await settleSignOut(plan, tracker, ctx.state, workingId, emit);
|
|
23754
23865
|
}
|
|
23755
23866
|
} finally {
|
|
23756
23867
|
await settleRunEnd({
|
|
@@ -23787,6 +23898,26 @@ async function buildEnvironment(route2, ship, ticket) {
|
|
|
23787
23898
|
const attachments = await tracker.attachmentsProbe().catch(() => null);
|
|
23788
23899
|
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) });
|
|
23789
23900
|
}
|
|
23901
|
+
async function settleSignOut(plan, tracker, state, ticketId, emit) {
|
|
23902
|
+
const toolchain = plan.toolchain;
|
|
23903
|
+
if (!toolchain) return;
|
|
23904
|
+
if (!streamShowsSignedOut(plan.streamPath)) {
|
|
23905
|
+
if (streamShowsRealTurn(plan.streamPath)) clearShipAttention(state, signedOutKey(toolchain));
|
|
23906
|
+
return;
|
|
23907
|
+
}
|
|
23908
|
+
if (ticketId) {
|
|
23909
|
+
try {
|
|
23910
|
+
const affinity = await tracker.claimAffinity();
|
|
23911
|
+
const current = await tracker.ticket(ticketId);
|
|
23912
|
+
if (affinity && current[affinity.column] === affinity.shipId) {
|
|
23913
|
+
await tracker.updateTicket(ticketId, { [affinity.column]: null }, current.updated_at);
|
|
23914
|
+
}
|
|
23915
|
+
} catch (e) {
|
|
23916
|
+
emit.warn(`could not release the ticket hold after a sign-out: ${e.message}`, { step: "agent" });
|
|
23917
|
+
}
|
|
23918
|
+
}
|
|
23919
|
+
throw new SignedOutError(toolchain, plan.authMode ?? "login");
|
|
23920
|
+
}
|
|
23790
23921
|
|
|
23791
23922
|
// src/control-api.ts
|
|
23792
23923
|
import { createHash as createHash11 } from "crypto";
|
|
@@ -24477,7 +24608,7 @@ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/
|
|
|
24477
24608
|
|
|
24478
24609
|
// src/periscope-endpoints.ts
|
|
24479
24610
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
24480
|
-
import { chmodSync as chmodSync5, existsSync as existsSync51, mkdirSync as mkdirSync37, readdirSync as readdirSync19, readFileSync as
|
|
24611
|
+
import { chmodSync as chmodSync5, existsSync as existsSync51, mkdirSync as mkdirSync37, readdirSync as readdirSync19, readFileSync as readFileSync46, rmSync as rmSync24, writeFileSync as writeFileSync37 } from "fs";
|
|
24481
24612
|
import { join as join54 } from "path";
|
|
24482
24613
|
var secretDir = (stateDir) => join54(stateDir, "periscope-mcp");
|
|
24483
24614
|
var secretFile = (stateDir, id) => join54(secretDir(stateDir), `${id}.json`);
|
|
@@ -24494,7 +24625,7 @@ function mintPeriscopeSecret(stateDir, ticketRecordId) {
|
|
|
24494
24625
|
}
|
|
24495
24626
|
function readPeriscopeSecret(stateDir, ticketRecordId) {
|
|
24496
24627
|
try {
|
|
24497
|
-
const v = JSON.parse(
|
|
24628
|
+
const v = JSON.parse(readFileSync46(secretFile(stateDir, ticketRecordId), "utf8"));
|
|
24498
24629
|
return typeof v.secret === "string" && v.secret ? v.secret : void 0;
|
|
24499
24630
|
} catch {
|
|
24500
24631
|
return void 0;
|
|
@@ -24505,7 +24636,7 @@ function removePeriscopeSecret(stateDir, ticketRecordId) {
|
|
|
24505
24636
|
}
|
|
24506
24637
|
function readPeriscopeEndpoint(stateDir, ticketRecordId) {
|
|
24507
24638
|
try {
|
|
24508
|
-
return JSON.parse(
|
|
24639
|
+
return JSON.parse(readFileSync46(endpointFile(stateDir, ticketRecordId), "utf8"));
|
|
24509
24640
|
} catch {
|
|
24510
24641
|
return void 0;
|
|
24511
24642
|
}
|
|
@@ -25254,7 +25385,7 @@ if (command === "provision") {
|
|
|
25254
25385
|
process.exit(outcome.code);
|
|
25255
25386
|
}
|
|
25256
25387
|
if (command === "pool-member") {
|
|
25257
|
-
const pool = poolConfigFrom(argv, process.env, () =>
|
|
25388
|
+
const pool = poolConfigFrom(argv, process.env, () => readFileSync47(0, "utf8"));
|
|
25258
25389
|
if (typeof pool === "string") {
|
|
25259
25390
|
process.stderr.write(`crew pool-member: ${pool}
|
|
25260
25391
|
`);
|
|
@@ -25415,7 +25546,7 @@ if (command === "passenger-sync-daemon") {
|
|
|
25415
25546
|
if (intelFlavor(loadRepoConfig(t.dir)?.hooks.intel) === "serena") intelImage = sandboxImageFor(images ??= readSandboxState(ship.stateDir), t.name);
|
|
25416
25547
|
} catch {
|
|
25417
25548
|
}
|
|
25418
|
-
out.push({ ...repo, dir: t.dir, token, username: forgeFor(ship.forges, repo.host)?.entry.username, intelImage });
|
|
25549
|
+
out.push({ ...repo, dir: t.dir, token, username: forgeFor(ship.forges, repo.host)?.entry.username || forgeDescriptorFor(repo.host).credentialUsername, intelImage });
|
|
25419
25550
|
}
|
|
25420
25551
|
return out;
|
|
25421
25552
|
}, buildSandboxCachePass = function(c, ship, state2, emit2) {
|
|
@@ -25426,7 +25557,7 @@ if (command === "passenger-sync-daemon") {
|
|
|
25426
25557
|
volume: settings.volume,
|
|
25427
25558
|
repos: () => sandboxCacheRepos(c, ship),
|
|
25428
25559
|
lock: (dir) => acquireCheckoutLock(dir),
|
|
25429
|
-
fail: (key, message) => raiseShipAttention({ state: state2, emit: emit2, route: c, ship }, { kind: "sandbox_cache", key, message, since:
|
|
25560
|
+
fail: (key, message, failedAt) => raiseShipAttention({ state: state2, emit: emit2, route: c, ship }, { kind: "sandbox_cache", key, message, since: failedAt, lastFailedAt: failedAt }).then(() => void 0),
|
|
25430
25561
|
ok: (key) => clearShipAttention(state2, key)
|
|
25431
25562
|
});
|
|
25432
25563
|
return async () => {
|
|
@@ -25518,7 +25649,7 @@ if (command === "passenger-sync-daemon") {
|
|
|
25518
25649
|
throw e;
|
|
25519
25650
|
}
|
|
25520
25651
|
if (command === "credential") {
|
|
25521
|
-
const r = runCredential(positional[1],
|
|
25652
|
+
const r = runCredential(positional[1], readFileSync47(0, "utf8"), cfg.ship.forges, cfg.ship.stateDir);
|
|
25522
25653
|
process.stdout.write(r.out);
|
|
25523
25654
|
process.stderr.write(r.err);
|
|
25524
25655
|
process.exit(r.code);
|
|
@@ -25530,9 +25661,9 @@ if (command === "passenger-sync-daemon") {
|
|
|
25530
25661
|
forges: cfg.ship.forges,
|
|
25531
25662
|
stateDir: cfg.ship.stateDir,
|
|
25532
25663
|
configFile: cfg.configFile,
|
|
25533
|
-
readFile: (p) =>
|
|
25664
|
+
readFile: (p) => readFileSync47(p, "utf8"),
|
|
25534
25665
|
writeFile: (p, t) => writeFileSync38(p, t),
|
|
25535
|
-
stdin: () =>
|
|
25666
|
+
stdin: () => readFileSync47(0, "utf8"),
|
|
25536
25667
|
env: process.env
|
|
25537
25668
|
}
|
|
25538
25669
|
);
|
|
@@ -25929,7 +26060,7 @@ if (command === "passenger-sync-daemon") {
|
|
|
25929
26060
|
for (const a of plan.actions) {
|
|
25930
26061
|
if (a.kind === "enable") {
|
|
25931
26062
|
if (prompter && !await prompter.confirm(`Route ${a.route} passes every check \u2014 set enabled: true in ${cfg.configFile}?`, false)) continue;
|
|
25932
|
-
writeFileSync38(cfg.configFile, planEnable(
|
|
26063
|
+
writeFileSync38(cfg.configFile, planEnable(readFileSync47(cfg.configFile, "utf8"), a.route));
|
|
25933
26064
|
enabledSound.add(a.route);
|
|
25934
26065
|
changed2.push(`enabled route ${a.route} in ${cfg.configFile}`);
|
|
25935
26066
|
} else {
|
|
@@ -27430,7 +27561,7 @@ ${cu.tail.trimEnd()}
|
|
|
27430
27561
|
`);
|
|
27431
27562
|
if (!dryRun) {
|
|
27432
27563
|
const resolvedPath = resolvedPathFor(cfg.ship.stateDir, target.route);
|
|
27433
|
-
const raw = existsSync52(resolvedPath) ? JSON.parse(
|
|
27564
|
+
const raw = existsSync52(resolvedPath) ? JSON.parse(readFileSync47(resolvedPath, "utf8")) : {};
|
|
27434
27565
|
raw.agentSkills = result.agentSkills;
|
|
27435
27566
|
mkdirSync38(dirOf2(resolvedPath), { recursive: true });
|
|
27436
27567
|
writeFileSync38(resolvedPath, `${JSON.stringify(raw, null, 2)}
|
|
@@ -27456,7 +27587,7 @@ ${cu.tail.trimEnd()}
|
|
|
27456
27587
|
throw e;
|
|
27457
27588
|
}
|
|
27458
27589
|
const oldName = cfg.ship.name;
|
|
27459
|
-
writeFileSync38(cfg.configFile, setShipNameInYaml(
|
|
27590
|
+
writeFileSync38(cfg.configFile, setShipNameInYaml(readFileSync47(cfg.configFile, "utf8"), newName));
|
|
27460
27591
|
cfg.ship.name = newName;
|
|
27461
27592
|
let renameMachineId;
|
|
27462
27593
|
try {
|
|
@@ -27503,7 +27634,7 @@ ${cu.tail.trimEnd()}
|
|
|
27503
27634
|
process.exit(2);
|
|
27504
27635
|
};
|
|
27505
27636
|
if (sub !== "add" && sub !== "list" && sub !== "clone" && sub !== "hooks" && sub !== "check") usage2();
|
|
27506
|
-
const configText =
|
|
27637
|
+
const configText = readFileSync47(cfg.configFile, "utf8");
|
|
27507
27638
|
if (sub === "check") {
|
|
27508
27639
|
try {
|
|
27509
27640
|
const routeArg = value("route") ?? positional[2];
|
|
@@ -27544,7 +27675,7 @@ ${cu.tail.trimEnd()}
|
|
|
27544
27675
|
}
|
|
27545
27676
|
}, read: (r) => {
|
|
27546
27677
|
try {
|
|
27547
|
-
return
|
|
27678
|
+
return readFileSync47(resolvePath(dir, r), "utf8");
|
|
27548
27679
|
} catch {
|
|
27549
27680
|
return void 0;
|
|
27550
27681
|
}
|
|
@@ -27695,7 +27826,7 @@ ${cu.tail.trimEnd()}
|
|
|
27695
27826
|
let resolvedRemotes;
|
|
27696
27827
|
if (existsSync52(resolvedFile)) {
|
|
27697
27828
|
try {
|
|
27698
|
-
resolvedRemotes = JSON.parse(
|
|
27829
|
+
resolvedRemotes = JSON.parse(readFileSync47(resolvedFile, "utf8"));
|
|
27699
27830
|
} catch {
|
|
27700
27831
|
}
|
|
27701
27832
|
}
|
|
@@ -27717,7 +27848,7 @@ ${cu.tail.trimEnd()}
|
|
|
27717
27848
|
repoHasHooks: (d) => REPO_CONFIG_FILENAMES.some((f) => {
|
|
27718
27849
|
try {
|
|
27719
27850
|
const path = resolvePath(d, f);
|
|
27720
|
-
return Object.keys(parseRepoConfig(
|
|
27851
|
+
return Object.keys(parseRepoConfig(readFileSync47(path, "utf8"), path).hooks).length > 0;
|
|
27721
27852
|
} catch {
|
|
27722
27853
|
return false;
|
|
27723
27854
|
}
|
|
@@ -27826,7 +27957,7 @@ ${cu.tail.trimEnd()}
|
|
|
27826
27957
|
process.stdout.write(`created Repos row ${String(rowPayload.name)} (${String(rowPayload.remote)}) ${created.id}
|
|
27827
27958
|
`);
|
|
27828
27959
|
if (existsSync52(resolvedFile)) {
|
|
27829
|
-
const raw = JSON.parse(
|
|
27960
|
+
const raw = JSON.parse(readFileSync47(resolvedFile, "utf8"));
|
|
27830
27961
|
raw.repoNames = { ...raw.repoNames, [created.id]: String(rowPayload.name) };
|
|
27831
27962
|
raw.repoRemotes = { ...raw.repoRemotes, [created.id]: String(rowPayload.remote) };
|
|
27832
27963
|
writeFileSync38(resolvedFile, `${JSON.stringify(raw, null, 2)}
|
|
@@ -28204,7 +28335,7 @@ Signed in as ${result.identity.email} \u2014 minted an API key in workspace "${r
|
|
|
28204
28335
|
process.exit(2);
|
|
28205
28336
|
}
|
|
28206
28337
|
if (found.shipNameAdopted && !dryRun) {
|
|
28207
|
-
writeFileSync38(cfg.configFile, setShipNameInYaml(
|
|
28338
|
+
writeFileSync38(cfg.configFile, setShipNameInYaml(readFileSync47(cfg.configFile, "utf8"), found.shipNameAdopted));
|
|
28208
28339
|
cfg.ship.name = found.shipNameAdopted;
|
|
28209
28340
|
}
|
|
28210
28341
|
if (found.shipRow) {
|
|
@@ -28250,7 +28381,7 @@ Signed in as ${result.identity.email} \u2014 minted an API key in workspace "${r
|
|
|
28250
28381
|
const hadPreviousFile = existsSync52(resolvedPath);
|
|
28251
28382
|
if (hadPreviousFile) {
|
|
28252
28383
|
try {
|
|
28253
|
-
previous = JSON.parse(
|
|
28384
|
+
previous = JSON.parse(readFileSync47(resolvedPath, "utf8"));
|
|
28254
28385
|
} catch {
|
|
28255
28386
|
}
|
|
28256
28387
|
}
|
|
@@ -28838,8 +28969,13 @@ Signed in as ${result.identity.email} \u2014 minted an API key in workspace "${r
|
|
|
28838
28969
|
}
|
|
28839
28970
|
const dropped = flag("prune") ? await cache.prune(served) : [];
|
|
28840
28971
|
const mirrors = await cache.list();
|
|
28972
|
+
const open = openShipAttention(new State(cfg.ship.stateDir));
|
|
28973
|
+
const failures = served.flatMap((r) => {
|
|
28974
|
+
const item = open.find((i) => i.kind === "sandbox_cache" && i.key === sandboxCacheKey(settings.volume, r));
|
|
28975
|
+
return item ? [{ repo: `${r.host}/${r.path}`, lastFailedAt: item.lastFailedAt ?? item.since, message: item.message }] : [];
|
|
28976
|
+
});
|
|
28841
28977
|
if (flag("json")) {
|
|
28842
|
-
process.stdout.write(`${JSON.stringify({ volume: settings.volume, mirrors, dropped }, null, 2)}
|
|
28978
|
+
process.stdout.write(`${JSON.stringify({ volume: settings.volume, mirrors, failures, dropped }, null, 2)}
|
|
28843
28979
|
`);
|
|
28844
28980
|
} else {
|
|
28845
28981
|
for (const d of dropped) process.stdout.write(`dropped ${d.host}/${d.path}
|
|
@@ -28850,6 +28986,8 @@ Signed in as ${result.identity.email} \u2014 minted an API key in workspace "${r
|
|
|
28850
28986
|
process.stdout.write(`${m.repo.host}/${m.repo.path} last refresh ${m.lastRefresh ?? "never"}${m.intel ? ` intel ${m.intel.commit.slice(0, 12)} (${m.intel.indexedAt ?? "age unknown"})` : ""}
|
|
28851
28987
|
`);
|
|
28852
28988
|
}
|
|
28989
|
+
for (const f of failures) process.stdout.write(`${f.repo} REFRESH FAILING (last failed ${f.lastFailedAt}): ${f.message}
|
|
28990
|
+
`);
|
|
28853
28991
|
}
|
|
28854
28992
|
} catch (e) {
|
|
28855
28993
|
process.stderr.write(`crew sandbox cache: ${e instanceof Error ? e.message : String(e)}
|
|
@@ -29760,7 +29898,7 @@ ${where.join("\n")}`);
|
|
|
29760
29898
|
};
|
|
29761
29899
|
const droppedRoutes = [];
|
|
29762
29900
|
try {
|
|
29763
|
-
const rawCfg = parseYaml2(
|
|
29901
|
+
const rawCfg = parseYaml2(readFileSync47(cfg.configFile, "utf8"));
|
|
29764
29902
|
for (const r of rawCfg?.routes ?? []) {
|
|
29765
29903
|
if (typeof r?.route !== "string" || cfg.routes.some((x) => x.route === r.route)) continue;
|
|
29766
29904
|
try {
|
|
@@ -29879,7 +30017,7 @@ ${where.join("\n")}`);
|
|
|
29879
30017
|
}
|
|
29880
30018
|
case "log": {
|
|
29881
30019
|
try {
|
|
29882
|
-
const text2 =
|
|
30020
|
+
const text2 = readFileSync47(cfg.ship.logFile, "utf8").split("\n");
|
|
29883
30021
|
process.stdout.write(`${text2.slice(-(Number(value("tail")) || 40)).join("\n")}
|
|
29884
30022
|
`);
|
|
29885
30023
|
} catch {
|
|
@@ -29902,7 +30040,7 @@ ${where.join("\n")}`);
|
|
|
29902
30040
|
};
|
|
29903
30041
|
if (!route2.resolved) fail2(`route ${route2.route} is not connected \u2014 run \`crew connect\` first`);
|
|
29904
30042
|
const tracker = new Tracker(route2, cfg.ship);
|
|
29905
|
-
const configText =
|
|
30043
|
+
const configText = readFileSync47(cfg.configFile, "utf8");
|
|
29906
30044
|
const cfgBase = dirname34(cfg.configFile);
|
|
29907
30045
|
const configured2 = configuredRepos(configText, route2.route, cfgBase);
|
|
29908
30046
|
const dir = configured2.find((r) => r.name === SAMPLE_REPO)?.dir ?? sampleDir(configured2.map((r) => r.dir), route2.reposBasePath, route2.route.split("/")[0]);
|
|
@@ -29940,7 +30078,7 @@ ${where.join("\n")}`);
|
|
|
29940
30078
|
if (row) {
|
|
29941
30079
|
await tracker.deleteRepoRow(row.id);
|
|
29942
30080
|
if (existsSync52(resolvedFile)) {
|
|
29943
|
-
const raw = JSON.parse(
|
|
30081
|
+
const raw = JSON.parse(readFileSync47(resolvedFile, "utf8"));
|
|
29944
30082
|
if (raw.repoNames) delete raw.repoNames[row.id];
|
|
29945
30083
|
if (raw.repoRemotes) delete raw.repoRemotes[row.id];
|
|
29946
30084
|
writeFileSync38(resolvedFile, `${JSON.stringify(raw, null, 2)}
|
|
@@ -29980,7 +30118,7 @@ ${where.join("\n")}`);
|
|
|
29980
30118
|
});
|
|
29981
30119
|
repoId = (await tracker.createRepoRow(payload)).id;
|
|
29982
30120
|
if (existsSync52(resolvedFile)) {
|
|
29983
|
-
const raw = JSON.parse(
|
|
30121
|
+
const raw = JSON.parse(readFileSync47(resolvedFile, "utf8"));
|
|
29984
30122
|
raw.repoNames = { ...raw.repoNames, [repoId]: SAMPLE_REPO };
|
|
29985
30123
|
raw.repoRemotes = { ...raw.repoRemotes, [repoId]: SAMPLE_REMOTE };
|
|
29986
30124
|
writeFileSync38(resolvedFile, `${JSON.stringify(raw, null, 2)}
|
|
@@ -30399,6 +30537,14 @@ watermark: ${state.watermark()}
|
|
|
30399
30537
|
for (const message of managedRuntimeWarnings(shipKind, cfg.ship)) problems.push({ severity: "attention", kind: "managed_runtime_default", message });
|
|
30400
30538
|
for (const message of managedGitIdentityWarnings(shipKind, readGlobalGitIdentity())) problems.push({ severity: "attention", kind: "managed_git_identity", message });
|
|
30401
30539
|
}
|
|
30540
|
+
const cacheSettings = cfg.ship.runner === "sandbox" ? cacheSettingsOf(cfg.ship.sandbox) : null;
|
|
30541
|
+
if (cacheSettings && !flag("offline")) {
|
|
30542
|
+
try {
|
|
30543
|
+
const missing = unmirroredRepos(sandboxCacheRepos(route2, cfg.ship), await new SandboxCache(cacheSettings).list());
|
|
30544
|
+
for (const r of missing) problems.push({ severity: "attention", kind: "sandbox_cache_unmirrored", route: route2.route, message: `${r} has no mirror in the cache volume ${cacheSettings.volume}, so sandboxed runs cannot clone it`, remedy: "see `crew sandbox cache` for the last refresh failure" });
|
|
30545
|
+
} catch {
|
|
30546
|
+
}
|
|
30547
|
+
}
|
|
30402
30548
|
for (const t of rejectedTunnels(cfg.ship.stateDir)) {
|
|
30403
30549
|
problems.push({ severity: "attention", kind: TUNNEL_REJECTED_KEY, message: tunnelRejectedMessage(t.workspaceId, t.quickExits), remedy: "rotate the slug with `crew rotate-passenger-url`" });
|
|
30404
30550
|
}
|
|
@@ -30454,7 +30600,7 @@ routes: ${cfg.routes.map((c) => c.route).join(", ")}
|
|
|
30454
30600
|
const unitPlan = planInstall(cfg.ship, CREW_HOME, host, detectSystemd(), "run", installContext());
|
|
30455
30601
|
const abandons = unitAbandonsAgents(unitPlan, (p) => {
|
|
30456
30602
|
try {
|
|
30457
|
-
return
|
|
30603
|
+
return readFileSync47(p, "utf8");
|
|
30458
30604
|
} catch {
|
|
30459
30605
|
return null;
|
|
30460
30606
|
}
|
package/package.json
CHANGED