squadrant 0.26.1 → 0.26.3

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.
@@ -423,22 +423,22 @@ function defaultCmuxConfigPath() {
423
423
  return join(homedir(), ".config", "cmux", "cmux.json");
424
424
  }
425
425
  function ensureSocketAutomation(opts = {}) {
426
- const path28 = opts.path ?? defaultCmuxConfigPath();
427
- if (!existsSync(path28)) {
428
- mkdirSync(dirname(path28), { recursive: true });
429
- writeFileSync(path28, MINIMAL_TEMPLATE);
430
- return { path: path28, changed: true, alreadySet: false };
426
+ const path29 = opts.path ?? defaultCmuxConfigPath();
427
+ if (!existsSync(path29)) {
428
+ mkdirSync(dirname(path29), { recursive: true });
429
+ writeFileSync(path29, MINIMAL_TEMPLATE);
430
+ return { path: path29, changed: true, alreadySet: false };
431
431
  }
432
- const text = readFileSync(path28, "utf-8");
432
+ const text = readFileSync(path29, "utf-8");
433
433
  const current = parse(text)?.automation?.socketControlMode;
434
434
  if (current === AUTOMATION_MODE) {
435
- return { path: path28, changed: false, alreadySet: true };
435
+ return { path: path29, changed: false, alreadySet: true };
436
436
  }
437
437
  const edits = modify(text, [...SOCKET_CONTROL_MODE_PATH], AUTOMATION_MODE, {
438
438
  formattingOptions: { insertSpaces: true, tabSize: 2 }
439
439
  });
440
- writeFileSync(path28, applyEdits(text, edits));
441
- return { path: path28, changed: true, alreadySet: false };
440
+ writeFileSync(path29, applyEdits(text, edits));
441
+ return { path: path29, changed: true, alreadySet: false };
442
442
  }
443
443
  var SOCKET_CONTROL_MODE_PATH, AUTOMATION_MODE, MINIMAL_TEMPLATE;
444
444
  var init_cmux_config = __esm({
@@ -588,9 +588,9 @@ import { join as join4 } from "path";
588
588
  function defaultStatePath() {
589
589
  return join4(homedir3(), ".config", "squadrant", "state", "cmux-autoconfig.json");
590
590
  }
591
- function readState(path28) {
591
+ function readState(path29) {
592
592
  try {
593
- return JSON.parse(readConfigFileSync(path28));
593
+ return JSON.parse(readConfigFileSync(path29));
594
594
  } catch {
595
595
  return {};
596
596
  }
@@ -1774,12 +1774,12 @@ async function* readFromCursor(opts) {
1774
1774
  continue;
1775
1775
  throw e;
1776
1776
  }
1777
- for (const line of buf.split("\n")) {
1778
- if (!line.trim())
1777
+ for (const line2 of buf.split("\n")) {
1778
+ if (!line2.trim())
1779
1779
  continue;
1780
1780
  let entry;
1781
1781
  try {
1782
- entry = JSON.parse(line);
1782
+ entry = JSON.parse(line2);
1783
1783
  } catch {
1784
1784
  continue;
1785
1785
  }
@@ -1881,17 +1881,17 @@ function createDecoder(onParseError) {
1881
1881
  const out = [];
1882
1882
  let idx;
1883
1883
  while ((idx = buf.indexOf("\n")) >= 0) {
1884
- const line = buf.slice(0, idx);
1884
+ const line2 = buf.slice(0, idx);
1885
1885
  buf = buf.slice(idx + 1);
1886
- if (!line.trim())
1886
+ if (!line2.trim())
1887
1887
  continue;
1888
1888
  try {
1889
- const parsed = JSON.parse(line);
1889
+ const parsed = JSON.parse(line2);
1890
1890
  if (typeof parsed === "object" && parsed !== null && parsed.type === "_keepalive")
1891
1891
  continue;
1892
1892
  out.push(parsed);
1893
1893
  } catch {
1894
- onParseError?.(line);
1894
+ onParseError?.(line2);
1895
1895
  }
1896
1896
  }
1897
1897
  return out;
@@ -2051,11 +2051,11 @@ function encodeFrame(f) {
2051
2051
  }
2052
2052
  function decodeFrames(wire) {
2053
2053
  const out = [];
2054
- for (const line of wire.split("\n")) {
2055
- if (!line.trim())
2054
+ for (const line2 of wire.split("\n")) {
2055
+ if (!line2.trim())
2056
2056
  continue;
2057
2057
  try {
2058
- const parsed = JSON.parse(line);
2058
+ const parsed = JSON.parse(line2);
2059
2059
  if (parsed.type === "_keepalive")
2060
2060
  continue;
2061
2061
  out.push(parsed);
@@ -2537,10 +2537,10 @@ function detectForeignInstall(parsed, thisEntry, registeredEntryExists) {
2537
2537
  isUpgrade: isVersionUpgrade(parsed.daemonEntry, thisEntry)
2538
2538
  };
2539
2539
  }
2540
- function sanitizePathForPlist(path28) {
2540
+ function sanitizePathForPlist(path29) {
2541
2541
  const seen = /* @__PURE__ */ new Set();
2542
2542
  const stable = [];
2543
- for (const p of path28.split(":")) {
2543
+ for (const p of path29.split(":")) {
2544
2544
  if (!p)
2545
2545
  continue;
2546
2546
  if (p.includes("/.claude/plugins/"))
@@ -3243,14 +3243,14 @@ function detectTrailingQuestion(text) {
3243
3243
  let inFence = false;
3244
3244
  let lastLine = null;
3245
3245
  for (const raw of text.split(/\r?\n/)) {
3246
- const line = raw.trim();
3247
- if (line.startsWith("```")) {
3246
+ const line2 = raw.trim();
3247
+ if (line2.startsWith("```")) {
3248
3248
  inFence = !inFence;
3249
3249
  continue;
3250
3250
  }
3251
- if (inFence || line === "")
3251
+ if (inFence || line2 === "")
3252
3252
  continue;
3253
- lastLine = line;
3253
+ lastLine = line2;
3254
3254
  }
3255
3255
  if (lastLine && lastLine.endsWith("?"))
3256
3256
  return lastLine;
@@ -3261,9 +3261,9 @@ function isQuotedLine(raw) {
3261
3261
  return QUOTED_PREFIX_RE.test(noAnsi);
3262
3262
  }
3263
3263
  function stripChrome(raw) {
3264
- let line = raw.replace(/\[[0-9;]*m/g, "");
3265
- line = line.replace(/^[\s│┃▏▕|]+/, "").replace(/[\s│┃▏▕|]+$/, "");
3266
- const trimmed = line.trim();
3264
+ let line2 = raw.replace(/\[[0-9;]*m/g, "");
3265
+ line2 = line2.replace(/^[\s│┃▏▕|]+/, "").replace(/[\s│┃▏▕|]+$/, "");
3266
+ const trimmed = line2.trim();
3267
3267
  if (trimmed === "")
3268
3268
  return null;
3269
3269
  if (PURE_CHROME_RE.test(trimmed))
@@ -3924,12 +3924,12 @@ function extractUserIntentFromTranscript(jsonl) {
3924
3924
  return null;
3925
3925
  const lines = jsonl.split(/\r?\n/);
3926
3926
  for (let i = lines.length - 1; i >= 0; i--) {
3927
- const line = lines[i].trim();
3928
- if (!line)
3927
+ const line2 = lines[i].trim();
3928
+ if (!line2)
3929
3929
  continue;
3930
3930
  let entry;
3931
3931
  try {
3932
- entry = JSON.parse(line);
3932
+ entry = JSON.parse(line2);
3933
3933
  } catch {
3934
3934
  continue;
3935
3935
  }
@@ -4378,10 +4378,10 @@ async function reapCrewChildren(taskId, graceMs = 2e3, execFn = nodeExec) {
4378
4378
  execFn("ps auxE", { maxBuffer: 64 * 1024 * 1024 }, (err, out) => err ? reject(err) : resolve4(out));
4379
4379
  });
4380
4380
  const pids = [];
4381
- for (const line of stdout.split("\n").slice(1)) {
4382
- if (!line.includes(marker))
4381
+ for (const line2 of stdout.split("\n").slice(1)) {
4382
+ if (!line2.includes(marker))
4383
4383
  continue;
4384
- const pid = parseInt(line.trim().split(/\s+/)[1], 10);
4384
+ const pid = parseInt(line2.trim().split(/\s+/)[1], 10);
4385
4385
  if (!isNaN(pid) && pid !== process.pid)
4386
4386
  pids.push(pid);
4387
4387
  }
@@ -4662,9 +4662,13 @@ async function runCrewSpawn(input, config, deps) {
4662
4662
  await deps.runtime.sendToPane(pane2, `cd ${shellQuote(spawnCwd)} && ${envPrefix}${routerPrefix} ${niceCrewCommand(cliCommand2)}`);
4663
4663
  const preLaunchScreen = await deps.runtime.readPaneScreen(pane2) ?? "";
4664
4664
  const claudeFirstTurn = spillOversizedFirstTurn(firstTurnTask, rec.id);
4665
- const sendPromise = deps.sendFirstTurn(pane2, `${claudeFirstTurn}
4665
+ const peerBrief = `${firstTurnTask}
4666
4666
 
4667
- ${buildCompletionProtocol(rec.id, input.project)}`, preLaunchScreen);
4667
+ ${buildCompletionProtocol(rec.id, input.project)}`;
4668
+ const peerResult = deps.sendFirstTurnPeer ? await deps.sendFirstTurnPeer({ pane: pane2, taskId: rec.id, project: input.project, messagingSocketPath, message: peerBrief }).catch(() => ({ kind: "fallback" })) : { kind: "fallback" };
4669
+ const sendPromise = peerResult.kind === "fallback" ? deps.sendFirstTurn(pane2, `${claudeFirstTurn}
4670
+
4671
+ ${buildCompletionProtocol(rec.id, input.project)}`, preLaunchScreen) : Promise.resolve({ delivered: peerResult.kind === "delivered" });
4668
4672
  let agentNotStarted = false;
4669
4673
  const scrapeDelivered = sendPromise.then((r) => {
4670
4674
  agentNotStarted = !!r.agentNotStarted;
@@ -5076,11 +5080,11 @@ var init_captain_record = __esm({
5076
5080
  // packages/core/dist/opencode-session.js
5077
5081
  import { execFileSync as execFileSync4 } from "child_process";
5078
5082
  async function listSessions(port, fetchImpl = fetch, timeoutMs = 5e3) {
5079
- for (const path28 of ["/session", "/api/session"]) {
5083
+ for (const path29 of ["/session", "/api/session"]) {
5080
5084
  const ac = new AbortController();
5081
5085
  const t = setTimeout(() => ac.abort(), timeoutMs);
5082
5086
  try {
5083
- const res = await fetchImpl(`http://127.0.0.1:${port}${path28}`, { signal: ac.signal });
5087
+ const res = await fetchImpl(`http://127.0.0.1:${port}${path29}`, { signal: ac.signal });
5084
5088
  if (!res.ok)
5085
5089
  continue;
5086
5090
  const rows = await res.json();
@@ -5095,8 +5099,8 @@ async function listSessions(port, fetchImpl = fetch, timeoutMs = 5e3) {
5095
5099
  }
5096
5100
  function parseLiveOpencodeServers(psOutput) {
5097
5101
  const out = [];
5098
- for (const line of psOutput.split("\n")) {
5099
- const m = line.match(/^\s*(\d+)\s+(.+)$/);
5102
+ for (const line2 of psOutput.split("\n")) {
5103
+ const m = line2.match(/^\s*(\d+)\s+(.+)$/);
5100
5104
  if (!m)
5101
5105
  continue;
5102
5106
  const pid = Number(m[1]);
@@ -5122,8 +5126,8 @@ function defaultPsOutput() {
5122
5126
  function defaultCwdOf(pid) {
5123
5127
  try {
5124
5128
  const out = execFileSync4("lsof", ["-a", "-p", String(pid), "-d", "cwd", "-Fn"], { encoding: "utf-8", timeout: 2e3 });
5125
- const line = out.split("\n").find((l) => l.startsWith("n"));
5126
- return line ? line.slice(1) : null;
5129
+ const line2 = out.split("\n").find((l) => l.startsWith("n"));
5130
+ return line2 ? line2.slice(1) : null;
5127
5131
  } catch {
5128
5132
  return null;
5129
5133
  }
@@ -5773,10 +5777,10 @@ function distBuiltAt() {
5773
5777
  return 0;
5774
5778
  }
5775
5779
  }
5776
- function gatherLogStats(path28, now, windowMs) {
5780
+ function gatherLogStats(path29, now, windowMs) {
5777
5781
  let sizeBytes = 0;
5778
5782
  try {
5779
- sizeBytes = statSync3(path28).size;
5783
+ sizeBytes = statSync3(path29).size;
5780
5784
  } catch {
5781
5785
  return { errorCount: 0, sizeBytes: 0, windowMs };
5782
5786
  }
@@ -5787,7 +5791,7 @@ function gatherLogStats(path28, now, windowMs) {
5787
5791
  const len = sizeBytes - start;
5788
5792
  let text = "";
5789
5793
  try {
5790
- const fd = openSync2(path28, "r");
5794
+ const fd = openSync2(path29, "r");
5791
5795
  try {
5792
5796
  const buf = Buffer.alloc(len);
5793
5797
  readSync(fd, buf, 0, len, start);
@@ -5800,10 +5804,10 @@ function gatherLogStats(path28, now, windowMs) {
5800
5804
  }
5801
5805
  const cutoff = now - windowMs;
5802
5806
  let errorCount = 0;
5803
- for (const line of text.split("\n")) {
5804
- if (!/error|failed/i.test(line))
5807
+ for (const line2 of text.split("\n")) {
5808
+ if (!/error|failed/i.test(line2))
5805
5809
  continue;
5806
- const m = line.match(/\d{4}-\d{2}-\d{2}T[\d:.]+Z/);
5810
+ const m = line2.match(/\d{4}-\d{2}-\d{2}T[\d:.]+Z/);
5807
5811
  if (m) {
5808
5812
  const ts = Date.parse(m[0]);
5809
5813
  if (!Number.isNaN(ts) && ts < cutoff)
@@ -7978,10 +7982,10 @@ function scan(bufRef, acc) {
7978
7982
  let saw = false;
7979
7983
  let idx;
7980
7984
  while ((idx = bufRef.value.indexOf("\n")) !== -1) {
7981
- const line = bufRef.value.slice(0, idx).trim();
7985
+ const line2 = bufRef.value.slice(0, idx).trim();
7982
7986
  bufRef.value = bufRef.value.slice(idx + 1);
7983
- if (line.startsWith("data:")) {
7984
- const payload = line.slice(5).trim();
7987
+ if (line2.startsWith("data:")) {
7988
+ const payload = line2.slice(5).trim();
7985
7989
  if (payload && payload !== "[DONE]") {
7986
7990
  try {
7987
7991
  if (absorb(JSON.parse(payload), acc))
@@ -8032,8 +8036,8 @@ var init_stream = __esm({
8032
8036
  // packages/core/dist/router/shim.js
8033
8037
  import { createServer as createServer3 } from "http";
8034
8038
  import { Readable } from "stream";
8035
- function joinUrl(base, path28) {
8036
- return base.replace(/\/+$/, "") + path28;
8039
+ function joinUrl(base, path29) {
8040
+ return base.replace(/\/+$/, "") + path29;
8037
8041
  }
8038
8042
  async function readBody(req) {
8039
8043
  const chunks = [];
@@ -8209,8 +8213,8 @@ function createRouterShim(opts) {
8209
8213
  writeJson(res, 200, { input_tokens: Math.max(1, Math.ceil(text.length / 4)) });
8210
8214
  }
8211
8215
  function handler(req, res) {
8212
- const path28 = pathnameOf(req.url);
8213
- if (req.method === "POST" && path28 === "/v1/messages") {
8216
+ const path29 = pathnameOf(req.url);
8217
+ if (req.method === "POST" && path29 === "/v1/messages") {
8214
8218
  void handleMessages(req, res).catch((err) => {
8215
8219
  log(`router internal error: ${err instanceof Error ? err.message : String(err)}`);
8216
8220
  if (!res.headersSent) {
@@ -8222,18 +8226,18 @@ function createRouterShim(opts) {
8222
8226
  });
8223
8227
  return;
8224
8228
  }
8225
- if (req.method === "POST" && path28 === "/v1/messages/count_tokens") {
8229
+ if (req.method === "POST" && path29 === "/v1/messages/count_tokens") {
8226
8230
  void handleCountTokens(req, res).catch(() => {
8227
8231
  if (!res.headersSent)
8228
8232
  writeJson(res, 502, anthropicError(502, "api_error", "router internal error").body);
8229
8233
  });
8230
8234
  return;
8231
8235
  }
8232
- if (req.method === "GET" && path28 === "/v1/models") {
8236
+ if (req.method === "GET" && path29 === "/v1/models") {
8233
8237
  writeJson(res, 200, modelsList([...advertisedModels]));
8234
8238
  return;
8235
8239
  }
8236
- if (req.method === "GET" && path28 === "/healthz") {
8240
+ if (req.method === "GET" && path29 === "/healthz") {
8237
8241
  writeJson(res, 200, { ready: server?.listening === true, upstreamReachable, lastError });
8238
8242
  return;
8239
8243
  }
@@ -8502,11 +8506,11 @@ async function probeCaptainChannel(project, opts = {}) {
8502
8506
  }
8503
8507
  }
8504
8508
  async function httpReachable(port, fetchImpl, timeoutMs) {
8505
- for (const path28 of ["/session", "/api/session"]) {
8509
+ for (const path29 of ["/session", "/api/session"]) {
8506
8510
  const ac = new AbortController();
8507
8511
  const t = setTimeout(() => ac.abort(), timeoutMs);
8508
8512
  try {
8509
- const res = await fetchImpl(`http://127.0.0.1:${port}${path28}`, { signal: ac.signal });
8513
+ const res = await fetchImpl(`http://127.0.0.1:${port}${path29}`, { signal: ac.signal });
8510
8514
  if (res.ok)
8511
8515
  return true;
8512
8516
  } catch {
@@ -8889,6 +8893,30 @@ async function runCrewAnswer(project, name, option, runtime, workspaceId, deps,
8889
8893
  if (!crew) {
8890
8894
  throw new Error(`Crew '${name}' not found for ${project}. Run 'squadrant crew list ${project}'.`);
8891
8895
  }
8896
+ const match = runtime.findDialog && runtime.answerDialog ? await deps.dialogMatch?.() : void 0;
8897
+ if (match) {
8898
+ const dialog = await runtime.findDialog(match).catch(() => void 0);
8899
+ if (dialog) {
8900
+ const log2 = deps.log ?? (() => {
8901
+ });
8902
+ const options2 = dialog.options.map((o) => ({ ...o, highlighted: false }));
8903
+ let target2;
8904
+ try {
8905
+ target2 = resolveOption(options2, option);
8906
+ if (opts?.expect && !target2.label.toLowerCase().includes(opts.expect.toLowerCase()))
8907
+ target2 = void 0;
8908
+ } catch {
8909
+ target2 = void 0;
8910
+ }
8911
+ if (target2) {
8912
+ log2(`\u2192 answering ${target2.index}. "${target2.label}" via the runtime (no keystrokes)`);
8913
+ const ok2 = await runtime.answerDialog(dialog, opts?.text ? { text: opts.text } : { label: target2.label }).catch(() => false);
8914
+ if (ok2)
8915
+ return { selected: target2, closed: true };
8916
+ }
8917
+ log2("runtime answer not applied \u2014 falling back to keystrokes");
8918
+ }
8919
+ }
8892
8920
  const modal = await deps.readModalOptions(crew);
8893
8921
  if (!modal || modal.options.length === 0) {
8894
8922
  throw new Error(`Crew '${name}' has no interactive option prompt visible right now \u2014 nothing to answer. Read its screen with 'squadrant crew read ${project} ${name}' to check its state.`);
@@ -9268,6 +9296,58 @@ var init_source = __esm({
9268
9296
  }
9269
9297
  });
9270
9298
 
9299
+ // packages/core/dist/peer-first-turn.js
9300
+ function screenShowsTrustPanel(screen) {
9301
+ return /do you trust the files in this folder|is this a project you created or one you trust|is this a project you trust/i.test(screen);
9302
+ }
9303
+ function trustPanelAcceptKeys(screen) {
9304
+ return /❯\s*(\d\.\s*)?No\b/.test(screen) ? ["Down", "Enter"] : ["Enter"];
9305
+ }
9306
+ async function deliverFirstTurnViaPeer(message, deps) {
9307
+ const pollMs = deps.pollMs ?? DEFAULT_POLL_MS2;
9308
+ const deadline = deps.now() + (deps.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS);
9309
+ let lastTrustAnswer = -Infinity;
9310
+ for (; ; ) {
9311
+ if (deps.statusOf()?.status === "idle")
9312
+ break;
9313
+ if (deps.now() >= deadline)
9314
+ return { kind: "fallback" };
9315
+ if (!deps.statusOf() && deps.now() - lastTrustAnswer >= TRUST_ANSWER_COOLDOWN_MS) {
9316
+ const screen = await deps.readScreen().catch(() => "");
9317
+ if (screenShowsTrustPanel(screen)) {
9318
+ lastTrustAnswer = deps.now();
9319
+ for (const key of trustPanelAcceptKeys(screen))
9320
+ await deps.pressKey(key).catch(() => {
9321
+ });
9322
+ }
9323
+ }
9324
+ await deps.sleep(pollMs);
9325
+ }
9326
+ const outcome = await deps.send(message);
9327
+ if (fallsBackToPane(outcome))
9328
+ return { kind: "fallback" };
9329
+ if (outcome.status === "accepted" && outcome.confirmed)
9330
+ return { kind: "delivered" };
9331
+ const confirmDeadline = deps.now() + (deps.confirmGraceMs ?? DEFAULT_CONFIRM_GRACE_MS);
9332
+ for (; ; ) {
9333
+ if (await deps.isConfirmed().catch(() => false))
9334
+ return { kind: "delivered" };
9335
+ if (deps.now() >= confirmDeadline)
9336
+ return { kind: "unconfirmed" };
9337
+ await deps.sleep(pollMs);
9338
+ }
9339
+ }
9340
+ var DEFAULT_READY_TIMEOUT_MS, DEFAULT_POLL_MS2, DEFAULT_CONFIRM_GRACE_MS, TRUST_ANSWER_COOLDOWN_MS;
9341
+ var init_peer_first_turn = __esm({
9342
+ "packages/core/dist/peer-first-turn.js"() {
9343
+ init_control_channel();
9344
+ DEFAULT_READY_TIMEOUT_MS = 9e4;
9345
+ DEFAULT_POLL_MS2 = 250;
9346
+ DEFAULT_CONFIRM_GRACE_MS = 1e4;
9347
+ TRUST_ANSWER_COOLDOWN_MS = 5e3;
9348
+ }
9349
+ });
9350
+
9271
9351
  // packages/core/dist/knowledge/paths.js
9272
9352
  import path14 from "path";
9273
9353
  function kbDir(hubVault, kb) {
@@ -9689,28 +9769,28 @@ function requireSnippet() {
9689
9769
  const maxLineLength = options.maxLength - (options.indent + lineNoLength + 3);
9690
9770
  for (let i = 1; i <= options.linesBefore; i++) {
9691
9771
  if (foundLineNo - i < 0) break;
9692
- const line2 = getLine(
9772
+ const line22 = getLine(
9693
9773
  mark2.buffer,
9694
9774
  lineStarts[foundLineNo - i],
9695
9775
  lineEnds[foundLineNo - i],
9696
9776
  mark2.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]),
9697
9777
  maxLineLength
9698
9778
  );
9699
- result = common2.repeat(" ", options.indent) + padStart((mark2.line - i + 1).toString(), lineNoLength) + " | " + line2.str + "\n" + result;
9779
+ result = common2.repeat(" ", options.indent) + padStart((mark2.line - i + 1).toString(), lineNoLength) + " | " + line22.str + "\n" + result;
9700
9780
  }
9701
- const line = getLine(mark2.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark2.position, maxLineLength);
9702
- result += common2.repeat(" ", options.indent) + padStart((mark2.line + 1).toString(), lineNoLength) + " | " + line.str + "\n";
9703
- result += common2.repeat("-", options.indent + lineNoLength + 3 + line.pos) + "^\n";
9781
+ const line2 = getLine(mark2.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark2.position, maxLineLength);
9782
+ result += common2.repeat(" ", options.indent) + padStart((mark2.line + 1).toString(), lineNoLength) + " | " + line2.str + "\n";
9783
+ result += common2.repeat("-", options.indent + lineNoLength + 3 + line2.pos) + "^\n";
9704
9784
  for (let i = 1; i <= options.linesAfter; i++) {
9705
9785
  if (foundLineNo + i >= lineEnds.length) break;
9706
- const line2 = getLine(
9786
+ const line22 = getLine(
9707
9787
  mark2.buffer,
9708
9788
  lineStarts[foundLineNo + i],
9709
9789
  lineEnds[foundLineNo + i],
9710
9790
  mark2.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]),
9711
9791
  maxLineLength
9712
9792
  );
9713
- result += common2.repeat(" ", options.indent) + padStart((mark2.line + i + 1).toString(), lineNoLength) + " | " + line2.str + "\n";
9793
+ result += common2.repeat(" ", options.indent) + padStart((mark2.line + i + 1).toString(), lineNoLength) + " | " + line22.str + "\n";
9714
9794
  }
9715
9795
  return result.replace(/\n$/, "");
9716
9796
  }
@@ -11997,17 +12077,17 @@ function requireDumper() {
11997
12077
  let result = "";
11998
12078
  const length = string.length;
11999
12079
  while (position < length) {
12000
- let line;
12080
+ let line2;
12001
12081
  const next = string.indexOf("\n", position);
12002
12082
  if (next === -1) {
12003
- line = string.slice(position);
12083
+ line2 = string.slice(position);
12004
12084
  position = length;
12005
12085
  } else {
12006
- line = string.slice(position, next + 1);
12086
+ line2 = string.slice(position, next + 1);
12007
12087
  position = next + 1;
12008
12088
  }
12009
- if (line.length && line !== "\n") result += ind;
12010
- result += line;
12089
+ if (line2.length && line2 !== "\n") result += ind;
12090
+ result += line2;
12011
12091
  }
12012
12092
  return result;
12013
12093
  }
@@ -12192,15 +12272,15 @@ function requireDumper() {
12192
12272
  let match;
12193
12273
  while (match = lineRe.exec(string)) {
12194
12274
  const prefix = match[1];
12195
- const line = match[2];
12196
- moreIndented = line[0] === " ";
12197
- result += prefix + (!prevMoreIndented && !moreIndented && line !== "" ? "\n" : "") + foldLine(line, width);
12275
+ const line2 = match[2];
12276
+ moreIndented = line2[0] === " ";
12277
+ result += prefix + (!prevMoreIndented && !moreIndented && line2 !== "" ? "\n" : "") + foldLine(line2, width);
12198
12278
  prevMoreIndented = moreIndented;
12199
12279
  }
12200
12280
  return result;
12201
12281
  }
12202
- function foldLine(line, width) {
12203
- if (line === "" || line[0] === " ") return line;
12282
+ function foldLine(line2, width) {
12283
+ if (line2 === "" || line2[0] === " ") return line2;
12204
12284
  const breakRe = / [^ ]/g;
12205
12285
  let match;
12206
12286
  let start = 0;
@@ -12208,20 +12288,20 @@ function requireDumper() {
12208
12288
  let curr = 0;
12209
12289
  let next = 0;
12210
12290
  let result = "";
12211
- while (match = breakRe.exec(line)) {
12291
+ while (match = breakRe.exec(line2)) {
12212
12292
  next = match.index;
12213
12293
  if (next - start > width) {
12214
12294
  end = curr > start ? curr : next;
12215
- result += "\n" + line.slice(start, end);
12295
+ result += "\n" + line2.slice(start, end);
12216
12296
  start = end + 1;
12217
12297
  }
12218
12298
  curr = next;
12219
12299
  }
12220
12300
  result += "\n";
12221
- if (line.length - start > width && curr > start) {
12222
- result += line.slice(start, curr) + "\n" + line.slice(curr + 1);
12301
+ if (line2.length - start > width && curr > start) {
12302
+ result += line2.slice(start, curr) + "\n" + line2.slice(curr + 1);
12223
12303
  } else {
12224
- result += line.slice(start);
12304
+ result += line2.slice(start);
12225
12305
  }
12226
12306
  return result.slice(1);
12227
12307
  }
@@ -12630,6 +12710,220 @@ var init_sources = __esm({
12630
12710
  }
12631
12711
  });
12632
12712
 
12713
+ // packages/core/dist/knowledge/inject.js
12714
+ import fs19 from "fs";
12715
+ import path18 from "path";
12716
+ function sessionOrder(a, b) {
12717
+ const proj = (r) => r.layer.startsWith("project:") ? 0 : 1;
12718
+ const mod = (r) => r.modality === "must-not" ? 0 : 1;
12719
+ return proj(a) - proj(b) || mod(a) - mod(b) || a.id.localeCompare(b.id);
12720
+ }
12721
+ function formatSessionContext(kbs, rules, cap = SESSION_RULE_CAP) {
12722
+ const hard = rules.filter((r) => r.status === "active" && (r.modality === "must" || r.modality === "must-not")).sort(sessionOrder);
12723
+ const shown = hard.slice(0, cap);
12724
+ const lines = [
12725
+ `<squadrant-project-rules kb="${kbs.join(",")}">`,
12726
+ `Rules KB: ${kbs.join(", ")}. ${DATA_NOTE}`,
12727
+ ...shown.map(line)
12728
+ ];
12729
+ if (hard.length > shown.length)
12730
+ lines.push(`+${hard.length - shown.length} more: squadrant rules list --brief`);
12731
+ lines.push("Look up rules for a task with `squadrant rules search <terms>` / `squadrant rules show <id>` (rules-ops skill).");
12732
+ lines.push("</squadrant-project-rules>");
12733
+ return { text: lines.join("\n"), ids: shown.map((r) => r.id) };
12734
+ }
12735
+ function cleanPromptQuery(prompt) {
12736
+ const text = prompt.replace(/```[\s\S]*?(```|$)/g, " ").split("\n").filter((l) => l.length <= MAX_LINE_CHARS).join("\n").slice(0, MAX_PROMPT_CHARS).toLowerCase().replace(/https?:\/\/\S+/g, " ");
12737
+ const terms = [];
12738
+ const add = (t) => {
12739
+ if (t.length < 3 && !SHORT_TERMS.has(t) || /^\d+$/.test(t) || STOPWORDS.has(t) || terms.includes(t))
12740
+ return;
12741
+ terms.push(t);
12742
+ };
12743
+ for (const raw of text.split(/[^a-z0-9._-]+/)) {
12744
+ const t = raw.replace(/^[._-]+|[._-]+$/g, "");
12745
+ if (STOPWORDS.has(t))
12746
+ continue;
12747
+ add(t);
12748
+ const parts = t.split(/[._-]+/);
12749
+ if (parts.length > 1 && parts.every((x) => x.length >= 3 && !PREFIXES.has(x)))
12750
+ parts.forEach(add);
12751
+ if (terms.length >= MAX_TERMS)
12752
+ break;
12753
+ }
12754
+ return terms.slice(0, MAX_TERMS).join(" ");
12755
+ }
12756
+ function wholeWordTerms(rule, terms) {
12757
+ const text = [
12758
+ rule.id,
12759
+ ...rule.triggers?.keywords ?? [],
12760
+ ...rule.triggers?.expanded ?? [],
12761
+ rule.triggers?.when ?? "",
12762
+ rule.statement
12763
+ ].join("\n").toLowerCase();
12764
+ return terms.filter((t) => {
12765
+ const base = t.length > 4 ? t.replace(/(es|s)$/, "") : t;
12766
+ return new RegExp(`(^|[^a-z0-9])(?:${escapeRe(t)}|${escapeRe(base)}(?:s|es)?)($|[^a-z0-9])`).test(text);
12767
+ });
12768
+ }
12769
+ function selectPromptHits(hits, query, seen, opts = {}) {
12770
+ const minScore = opts.minScore ?? PROMPT_MIN_SCORE;
12771
+ const terms = query.split(" ").filter(Boolean);
12772
+ return hits.filter((h) => {
12773
+ if (seen.has(h.rule.id))
12774
+ return false;
12775
+ const n = wholeWordTerms(h.rule, terms).length;
12776
+ return n >= 2 && h.score >= minScore || n === 1 && h.score >= PROMPT_SINGLE_TERM_MIN_SCORE;
12777
+ }).slice(0, opts.cap ?? PROMPT_RULE_CAP);
12778
+ }
12779
+ function isSystemPrompt(prompt) {
12780
+ const t = prompt.trimStart();
12781
+ return /^(⚠|🗒|\[stale\b|CREW [A-Z]|Another Claude session sent a message)/u.test(t) || t.includes("<cross-session-message");
12782
+ }
12783
+ function promptText(prompt) {
12784
+ const m = BRIEF_POINTER_RE.exec(prompt.trimStart());
12785
+ if (!m)
12786
+ return prompt;
12787
+ try {
12788
+ return fs19.readFileSync(m[1], "utf8").slice(0, MAX_PROMPT_CHARS * 2);
12789
+ } catch {
12790
+ return prompt;
12791
+ }
12792
+ }
12793
+ function formatPromptContext(hits) {
12794
+ return [
12795
+ '<squadrant-project-rules match="prompt">',
12796
+ `Rules that may apply to this prompt. ${DATA_NOTE}`,
12797
+ ...hits.map((h) => line(h.rule)),
12798
+ "</squadrant-project-rules>"
12799
+ ].join("\n");
12800
+ }
12801
+ function injectStateDir(stateRoot) {
12802
+ return path18.join(stateRoot, "rules-inject");
12803
+ }
12804
+ function readSeenRules(stateRoot, sessionId) {
12805
+ try {
12806
+ const ids = JSON.parse(fs19.readFileSync(sessionFile(stateRoot, sessionId), "utf8"));
12807
+ return new Set(Array.isArray(ids) ? ids.filter((x) => typeof x === "string") : []);
12808
+ } catch {
12809
+ return /* @__PURE__ */ new Set();
12810
+ }
12811
+ }
12812
+ function recordSeenRules(stateRoot, sessionId, ids) {
12813
+ if (!ids.length)
12814
+ return;
12815
+ const seen = readSeenRules(stateRoot, sessionId);
12816
+ for (const id of ids)
12817
+ seen.add(id);
12818
+ fs19.mkdirSync(injectStateDir(stateRoot), { recursive: true });
12819
+ fs19.writeFileSync(sessionFile(stateRoot, sessionId), JSON.stringify([...seen]));
12820
+ }
12821
+ function pruneSeenRules(stateRoot, now = Date.now()) {
12822
+ const dir = injectStateDir(stateRoot);
12823
+ let names;
12824
+ try {
12825
+ names = fs19.readdirSync(dir);
12826
+ } catch {
12827
+ return;
12828
+ }
12829
+ for (const n of names) {
12830
+ const f = path18.join(dir, n);
12831
+ try {
12832
+ if (now - fs19.statSync(f).mtimeMs > SEEN_TTL_MS)
12833
+ fs19.unlinkSync(f);
12834
+ } catch {
12835
+ }
12836
+ }
12837
+ }
12838
+ async function withBudget(fn, budgetMs = INJECT_BUDGET_MS) {
12839
+ const start = Date.now();
12840
+ let timer;
12841
+ try {
12842
+ const timeout = new Promise((resolve4) => {
12843
+ timer = setTimeout(() => resolve4(null), budgetMs);
12844
+ });
12845
+ const out = await Promise.race([Promise.resolve().then(fn), timeout]);
12846
+ return Date.now() - start > budgetMs ? null : out;
12847
+ } catch {
12848
+ return null;
12849
+ } finally {
12850
+ clearTimeout(timer);
12851
+ }
12852
+ }
12853
+ function resolveInjectProject(cfg, cwd, env, project) {
12854
+ const named = project ?? env.SQUADRANT_CREW_PROJECT;
12855
+ if (named)
12856
+ return cfg.projects[named] ? named : null;
12857
+ let best = null;
12858
+ let bestLen = -1;
12859
+ for (const [name, pc] of Object.entries(cfg.projects)) {
12860
+ const root = resolveHome(pc.path);
12861
+ if ((cwd === root || cwd.startsWith(root + path18.sep)) && root.length > bestLen) {
12862
+ best = name;
12863
+ bestLen = root.length;
12864
+ }
12865
+ }
12866
+ return best;
12867
+ }
12868
+ function computeRulesInjection(i) {
12869
+ if (i.env.SQUADRANT_RULES_INJECT === "0")
12870
+ return null;
12871
+ const p = typeof i.payload === "object" && i.payload !== null ? i.payload : {};
12872
+ const cwd = typeof p.cwd === "string" && p.cwd ? p.cwd : i.cwd;
12873
+ const project = resolveInjectProject(i.cfg, cwd, i.env, i.project);
12874
+ if (!project)
12875
+ return null;
12876
+ const kbs = subscribedKbs(i.cfg, project);
12877
+ if (!kbs.length)
12878
+ return null;
12879
+ const sessionId = typeof p.session_id === "string" && p.session_id ? p.session_id : null;
12880
+ if (i.event === "session-start") {
12881
+ const { text, ids } = formatSessionContext(kbs, resolveProjectRules(i.cfg, project).rules);
12882
+ if (sessionId) {
12883
+ pruneSeenRules(i.stateRoot);
12884
+ recordSeenRules(i.stateRoot, sessionId, ids);
12885
+ }
12886
+ return text;
12887
+ }
12888
+ if (typeof p.prompt !== "string" || isSystemPrompt(p.prompt))
12889
+ return null;
12890
+ const query = cleanPromptQuery(promptText(p.prompt));
12891
+ if (!query)
12892
+ return null;
12893
+ const seen = sessionId ? readSeenRules(i.stateRoot, sessionId) : /* @__PURE__ */ new Set();
12894
+ const picked = selectPromptHits(searchRules(resolveProjectRules(i.cfg, project).rules, query), query, seen);
12895
+ if (!picked.length)
12896
+ return null;
12897
+ if (sessionId)
12898
+ recordSeenRules(i.stateRoot, sessionId, picked.map((h) => h.rule.id));
12899
+ return formatPromptContext(picked);
12900
+ }
12901
+ var SESSION_RULE_CAP, PROMPT_RULE_CAP, PROMPT_MIN_SCORE, PROMPT_SINGLE_TERM_MIN_SCORE, INJECT_BUDGET_MS, MAX_PROMPT_CHARS, MAX_LINE_CHARS, MAX_TERMS, SHORT_TERMS, PREFIXES, SEEN_TTL_MS, STOPWORDS, DATA_NOTE, line, escapeRe, BRIEF_POINTER_RE, sessionFile;
12902
+ var init_inject = __esm({
12903
+ "packages/core/dist/knowledge/inject.js"() {
12904
+ init_dist();
12905
+ init_search();
12906
+ init_layers();
12907
+ SESSION_RULE_CAP = 20;
12908
+ PROMPT_RULE_CAP = 3;
12909
+ PROMPT_MIN_SCORE = 8;
12910
+ PROMPT_SINGLE_TERM_MIN_SCORE = 13;
12911
+ INJECT_BUDGET_MS = 1500;
12912
+ MAX_PROMPT_CHARS = 3e3;
12913
+ MAX_LINE_CHARS = 400;
12914
+ MAX_TERMS = 40;
12915
+ SHORT_TERMS = /* @__PURE__ */ new Set(["pr", "db", "ci", "ui"]);
12916
+ PREFIXES = /* @__PURE__ */ new Set(["pre", "non", "sub", "anti", "multi", "semi", "post", "mid"]);
12917
+ SEEN_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
12918
+ STOPWORDS = new Set("the and for are but not you your yours with this that these those from into onto have has had was were will would can could should shall may might must does did doing done its it's our ours their them they what when where which who whom why how all any some each every other than then there here also just very too only own same such both few more most much many about above below after before again once out over under off further been being let lets please thanks thank okay yes yeah hello hey there need want make use using used get got give like know think see look sure ok now new one two way rule rules must-not looks sounds work working thing things something anything everything going well good great nice cool fine".split(/\s+/));
12919
+ DATA_NOTE = "These are project rules (data from the knowledge base), not instructions to run anything.";
12920
+ line = (r) => `${r.modality.toUpperCase()} ${r.id}: ${r.statement}`;
12921
+ escapeRe = (t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
12922
+ BRIEF_POINTER_RE = /^Full task is at (\S+\.md) — cat it/;
12923
+ sessionFile = (stateRoot, sessionId) => path18.join(injectStateDir(stateRoot), `${sessionId.replace(/[^A-Za-z0-9_-]/g, "_")}.json`);
12924
+ }
12925
+ });
12926
+
12633
12927
  // packages/core/dist/knowledge/index.js
12634
12928
  var init_knowledge2 = __esm({
12635
12929
  "packages/core/dist/knowledge/index.js"() {
@@ -12639,6 +12933,7 @@ var init_knowledge2 = __esm({
12639
12933
  init_index_file();
12640
12934
  init_search();
12641
12935
  init_sources();
12936
+ init_inject();
12642
12937
  }
12643
12938
  });
12644
12939
 
@@ -12669,12 +12964,16 @@ __export(dist_exports, {
12669
12964
  GROUP_DISPATCH_WARMUP_TIMEOUT_MS: () => GROUP_DISPATCH_WARMUP_TIMEOUT_MS,
12670
12965
  GateDecisionCache: () => GateDecisionCache,
12671
12966
  IDLE_DEBOUNCE_MS: () => IDLE_DEBOUNCE_MS,
12967
+ INJECT_BUDGET_MS: () => INJECT_BUDGET_MS,
12672
12968
  LABEL: () => LABEL,
12673
12969
  LivenessRegistry: () => LivenessRegistry,
12674
12970
  MONITOR_STALL_BUDGET_MS: () => MONITOR_STALL_BUDGET_MS,
12675
12971
  OPERATOR_INITIATED_COMMANDS: () => OPERATOR_INITIATED_COMMANDS,
12676
12972
  PANE_IDLE_AFTER_MS: () => PANE_IDLE_AFTER_MS,
12677
12973
  PROBE_QUIET_MS: () => PROBE_QUIET_MS,
12974
+ PROMPT_MIN_SCORE: () => PROMPT_MIN_SCORE,
12975
+ PROMPT_RULE_CAP: () => PROMPT_RULE_CAP,
12976
+ PROMPT_SINGLE_TERM_MIN_SCORE: () => PROMPT_SINGLE_TERM_MIN_SCORE,
12678
12977
  PROPOSED_DIR: () => PROPOSED_DIR,
12679
12978
  PROTOCOL_VERSION: () => PROTOCOL_VERSION,
12680
12979
  READ_ONLY_CREW_SUBCOMMANDS: () => READ_ONLY_CREW_SUBCOMMANDS,
@@ -12682,6 +12981,7 @@ __export(dist_exports, {
12682
12981
  ROUTER_READY_ATTEMPTS: () => ROUTER_READY_ATTEMPTS,
12683
12982
  ROUTER_READY_DELAY_MS: () => ROUTER_READY_DELAY_MS,
12684
12983
  SERVER_TOOL_TYPE_RE: () => SERVER_TOOL_TYPE_RE,
12984
+ SESSION_RULE_CAP: () => SESSION_RULE_CAP,
12685
12985
  SIDE_SESSION_ENV: () => SIDE_SESSION_ENV,
12686
12986
  SOURCES_TEMPLATE: () => SOURCES_TEMPLATE,
12687
12987
  STALE_THRESHOLD_MS: () => STALE_THRESHOLD_MS,
@@ -12722,9 +13022,11 @@ __export(dist_exports, {
12722
13022
  classifyCaptainPane: () => classifyCaptainPane,
12723
13023
  classifyHealth: () => classifyHealth,
12724
13024
  claudeEnvShadowsRouter: () => claudeEnvShadowsRouter,
13025
+ cleanPromptQuery: () => cleanPromptQuery,
12725
13026
  clearPending: () => clearPending,
12726
13027
  closeWorkItem: () => closeWorkItem,
12727
13028
  compileIndex: () => compileIndex,
13029
+ computeRulesInjection: () => computeRulesInjection,
12728
13030
  computeTemplateHash: () => computeTemplateHash,
12729
13031
  consumeExitMarker: () => consumeExitMarker,
12730
13032
  createAttach: () => createAttach,
@@ -12765,6 +13067,7 @@ __export(dist_exports, {
12765
13067
  defaultIsPidAlive: () => defaultIsPidAlive,
12766
13068
  defaultListenError: () => defaultListenError,
12767
13069
  defaultWorkRoot: () => defaultWorkRoot,
13070
+ deliverFirstTurnViaPeer: () => deliverFirstTurnViaPeer,
12768
13071
  deliverStartupPrompt: () => deliverStartupPrompt,
12769
13072
  deliverToCaptain: () => deliverToCaptain,
12770
13073
  deliverable: () => deliverable,
@@ -12798,6 +13101,8 @@ __export(dist_exports, {
12798
13101
  formatLifecycle: () => formatLifecycle,
12799
13102
  formatMediaReceipt: () => formatMediaReceipt,
12800
13103
  formatPermissionDecision: () => formatPermissionDecision,
13104
+ formatPromptContext: () => formatPromptContext,
13105
+ formatSessionContext: () => formatSessionContext,
12801
13106
  formatUsageLine: () => formatUsageLine,
12802
13107
  formatWatchdogWarning: () => formatWatchdogWarning,
12803
13108
  freshTrace: () => freshTrace,
@@ -12807,6 +13112,7 @@ __export(dist_exports, {
12807
13112
  hasModalOptionList: () => hasModalOptionList,
12808
13113
  healCmdFor: () => healCmdFor,
12809
13114
  inboundBody: () => inboundBody,
13115
+ injectStateDir: () => injectStateDir,
12810
13116
  isAuthorized: () => isAuthorized,
12811
13117
  isBareSpawn: () => isBareSpawn,
12812
13118
  isCaptainAlive: () => isCaptainAlive,
@@ -12822,6 +13128,7 @@ __export(dist_exports, {
12822
13128
  isReadOnlyTopLevelCommand: () => isReadOnlyTopLevelCommand,
12823
13129
  isSideTitle: () => isSideTitle,
12824
13130
  isStickyAttention: () => isStickyAttention,
13131
+ isSystemPrompt: () => isSystemPrompt,
12825
13132
  isTurnAccepted: () => isTurnAccepted,
12826
13133
  isVersionUpgrade: () => isVersionUpgrade,
12827
13134
  joinUrl: () => joinUrl,
@@ -12867,6 +13174,7 @@ __export(dist_exports, {
12867
13174
  programArgsBlock: () => programArgsBlock,
12868
13175
  projectHealth: () => projectHealth,
12869
13176
  projectRulesDir: () => projectRulesDir,
13177
+ pruneSeenRules: () => pruneSeenRules,
12870
13178
  pruneTopics: () => pruneTopics,
12871
13179
  purgeExpiredWorkItems: () => purgeExpiredWorkItems,
12872
13180
  readCaptainAddress: () => readCaptainAddress,
@@ -12874,11 +13182,13 @@ __export(dist_exports, {
12874
13182
  readFromCursor: () => readFromCursor,
12875
13183
  readIndex: () => readIndex,
12876
13184
  readRunningMarker: () => readRunningMarker,
13185
+ readSeenRules: () => readSeenRules,
12877
13186
  readUserIntent: () => readUserIntent,
12878
13187
  realpathOrSelf: () => realpathOrSelf,
12879
13188
  reapCrewChildren: () => reapCrewChildren,
12880
13189
  reapOrphanedCrews: () => reapOrphanedCrews,
12881
13190
  reconcileLiveness: () => reconcileLiveness,
13191
+ recordSeenRules: () => recordSeenRules,
12882
13192
  recordSession: () => recordSession,
12883
13193
  recoverStall: () => recoverStall,
12884
13194
  reduce: () => reduce,
@@ -12900,6 +13210,7 @@ __export(dist_exports, {
12900
13210
  resolveGateMode: () => resolveGateMode,
12901
13211
  resolveGatePolicy: () => resolveGatePolicy,
12902
13212
  resolveGateTools: () => resolveGateTools,
13213
+ resolveInjectProject: () => resolveInjectProject,
12903
13214
  resolveProject: () => resolveProject,
12904
13215
  resolveProjectRules: () => resolveProjectRules,
12905
13216
  resolveRouterCredentials: () => resolveRouterCredentials,
@@ -12938,7 +13249,9 @@ __export(dist_exports, {
12938
13249
  saveState: () => saveState,
12939
13250
  screenHasSplashMarker: () => screenHasSplashMarker,
12940
13251
  screenHash: () => screenHash,
13252
+ screenShowsTrustPanel: () => screenShowsTrustPanel,
12941
13253
  searchRules: () => searchRules,
13254
+ selectPromptHits: () => selectPromptHits,
12942
13255
  sendRequest: () => sendRequest,
12943
13256
  setLastUserId: () => setLastUserId,
12944
13257
  setNotify: () => setNotify,
@@ -12962,11 +13275,14 @@ __export(dist_exports, {
12962
13275
  toControlEvent: () => toControlEvent,
12963
13276
  topicKey: () => topicKey,
12964
13277
  topicName: () => topicName,
13278
+ trustPanelAcceptKeys: () => trustPanelAcceptKeys,
12965
13279
  tryAcquireDaemonLock: () => tryAcquireDaemonLock,
12966
13280
  usageFromJson: () => usageFromJson,
12967
13281
  validateKb: () => validateKb,
12968
13282
  waitForCaptainDelivery: () => waitForCaptainDelivery,
12969
13283
  waitForWarmup: () => waitForWarmup,
13284
+ wholeWordTerms: () => wholeWordTerms,
13285
+ withBudget: () => withBudget,
12970
13286
  writeCaptainAddress: () => writeCaptainAddress,
12971
13287
  writeCursor: () => writeCursor,
12972
13288
  writeExitMarker: () => writeExitMarker,
@@ -13022,6 +13338,7 @@ var init_dist2 = __esm({
13022
13338
  init_conformance();
13023
13339
  init_source();
13024
13340
  init_control_channel();
13341
+ init_peer_first_turn();
13025
13342
  init_captain_channel();
13026
13343
  init_captain_record();
13027
13344
  init_opencode_session();
@@ -13069,7 +13386,7 @@ import { readdirSync as readdirSync4, readFileSync as readFileSync12 } from "fs"
13069
13386
  import { join as join18 } from "path";
13070
13387
 
13071
13388
  // packages/agents/dist/claude/registry.js
13072
- import fs19 from "fs";
13389
+ import fs20 from "fs";
13073
13390
  import { join as join17 } from "path";
13074
13391
  import { homedir as homedir7 } from "os";
13075
13392
  var CLAUDE_SESSIONS_DIR = join17(homedir7(), ".claude", "sessions");
@@ -13114,11 +13431,11 @@ function toLifecycleSnapshot(entry, taskId, alive, now) {
13114
13431
  function readClaudeStatusBySocketPath(socketPath) {
13115
13432
  let files;
13116
13433
  try {
13117
- files = fs19.readdirSync(CLAUDE_SESSIONS_DIR);
13434
+ files = fs20.readdirSync(CLAUDE_SESSIONS_DIR);
13118
13435
  } catch {
13119
13436
  return void 0;
13120
13437
  }
13121
- const entries = parseRegistryDir(files, (name) => fs19.readFileSync(join17(CLAUDE_SESSIONS_DIR, name), "utf8"));
13438
+ const entries = parseRegistryDir(files, (name) => fs20.readFileSync(join17(CLAUDE_SESSIONS_DIR, name), "utf8"));
13122
13439
  const entry = entries.find((e) => e.messagingSocketPath === socketPath);
13123
13440
  if (!entry)
13124
13441
  return void 0;
@@ -13141,38 +13458,38 @@ import { homedir as homedir8 } from "os";
13141
13458
  var SQUADRANT_STATE_DIR = join19(homedir8(), ".config", "squadrant", "state");
13142
13459
 
13143
13460
  // packages/agents/dist/drivers/launch-cmd.js
13144
- import fs20 from "fs";
13145
- import path18 from "path";
13461
+ import fs21 from "fs";
13462
+ import path19 from "path";
13146
13463
 
13147
13464
  // packages/agents/dist/projection/cursor.js
13148
13465
  import { mkdir, readFile, writeFile } from "fs/promises";
13149
- import path19 from "path";
13466
+ import path20 from "path";
13150
13467
  import os8 from "os";
13151
13468
 
13152
13469
  // packages/agents/dist/projection/codex.js
13153
13470
  import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
13154
- import path20 from "path";
13471
+ import path21 from "path";
13155
13472
  import os9 from "os";
13156
13473
 
13157
13474
  // packages/agents/dist/projection/gemini.js
13158
13475
  import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
13159
- import path21 from "path";
13476
+ import path22 from "path";
13160
13477
  import os10 from "os";
13161
13478
 
13162
13479
  // packages/agents/dist/projection/opencode.js
13163
13480
  import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
13164
- import path22 from "path";
13481
+ import path23 from "path";
13165
13482
  import os11 from "os";
13166
13483
 
13167
13484
  // packages/agents/dist/projection/opencode-skills.js
13168
- import fs21 from "fs";
13485
+ import fs22 from "fs";
13169
13486
  import os12 from "os";
13170
- import path23 from "path";
13487
+ import path24 from "path";
13171
13488
  var OPENCODE_SKILL_MARKER = ".squadrant-managed";
13172
13489
  var MARKER_BODY = "squadrant\n";
13173
13490
  function defaultOpencodeSkillsRoot(env = process.env) {
13174
- const configHome = env.XDG_CONFIG_HOME || path23.join(os12.homedir(), ".config");
13175
- return path23.join(configHome, "opencode", "skills");
13491
+ const configHome = env.XDG_CONFIG_HOME || path24.join(os12.homedir(), ".config");
13492
+ return path24.join(configHome, "opencode", "skills");
13176
13493
  }
13177
13494
  var SAFE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
13178
13495
  function parseSkillName(raw) {
@@ -13187,62 +13504,62 @@ function parseSkillName(raw) {
13187
13504
  }
13188
13505
  function listSourceSkills(sourceSkillsDir) {
13189
13506
  const out = /* @__PURE__ */ new Map();
13190
- if (!fs21.existsSync(sourceSkillsDir))
13507
+ if (!fs22.existsSync(sourceSkillsDir))
13191
13508
  return out;
13192
- for (const entry of fs21.readdirSync(sourceSkillsDir, { withFileTypes: true })) {
13509
+ for (const entry of fs22.readdirSync(sourceSkillsDir, { withFileTypes: true })) {
13193
13510
  if (!entry.isDirectory())
13194
13511
  continue;
13195
- const skillPath = path23.join(sourceSkillsDir, entry.name, "SKILL.md");
13196
- if (!fs21.existsSync(skillPath))
13512
+ const skillPath = path24.join(sourceSkillsDir, entry.name, "SKILL.md");
13513
+ if (!fs22.existsSync(skillPath))
13197
13514
  continue;
13198
- const name = parseSkillName(fs21.readFileSync(skillPath, "utf-8"));
13515
+ const name = parseSkillName(fs22.readFileSync(skillPath, "utf-8"));
13199
13516
  if (name && SAFE_NAME.test(name))
13200
13517
  out.set(name, skillPath);
13201
13518
  }
13202
13519
  return out;
13203
13520
  }
13204
13521
  function hasMarker(dir) {
13205
- return fs21.existsSync(path23.join(dir, OPENCODE_SKILL_MARKER));
13522
+ return fs22.existsSync(path24.join(dir, OPENCODE_SKILL_MARKER));
13206
13523
  }
13207
13524
  function syncOpencodeSkills(opts) {
13208
13525
  const result = { written: [], unchanged: [], removed: [], skipped: [] };
13209
13526
  const wanted = listSourceSkills(opts.sourceSkillsDir);
13210
- if (wanted.size === 0 && !fs21.existsSync(opts.sourceSkillsDir))
13527
+ if (wanted.size === 0 && !fs22.existsSync(opts.sourceSkillsDir))
13211
13528
  return result;
13212
13529
  if (!opts.dryRun)
13213
- fs21.mkdirSync(opts.skillsRoot, { recursive: true });
13530
+ fs22.mkdirSync(opts.skillsRoot, { recursive: true });
13214
13531
  for (const [name, srcPath] of wanted) {
13215
- const targetDir = path23.join(opts.skillsRoot, name);
13216
- const targetSkill = path23.join(targetDir, "SKILL.md");
13532
+ const targetDir = path24.join(opts.skillsRoot, name);
13533
+ const targetSkill = path24.join(targetDir, "SKILL.md");
13217
13534
  const managed = hasMarker(targetDir);
13218
- if (fs21.existsSync(targetSkill) && !managed) {
13535
+ if (fs22.existsSync(targetSkill) && !managed) {
13219
13536
  result.skipped.push({ name, reason: "foreign-collision" });
13220
13537
  continue;
13221
13538
  }
13222
- const current = fs21.existsSync(targetSkill) ? fs21.readFileSync(targetSkill) : null;
13223
- if (current && current.equals(fs21.readFileSync(srcPath))) {
13539
+ const current = fs22.existsSync(targetSkill) ? fs22.readFileSync(targetSkill) : null;
13540
+ if (current && current.equals(fs22.readFileSync(srcPath))) {
13224
13541
  if (!managed && !opts.dryRun) {
13225
- fs21.writeFileSync(path23.join(targetDir, OPENCODE_SKILL_MARKER), MARKER_BODY);
13542
+ fs22.writeFileSync(path24.join(targetDir, OPENCODE_SKILL_MARKER), MARKER_BODY);
13226
13543
  }
13227
13544
  result.unchanged.push(name);
13228
13545
  continue;
13229
13546
  }
13230
13547
  if (!opts.dryRun) {
13231
- fs21.mkdirSync(targetDir, { recursive: true });
13232
- fs21.copyFileSync(srcPath, targetSkill);
13233
- fs21.writeFileSync(path23.join(targetDir, OPENCODE_SKILL_MARKER), MARKER_BODY);
13548
+ fs22.mkdirSync(targetDir, { recursive: true });
13549
+ fs22.copyFileSync(srcPath, targetSkill);
13550
+ fs22.writeFileSync(path24.join(targetDir, OPENCODE_SKILL_MARKER), MARKER_BODY);
13234
13551
  }
13235
13552
  result.written.push(name);
13236
13553
  }
13237
- if (fs21.existsSync(opts.skillsRoot)) {
13238
- for (const entry of fs21.readdirSync(opts.skillsRoot, { withFileTypes: true })) {
13554
+ if (fs22.existsSync(opts.skillsRoot)) {
13555
+ for (const entry of fs22.readdirSync(opts.skillsRoot, { withFileTypes: true })) {
13239
13556
  if (!entry.isDirectory() || wanted.has(entry.name))
13240
13557
  continue;
13241
- const dir = path23.join(opts.skillsRoot, entry.name);
13558
+ const dir = path24.join(opts.skillsRoot, entry.name);
13242
13559
  if (!hasMarker(dir))
13243
13560
  continue;
13244
13561
  if (!opts.dryRun)
13245
- fs21.rmSync(dir, { recursive: true, force: true });
13562
+ fs22.rmSync(dir, { recursive: true, force: true });
13246
13563
  result.removed.push(entry.name);
13247
13564
  }
13248
13565
  }
@@ -13250,7 +13567,7 @@ function syncOpencodeSkills(opts) {
13250
13567
  }
13251
13568
  function syncShippedOpencodeSkills(opts) {
13252
13569
  return syncOpencodeSkills({
13253
- sourceSkillsDir: path23.join(opts.pkgRoot, "plugin", "skills"),
13570
+ sourceSkillsDir: path24.join(opts.pkgRoot, "plugin", "skills"),
13254
13571
  skillsRoot: opts.skillsRoot ?? defaultOpencodeSkillsRoot(),
13255
13572
  dryRun: opts.dryRun
13256
13573
  });
@@ -13258,7 +13575,7 @@ function syncShippedOpencodeSkills(opts) {
13258
13575
 
13259
13576
  // packages/agents/dist/projection/claude.js
13260
13577
  import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
13261
- import path24 from "path";
13578
+ import path25 from "path";
13262
13579
  import os13 from "os";
13263
13580
 
13264
13581
  // packages/agents/dist/codex/app-server-client.js
@@ -13269,12 +13586,12 @@ function _parseChunk(acc, chunk) {
13269
13586
  const out = [];
13270
13587
  let idx;
13271
13588
  while ((idx = acc.buf.indexOf("\n")) >= 0) {
13272
- const line = acc.buf.slice(0, idx);
13589
+ const line2 = acc.buf.slice(0, idx);
13273
13590
  acc.buf = acc.buf.slice(idx + 1);
13274
- if (!line.trim())
13591
+ if (!line2.trim())
13275
13592
  continue;
13276
13593
  try {
13277
- out.push(JSON.parse(line));
13594
+ out.push(JSON.parse(line2));
13278
13595
  } catch {
13279
13596
  }
13280
13597
  }
@@ -13996,9 +14313,9 @@ var OpencodeSseBridge = class {
13996
14313
  buf += decoder.decode(value, { stream: true });
13997
14314
  let nl;
13998
14315
  while ((nl = buf.indexOf("\n")) >= 0) {
13999
- const line = buf.slice(0, nl);
14316
+ const line2 = buf.slice(0, nl);
14000
14317
  buf = buf.slice(nl + 1);
14001
- this.handleLine(taskId, line);
14318
+ this.handleLine(taskId, line2);
14002
14319
  }
14003
14320
  }
14004
14321
  } finally {
@@ -14009,16 +14326,16 @@ var OpencodeSseBridge = class {
14009
14326
  }
14010
14327
  }
14011
14328
  handleLine(taskId, rawLine) {
14012
- let line = rawLine.trim();
14013
- if (!line)
14329
+ let line2 = rawLine.trim();
14330
+ if (!line2)
14014
14331
  return;
14015
- if (line.startsWith("data:"))
14016
- line = line.slice(5).trim();
14017
- if (!line.startsWith("{"))
14332
+ if (line2.startsWith("data:"))
14333
+ line2 = line2.slice(5).trim();
14334
+ if (!line2.startsWith("{"))
14018
14335
  return;
14019
14336
  let json2;
14020
14337
  try {
14021
- json2 = JSON.parse(line);
14338
+ json2 = JSON.parse(line2);
14022
14339
  } catch {
14023
14340
  return;
14024
14341
  }
@@ -14376,13 +14693,13 @@ function buildUserEnvelope(opts) {
14376
14693
  };
14377
14694
  }
14378
14695
  function writeLine(socketPath, envelope, deps) {
14379
- const line = `${JSON.stringify(envelope)}
14696
+ const line2 = `${JSON.stringify(envelope)}
14380
14697
  `;
14381
- if (Buffer.byteLength(line, "utf8") > MAX_LINE_BYTES) {
14698
+ if (Buffer.byteLength(line2, "utf8") > MAX_LINE_BYTES) {
14382
14699
  return Promise.resolve({
14383
14700
  ok: false,
14384
14701
  reason: "transport",
14385
- error: `line exceeds the receiver's 1 MiB buffer cap (${Buffer.byteLength(line, "utf8")} bytes)`
14702
+ error: `line exceeds the receiver's 1 MiB buffer cap (${Buffer.byteLength(line2, "utf8")} bytes)`
14386
14703
  });
14387
14704
  }
14388
14705
  return new Promise((resolve4) => {
@@ -14402,7 +14719,7 @@ function writeLine(socketPath, envelope, deps) {
14402
14719
  done({ ok: false, reason: "transport", error: `timeout after ${deps.timeoutMs ?? DEFAULT_TIMEOUT_MS}ms` });
14403
14720
  }, deps.timeoutMs ?? DEFAULT_TIMEOUT_MS);
14404
14721
  sock.on("connect", () => {
14405
- sock.write(line, () => {
14722
+ sock.write(line2, () => {
14406
14723
  clearTimeout(timer);
14407
14724
  try {
14408
14725
  sock.end();
@@ -14563,20 +14880,20 @@ var ClaudeReceiptListener = class {
14563
14880
  buf += chunk;
14564
14881
  let nl;
14565
14882
  while ((nl = buf.indexOf("\n")) !== -1) {
14566
- const line = buf.slice(0, nl);
14883
+ const line2 = buf.slice(0, nl);
14567
14884
  buf = buf.slice(nl + 1);
14568
- this.dispatch(line);
14885
+ this.dispatch(line2);
14569
14886
  }
14570
14887
  });
14571
14888
  conn.on("error", () => {
14572
14889
  });
14573
14890
  }
14574
- dispatch(line) {
14575
- if (!line.trim())
14891
+ dispatch(line2) {
14892
+ if (!line2.trim())
14576
14893
  return;
14577
14894
  let f;
14578
14895
  try {
14579
- f = JSON.parse(line);
14896
+ f = JSON.parse(line2);
14580
14897
  } catch {
14581
14898
  this.deps.log?.(`claude-receipt: discarded non-JSON frame`);
14582
14899
  return;
@@ -14603,9 +14920,9 @@ var ClaudeReceiptListener = class {
14603
14920
  };
14604
14921
 
14605
14922
  // packages/agents/dist/claude/api-key-approval.js
14606
- import fs22 from "fs";
14923
+ import fs23 from "fs";
14607
14924
  import os14 from "os";
14608
- import path25 from "path";
14925
+ import path26 from "path";
14609
14926
 
14610
14927
  // packages/agents/dist/opencode/http-channel.js
14611
14928
  init_dist2();
@@ -14697,10 +15014,10 @@ var OpencodeHttpChannel = class {
14697
15014
  return cached;
14698
15015
  const directory = this.directoryFor?.(taskId);
14699
15016
  const createdAfterMs = this.createdAfterFor?.(taskId);
14700
- for (const path28 of ["/session?", "/api/session?"]) {
15017
+ for (const path29 of ["/session?", "/api/session?"]) {
14701
15018
  let res;
14702
15019
  try {
14703
- res = await this.request(`http://127.0.0.1:${port}${path28}`, { method: "GET" });
15020
+ res = await this.request(`http://127.0.0.1:${port}${path29}`, { method: "GET" });
14704
15021
  } catch {
14705
15022
  return void 0;
14706
15023
  }
@@ -14836,6 +15153,15 @@ async function cmuxHasInputGuards() {
14836
15153
  inputGuardsCache = major > 0 || minor >= 65;
14837
15154
  return inputGuardsCache;
14838
15155
  }
15156
+ function feedSessionOf(item) {
15157
+ const parts = item.workstream_id?.split(":");
15158
+ if (parts?.[0] !== "cmux-feed-v1" || !parts[2])
15159
+ return void 0;
15160
+ return Buffer.from(parts[2], "base64").toString("utf-8");
15161
+ }
15162
+ async function feedRpc(method, params) {
15163
+ return JSON.parse(await cmux(["rpc", method, JSON.stringify(params)]));
15164
+ }
14839
15165
  function parseList(output) {
14840
15166
  let parsed;
14841
15167
  try {
@@ -14878,13 +15204,13 @@ function parseDraftFromScreen(screen) {
14878
15204
  if (topHR === -1)
14879
15205
  return null;
14880
15206
  const inputLines = lines.slice(topHR + 1, bottomHR);
14881
- for (const line of inputLines) {
15207
+ for (const line2 of inputLines) {
14882
15208
  let extracted;
14883
- const boxMatch = line.match(/│\s*[>❯]\s+(.*?)\s*│/);
15209
+ const boxMatch = line2.match(/│\s*[>❯]\s+(.*?)\s*│/);
14884
15210
  if (boxMatch) {
14885
15211
  extracted = boxMatch[1].trim();
14886
15212
  } else {
14887
- const plainMatch = line.match(/^\s*[>❯]\s*(.*)$/);
15213
+ const plainMatch = line2.match(/^\s*[>❯]\s*(.*)$/);
14888
15214
  if (plainMatch)
14889
15215
  extracted = plainMatch[1].trim();
14890
15216
  }
@@ -14962,8 +15288,8 @@ function readInputBoxRaw(screen, opts) {
14962
15288
  if (topHR === -1)
14963
15289
  return null;
14964
15290
  const parts = [];
14965
- for (const line of lines.slice(topHR + 1, bottomHR)) {
14966
- let s = line.replace(/│/g, " ");
15291
+ for (const line2 of lines.slice(topHR + 1, bottomHR)) {
15292
+ let s = line2.replace(/│/g, " ");
14967
15293
  s = s.replace(/^\s*[>❯]\s?/, "");
14968
15294
  s = s.replace(/\s*[▌█▔▎▏]+\s*$/, "");
14969
15295
  parts.push(s);
@@ -15200,6 +15526,26 @@ function createCmuxDriver() {
15200
15526
  await cmux(["send-key", "--workspace", wsId, "--surface", surfaceId, "Enter"]);
15201
15527
  return { workspaceId: wsId, surfaceId, title: opts.title };
15202
15528
  },
15529
+ // #916: cmux >= 0.65 `surface.input_state` reads the render grid (incl. faint
15530
+ // spans) without touching the pane. The RPC needs a surface UUID, and an
15531
+ // unknown ref would silently fall back to the focused surface, so resolve the
15532
+ // ref through the tree first. Anything unexpected → undefined (old path).
15533
+ async inputState(pane) {
15534
+ try {
15535
+ if (!await cmuxHasInputGuards())
15536
+ return void 0;
15537
+ const tree = JSON.parse(await cmux(["tree", "--workspace", pane.workspaceId, "--json", "--id-format", "both"]));
15538
+ const id = tree.windows?.flatMap((w) => w.workspaces ?? []).flatMap((w) => w.panes ?? []).flatMap((p) => p.surfaces ?? []).find((s) => s.ref === pane.surfaceId)?.id;
15539
+ if (!id)
15540
+ return void 0;
15541
+ const r = JSON.parse(await cmux(["rpc", "surface.input_state", JSON.stringify({ surface_id: id })]));
15542
+ if (r.agent !== true)
15543
+ return "unknown";
15544
+ return r.state === "empty" || r.state === "draft" || r.state === "dialog" ? r.state : "unknown";
15545
+ } catch {
15546
+ return void 0;
15547
+ }
15548
+ },
15203
15549
  async sendToSurface(surface, text, opts) {
15204
15550
  const ws = surface.workspaceId;
15205
15551
  const sf = surface.surfaceId;
@@ -15226,6 +15572,17 @@ function createCmuxDriver() {
15226
15572
  `);
15227
15573
  }
15228
15574
  };
15575
+ if (opts?.agent !== "opencode") {
15576
+ const state = await this.inputState?.(surface);
15577
+ if (state === "draft")
15578
+ throw new DeferDelivery(null, "draft");
15579
+ if (state === "dialog")
15580
+ throw new DeferDelivery(null, "modal");
15581
+ if (state === "empty") {
15582
+ await deliver();
15583
+ return;
15584
+ }
15585
+ }
15229
15586
  let screen = "";
15230
15587
  try {
15231
15588
  screen = await cmux(["read-screen", "--workspace", ws, "--surface", sf]);
@@ -15304,6 +15661,39 @@ function createCmuxDriver() {
15304
15661
  args.push("--focus", "true");
15305
15662
  await cmux(args);
15306
15663
  },
15664
+ // Feed-backed structured answer (#918). cmux >= 0.65 only; any miss
15665
+ // (old cmux, no matching item, unsupported shape) is undefined so the
15666
+ // caller keeps the keystroke path.
15667
+ async findDialog(match) {
15668
+ if (!await cmuxHasInputGuards())
15669
+ return void 0;
15670
+ let items;
15671
+ try {
15672
+ items = (await feedRpc("feed.list", { pending_only: true })).items ?? [];
15673
+ } catch {
15674
+ return void 0;
15675
+ }
15676
+ const mine = items.filter((i) => match.agentSessionId ? feedSessionOf(i) === match.agentSessionId : !!match.cwd && i.cwd === match.cwd);
15677
+ if (mine.length !== 1 || !mine[0].request_id)
15678
+ return void 0;
15679
+ const item = mine[0];
15680
+ if (item.kind !== "question" || item.questions?.length !== 1)
15681
+ return void 0;
15682
+ const labels = (item.questions[0].options ?? []).map((o) => o.label ?? "");
15683
+ if (labels.length === 0)
15684
+ return void 0;
15685
+ return {
15686
+ id: item.request_id,
15687
+ options: labels.map((label, i) => ({ index: i + 1, label }))
15688
+ };
15689
+ },
15690
+ async answerDialog(dialog, answer) {
15691
+ const reply = answer.text ?? answer.label;
15692
+ if (!reply)
15693
+ return false;
15694
+ const res = await feedRpc("feed.question.reply", { request_id: dialog.id, selections: [reply] });
15695
+ return res.delivered === true;
15696
+ },
15307
15697
  async showPatch(opts) {
15308
15698
  const args = ["diff", "-", "--workspace", opts.workspaceId, "--layout", opts.layout ?? "split"];
15309
15699
  if (opts.title)
@@ -15436,9 +15826,9 @@ var NotifierRegistry = class {
15436
15826
  };
15437
15827
 
15438
15828
  // packages/workspaces/dist/workspaces/obsidian.js
15439
- import fs23 from "fs/promises";
15829
+ import fs24 from "fs/promises";
15440
15830
  import { existsSync as existsSync11 } from "fs";
15441
- import path26 from "path";
15831
+ import path27 from "path";
15442
15832
 
15443
15833
  // packages/workspaces/dist/workspaces/registry.js
15444
15834
  init_dist();
@@ -15536,18 +15926,18 @@ var CmuxEventsBridge = class {
15536
15926
  this.buf += typeof chunk === "string" ? chunk : chunk.toString("utf-8");
15537
15927
  let nl;
15538
15928
  while ((nl = this.buf.indexOf("\n")) >= 0) {
15539
- const line = this.buf.slice(0, nl);
15929
+ const line2 = this.buf.slice(0, nl);
15540
15930
  this.buf = this.buf.slice(nl + 1);
15541
- this.handleLine(line);
15931
+ this.handleLine(line2);
15542
15932
  }
15543
15933
  }
15544
15934
  handleLine(rawLine) {
15545
- const line = rawLine.trim();
15546
- if (!line || line[0] !== "{")
15935
+ const line2 = rawLine.trim();
15936
+ if (!line2 || line2[0] !== "{")
15547
15937
  return;
15548
15938
  let f;
15549
15939
  try {
15550
- f = JSON.parse(line);
15940
+ f = JSON.parse(line2);
15551
15941
  } catch {
15552
15942
  return;
15553
15943
  }
@@ -15988,9 +16378,9 @@ function defaultListFiles(dir) {
15988
16378
  return [];
15989
16379
  }
15990
16380
  }
15991
- function defaultReadFile(path28) {
16381
+ function defaultReadFile(path29) {
15992
16382
  try {
15993
- return readFileSync17(path28, "utf-8");
16383
+ return readFileSync17(path29, "utf-8");
15994
16384
  } catch {
15995
16385
  return void 0;
15996
16386
  }
@@ -16368,16 +16758,16 @@ function extractDetail(sub, payload) {
16368
16758
  }
16369
16759
  return void 0;
16370
16760
  }
16371
- function defaultReadFile2(path28) {
16761
+ function defaultReadFile2(path29) {
16372
16762
  try {
16373
- return readFileSync18(path28, "utf-8");
16763
+ return readFileSync18(path29, "utf-8");
16374
16764
  } catch {
16375
16765
  return void 0;
16376
16766
  }
16377
16767
  }
16378
- function defaultWriteFile(path28, content) {
16379
- mkdirSync8(path28.replace(/\/[^/]+$/, ""), { recursive: true });
16380
- writeFileSync11(path28, content, "utf-8");
16768
+ function defaultWriteFile(path29, content) {
16769
+ mkdirSync8(path29.replace(/\/[^/]+$/, ""), { recursive: true });
16770
+ writeFileSync11(path29, content, "utf-8");
16381
16771
  }
16382
16772
 
16383
16773
  // packages/workspaces/dist/crew-pane.js
@@ -16404,6 +16794,11 @@ async function settleInputBox(runtime, pane) {
16404
16794
  return sawContent;
16405
16795
  }
16406
16796
  async function confirmedSendToPane(runtime, pane, message) {
16797
+ const native = await runtime.inputState?.(pane).catch(() => void 0);
16798
+ if (native === "dialog")
16799
+ return { delivered: false, blockedByModal: true };
16800
+ if (native === "draft")
16801
+ return { delivered: false };
16407
16802
  const preSendScreen = await runtime.readPaneScreen(pane) ?? "";
16408
16803
  if (hasModalOptionList2(preSendScreen)) {
16409
16804
  return { delivered: false, blockedByModal: true };
@@ -16457,9 +16852,9 @@ init_dist();
16457
16852
 
16458
16853
  // packages/cli/src/lib/daemon-restart-broadcast.ts
16459
16854
  init_dist();
16460
- import path27 from "path";
16855
+ import path28 from "path";
16461
16856
  function statePath2(stateRoot) {
16462
- return path27.join(stateRoot, "daemon-restart-state.json");
16857
+ return path28.join(stateRoot, "daemon-restart-state.json");
16463
16858
  }
16464
16859
  function computeRestartSignature(version, buildMtimeMs) {
16465
16860
  return `${version}::${buildMtimeMs}`;
@@ -16508,7 +16903,7 @@ async function maybeBroadcastDaemonRestart(opts) {
16508
16903
 
16509
16904
  // packages/cli/src/lib/captain-channel-factory.ts
16510
16905
  import { createServer as createServer4, connect as netConnect } from "net";
16511
- import fs24 from "fs";
16906
+ import fs25 from "fs";
16512
16907
  import { join as join26 } from "path";
16513
16908
  import { randomUUID as randomUUID5 } from "crypto";
16514
16909
  import chalk2 from "chalk";
@@ -16517,15 +16912,15 @@ var shared;
16517
16912
  var registryEntryPath = () => join26(CLAUDE_SESSIONS_DIR, `${process.pid}.json`);
16518
16913
  function unregisterSenderIdentity() {
16519
16914
  try {
16520
- fs24.unlinkSync(registryEntryPath());
16915
+ fs25.unlinkSync(registryEntryPath());
16521
16916
  } catch {
16522
16917
  }
16523
16918
  }
16524
16919
  function registerSenderIdentity(socketPath) {
16525
16920
  try {
16526
16921
  unregisterSenderIdentity();
16527
- fs24.mkdirSync(CLAUDE_SESSIONS_DIR, { recursive: true });
16528
- fs24.writeFileSync(
16922
+ fs25.mkdirSync(CLAUDE_SESSIONS_DIR, { recursive: true });
16923
+ fs25.writeFileSync(
16529
16924
  registryEntryPath(),
16530
16925
  JSON.stringify({
16531
16926
  pid: process.pid,
@@ -16551,7 +16946,7 @@ async function sharedReceiptListener() {
16551
16946
  // must never be the reason we refuse to start.
16552
16947
  unlinkStale: (p) => {
16553
16948
  try {
16554
- fs24.unlinkSync(p);
16949
+ fs25.unlinkSync(p);
16555
16950
  } catch {
16556
16951
  }
16557
16952
  },
@@ -16576,7 +16971,7 @@ async function buildCaptainChannel() {
16576
16971
  // in /tmp/x registers cwd "/private/tmp/x" on macOS, so cwd matching silently
16577
16972
  // missed and every captain ping reported accepted-unconfirmed.
16578
16973
  statusFor: (taskId) => readClaudeStatusBySocketPath(captainSocketPath(taskId)),
16579
- wire: (p, e) => writeLine(p, e, { connect: (path28) => netConnect(path28) }),
16974
+ wire: (p, e) => writeLine(p, e, { connect: (path29) => netConnect(path29) }),
16580
16975
  receipts,
16581
16976
  newMsgId: () => randomUUID5(),
16582
16977
  sleep: (ms) => new Promise((r) => setTimeout(r, ms)),