@tablation/crew 0.109.0 → 0.110.0
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 +78 -26
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -10767,7 +10767,7 @@ async function reconcileRuns(o) {
|
|
|
10767
10767
|
}
|
|
10768
10768
|
|
|
10769
10769
|
// src/live-runs.ts
|
|
10770
|
-
import { existsSync as existsSync23, readdirSync as readdirSync10 } from "fs";
|
|
10770
|
+
import { existsSync as existsSync23, readdirSync as readdirSync10, statSync as statSync8 } from "fs";
|
|
10771
10771
|
import { join as join25 } from "path";
|
|
10772
10772
|
function liveRuns(stateDir, isAlive = runIsAlive) {
|
|
10773
10773
|
const dir = join25(stateDir, "streams");
|
|
@@ -10783,6 +10783,23 @@ function liveRuns(stateDir, isAlive = runIsAlive) {
|
|
|
10783
10783
|
}
|
|
10784
10784
|
return out.sort((a, b) => a.spawnedAt.localeCompare(b.spawnedAt));
|
|
10785
10785
|
}
|
|
10786
|
+
function runActivity(stateDir, isAlive = runIsAlive) {
|
|
10787
|
+
const activeRuns = liveRuns(stateDir, isAlive).length;
|
|
10788
|
+
const dir = join25(stateDir, "streams");
|
|
10789
|
+
let newest = 0;
|
|
10790
|
+
if (existsSync23(dir)) {
|
|
10791
|
+
for (const name of readdirSync10(dir)) {
|
|
10792
|
+
if (!name.endsWith(".jsonl") || name.endsWith(".events.jsonl")) continue;
|
|
10793
|
+
const streamPath = join25(dir, name);
|
|
10794
|
+
if (!runFinished(streamPath)) continue;
|
|
10795
|
+
try {
|
|
10796
|
+
newest = Math.max(newest, statSync8(`${streamPath}.meta.json`).mtimeMs);
|
|
10797
|
+
} catch {
|
|
10798
|
+
}
|
|
10799
|
+
}
|
|
10800
|
+
}
|
|
10801
|
+
return { activeRuns, lastRunEndedAt: newest ? new Date(newest).toISOString() : null };
|
|
10802
|
+
}
|
|
10786
10803
|
function siblingRuns(runs, ownTicketRecordId) {
|
|
10787
10804
|
return runs.filter((r) => !ownTicketRecordId || r.ticketRecordId !== ownTicketRecordId);
|
|
10788
10805
|
}
|
|
@@ -12572,7 +12589,7 @@ async function signOutSessions(o) {
|
|
|
12572
12589
|
}
|
|
12573
12590
|
|
|
12574
12591
|
// src/reset.ts
|
|
12575
|
-
import { existsSync as existsSync26, mkdirSync as mkdirSync17, readFileSync as readFileSync24, readdirSync as readdirSync12, rmSync as rmSync16, statSync as
|
|
12592
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync17, readFileSync as readFileSync24, readdirSync as readdirSync12, rmSync as rmSync16, statSync as statSync9, writeFileSync as writeFileSync18 } from "fs";
|
|
12576
12593
|
import { dirname as dirname12, join as join29 } from "path";
|
|
12577
12594
|
import { hostFromUrl as hostFromUrl3 } from "@tablation/client";
|
|
12578
12595
|
function clonedCheckoutsFile(stateDir) {
|
|
@@ -12670,7 +12687,7 @@ function removeState(stateDir, dryRun) {
|
|
|
12670
12687
|
const targets = [join29(stateDir, "resolved"), join29(stateDir, "keys"), clonedCheckoutsFile(stateDir), join29(stateDir, "connect-session.json"), join29(stateDir, "reload-requested"), join29(stateDir, "daemon.started")];
|
|
12671
12688
|
try {
|
|
12672
12689
|
for (const name of readdirSync12(stateDir)) {
|
|
12673
|
-
if (name.startsWith(".") &&
|
|
12690
|
+
if (name.startsWith(".") && statSync9(join29(stateDir, name)).isFile()) targets.push(join29(stateDir, name));
|
|
12674
12691
|
}
|
|
12675
12692
|
} catch {
|
|
12676
12693
|
}
|
|
@@ -12798,6 +12815,7 @@ async function runPoolMember(deps) {
|
|
|
12798
12815
|
}
|
|
12799
12816
|
};
|
|
12800
12817
|
let reported;
|
|
12818
|
+
let busy = false;
|
|
12801
12819
|
const report = async (state, o = {}) => {
|
|
12802
12820
|
const body = {
|
|
12803
12821
|
state,
|
|
@@ -12807,6 +12825,12 @@ async function runPoolMember(deps) {
|
|
|
12807
12825
|
reason: o.reason ?? null,
|
|
12808
12826
|
crewVersion: deps.host.crewVersion
|
|
12809
12827
|
};
|
|
12828
|
+
const act = state === "running" ? deps.activity?.() : void 0;
|
|
12829
|
+
if (act) {
|
|
12830
|
+
body.activeRuns = act.activeRuns;
|
|
12831
|
+
body.lastRunEndedAt = act.lastRunEndedAt;
|
|
12832
|
+
}
|
|
12833
|
+
if (act) busy = act.activeRuns > 0;
|
|
12810
12834
|
const r = await settle("status", () => deps.api.status(body));
|
|
12811
12835
|
if (!r) return "stopped";
|
|
12812
12836
|
if (r.status === 401) return "credential";
|
|
@@ -12902,7 +12926,25 @@ async function runPoolMember(deps) {
|
|
|
12902
12926
|
if (!current) await deps.maybeSelfUpgrade?.().catch((e) => {
|
|
12903
12927
|
deps.log(`self-upgrade: ${e.message}`);
|
|
12904
12928
|
});
|
|
12905
|
-
|
|
12929
|
+
let stopWatch;
|
|
12930
|
+
let flipping = false;
|
|
12931
|
+
if (current && deps.watch && deps.activity) {
|
|
12932
|
+
const held = current;
|
|
12933
|
+
stopWatch = deps.watch(() => {
|
|
12934
|
+
const now = deps.activity().activeRuns > 0;
|
|
12935
|
+
if (flipping || now === busy) return;
|
|
12936
|
+
flipping = true;
|
|
12937
|
+
void report("running", { leaseId: held }).catch(() => void 0).finally(() => {
|
|
12938
|
+
flipping = false;
|
|
12939
|
+
});
|
|
12940
|
+
});
|
|
12941
|
+
}
|
|
12942
|
+
let ans;
|
|
12943
|
+
try {
|
|
12944
|
+
ans = await settle("lease", () => deps.api.lease(platform2.pollWaitSeconds || DEFAULT_POLL_WAIT_SECONDS, current ?? void 0));
|
|
12945
|
+
} finally {
|
|
12946
|
+
stopWatch?.();
|
|
12947
|
+
}
|
|
12906
12948
|
if (!ans) return POOL_EXIT.ok;
|
|
12907
12949
|
if (ans.status === 401) {
|
|
12908
12950
|
deps.log("the pool credential is unknown or revoked (401)");
|
|
@@ -12915,10 +12957,10 @@ async function runPoolMember(deps) {
|
|
|
12915
12957
|
}
|
|
12916
12958
|
if (ans.status === 204) {
|
|
12917
12959
|
const url = current ? deps.relayUrl() : null;
|
|
12918
|
-
if (current && url && url
|
|
12960
|
+
if (current && (url !== relayReported && url || deps.activity)) {
|
|
12919
12961
|
const r2 = await report("running", { leaseId: current });
|
|
12920
12962
|
if (r2 === "credential") return POOL_EXIT.credential;
|
|
12921
|
-
relayReported = url;
|
|
12963
|
+
relayReported = url ?? relayReported;
|
|
12922
12964
|
}
|
|
12923
12965
|
continue;
|
|
12924
12966
|
}
|
|
@@ -13992,6 +14034,16 @@ function realPoolMemberDeps(o) {
|
|
|
13992
14034
|
}
|
|
13993
14035
|
return null;
|
|
13994
14036
|
},
|
|
14037
|
+
activity() {
|
|
14038
|
+
const cfg = loadShip(o.crewHome);
|
|
14039
|
+
return cfg ? runActivity(cfg.ship.stateDir) : { activeRuns: 0, lastRunEndedAt: null };
|
|
14040
|
+
},
|
|
14041
|
+
watch(onTick) {
|
|
14042
|
+
const t = setInterval(onTick, 2e3);
|
|
14043
|
+
return () => {
|
|
14044
|
+
clearInterval(t);
|
|
14045
|
+
};
|
|
14046
|
+
},
|
|
13995
14047
|
sleep: (ms3) => new Promise((r) => setTimeout(r, ms3)),
|
|
13996
14048
|
log: o.log,
|
|
13997
14049
|
stopping: o.stopping
|
|
@@ -17811,7 +17863,7 @@ function missingReleaserWarning(repo, release, ships, now = Date.now()) {
|
|
|
17811
17863
|
}
|
|
17812
17864
|
|
|
17813
17865
|
// src/watch.ts
|
|
17814
|
-
import { watch as watchFile, existsSync as existsSync34, statSync as
|
|
17866
|
+
import { watch as watchFile, existsSync as existsSync34, statSync as statSync10, openSync as openSync4, readSync as readSync2, closeSync as closeSync4 } from "fs";
|
|
17815
17867
|
var E = "\x1B[";
|
|
17816
17868
|
var dim = (s) => `${E}2m${s}${E}0m`;
|
|
17817
17869
|
var bold = (s) => `${E}1m${s}${E}0m`;
|
|
@@ -17913,7 +17965,7 @@ function renderHeaders(states, now = Date.now()) {
|
|
|
17913
17965
|
}
|
|
17914
17966
|
function readFrom(file, from) {
|
|
17915
17967
|
if (!existsSync34(file)) return { events: [], offset: from };
|
|
17916
|
-
const size =
|
|
17968
|
+
const size = statSync10(file).size;
|
|
17917
17969
|
if (size < from) return readFrom(file, 0);
|
|
17918
17970
|
if (size === from) return { events: [], offset: from };
|
|
17919
17971
|
const fd = openSync4(file, "r");
|
|
@@ -19913,7 +19965,7 @@ function applyRemoteBranchCleanup(cwd, remote, branches2, dryRun, log) {
|
|
|
19913
19965
|
}
|
|
19914
19966
|
|
|
19915
19967
|
// src/stream-sweep.ts
|
|
19916
|
-
import { existsSync as existsSync38, readdirSync as readdirSync15, rmSync as rmSync18, statSync as
|
|
19968
|
+
import { existsSync as existsSync38, readdirSync as readdirSync15, rmSync as rmSync18, statSync as statSync11 } from "fs";
|
|
19917
19969
|
import { join as join40 } from "path";
|
|
19918
19970
|
var DAY_MS2 = 24 * 60 * 60 * 1e3;
|
|
19919
19971
|
function planStreamSweep(stateDir, retentionDays, now = Date.now()) {
|
|
@@ -19922,7 +19974,7 @@ function planStreamSweep(stateDir, retentionDays, now = Date.now()) {
|
|
|
19922
19974
|
const cutoff = now - retentionDays * DAY_MS2;
|
|
19923
19975
|
return readdirSync15(dir).map((name) => join40(dir, name)).filter((path) => {
|
|
19924
19976
|
try {
|
|
19925
|
-
return
|
|
19977
|
+
return statSync11(path).mtimeMs < cutoff;
|
|
19926
19978
|
} catch {
|
|
19927
19979
|
return false;
|
|
19928
19980
|
}
|
|
@@ -19950,7 +20002,7 @@ function planEventsSweep(stateDir, retentionDays, now = Date.now()) {
|
|
|
19950
20002
|
const cutoff = now - retentionDays * DAY_MS2;
|
|
19951
20003
|
return readdirSync15(stateDir).filter((name) => ROTATED_EVENTS_RE.test(name)).map((name) => join40(stateDir, name)).filter((path) => {
|
|
19952
20004
|
try {
|
|
19953
|
-
return
|
|
20005
|
+
return statSync11(path).mtimeMs < cutoff;
|
|
19954
20006
|
} catch {
|
|
19955
20007
|
return false;
|
|
19956
20008
|
}
|
|
@@ -19958,7 +20010,7 @@ function planEventsSweep(stateDir, retentionDays, now = Date.now()) {
|
|
|
19958
20010
|
}
|
|
19959
20011
|
|
|
19960
20012
|
// src/cli.ts
|
|
19961
|
-
import { realpathSync as realpathSync3, readFileSync as readFileSync40, existsSync as existsSync45, mkdirSync as mkdirSync32, writeFileSync as writeFileSync33, rmSync as rmSync23, unlinkSync as unlinkSync5, copyFileSync as copyFileSync2, renameSync as renameSync6, statSync as
|
|
20013
|
+
import { realpathSync as realpathSync3, readFileSync as readFileSync40, existsSync as existsSync45, mkdirSync as mkdirSync32, writeFileSync as writeFileSync33, rmSync as rmSync23, unlinkSync as unlinkSync5, copyFileSync as copyFileSync2, renameSync as renameSync6, statSync as statSync15, readdirSync as readdirSync20 } from "fs";
|
|
19962
20014
|
import { createInterface } from "readline/promises";
|
|
19963
20015
|
|
|
19964
20016
|
// src/periscope-cmd.ts
|
|
@@ -20386,7 +20438,7 @@ ${tail2(preview.output)}`);
|
|
|
20386
20438
|
|
|
20387
20439
|
// src/periscope-idle.ts
|
|
20388
20440
|
import { execFileSync as execFileSync10 } from "child_process";
|
|
20389
|
-
import { statSync as
|
|
20441
|
+
import { statSync as statSync12 } from "fs";
|
|
20390
20442
|
import { join as join42 } from "path";
|
|
20391
20443
|
var MAX_SCANNED_FILES = 2e4;
|
|
20392
20444
|
function newestWorktreeMtime(root) {
|
|
@@ -20407,7 +20459,7 @@ function newestWorktreeMtime(root) {
|
|
|
20407
20459
|
if (!rel) continue;
|
|
20408
20460
|
if (++scanned > MAX_SCANNED_FILES) break;
|
|
20409
20461
|
try {
|
|
20410
|
-
const m =
|
|
20462
|
+
const m = statSync12(join42(root, rel)).mtimeMs;
|
|
20411
20463
|
if (newest === null || m > newest) newest = m;
|
|
20412
20464
|
} catch {
|
|
20413
20465
|
}
|
|
@@ -20935,7 +20987,7 @@ function describeCause(err3) {
|
|
|
20935
20987
|
}
|
|
20936
20988
|
|
|
20937
20989
|
// src/daemon.ts
|
|
20938
|
-
import { existsSync as existsSync42, mkdirSync as mkdirSync30, readFileSync as readFileSync38, readdirSync as readdirSync17, rmSync as rmSync20, statSync as
|
|
20990
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync30, readFileSync as readFileSync38, readdirSync as readdirSync17, rmSync as rmSync20, statSync as statSync13, writeFileSync as writeFileSync31 } from "fs";
|
|
20939
20991
|
import { join as join45 } from "path";
|
|
20940
20992
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
20941
20993
|
var DEFAULT_FLOOR_MS = 5e3;
|
|
@@ -21016,7 +21068,7 @@ async function runDaemonLoop(o) {
|
|
|
21016
21068
|
function latestMtime(path) {
|
|
21017
21069
|
let stat2;
|
|
21018
21070
|
try {
|
|
21019
|
-
stat2 =
|
|
21071
|
+
stat2 = statSync13(path);
|
|
21020
21072
|
} catch {
|
|
21021
21073
|
return 0;
|
|
21022
21074
|
}
|
|
@@ -21040,7 +21092,7 @@ function reloadSentinelFor(stateDir) {
|
|
|
21040
21092
|
}
|
|
21041
21093
|
function readReloadRequestedAt(stateDir) {
|
|
21042
21094
|
try {
|
|
21043
|
-
return
|
|
21095
|
+
return statSync13(reloadSentinelFor(stateDir)).mtimeMs;
|
|
21044
21096
|
} catch {
|
|
21045
21097
|
return null;
|
|
21046
21098
|
}
|
|
@@ -21065,7 +21117,7 @@ function readDaemonStarted(stateDir) {
|
|
|
21065
21117
|
function configChangedAfter(files, startedAt) {
|
|
21066
21118
|
for (const f of files) {
|
|
21067
21119
|
try {
|
|
21068
|
-
if (
|
|
21120
|
+
if (statSync13(f).mtimeMs > startedAt) return f;
|
|
21069
21121
|
} catch {
|
|
21070
21122
|
}
|
|
21071
21123
|
}
|
|
@@ -21628,7 +21680,7 @@ import {
|
|
|
21628
21680
|
readSync as readSync3,
|
|
21629
21681
|
readdirSync as readdirSync18,
|
|
21630
21682
|
rmSync as rmSync21,
|
|
21631
|
-
statSync as
|
|
21683
|
+
statSync as statSync14,
|
|
21632
21684
|
watch
|
|
21633
21685
|
} from "fs";
|
|
21634
21686
|
import { createConnection } from "net";
|
|
@@ -21972,7 +22024,7 @@ function readRange(path, from, max) {
|
|
|
21972
22024
|
}
|
|
21973
22025
|
}
|
|
21974
22026
|
function lastLines2(path, n) {
|
|
21975
|
-
const st =
|
|
22027
|
+
const st = statSync14(path);
|
|
21976
22028
|
const cursorAt = (off) => encodeCursor({ dev: st.dev, ino: st.ino, off });
|
|
21977
22029
|
if (n <= 0 || st.size === 0) return { lines: [], cursor: cursorAt(st.size), reset: false };
|
|
21978
22030
|
let start = st.size;
|
|
@@ -22006,7 +22058,7 @@ function readTail(live, opts) {
|
|
|
22006
22058
|
} else {
|
|
22007
22059
|
const found = candidates(live, opts.rotated ?? false).find((p) => {
|
|
22008
22060
|
try {
|
|
22009
|
-
const s =
|
|
22061
|
+
const s = statSync14(p);
|
|
22010
22062
|
return s.ino === cur.ino && s.dev === cur.dev;
|
|
22011
22063
|
} catch {
|
|
22012
22064
|
return false;
|
|
@@ -22017,7 +22069,7 @@ function readTail(live, opts) {
|
|
|
22017
22069
|
off = cur.off;
|
|
22018
22070
|
} else reset = true;
|
|
22019
22071
|
}
|
|
22020
|
-
let size =
|
|
22072
|
+
let size = statSync14(path).size;
|
|
22021
22073
|
if (off > size) {
|
|
22022
22074
|
off = 0;
|
|
22023
22075
|
reset = true;
|
|
@@ -22025,12 +22077,12 @@ function readTail(live, opts) {
|
|
|
22025
22077
|
if (off >= size && path !== live) {
|
|
22026
22078
|
path = live;
|
|
22027
22079
|
off = 0;
|
|
22028
|
-
size =
|
|
22080
|
+
size = statSync14(path).size;
|
|
22029
22081
|
}
|
|
22030
22082
|
const { text: text2 } = readRange(path, off, max);
|
|
22031
22083
|
const cut = text2.lastIndexOf("\n");
|
|
22032
22084
|
const whole = cut < 0 ? "" : text2.slice(0, cut + 1);
|
|
22033
|
-
const st =
|
|
22085
|
+
const st = statSync14(path);
|
|
22034
22086
|
return {
|
|
22035
22087
|
lines: whole.split("\n").filter((l) => l.length),
|
|
22036
22088
|
cursor: encodeCursor({ dev: st.dev, ino: st.ino, off: off + Buffer.byteLength(whole) }),
|
|
@@ -28058,7 +28110,7 @@ routes: ${cfg.routes.map((c) => c.route).join(", ")}
|
|
|
28058
28110
|
}
|
|
28059
28111
|
try {
|
|
28060
28112
|
const evFile = eventFileFor(cfg.ship.stateDir);
|
|
28061
|
-
const evSize = existsSync45(evFile) ?
|
|
28113
|
+
const evSize = existsSync45(evFile) ? statSync15(evFile).size : 0;
|
|
28062
28114
|
process.stdout.write(
|
|
28063
28115
|
evSize > cfg.ship.eventsRotateBytes * 4 ? `events log: WARN ${evFile} is ${Math.round(evSize / 1048576)} MB (> 4x eventsRotateBytes); run \`crew reap\` to rotate it
|
|
28064
28116
|
` : "events log: ok\n"
|
|
@@ -28092,7 +28144,7 @@ routes: ${cfg.routes.map((c) => c.route).join(", ")}
|
|
|
28092
28144
|
const changed2 = configChangedAfter(daemonConfigPaths(cfg), daemonStartedAt);
|
|
28093
28145
|
if (changed2) {
|
|
28094
28146
|
process.stdout.write(
|
|
28095
|
-
`daemon config: WARN ${changed2} changed at ${new Date(
|
|
28147
|
+
`daemon config: WARN ${changed2} changed at ${new Date(statSync15(changed2).mtimeMs).toISOString()} but the daemon started at ${new Date(daemonStartedAt).toISOString()} \u2014 run \`crew reload\`
|
|
28096
28148
|
`
|
|
28097
28149
|
);
|
|
28098
28150
|
}
|
package/package.json
CHANGED