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 CHANGED
@@ -2926,7 +2926,28 @@ function hasCCInputBox(screen) {
2926
2926
  return false;
2927
2927
  return lines.slice(topHR + 1, bottomHR).some((l) => /[>❯]/.test(l));
2928
2928
  }
2929
- function readInputBoxRaw(screen) {
2929
+ function hasModalOptionList(screen) {
2930
+ if (!screen)
2931
+ return false;
2932
+ const lines = screen.split(/\r?\n/);
2933
+ const HR_RE = /^\s*─{10,}\s*$/;
2934
+ let bottomHR = -1;
2935
+ let topHR = -1;
2936
+ for (let i = lines.length - 1; i >= 0; i--) {
2937
+ if (HR_RE.test(lines[i])) {
2938
+ if (bottomHR === -1)
2939
+ bottomHR = i;
2940
+ else {
2941
+ topHR = i;
2942
+ break;
2943
+ }
2944
+ }
2945
+ }
2946
+ if (topHR === -1)
2947
+ return false;
2948
+ return lines.slice(topHR + 1, bottomHR).some((l) => /^\s*\d+\.\s/.test(l));
2949
+ }
2950
+ function readInputBoxRaw(screen, opts) {
2930
2951
  if (!screen)
2931
2952
  return null;
2932
2953
  const lines = screen.split(/\r?\n/);
@@ -2952,7 +2973,8 @@ function readInputBoxRaw(screen) {
2952
2973
  s = s.replace(/\s*[▌█▔▎▏]+\s*$/, "");
2953
2974
  parts.push(s);
2954
2975
  }
2955
- return parts.join("").replace(/\s+$/, "");
2976
+ const joined = parts.join("");
2977
+ return opts?.trim === false ? joined : joined.replace(/\s+$/, "");
2956
2978
  }
2957
2979
  function classifyStartupSurface(screen) {
2958
2980
  if (CC_WORKING_RE.test(screen))
@@ -2973,6 +2995,19 @@ function classifySendOutcome(payload, postBox) {
2973
2995
  return "stuck";
2974
2996
  return "unknown";
2975
2997
  }
2998
+ function classifyDraftLiveness(before, after) {
2999
+ if (before === null || after === null)
3000
+ return "inconclusive";
3001
+ if (after === "")
3002
+ return "no-draft";
3003
+ if (before.length > 0) {
3004
+ const segs = [...new Intl.Segmenter().segment(before)];
3005
+ const expected = segs.slice(0, -1).map((s) => s.segment).join("").replace(/\s+$/, "");
3006
+ if (after === expected)
3007
+ return "real-draft";
3008
+ }
3009
+ return "inconclusive";
3010
+ }
2976
3011
  function createCmuxDriver() {
2977
3012
  return {
2978
3013
  name: "cmux",
@@ -3163,6 +3198,8 @@ function createCmuxDriver() {
3163
3198
  const draft = parseDraftFromScreen(screen);
3164
3199
  if (draft === null)
3165
3200
  throw new DeferDelivery(null);
3201
+ if (hasModalOptionList(screen))
3202
+ throw new DeferDelivery(null);
3166
3203
  if (draft === "") {
3167
3204
  await deliver();
3168
3205
  return;
@@ -3170,18 +3207,38 @@ function createCmuxDriver() {
3170
3207
  if (!opts?.probe)
3171
3208
  throw new DeferDelivery(draft);
3172
3209
  const before = readInputBoxRaw(screen);
3210
+ const rawBefore = readInputBoxRaw(screen, { trim: false });
3173
3211
  await cmux(["send-key", "--workspace", ws, "--surface", sf, "backspace"]);
3212
+ await new Promise((r) => setTimeout(r, 50));
3174
3213
  let afterScreen = "";
3175
3214
  try {
3176
3215
  afterScreen = await cmux(["read-screen", "--workspace", ws, "--surface", sf]);
3177
3216
  } catch {
3178
3217
  }
3179
3218
  const after = readInputBoxRaw(afterScreen);
3180
- if (before !== null && after !== null && after.length > 0 && after === before.slice(0, -1)) {
3181
- await cmux(["send", "--workspace", ws, "--surface", sf, before.slice(-1)]);
3219
+ const rawAfter = readInputBoxRaw(afterScreen, { trim: false });
3220
+ const liveness = classifyDraftLiveness(before, after);
3221
+ if (liveness === "real-draft") {
3222
+ const segs = before ? [...new Intl.Segmenter().segment(before)] : [];
3223
+ const lastGrapheme = segs.length > 0 ? segs[segs.length - 1].segment : before.slice(-1);
3224
+ await cmux(["send", "--workspace", ws, "--surface", sf, lastGrapheme]);
3182
3225
  throw new DeferDelivery(draft);
3183
3226
  }
3184
- await deliver();
3227
+ if (liveness === "no-draft") {
3228
+ await deliver();
3229
+ return;
3230
+ }
3231
+ if (rawBefore !== null && rawAfter !== null) {
3232
+ if (rawBefore !== rawAfter) {
3233
+ const segs = [...new Intl.Segmenter().segment(rawBefore)];
3234
+ const lastGrapheme = segs.length > 0 ? segs[segs.length - 1].segment : rawBefore.slice(-1);
3235
+ await cmux(["send", "--workspace", ws, "--surface", sf, lastGrapheme]);
3236
+ throw new DeferDelivery(draft);
3237
+ }
3238
+ await deliver();
3239
+ return;
3240
+ }
3241
+ throw new DeferDelivery(draft);
3185
3242
  },
3186
3243
  async listSurfaces(workspaceId) {
3187
3244
  let output;
@@ -4079,8 +4136,8 @@ async function sendFirstTurnWhenReady(runtime, pane, task, preLaunchScreen, acce
4079
4136
  let stable = false;
4080
4137
  for (let i = 0; i < maxPolls && !stable; i++) {
4081
4138
  const screen = await runtime.readPaneScreen(pane) ?? "";
4082
- const hasInputBox = !!acceptanceConfig?.splashMarker || hasCCInputBox(screen);
4083
- if (screen.length > 0 && screen === previousScreen && screen !== preLaunchScreen && hasInputBox) {
4139
+ const ready = acceptanceConfig?.splashMarker ? true : hasCCInputBox(screen) && classifyStartupSurface(screen) === "idle";
4140
+ if (screen.length > 0 && screen === previousScreen && screen !== preLaunchScreen && ready) {
4084
4141
  stable = true;
4085
4142
  } else {
4086
4143
  previousScreen = screen;
@@ -4143,7 +4200,7 @@ var init_crew_pane = __esm({
4143
4200
  init_dist2();
4144
4201
  SEND_FIRST_TURN_FLOOR_MS = 1500;
4145
4202
  POLL_INTERVAL_MS = 750;
4146
- SEND_FIRST_TURN_TIMEOUT_MS = 2e4;
4203
+ SEND_FIRST_TURN_TIMEOUT_MS = 9e4;
4147
4204
  POST_SEND_CHECK_MS = 750;
4148
4205
  SPLASH_MAX_CHECKS = 20;
4149
4206
  SPLASH_RESEND_EVERY_N = 4;