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.
@@ -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
- await writeCursor({ stateRoot, project, subscriber: CURSOR_SUBSCRIBER, lastAckedSeq: entry.seq });
2070
- continue;
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 readInputBoxRaw(screen) {
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
- return parts.join("").replace(/\s+$/, "");
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
- if (before !== null && after !== null && after.length > 0 && after === before.slice(0, -1)) {
4636
- await cmux(["send", "--workspace", ws, "--surface", sf, before.slice(-1)]);
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
- await deliver();
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;