squadrant 0.16.1 → 0.16.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/index.js +51 -10
- package/dist/index.js.map +1 -1
- package/dist/squadrantd.js +18 -5
- package/dist/squadrantd.js.map +1 -1
- package/package.json +3 -2
- package/plugin/skills/captain-ops/SKILL.md +1 -1
- package/scripts/heavy-lock.mjs +129 -0
package/dist/index.js
CHANGED
|
@@ -1950,7 +1950,7 @@ async function appendToMailbox(opts) {
|
|
|
1950
1950
|
}));
|
|
1951
1951
|
}
|
|
1952
1952
|
async function appendCaptainMessage(opts) {
|
|
1953
|
-
|
|
1953
|
+
return appendEntry(opts.stateRoot, opts.project, (seq) => ({
|
|
1954
1954
|
seq,
|
|
1955
1955
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1956
1956
|
kind: "captain.message",
|
|
@@ -1978,6 +1978,18 @@ async function readCursor(opts) {
|
|
|
1978
1978
|
return null;
|
|
1979
1979
|
}
|
|
1980
1980
|
}
|
|
1981
|
+
async function waitForCaptainDelivery(opts) {
|
|
1982
|
+
const subscriber = opts.subscriber ?? "captain";
|
|
1983
|
+
const deadline = Date.now() + opts.timeoutMs;
|
|
1984
|
+
for (; ; ) {
|
|
1985
|
+
const cursor = await readCursor({ stateRoot: opts.stateRoot, project: opts.project, subscriber });
|
|
1986
|
+
if (cursor && cursor.lastAckedSeq >= opts.seq)
|
|
1987
|
+
return true;
|
|
1988
|
+
if (Date.now() >= deadline)
|
|
1989
|
+
return false;
|
|
1990
|
+
await new Promise((r) => setTimeout(r, opts.pollMs));
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1981
1993
|
async function writeCursor(opts) {
|
|
1982
1994
|
await fs9.mkdir(inboxDir(opts.stateRoot), { recursive: true });
|
|
1983
1995
|
const dest = cursorPath(opts.stateRoot, opts.project, opts.subscriber);
|
|
@@ -2389,6 +2401,9 @@ function reconcileLiveness(prev, next) {
|
|
|
2389
2401
|
}
|
|
2390
2402
|
if (next.startedAt >= prev.startedAt || next.lastState === "end")
|
|
2391
2403
|
return next;
|
|
2404
|
+
const prevAlive = prev.lastState === "start" && prev.pidAlive;
|
|
2405
|
+
if (!prevAlive && next.lastState === "start" && next.pidAlive)
|
|
2406
|
+
return next;
|
|
2392
2407
|
return prev;
|
|
2393
2408
|
}
|
|
2394
2409
|
var CREW_STALE_MS, CREW_GONE_MS, TERMINAL;
|
|
@@ -3394,9 +3409,15 @@ async function runLivenessTick(deps) {
|
|
|
3394
3409
|
return;
|
|
3395
3410
|
}
|
|
3396
3411
|
const seen = /* @__PURE__ */ new Set();
|
|
3412
|
+
const knownCaptainSessions = /* @__PURE__ */ new Map();
|
|
3413
|
+
for (const e of deps.registry.all()) {
|
|
3414
|
+
if (e.role === "captain")
|
|
3415
|
+
knownCaptainSessions.set(e.sessionId, e.project);
|
|
3416
|
+
}
|
|
3397
3417
|
const byProject = /* @__PURE__ */ new Map();
|
|
3398
3418
|
for (const r of records) {
|
|
3399
|
-
|
|
3419
|
+
const role = r.role === "captain" || knownCaptainSessions.get(r.sessionId) === r.project ? "captain" : r.role;
|
|
3420
|
+
if (role !== "captain")
|
|
3400
3421
|
continue;
|
|
3401
3422
|
let arr = byProject.get(r.project);
|
|
3402
3423
|
if (!arr) {
|
|
@@ -3428,10 +3449,14 @@ async function runLivenessTick(deps) {
|
|
|
3428
3449
|
logEntry(deps.log, project, deps.registry.get(project));
|
|
3429
3450
|
}
|
|
3430
3451
|
for (const e of deps.registry.all()) {
|
|
3431
|
-
if (e.role
|
|
3432
|
-
|
|
3433
|
-
|
|
3452
|
+
if (e.role !== "captain" || e.lastState !== "start" || seen.has(e.project))
|
|
3453
|
+
continue;
|
|
3454
|
+
if (e.pid == null || deps.isPidAlive(e.pid)) {
|
|
3455
|
+
deps.log?.(`[${e.role}/runtime] ${e.project} pid=${e.pid} missing from snapshot but not confirmed dead \u2014 leaving alive`);
|
|
3456
|
+
continue;
|
|
3434
3457
|
}
|
|
3458
|
+
deps.registry.markEnded(e.project, now);
|
|
3459
|
+
logEntry(deps.log, e.project, deps.registry.get(e.project));
|
|
3435
3460
|
}
|
|
3436
3461
|
if (deps.reap) {
|
|
3437
3462
|
for (const e of deps.registry.all()) {
|
|
@@ -5882,8 +5907,7 @@ async function runCrewSend(project, name, message, runtime, workspaceId, deps) {
|
|
|
5882
5907
|
throw new Error(blockedByModalMessage());
|
|
5883
5908
|
}
|
|
5884
5909
|
if (!delivered) {
|
|
5885
|
-
|
|
5886
|
-
`);
|
|
5910
|
+
throw new Error(`Message not delivered to crew '${name}' \u2014 the paste/submit could not be confirmed. Re-send with 'squadrant crew send ${project} ${name}'.`);
|
|
5887
5911
|
}
|
|
5888
5912
|
}
|
|
5889
5913
|
async function runCrewRead(project, name, runtime, workspaceId) {
|
|
@@ -6144,6 +6168,7 @@ __export(dist_exports2, {
|
|
|
6144
6168
|
topicKey: () => topicKey,
|
|
6145
6169
|
topicName: () => topicName,
|
|
6146
6170
|
tryAcquireDaemonLock: () => tryAcquireDaemonLock,
|
|
6171
|
+
waitForCaptainDelivery: () => waitForCaptainDelivery,
|
|
6147
6172
|
waitForWarmup: () => waitForWarmup,
|
|
6148
6173
|
writeCursor: () => writeCursor,
|
|
6149
6174
|
writeTelegramConfig: () => writeTelegramConfig
|
|
@@ -13767,7 +13792,9 @@ runtimeCommand.command("status").description("Print 'running' or 'stopped' for a
|
|
|
13767
13792
|
process.exit(2);
|
|
13768
13793
|
}
|
|
13769
13794
|
});
|
|
13770
|
-
|
|
13795
|
+
var SEND_CONFIRM_TIMEOUT_MS = 15e3;
|
|
13796
|
+
var SEND_CONFIRM_POLL_MS = 500;
|
|
13797
|
+
async function runRuntimeSend(arg1, arg2, opts, confirmOpts) {
|
|
13771
13798
|
const config = loadConfig();
|
|
13772
13799
|
const registry = buildRegistry();
|
|
13773
13800
|
if (opts.command && arg2 !== void 0) {
|
|
@@ -13777,7 +13804,7 @@ async function runRuntimeSend(arg1, arg2, opts) {
|
|
|
13777
13804
|
const message = opts.command ? arg1 : arg2;
|
|
13778
13805
|
if (!message) throw new Error("Message is required");
|
|
13779
13806
|
const { requireDaemon: requireDaemon2 } = await Promise.resolve().then(() => (init_require_daemon(), require_daemon_exports));
|
|
13780
|
-
const { appendCaptainMessage: appendCaptainMessage2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports2));
|
|
13807
|
+
const { appendCaptainMessage: appendCaptainMessage2, waitForCaptainDelivery: waitForCaptainDelivery2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports2));
|
|
13781
13808
|
await requireDaemon2();
|
|
13782
13809
|
const resolved = resolveTarget(registry, config, target, !!opts.command);
|
|
13783
13810
|
await needRef(resolved);
|
|
@@ -13785,16 +13812,30 @@ async function runRuntimeSend(arg1, arg2, opts) {
|
|
|
13785
13812
|
const { join: join30, dirname: dirname10 } = await import("path");
|
|
13786
13813
|
const { DEFAULT_CONFIG_PATH: DEFAULT_CONFIG_PATH2 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
|
|
13787
13814
|
const stateRoot = join30(dirname10(DEFAULT_CONFIG_PATH2), "state");
|
|
13788
|
-
await appendCaptainMessage2({
|
|
13815
|
+
const seq = await appendCaptainMessage2({
|
|
13789
13816
|
stateRoot,
|
|
13790
13817
|
project: finalProject,
|
|
13791
13818
|
text: message,
|
|
13792
13819
|
source: "cli"
|
|
13793
13820
|
});
|
|
13821
|
+
const timeoutMs = confirmOpts?.timeoutMs ?? SEND_CONFIRM_TIMEOUT_MS;
|
|
13822
|
+
const delivered = await waitForCaptainDelivery2({
|
|
13823
|
+
stateRoot,
|
|
13824
|
+
project: finalProject,
|
|
13825
|
+
seq,
|
|
13826
|
+
timeoutMs,
|
|
13827
|
+
pollMs: confirmOpts?.pollMs ?? SEND_CONFIRM_POLL_MS
|
|
13828
|
+
});
|
|
13829
|
+
if (!delivered) {
|
|
13830
|
+
throw new Error(
|
|
13831
|
+
`Message queued for '${finalProject}' (seq=${seq}) but delivery was not confirmed within ${Math.round(timeoutMs / 1e3)}s. It may still be pending \u2014 check with 'squadrant runtime read-screen ${finalProject}${opts.command ? " --command" : ""}'.`
|
|
13832
|
+
);
|
|
13833
|
+
}
|
|
13794
13834
|
}
|
|
13795
13835
|
runtimeCommand.command("send").description("Send a message to a target workspace AND commit with Enter. With --command, the first positional is the message.").argument("<arg1>", "Project name, or the message when --command is used").argument("[arg2]", "Message (when target is a project). Omit when using --command.").option("--command", "Target the command workspace").action(async (arg1, arg2, opts) => {
|
|
13796
13836
|
try {
|
|
13797
13837
|
await runRuntimeSend(arg1, arg2, opts);
|
|
13838
|
+
console.log(chalk18.green("\u2714 Delivered (confirmed)"));
|
|
13798
13839
|
} catch (err) {
|
|
13799
13840
|
console.error(chalk18.red(err.message));
|
|
13800
13841
|
process.exit(1);
|