squadrant 0.13.3 → 0.13.5
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 +65 -8
- package/dist/index.js.map +1 -1
- package/dist/squadrantd.js +71 -7
- package/dist/squadrantd.js.map +1 -1
- package/package.json +1 -1
package/dist/squadrantd.js
CHANGED
|
@@ -1974,6 +1974,7 @@ var CaptainDelivery = class {
|
|
|
1974
1974
|
// packages/core/dist/daemon/delivery-loop.js
|
|
1975
1975
|
var CURSOR_SUBSCRIBER = "captain";
|
|
1976
1976
|
var CAPTAIN_GONE_STREAK_K = 3;
|
|
1977
|
+
var TERMINAL_KINDS = /* @__PURE__ */ new Set(["task.done", "task.failed", "task.cancelled", "task.blocked"]);
|
|
1977
1978
|
function discoverCaptainSurface(surfaces, captainTitle) {
|
|
1978
1979
|
return surfaces.find((s) => s.title === captainTitle) ?? null;
|
|
1979
1980
|
}
|
|
@@ -2066,13 +2067,19 @@ function createDelivery(ctx, daemonCmux) {
|
|
|
2066
2067
|
}
|
|
2067
2068
|
for await (const entry of readFromCursor({ stateRoot, project, fromSeq: lastAcked + 1 })) {
|
|
2068
2069
|
if (new Date(entry.ts).getTime() < sessionStartMs - STALE_THRESHOLD_MS) {
|
|
2069
|
-
|
|
2070
|
-
|
|
2070
|
+
if (!TERMINAL_KINDS.has(entry.kind)) {
|
|
2071
|
+
log(`delivery seq=${entry.seq} kind=${entry.kind} outcome=stale-skipped`);
|
|
2072
|
+
await writeCursor({ stateRoot, project, subscriber: CURSOR_SUBSCRIBER, lastAckedSeq: entry.seq });
|
|
2073
|
+
continue;
|
|
2074
|
+
}
|
|
2075
|
+
log(`delivery seq=${entry.seq} kind=${entry.kind} outcome=stale-terminal-deliver`);
|
|
2071
2076
|
}
|
|
2072
2077
|
const result = await d.deliver(entry, (text, sendOpts) => cmux2.send(surface, text, sendOpts));
|
|
2073
2078
|
if ("delivered" in result) {
|
|
2079
|
+
log(`delivery seq=${entry.seq} kind=${entry.kind} outcome=delivered`);
|
|
2074
2080
|
await writeCursor({ stateRoot, project, subscriber: CURSOR_SUBSCRIBER, lastAckedSeq: entry.seq });
|
|
2075
2081
|
} else {
|
|
2082
|
+
log(`delivery seq=${entry.seq} kind=${entry.kind} outcome=deferred`);
|
|
2076
2083
|
break;
|
|
2077
2084
|
}
|
|
2078
2085
|
}
|
|
@@ -4388,7 +4395,28 @@ function parseDraftFromScreen(screen) {
|
|
|
4388
4395
|
}
|
|
4389
4396
|
return "";
|
|
4390
4397
|
}
|
|
4391
|
-
function
|
|
4398
|
+
function hasModalOptionList(screen) {
|
|
4399
|
+
if (!screen)
|
|
4400
|
+
return false;
|
|
4401
|
+
const lines = screen.split(/\r?\n/);
|
|
4402
|
+
const HR_RE = /^\s*─{10,}\s*$/;
|
|
4403
|
+
let bottomHR = -1;
|
|
4404
|
+
let topHR = -1;
|
|
4405
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
4406
|
+
if (HR_RE.test(lines[i])) {
|
|
4407
|
+
if (bottomHR === -1)
|
|
4408
|
+
bottomHR = i;
|
|
4409
|
+
else {
|
|
4410
|
+
topHR = i;
|
|
4411
|
+
break;
|
|
4412
|
+
}
|
|
4413
|
+
}
|
|
4414
|
+
}
|
|
4415
|
+
if (topHR === -1)
|
|
4416
|
+
return false;
|
|
4417
|
+
return lines.slice(topHR + 1, bottomHR).some((l) => /^\s*\d+\.\s/.test(l));
|
|
4418
|
+
}
|
|
4419
|
+
function readInputBoxRaw(screen, opts) {
|
|
4392
4420
|
if (!screen)
|
|
4393
4421
|
return null;
|
|
4394
4422
|
const lines = screen.split(/\r?\n/);
|
|
@@ -4414,7 +4442,8 @@ function readInputBoxRaw(screen) {
|
|
|
4414
4442
|
s = s.replace(/\s*[▌█▔▎▏]+\s*$/, "");
|
|
4415
4443
|
parts.push(s);
|
|
4416
4444
|
}
|
|
4417
|
-
|
|
4445
|
+
const joined = parts.join("");
|
|
4446
|
+
return opts?.trim === false ? joined : joined.replace(/\s+$/, "");
|
|
4418
4447
|
}
|
|
4419
4448
|
function sendDebugEnabled() {
|
|
4420
4449
|
return !!process.env.SQUADRANT_DEBUG_SEND;
|
|
@@ -4428,6 +4457,19 @@ function classifySendOutcome(payload, postBox) {
|
|
|
4428
4457
|
return "stuck";
|
|
4429
4458
|
return "unknown";
|
|
4430
4459
|
}
|
|
4460
|
+
function classifyDraftLiveness(before, after) {
|
|
4461
|
+
if (before === null || after === null)
|
|
4462
|
+
return "inconclusive";
|
|
4463
|
+
if (after === "")
|
|
4464
|
+
return "no-draft";
|
|
4465
|
+
if (before.length > 0) {
|
|
4466
|
+
const segs = [...new Intl.Segmenter().segment(before)];
|
|
4467
|
+
const expected = segs.slice(0, -1).map((s) => s.segment).join("").replace(/\s+$/, "");
|
|
4468
|
+
if (after === expected)
|
|
4469
|
+
return "real-draft";
|
|
4470
|
+
}
|
|
4471
|
+
return "inconclusive";
|
|
4472
|
+
}
|
|
4431
4473
|
function createCmuxDriver() {
|
|
4432
4474
|
return {
|
|
4433
4475
|
name: "cmux",
|
|
@@ -4618,6 +4660,8 @@ function createCmuxDriver() {
|
|
|
4618
4660
|
const draft = parseDraftFromScreen(screen);
|
|
4619
4661
|
if (draft === null)
|
|
4620
4662
|
throw new DeferDelivery(null);
|
|
4663
|
+
if (hasModalOptionList(screen))
|
|
4664
|
+
throw new DeferDelivery(null);
|
|
4621
4665
|
if (draft === "") {
|
|
4622
4666
|
await deliver();
|
|
4623
4667
|
return;
|
|
@@ -4625,18 +4669,38 @@ function createCmuxDriver() {
|
|
|
4625
4669
|
if (!opts?.probe)
|
|
4626
4670
|
throw new DeferDelivery(draft);
|
|
4627
4671
|
const before = readInputBoxRaw(screen);
|
|
4672
|
+
const rawBefore = readInputBoxRaw(screen, { trim: false });
|
|
4628
4673
|
await cmux(["send-key", "--workspace", ws, "--surface", sf, "backspace"]);
|
|
4674
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
4629
4675
|
let afterScreen = "";
|
|
4630
4676
|
try {
|
|
4631
4677
|
afterScreen = await cmux(["read-screen", "--workspace", ws, "--surface", sf]);
|
|
4632
4678
|
} catch {
|
|
4633
4679
|
}
|
|
4634
4680
|
const after = readInputBoxRaw(afterScreen);
|
|
4635
|
-
|
|
4636
|
-
|
|
4681
|
+
const rawAfter = readInputBoxRaw(afterScreen, { trim: false });
|
|
4682
|
+
const liveness = classifyDraftLiveness(before, after);
|
|
4683
|
+
if (liveness === "real-draft") {
|
|
4684
|
+
const segs = before ? [...new Intl.Segmenter().segment(before)] : [];
|
|
4685
|
+
const lastGrapheme = segs.length > 0 ? segs[segs.length - 1].segment : before.slice(-1);
|
|
4686
|
+
await cmux(["send", "--workspace", ws, "--surface", sf, lastGrapheme]);
|
|
4637
4687
|
throw new DeferDelivery(draft);
|
|
4638
4688
|
}
|
|
4639
|
-
|
|
4689
|
+
if (liveness === "no-draft") {
|
|
4690
|
+
await deliver();
|
|
4691
|
+
return;
|
|
4692
|
+
}
|
|
4693
|
+
if (rawBefore !== null && rawAfter !== null) {
|
|
4694
|
+
if (rawBefore !== rawAfter) {
|
|
4695
|
+
const segs = [...new Intl.Segmenter().segment(rawBefore)];
|
|
4696
|
+
const lastGrapheme = segs.length > 0 ? segs[segs.length - 1].segment : rawBefore.slice(-1);
|
|
4697
|
+
await cmux(["send", "--workspace", ws, "--surface", sf, lastGrapheme]);
|
|
4698
|
+
throw new DeferDelivery(draft);
|
|
4699
|
+
}
|
|
4700
|
+
await deliver();
|
|
4701
|
+
return;
|
|
4702
|
+
}
|
|
4703
|
+
throw new DeferDelivery(draft);
|
|
4640
4704
|
},
|
|
4641
4705
|
async listSurfaces(workspaceId) {
|
|
4642
4706
|
let output;
|