@staff0rd/assist 0.411.0 → 0.412.0

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
@@ -6,7 +6,7 @@ import { Command } from "commander";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "@staff0rd/assist",
9
- version: "0.411.0",
9
+ version: "0.412.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -143,10 +143,10 @@ import { stringify as stringifyYaml } from "yaml";
143
143
  // src/shared/loadRawYaml.ts
144
144
  import { existsSync, readFileSync } from "fs";
145
145
  import { parse as parseYaml } from "yaml";
146
- function loadRawYaml(path70) {
147
- if (!existsSync(path70)) return {};
146
+ function loadRawYaml(path71) {
147
+ if (!existsSync(path71)) return {};
148
148
  try {
149
- const content = readFileSync(path70, "utf8");
149
+ const content = readFileSync(path71, "utf8");
150
150
  return parseYaml(content) || {};
151
151
  } catch {
152
152
  return {};
@@ -1442,8 +1442,8 @@ function findUnmergedPaths() {
1442
1442
  }
1443
1443
  const found = /* @__PURE__ */ new Set();
1444
1444
  for (const line of output.split("\n")) {
1445
- const path70 = line.split(" ")[1];
1446
- if (path70) found.add(path70.trim());
1445
+ const path71 = line.split(" ")[1];
1446
+ if (path71) found.add(path71.trim());
1447
1447
  }
1448
1448
  return [...found];
1449
1449
  }
@@ -1542,8 +1542,8 @@ function getPreferredRemoteRepo(cwd) {
1542
1542
  function gitRefUrl(kind, ref, cwd) {
1543
1543
  const repo = getPreferredRemoteRepo(cwd);
1544
1544
  if (!repo) return void 0;
1545
- const path70 = kind === "branch" ? "tree" : "commit";
1546
- return `https://github.com/${repo.org}/${repo.repo}/${path70}/${ref}`;
1545
+ const path71 = kind === "branch" ? "tree" : "commit";
1546
+ return `https://github.com/${repo.org}/${repo.repo}/${path71}/${ref}`;
1547
1547
  }
1548
1548
 
1549
1549
  // src/commands/commit/collectCommitRefs.ts
@@ -3410,9 +3410,9 @@ import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
3410
3410
 
3411
3411
  // src/commands/verify/forbiddenStrings/findForbiddenStrings.ts
3412
3412
  import { minimatch as minimatch2 } from "minimatch";
3413
- function resolveStringsAtPath(data, path70) {
3413
+ function resolveStringsAtPath(data, path71) {
3414
3414
  let current = data;
3415
- for (const segment of path70.split(".")) {
3415
+ for (const segment of path71.split(".")) {
3416
3416
  if (current === null || typeof current !== "object") return [];
3417
3417
  current = current[segment];
3418
3418
  }
@@ -3425,10 +3425,10 @@ function resolveStringsAtPath(data, path70) {
3425
3425
  }
3426
3426
  function findRuleViolations(data, rule) {
3427
3427
  const violations = [];
3428
- for (const path70 of rule.paths) {
3429
- for (const value of resolveStringsAtPath(data, path70)) {
3428
+ for (const path71 of rule.paths) {
3429
+ for (const value of resolveStringsAtPath(data, path71)) {
3430
3430
  if (minimatch2(value, rule.disallowed))
3431
- violations.push({ file: rule.file, path: path70, value });
3431
+ violations.push({ file: rule.file, path: path71, value });
3432
3432
  }
3433
3433
  }
3434
3434
  return violations;
@@ -3467,8 +3467,8 @@ function forbiddenStrings() {
3467
3467
  process.exit(0);
3468
3468
  }
3469
3469
  console.log("Forbidden strings found:\n");
3470
- for (const { file, path: path70, value } of violations) {
3471
- console.log(` ${file} ${path70}: ${value}`);
3470
+ for (const { file, path: path71, value } of violations) {
3471
+ console.log(` ${file} ${path71}: ${value}`);
3472
3472
  }
3473
3473
  console.log(`
3474
3474
  Total: ${violations.length} forbidden string(s).`);
@@ -3760,15 +3760,15 @@ function readBaselineMigrations(repoRelativeDir, ref) {
3760
3760
  } catch {
3761
3761
  return baseline;
3762
3762
  }
3763
- const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path70) => MIGRATION_FILE3.test(basename(path70)));
3764
- for (const path70 of paths) {
3763
+ const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path71) => MIGRATION_FILE3.test(basename(path71)));
3764
+ for (const path71 of paths) {
3765
3765
  try {
3766
- const content = execSync12(`git show "${ref}:${path70}"`, {
3766
+ const content = execSync12(`git show "${ref}:${path71}"`, {
3767
3767
  encoding: "utf8",
3768
3768
  maxBuffer: 16 * 1024 * 1024,
3769
3769
  stdio: ["pipe", "pipe", "pipe"]
3770
3770
  });
3771
- baseline.set(basename(path70), content);
3771
+ baseline.set(basename(path71), content);
3772
3772
  } catch {
3773
3773
  }
3774
3774
  }
@@ -5106,8 +5106,16 @@ var daemonPaths = {
5106
5106
  };
5107
5107
 
5108
5108
  // src/commands/sessions/daemon/ensureHooksSettings.ts
5109
- var RUNNING = "assist sessions set-status running";
5110
- var WAITING = "assist sessions set-status waiting";
5109
+ var SET_STATUS = "assist sessions set-status";
5110
+ function running(source) {
5111
+ return `${SET_STATUS} running --source ${source}`;
5112
+ }
5113
+ function waiting(source) {
5114
+ return `${SET_STATUS} waiting --source ${source}`;
5115
+ }
5116
+ function ackWaiting(source) {
5117
+ return `${SET_STATUS} waiting --source ${source} --ack`;
5118
+ }
5111
5119
  function on(command, matcher) {
5112
5120
  const hooks = [{ type: "command", command }];
5113
5121
  return [matcher == null ? { hooks } : { matcher, hooks }];
@@ -5116,27 +5124,22 @@ var ASK_USER_QUESTION = "AskUserQuestion";
5116
5124
  var NOT_ASK_USER_QUESTION = `^(?!${ASK_USER_QUESTION}$).*`;
5117
5125
  var hooksSettings = {
5118
5126
  hooks: {
5119
- UserPromptSubmit: on(RUNNING),
5127
+ UserPromptSubmit: on(running("prompt")),
5120
5128
  PreToolUse: [
5121
- ...on(WAITING, ASK_USER_QUESTION),
5122
- ...on(RUNNING, NOT_ASK_USER_QUESTION)
5129
+ ...on(waiting("pretool"), ASK_USER_QUESTION),
5130
+ ...on(running("pretool"), NOT_ASK_USER_QUESTION)
5123
5131
  ],
5124
- // tool finished, agent resumes; restores running
5125
- PostToolUse: on(RUNNING),
5126
- Stop: on(WAITING),
5127
- Notification: on(WAITING),
5128
- /* why: a tool/plan approval prompt appears mid-turn, after PreToolUse has
5129
- * already set running; PermissionRequest fires when the agent blocks on
5130
- * that decision, so the card shows waiting rather than staying running while
5131
- * it is genuinely awaiting the user (#449). */
5132
- PermissionRequest: on(WAITING)
5132
+ PostToolUse: on(running("posttool")),
5133
+ Stop: on(ackWaiting("stop")),
5134
+ Notification: on(ackWaiting("notification")),
5135
+ PermissionRequest: on(ackWaiting("permission"))
5133
5136
  }
5134
5137
  };
5135
5138
  function ensureHooksSettings() {
5136
- const path70 = daemonPaths.hooksSettings;
5137
- mkdirSync5(dirname12(path70), { recursive: true });
5138
- writeFileSync15(path70, JSON.stringify(hooksSettings, null, 2));
5139
- return path70;
5139
+ const path71 = daemonPaths.hooksSettings;
5140
+ mkdirSync5(dirname12(path71), { recursive: true });
5141
+ writeFileSync15(path71, JSON.stringify(hooksSettings, null, 2));
5142
+ return path71;
5140
5143
  }
5141
5144
 
5142
5145
  // src/shared/spawnInherit.ts
@@ -5401,9 +5404,9 @@ var LOCAL_FILES = ["backlog.jsonl", "backlog.db"];
5401
5404
  function backupLocalBacklogFiles(dir) {
5402
5405
  const moved = [];
5403
5406
  for (const name of LOCAL_FILES) {
5404
- const path70 = join15(dir, ".assist", name);
5405
- if (existsSync18(path70)) {
5406
- renameSync(path70, `${path70}.bak`);
5407
+ const path71 = join15(dir, ".assist", name);
5408
+ if (existsSync18(path71)) {
5409
+ renameSync(path71, `${path71}.bak`);
5407
5410
  moved.push(`${name} \u2192 ${name}.bak`);
5408
5411
  }
5409
5412
  }
@@ -5875,8 +5878,8 @@ var backlogItemSchema = z3.strictObject({
5875
5878
  var backlogFileSchema = z3.array(backlogItemSchema);
5876
5879
 
5877
5880
  // src/commands/backlog/parseBacklogJsonl.ts
5878
- function parseBacklogJsonl(path70) {
5879
- const content = readFileSync14(path70, "utf8").trim();
5881
+ function parseBacklogJsonl(path71) {
5882
+ const content = readFileSync14(path71, "utf8").trim();
5880
5883
  if (content.length === 0) return [];
5881
5884
  return content.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => backlogItemSchema.parse(JSON.parse(line)));
5882
5885
  }
@@ -5958,8 +5961,8 @@ function findBacklogUp(startDir) {
5958
5961
 
5959
5962
  // src/commands/backlog/getCurrentOrigin.ts
5960
5963
  import { execFileSync } from "child_process";
5961
- function stripLeadingSlashes(path70) {
5962
- return path70.replace(/^\/+/, "");
5964
+ function stripLeadingSlashes(path71) {
5965
+ return path71.replace(/^\/+/, "");
5963
5966
  }
5964
5967
  function normalizeOrigin(raw) {
5965
5968
  const trimmed = raw.trim().replace(/\.git$/i, "").replace(/\/+$/, "");
@@ -6307,20 +6310,87 @@ function sendToDaemon(message) {
6307
6310
  });
6308
6311
  }
6309
6312
 
6313
+ // src/commands/sessions/daemon/sendToDaemonAwaitAck.ts
6314
+ var ACK_TIMEOUT_MS = 1e3;
6315
+ function sendToDaemonAwaitAck(message) {
6316
+ return new Promise((resolve19, reject) => {
6317
+ connectToDaemon().then((socket) => {
6318
+ let settled = false;
6319
+ const finish = (error) => {
6320
+ if (settled) return;
6321
+ settled = true;
6322
+ clearTimeout(timer);
6323
+ socket.destroy();
6324
+ if (error) reject(error);
6325
+ else resolve19();
6326
+ };
6327
+ const timer = setTimeout(
6328
+ () => finish(new Error("timed out awaiting daemon ack")),
6329
+ ACK_TIMEOUT_MS
6330
+ );
6331
+ let buffer = "";
6332
+ socket.on("data", (chunk) => {
6333
+ buffer += chunk.toString("utf8");
6334
+ let newline = buffer.indexOf("\n");
6335
+ while (newline !== -1) {
6336
+ const line = buffer.slice(0, newline);
6337
+ buffer = buffer.slice(newline + 1);
6338
+ if (isAck(line)) return finish();
6339
+ newline = buffer.indexOf("\n");
6340
+ }
6341
+ });
6342
+ socket.on("error", (error) => finish(error));
6343
+ socket.on(
6344
+ "close",
6345
+ () => finish(new Error("daemon closed before acknowledging"))
6346
+ );
6347
+ socket.write(`${JSON.stringify(message)}
6348
+ `);
6349
+ }, reject);
6350
+ });
6351
+ }
6352
+ function isAck(line) {
6353
+ try {
6354
+ return JSON.parse(line).type === "ack";
6355
+ } catch {
6356
+ return false;
6357
+ }
6358
+ }
6359
+
6310
6360
  // src/commands/sessions/setSessionStatus.ts
6311
6361
  var DELIVERY_ATTEMPTS = 3;
6312
6362
  var RETRY_DELAY_MS = 100;
6313
- async function setSessionStatus(status3) {
6363
+ async function setSessionStatus(status3, opts = {}) {
6314
6364
  const sessionId = process.env.ASSIST_SESSION_ID;
6315
- logHookFired(status3, sessionId);
6365
+ logHookFired(status3, sessionId, opts.source);
6316
6366
  if (!sessionId) return;
6317
- await deliverStatus(sessionId, status3);
6367
+ const payload = buildPayload(sessionId, status3, opts);
6368
+ if (opts.ack) await deliverReliably(sessionId, status3, payload);
6369
+ else await deliverBestEffort(sessionId, status3, payload);
6318
6370
  }
6319
- async function deliverStatus(sessionId, status3) {
6320
- const payload = { type: "set-status", sessionId, status: status3 };
6371
+ function buildPayload(sessionId, status3, opts) {
6372
+ const payload = {
6373
+ type: "set-status",
6374
+ sessionId,
6375
+ status: status3
6376
+ };
6377
+ if (opts.source) payload.source = opts.source;
6378
+ if (opts.ack) payload.ack = true;
6379
+ return payload;
6380
+ }
6381
+ async function deliverBestEffort(sessionId, status3, payload) {
6382
+ try {
6383
+ await sendToDaemon(payload);
6384
+ } catch (error) {
6385
+ appendDaemonLog(
6386
+ `set-status best-effort send failed: id=${sessionId} status=${status3}: ${describeError(error)}`
6387
+ );
6388
+ }
6389
+ }
6390
+ async function deliverReliably(sessionId, status3, payload) {
6321
6391
  for (let attempt = 1; attempt <= DELIVERY_ATTEMPTS; attempt++) {
6322
6392
  try {
6323
- await sendToDaemon(payload);
6393
+ await sendToDaemonAwaitAck(payload);
6324
6394
  return;
6325
6395
  } catch (error) {
6326
6396
  if (attempt < DELIVERY_ATTEMPTS) {
@@ -6328,7 +6398,7 @@ async function deliverStatus(sessionId, status3) {
6328
6398
  continue;
6329
6399
  }
6330
6400
  appendDaemonLog(
6331
- `set-status delivery failed after ${DELIVERY_ATTEMPTS} attempts: id=${sessionId} status=${status3}: ${describeError(error)}`
6401
+ `set-status ack'd delivery failed after ${DELIVERY_ATTEMPTS} attempts: id=${sessionId} status=${status3}: ${describeError(error)}`
6332
6402
  );
6333
6403
  }
6334
6404
  }
@@ -6339,9 +6409,9 @@ function sleep(ms) {
6339
6409
  function describeError(error) {
6340
6410
  return error instanceof Error ? error.message : String(error);
6341
6411
  }
6342
- function logHookFired(status3, sessionId) {
6412
+ function logHookFired(status3, sessionId, source) {
6343
6413
  appendDaemonLog(
6344
- `set-status hook fired: id=${sessionId ?? "none"} status=${status3}`
6414
+ `set-status hook fired: id=${sessionId ?? "none"} status=${status3}${source ? ` source=${source}` : ""}`
6345
6415
  );
6346
6416
  }
6347
6417
 
@@ -6499,24 +6569,24 @@ function getOwnerPath(itemId2) {
6499
6569
  function recordSignalOwner(itemId2) {
6500
6570
  const sessionId = process.env.ASSIST_SESSION_ID;
6501
6571
  if (!sessionId) return;
6502
- const path70 = getOwnerPath(itemId2);
6503
- mkdirSync7(dirname14(path70), { recursive: true });
6504
- writeFileSync17(path70, JSON.stringify({ sessionId }));
6572
+ const path71 = getOwnerPath(itemId2);
6573
+ mkdirSync7(dirname14(path71), { recursive: true });
6574
+ writeFileSync17(path71, JSON.stringify({ sessionId }));
6505
6575
  }
6506
6576
  function readSignalOwner(itemId2) {
6507
- const path70 = getOwnerPath(itemId2);
6508
- if (!existsSync21(path70)) return void 0;
6577
+ const path71 = getOwnerPath(itemId2);
6578
+ if (!existsSync21(path71)) return void 0;
6509
6579
  try {
6510
- const parsed = JSON.parse(readFileSync15(path70, "utf8"));
6580
+ const parsed = JSON.parse(readFileSync15(path71, "utf8"));
6511
6581
  return parsed.sessionId;
6512
6582
  } catch {
6513
6583
  return void 0;
6514
6584
  }
6515
6585
  }
6516
6586
  function clearSignalOwner(itemId2) {
6517
- const path70 = getOwnerPath(itemId2);
6587
+ const path71 = getOwnerPath(itemId2);
6518
6588
  try {
6519
- rmSync(path70);
6589
+ rmSync(path71);
6520
6590
  } catch {
6521
6591
  }
6522
6592
  }
@@ -6553,19 +6623,19 @@ function resolveSignalTarget(event, data) {
6553
6623
  function writeSignal(event, data) {
6554
6624
  const target = resolveSignalTarget(event, data);
6555
6625
  if (!target) return;
6556
- const path70 = getSignalPath(target);
6557
- if (!path70) return;
6626
+ const path71 = getSignalPath(target);
6627
+ if (!path71) return;
6558
6628
  const signal = { event, sessionId: target, ...data };
6559
- mkdirSync8(dirname15(path70), { recursive: true });
6560
- writeFileSync18(path70, JSON.stringify(signal));
6629
+ mkdirSync8(dirname15(path71), { recursive: true });
6630
+ writeFileSync18(path71, JSON.stringify(signal));
6561
6631
  }
6562
6632
 
6563
6633
  // src/commands/backlog/readSignal.ts
6564
6634
  function readSignal() {
6565
- const path70 = getSignalPath();
6566
- if (!path70 || !existsSync22(path70)) return void 0;
6635
+ const path71 = getSignalPath();
6636
+ if (!path71 || !existsSync22(path71)) return void 0;
6567
6637
  try {
6568
- return JSON.parse(readFileSync16(path70, "utf8"));
6638
+ return JSON.parse(readFileSync16(path71, "utf8"));
6569
6639
  } catch {
6570
6640
  return void 0;
6571
6641
  }
@@ -6698,13 +6768,13 @@ function activityPath(sessionId) {
6698
6768
  function emitActivity(activity2) {
6699
6769
  const sessionId = process.env.ASSIST_ACTIVITY_ID;
6700
6770
  if (!sessionId) return;
6701
- const path70 = activityPath(sessionId);
6702
- mkdirSync9(dirname16(path70), { recursive: true });
6703
- writeFileSync19(path70, JSON.stringify({ ...activity2, startedAt: Date.now() }));
6771
+ const path71 = activityPath(sessionId);
6772
+ mkdirSync9(dirname16(path71), { recursive: true });
6773
+ writeFileSync19(path71, JSON.stringify({ ...activity2, startedAt: Date.now() }));
6704
6774
  }
6705
- function readActivity(path70) {
6775
+ function readActivity(path71) {
6706
6776
  try {
6707
- return JSON.parse(readFileSync17(path70, "utf8"));
6777
+ return JSON.parse(readFileSync17(path71, "utf8"));
6708
6778
  } catch {
6709
6779
  return void 0;
6710
6780
  }
@@ -6714,9 +6784,9 @@ function reconcileActivity(sessionId, activity2) {
6714
6784
  removeActivity(sessionId);
6715
6785
  return;
6716
6786
  }
6717
- const path70 = activityPath(sessionId);
6718
- mkdirSync9(dirname16(path70), { recursive: true });
6719
- writeFileSync19(path70, JSON.stringify(activity2));
6787
+ const path71 = activityPath(sessionId);
6788
+ mkdirSync9(dirname16(path71), { recursive: true });
6789
+ writeFileSync19(path71, JSON.stringify(activity2));
6720
6790
  }
6721
6791
  function removeActivity(sessionId) {
6722
6792
  try {
@@ -7969,8 +8039,8 @@ async function loadItemSummaries(orm, origin) {
7969
8039
  // src/commands/backlog/originDisplayName.ts
7970
8040
  function originDisplayName(origin) {
7971
8041
  if (origin.startsWith("local:")) {
7972
- const path70 = origin.slice("local:".length).replace(/\/+$/, "");
7973
- const segments = path70.split("/").filter(Boolean);
8042
+ const path71 = origin.slice("local:".length).replace(/\/+$/, "");
8043
+ const segments = path71.split("/").filter(Boolean);
7974
8044
  return segments[segments.length - 1] ?? origin;
7975
8045
  }
7976
8046
  const firstSlash = origin.indexOf("/");
@@ -8406,7 +8476,7 @@ function findSynthesisForBranch(repoReviewsDir, branch2) {
8406
8476
  const parent = dirname20(branchKeyPath);
8407
8477
  const branchPrefix = basename5(branchKeyPath);
8408
8478
  if (!existsSync26(parent)) return null;
8409
- const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join24(parent, name, "synthesis.md")).filter((path70) => existsSync26(path70)).map((path70) => ({ path: path70, mtime: statSync2(path70).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
8479
+ const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join24(parent, name, "synthesis.md")).filter((path71) => existsSync26(path71)).map((path71) => ({ path: path71, mtime: statSync2(path71).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
8410
8480
  return synthesisFiles[0]?.path ?? null;
8411
8481
  }
8412
8482
 
@@ -8460,12 +8530,12 @@ async function getReviewSynthesis(req, res) {
8460
8530
  const cwd = getCwdParam(req, res);
8461
8531
  if (!cwd) return;
8462
8532
  try {
8463
- const path70 = await resolveSynthesisPath(cwd);
8464
- if (!path70) {
8533
+ const path71 = await resolveSynthesisPath(cwd);
8534
+ if (!path71) {
8465
8535
  respondJson(res, 404, { error: "No synthesis found" });
8466
8536
  return;
8467
8537
  }
8468
- respondJson(res, 200, { synthesis: readFileSync19(path70, "utf8") });
8538
+ respondJson(res, 200, { synthesis: readFileSync19(path71, "utf8") });
8469
8539
  } catch {
8470
8540
  respondJson(res, 404, { error: "No synthesis found" });
8471
8541
  }
@@ -8612,10 +8682,10 @@ function getStorePath(filename) {
8612
8682
  return join27(getStoreDir(), filename);
8613
8683
  }
8614
8684
  function loadJson(filename) {
8615
- const path70 = getStorePath(filename);
8616
- if (existsSync27(path70)) {
8685
+ const path71 = getStorePath(filename);
8686
+ if (existsSync27(path71)) {
8617
8687
  try {
8618
- return JSON.parse(readFileSync20(path70, "utf8"));
8688
+ return JSON.parse(readFileSync20(path71, "utf8"));
8619
8689
  } catch {
8620
8690
  return {};
8621
8691
  }
@@ -9725,9 +9795,9 @@ function originToSshUrl(origin) {
9725
9795
  const firstSlash = origin.indexOf("/");
9726
9796
  if (firstSlash <= 0) return null;
9727
9797
  const host = origin.slice(0, firstSlash);
9728
- const path70 = origin.slice(firstSlash + 1);
9729
- if (!path70) return null;
9730
- return `git@${host}:${path70}.git`;
9798
+ const path71 = origin.slice(firstSlash + 1);
9799
+ if (!path71) return null;
9800
+ return `git@${host}:${path71}.git`;
9731
9801
  }
9732
9802
 
9733
9803
  // src/commands/backlog/cloneRepo.ts
@@ -12036,9 +12106,9 @@ var __dirname4 = dirname21(__filename3);
12036
12106
  function packageRoot() {
12037
12107
  return __dirname4;
12038
12108
  }
12039
- function readLines(path70) {
12040
- if (!existsSync29(path70)) return [];
12041
- return readFileSync23(path70, "utf8").split("\n").filter((line) => line.trim() !== "");
12109
+ function readLines(path71) {
12110
+ if (!existsSync29(path71)) return [];
12111
+ return readFileSync23(path71, "utf8").split("\n").filter((line) => line.trim() !== "");
12042
12112
  }
12043
12113
  var cachedReads;
12044
12114
  var cachedWrites;
@@ -12530,14 +12600,14 @@ function showProgress(p, label2) {
12530
12600
  const pct = Math.round(p.done / p.total * 100);
12531
12601
  process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
12532
12602
  }
12533
- async function resolveCommand(cli, path70, description, depth, p) {
12534
- showProgress(p, path70.join(" "));
12535
- const subHelp = await runHelp([cli, ...path70]);
12603
+ async function resolveCommand(cli, path71, description, depth, p) {
12604
+ showProgress(p, path71.join(" "));
12605
+ const subHelp = await runHelp([cli, ...path71]);
12536
12606
  if (!subHelp || !hasSubcommands(subHelp)) {
12537
- return [{ path: path70, description }];
12607
+ return [{ path: path71, description }];
12538
12608
  }
12539
- const children = await discoverAt(cli, path70, depth + 1, p);
12540
- return children.length > 0 ? children : [{ path: path70, description }];
12609
+ const children = await discoverAt(cli, path71, depth + 1, p);
12610
+ return children.length > 0 ? children : [{ path: path71, description }];
12541
12611
  }
12542
12612
  async function discoverAt(cli, parentPath, depth, p) {
12543
12613
  if (depth > SAFETY_DEPTH) return [];
@@ -12685,9 +12755,9 @@ function logPath(cli) {
12685
12755
  return join31(homedir16(), ".assist", `cli-discover-${safeName}.log`);
12686
12756
  }
12687
12757
  function readCache(cli) {
12688
- const path70 = logPath(cli);
12689
- if (!existsSync31(path70)) return void 0;
12690
- return readFileSync25(path70, "utf8");
12758
+ const path71 = logPath(cli);
12759
+ if (!existsSync31(path71)) return void 0;
12760
+ return readFileSync25(path71, "utf8");
12691
12761
  }
12692
12762
  function writeCache(cli, output) {
12693
12763
  const dir = join31(homedir16(), ".assist");
@@ -12859,9 +12929,9 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
12859
12929
  }
12860
12930
  const cutoff = Date.now() - STALE_AFTER_MS;
12861
12931
  for (const entry of entries) {
12862
- const path70 = join33(dir, entry);
12932
+ const path71 = join33(dir, entry);
12863
12933
  try {
12864
- if (statSync3(path70).mtimeMs < cutoff) unlinkSync7(path70);
12934
+ if (statSync3(path71).mtimeMs < cutoff) unlinkSync7(path71);
12865
12935
  } catch {
12866
12936
  continue;
12867
12937
  }
@@ -12871,10 +12941,10 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
12871
12941
  // src/commands/codeComment/readPinState.ts
12872
12942
  import { existsSync as existsSync32, readFileSync as readFileSync26 } from "fs";
12873
12943
  function readPinState(pin) {
12874
- const path70 = getPinStatePath(pin);
12875
- if (!existsSync32(path70)) return void 0;
12944
+ const path71 = getPinStatePath(pin);
12945
+ if (!existsSync32(path71)) return void 0;
12876
12946
  try {
12877
- const state = JSON.parse(readFileSync26(path70, "utf8"));
12947
+ const state = JSON.parse(readFileSync26(path71, "utf8"));
12878
12948
  if (state.pin !== pin) return void 0;
12879
12949
  return state;
12880
12950
  } catch {
@@ -13770,8 +13840,8 @@ function stepIntoNested(container, key, nextKey) {
13770
13840
  }
13771
13841
  return ensureObject(container, resolved);
13772
13842
  }
13773
- function setNestedValue(obj, path70, value) {
13774
- const keys = path70.split(".");
13843
+ function setNestedValue(obj, path71, value) {
13844
+ const keys = path71.split(".");
13775
13845
  const result = { ...obj };
13776
13846
  let current = result;
13777
13847
  for (let i = 0; i < keys.length - 1; i++) {
@@ -13851,9 +13921,9 @@ function isTraversable(value) {
13851
13921
  function stepInto(current, key) {
13852
13922
  return isTraversable(current) ? current[key] : void 0;
13853
13923
  }
13854
- function getNestedValue(obj, path70) {
13924
+ function getNestedValue(obj, path71) {
13855
13925
  let current = obj;
13856
- for (const key of path70.split(".")) current = stepInto(current, key);
13926
+ for (const key of path71.split(".")) current = stepInto(current, key);
13857
13927
  return current;
13858
13928
  }
13859
13929
 
@@ -13969,10 +14039,10 @@ function getMigrationApprovalPath(migrationId) {
13969
14039
  // src/commands/dbMigration/readMigrationPinState.ts
13970
14040
  import { existsSync as existsSync34, readFileSync as readFileSync28 } from "fs";
13971
14041
  function readMigrationPinState(pin) {
13972
- const path70 = getMigrationPinPath(pin);
13973
- if (!existsSync34(path70)) return void 0;
14042
+ const path71 = getMigrationPinPath(pin);
14043
+ if (!existsSync34(path71)) return void 0;
13974
14044
  try {
13975
- const state = JSON.parse(readFileSync28(path70, "utf8"));
14045
+ const state = JSON.parse(readFileSync28(path71, "utf8"));
13976
14046
  if (state.pin !== pin) return void 0;
13977
14047
  if (!Number.isInteger(state.migrationId)) return void 0;
13978
14048
  return state;
@@ -15411,10 +15481,10 @@ function decideCommentGuard(input, existingContent) {
15411
15481
  import { existsSync as existsSync41, unlinkSync as unlinkSync11 } from "fs";
15412
15482
  function consumeMigrationApproval(migrationId) {
15413
15483
  sweepRestrictedDir();
15414
- const path70 = getMigrationApprovalPath(migrationId);
15415
- if (!existsSync41(path70)) return false;
15484
+ const path71 = getMigrationApprovalPath(migrationId);
15485
+ if (!existsSync41(path71)) return false;
15416
15486
  try {
15417
- unlinkSync11(path70);
15487
+ unlinkSync11(path71);
15418
15488
  return true;
15419
15489
  } catch {
15420
15490
  return false;
@@ -16588,9 +16658,9 @@ function parseRscRows(flight) {
16588
16658
  }
16589
16659
  function makeRscResolver(rows) {
16590
16660
  return (ref) => {
16591
- const [id, ...path70] = ref.slice(1).replace(/^[L@]/, "").split(":");
16661
+ const [id, ...path71] = ref.slice(1).replace(/^[L@]/, "").split(":");
16592
16662
  let v = rows[id];
16593
- for (const key of path70) {
16663
+ for (const key of path71) {
16594
16664
  if (v == null || typeof v !== "object") return void 0;
16595
16665
  v = v[key];
16596
16666
  }
@@ -17274,15 +17344,15 @@ function postComment(vars) {
17274
17344
  const stdout = startLine === void 0 ? runGhGraphql(MUTATION_SINGLE, base) : runGhGraphql(MUTATION_MULTI, { ...base, startLine });
17275
17345
  assertThreadCreated(stdout);
17276
17346
  }
17277
- function comment2(path70, line, body, startLine) {
17347
+ function comment2(path71, line, body, startLine) {
17278
17348
  validateBody(body);
17279
17349
  validateLine(line);
17280
17350
  if (startLine !== void 0) validateLine(startLine);
17281
17351
  try {
17282
17352
  const prId = getCurrentPrNodeId();
17283
- postComment({ prId, body, path: path70, line, startLine });
17353
+ postComment({ prId, body, path: path71, line, startLine });
17284
17354
  const range = startLine !== void 0 ? `${startLine}-${line}` : `${line}`;
17285
- console.log(`Added review comment on ${path70}:${range}`);
17355
+ console.log(`Added review comment on ${path71}:${range}`);
17286
17356
  } catch (error) {
17287
17357
  if (isGhNotInstalled(error)) {
17288
17358
  console.error("Error: GitHub CLI (gh) is not installed.");
@@ -18161,8 +18231,8 @@ function registerPrs(program2) {
18161
18231
  prsCommand.command("reply <comment-id> <body>").description("Reply to a comment thread without resolving it").action((commentId, body) => {
18162
18232
  reply(Number.parseInt(commentId, 10), body);
18163
18233
  });
18164
- prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path70, line, body) => {
18165
- comment2(path70, Number.parseInt(line, 10), body);
18234
+ prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path71, line, body) => {
18235
+ comment2(path71, Number.parseInt(line, 10), body);
18166
18236
  });
18167
18237
  configHelp(prsCommand, prsConfigHelp);
18168
18238
  }
@@ -18415,10 +18485,10 @@ function resolveOpSecret(reference) {
18415
18485
  }
18416
18486
 
18417
18487
  // src/commands/ravendb/ravenFetch.ts
18418
- async function ravenFetch(connection, path70) {
18488
+ async function ravenFetch(connection, path71) {
18419
18489
  const apiKey = resolveOpSecret(connection.apiKeyRef);
18420
18490
  let accessToken = await getAccessToken(apiKey);
18421
- const url = `${connection.url}${path70}`;
18491
+ const url = `${connection.url}${path71}`;
18422
18492
  const headers = {
18423
18493
  Authorization: `Bearer ${accessToken}`,
18424
18494
  "Content-Type": "application/json"
@@ -18522,16 +18592,16 @@ import chalk170 from "chalk";
18522
18592
  // src/commands/ravendb/buildQueryPath.ts
18523
18593
  function buildQueryPath(opts) {
18524
18594
  const db = encodeURIComponent(opts.db);
18525
- let path70;
18595
+ let path71;
18526
18596
  if (opts.collection) {
18527
- path70 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
18597
+ path71 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
18528
18598
  } else {
18529
- path70 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
18599
+ path71 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
18530
18600
  }
18531
18601
  if (opts.query) {
18532
- path70 += `&query=${encodeURIComponent(opts.query)}`;
18602
+ path71 += `&query=${encodeURIComponent(opts.query)}`;
18533
18603
  }
18534
- return path70;
18604
+ return path71;
18535
18605
  }
18536
18606
 
18537
18607
  // src/commands/ravendb/fetchAllPages.ts
@@ -18540,7 +18610,7 @@ async function fetchAllPages(connection, opts) {
18540
18610
  let start3 = 0;
18541
18611
  while (true) {
18542
18612
  const effectivePageSize = opts.limit !== void 0 ? Math.min(opts.pageSize, opts.limit - allResults.length) : opts.pageSize;
18543
- const path70 = buildQueryPath({
18613
+ const path71 = buildQueryPath({
18544
18614
  db: connection.database,
18545
18615
  collection: opts.collection,
18546
18616
  start: start3,
@@ -18548,7 +18618,7 @@ async function fetchAllPages(connection, opts) {
18548
18618
  sort: opts.sort,
18549
18619
  query: opts.query
18550
18620
  });
18551
- const data = await ravenFetch(connection, path70);
18621
+ const data = await ravenFetch(connection, path71);
18552
18622
  const results = data.Results ?? [];
18553
18623
  const totalResults = data.TotalResults ?? 0;
18554
18624
  if (results.length === 0) break;
@@ -20968,8 +21038,8 @@ async function handlePostSynthesis(synthesisPath, options2) {
20968
21038
  // src/commands/review/prepareReviewDir.ts
20969
21039
  import { existsSync as existsSync45, mkdirSync as mkdirSync18, unlinkSync as unlinkSync16, writeFileSync as writeFileSync36 } from "fs";
20970
21040
  function clearReviewFiles(paths) {
20971
- for (const path70 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
20972
- if (existsSync45(path70)) unlinkSync16(path70);
21041
+ for (const path71 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
21042
+ if (existsSync45(path71)) unlinkSync16(path71);
20973
21043
  }
20974
21044
  }
20975
21045
  function prepareReviewDir(paths, requestBody, force) {
@@ -22117,8 +22187,8 @@ import chalk191 from "chalk";
22117
22187
 
22118
22188
  // src/commands/seq/fetchSeq.ts
22119
22189
  import chalk188 from "chalk";
22120
- async function fetchSeq(conn, path70, params) {
22121
- const url = `${conn.url}${path70}?${params}`;
22190
+ async function fetchSeq(conn, path71, params) {
22191
+ const url = `${conn.url}${path71}?${params}`;
22122
22192
  const response = await fetch(url, {
22123
22193
  headers: {
22124
22194
  Accept: "application/json",
@@ -23605,9 +23675,9 @@ function findPortFile(roamDir) {
23605
23675
  return void 0;
23606
23676
  }
23607
23677
  const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
23608
- const path70 = join62(roamDir, name);
23678
+ const path71 = join62(roamDir, name);
23609
23679
  try {
23610
- return { path: path70, mtimeMs: statSync8(path70).mtimeMs };
23680
+ return { path: path71, mtimeMs: statSync8(path71).mtimeMs };
23611
23681
  } catch {
23612
23682
  return void 0;
23613
23683
  }
@@ -24026,11 +24096,11 @@ function findLinkIndex() {
24026
24096
  function parseLinkArgs() {
24027
24097
  const idx = findLinkIndex();
24028
24098
  if (idx === -1) return null;
24029
- const path70 = process.argv[idx + 1];
24099
+ const path71 = process.argv[idx + 1];
24030
24100
  const rest = process.argv.slice(idx + 2);
24031
24101
  const { value: prefix2 } = extractOption(rest, "--prefix");
24032
24102
  if (!prefix2) return null;
24033
- return { path: path70, prefix: prefix2 };
24103
+ return { path: path71, prefix: prefix2 };
24034
24104
  }
24035
24105
  function hasDuplicateLink(runList, linkPath) {
24036
24106
  return runList.some(
@@ -24911,6 +24981,7 @@ function dismissSession(sessions, id) {
24911
24981
  if (!s) return false;
24912
24982
  if (s.status !== "done") s.pty?.kill();
24913
24983
  s.activityWatcher?.close();
24984
+ s.transcriptWatcher?.close();
24914
24985
  removeActivity(s.id);
24915
24986
  if (s.activity?.itemId != null) releaseLock(s.activity.itemId);
24916
24987
  sessions.delete(id);
@@ -25017,113 +25088,18 @@ function logSpawnedSession(session) {
25017
25088
  );
25018
25089
  }
25019
25090
 
25020
- // src/commands/sessions/daemon/setStatus.ts
25021
- function setStatus2(session, newStatus) {
25022
- const now = Date.now();
25023
- if (session.status === "running" && session.runningSince != null) {
25024
- session.runningMs += now - session.runningSince;
25025
- }
25026
- session.runningSince = newStatus === "running" ? now : null;
25027
- session.status = newStatus;
25028
- }
25029
-
25030
- // src/commands/sessions/daemon/shouldAutoDismiss.ts
25031
- function shouldAutoDismiss(session, exitCode) {
25032
- if (session.status !== "done" || exitCode !== 0) {
25033
- return false;
25034
- }
25035
- if (session.reviewStarted) {
25036
- return session.autoAdvance === true;
25037
- }
25038
- const args = session.assistArgs;
25039
- if (args === void 0) return false;
25040
- if (args[0] === "update") return true;
25041
- return args.includes("--once") && args[0] !== "next";
25042
- }
25043
-
25044
- // src/commands/sessions/daemon/shouldAutoRun.ts
25045
- function shouldAutoRun(session) {
25046
- if (!session.autoRun) return { run: false, reason: null };
25047
- if (session.status !== "done")
25048
- return {
25049
- run: false,
25050
- reason: `session status is "${session.status}", not "done"`
25051
- };
25052
- if (session.commandType !== "assist")
25053
- return {
25054
- run: false,
25055
- reason: `command type is "${session.commandType}", not "assist"`
25056
- };
25057
- const cmd = session.assistArgs?.[0];
25058
- if (cmd !== "draft" && cmd !== "bug" && cmd !== "refine")
25059
- return {
25060
- run: false,
25061
- reason: `command "${cmd ?? "(none)"}" is not draft/bug/refine`
25062
- };
25063
- const itemId2 = session.activity?.itemId;
25064
- if (itemId2 == null)
25065
- return {
25066
- run: false,
25067
- reason: "no itemId in activity (draft did not create an item)"
25068
- };
25069
- return { run: true, itemId: itemId2 };
25070
- }
25071
-
25072
- // src/commands/sessions/daemon/watchEscInterrupt.ts
25073
- var ESC3 = "\x1B";
25074
- var SETTLE_MS = 1e3;
25075
- function isInterruptKey(data) {
25076
- return data === ESC3;
25077
- }
25078
- function scheduleSettle(session, onStatusChange) {
25079
- if (session.escInterruptTimer) clearTimeout(session.escInterruptTimer);
25080
- session.escInterruptTimer = setTimeout(() => {
25081
- session.escInterruptTimer = void 0;
25082
- if (session.status !== "running") return;
25083
- daemonLog(`session ${session.id} esc-interrupt settled -> waiting`);
25084
- onStatusChange(session, "waiting");
25085
- }, SETTLE_MS);
25086
- }
25087
- function watchEscInterrupt(session, data, onStatusChange) {
25088
- if (session.status !== "running") return;
25089
- if (!isInterruptKey(data)) return;
25090
- scheduleSettle(session, onStatusChange);
25091
- }
25092
- function noteOutputForEscInterrupt(session, onStatusChange) {
25093
- if (!session.escInterruptTimer) return;
25094
- scheduleSettle(session, onStatusChange);
25095
- }
25096
- function disarmEscInterrupt(session) {
25097
- if (!session.escInterruptTimer) return;
25098
- clearTimeout(session.escInterruptTimer);
25099
- session.escInterruptTimer = void 0;
25100
- }
25101
-
25102
- // src/commands/sessions/daemon/applyStatusChange.ts
25103
- function applyStatusChange(session, status3, exitCode, dismiss, notify2, reuseForRun) {
25104
- disarmEscInterrupt(session);
25105
- if (session.status === status3) return;
25106
- daemonLog(`session ${session.id} status: ${session.status} -> ${status3}`);
25107
- void flushPhaseActiveMs(session);
25108
- setStatus2(session, status3);
25109
- const autoRun = shouldAutoRun(session);
25110
- if (autoRun.run) {
25111
- reuseForRun(session, autoRun.itemId);
25112
- notify2();
25113
- return;
25114
- }
25115
- if (status3 === "done" && autoRun.reason != null) {
25091
+ // src/commands/sessions/daemon/applySetStatus.ts
25092
+ function applySetStatus(sessions, id, status3, source, onStatusChange) {
25093
+ const session = sessions.get(id);
25094
+ if (!session) {
25116
25095
  daemonLog(
25117
- `session ${session.id} auto-run enabled but skipped (exit ${exitCode ?? "none"}): ${autoRun.reason}`
25096
+ `set-status for unknown session id=${id} status=${status3} (no live session; ignoring)`
25118
25097
  );
25098
+ return;
25119
25099
  }
25120
- if (shouldAutoDismiss(session, exitCode)) dismiss(session.id);
25121
- else notify2();
25122
- }
25123
-
25124
- // src/commands/sessions/daemon/makeStatusChangeHandler.ts
25125
- function makeStatusChangeHandler(dismiss, notify2, reuseForRun) {
25126
- return (s, status3, exitCode) => applyStatusChange(s, status3, exitCode, dismiss, notify2, reuseForRun);
25100
+ if (source === "permission") session.permissionActive = true;
25101
+ if (status3 === "running") session.permissionActive = false;
25102
+ onStatusChange(session, status3);
25127
25103
  }
25128
25104
 
25129
25105
  // src/shared/db/recordPhaseCycleContext.ts
@@ -25282,12 +25258,102 @@ function recordSessionUsage(sessions, claudeSessionId, transcriptPath, usedPct,
25282
25258
  return false;
25283
25259
  }
25284
25260
 
25261
+ // src/commands/sessions/daemon/applyUsageRecord.ts
25262
+ function applyUsageRecord(sessions, windows, notify2, claudeSessionId, transcriptPath, usedPct) {
25263
+ if (recordSessionUsage(
25264
+ sessions,
25265
+ claudeSessionId,
25266
+ transcriptPath,
25267
+ usedPct,
25268
+ windows
25269
+ ))
25270
+ notify2();
25271
+ }
25272
+
25273
+ // src/commands/sessions/daemon/setStatus.ts
25274
+ function setStatus2(session, newStatus) {
25275
+ const now = Date.now();
25276
+ if (session.status === "running" && session.runningSince != null) {
25277
+ session.runningMs += now - session.runningSince;
25278
+ }
25279
+ session.runningSince = newStatus === "running" ? now : null;
25280
+ session.status = newStatus;
25281
+ }
25282
+
25283
+ // src/commands/sessions/daemon/shouldAutoDismiss.ts
25284
+ function shouldAutoDismiss(session, exitCode) {
25285
+ if (session.status !== "done" || exitCode !== 0) {
25286
+ return false;
25287
+ }
25288
+ if (session.reviewStarted) {
25289
+ return session.autoAdvance === true;
25290
+ }
25291
+ const args = session.assistArgs;
25292
+ if (args === void 0) return false;
25293
+ if (args[0] === "update") return true;
25294
+ return args.includes("--once") && args[0] !== "next";
25295
+ }
25296
+
25297
+ // src/commands/sessions/daemon/shouldAutoRun.ts
25298
+ function shouldAutoRun(session) {
25299
+ if (!session.autoRun) return { run: false, reason: null };
25300
+ if (session.status !== "done")
25301
+ return {
25302
+ run: false,
25303
+ reason: `session status is "${session.status}", not "done"`
25304
+ };
25305
+ if (session.commandType !== "assist")
25306
+ return {
25307
+ run: false,
25308
+ reason: `command type is "${session.commandType}", not "assist"`
25309
+ };
25310
+ const cmd = session.assistArgs?.[0];
25311
+ if (cmd !== "draft" && cmd !== "bug" && cmd !== "refine")
25312
+ return {
25313
+ run: false,
25314
+ reason: `command "${cmd ?? "(none)"}" is not draft/bug/refine`
25315
+ };
25316
+ const itemId2 = session.activity?.itemId;
25317
+ if (itemId2 == null)
25318
+ return {
25319
+ run: false,
25320
+ reason: "no itemId in activity (draft did not create an item)"
25321
+ };
25322
+ return { run: true, itemId: itemId2 };
25323
+ }
25324
+
25325
+ // src/commands/sessions/daemon/applyStatusChange.ts
25326
+ function applyStatusChange(session, status3, exitCode, dismiss, notify2, reuseForRun) {
25327
+ if (session.status === status3) return;
25328
+ daemonLog(`session ${session.id} status: ${session.status} -> ${status3}`);
25329
+ void flushPhaseActiveMs(session);
25330
+ setStatus2(session, status3);
25331
+ const autoRun = shouldAutoRun(session);
25332
+ if (autoRun.run) {
25333
+ reuseForRun(session, autoRun.itemId);
25334
+ notify2();
25335
+ return;
25336
+ }
25337
+ if (status3 === "done" && autoRun.reason != null) {
25338
+ daemonLog(
25339
+ `session ${session.id} auto-run enabled but skipped (exit ${exitCode ?? "none"}): ${autoRun.reason}`
25340
+ );
25341
+ }
25342
+ if (shouldAutoDismiss(session, exitCode)) dismiss(session.id);
25343
+ else notify2();
25344
+ }
25345
+
25346
+ // src/commands/sessions/daemon/makeStatusChangeHandler.ts
25347
+ function makeStatusChangeHandler(dismiss, notify2, reuseForRun) {
25348
+ return (s, status3, exitCode) => applyStatusChange(s, status3, exitCode, dismiss, notify2, reuseForRun);
25349
+ }
25350
+
25285
25351
  // src/commands/sessions/daemon/errorTail.ts
25286
- var ESC4 = String.fromCharCode(27);
25352
+ var ESC3 = String.fromCharCode(27);
25287
25353
  var CSI = String.fromCharCode(155);
25288
25354
  var BEL = String.fromCharCode(7);
25289
25355
  var ANSI = new RegExp(
25290
- String.raw`[${ESC4}${CSI}][[\]()#;?]*(?:(?:[a-zA-Z\d]*(?:;[a-zA-Z\d]*)*)?${BEL}|(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-ntqry=><~])`,
25356
+ String.raw`[${ESC3}${CSI}][[\]()#;?]*(?:(?:[a-zA-Z\d]*(?:;[a-zA-Z\d]*)*)?${BEL}|(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-ntqry=><~])`,
25291
25357
  "g"
25292
25358
  );
25293
25359
  var MAX_TAIL_LINES = 40;
@@ -25355,10 +25421,10 @@ async function seedRunningMsFromUsage(session, notify2) {
25355
25421
 
25356
25422
  // src/commands/sessions/daemon/watchActivity.ts
25357
25423
  var DEBOUNCE_MS = 50;
25358
- function watchActivity(session, notify2) {
25424
+ function watchActivity(session, notify2, onClaudeSessionId) {
25359
25425
  if (session.commandType !== "assist" || !session.cwd) return;
25360
- const path70 = activityPath(session.id);
25361
- const dir = dirname29(path70);
25426
+ const path71 = activityPath(session.id);
25427
+ const dir = dirname29(path71);
25362
25428
  try {
25363
25429
  mkdirSync25(dir, { recursive: true });
25364
25430
  } catch {
@@ -25368,21 +25434,23 @@ function watchActivity(session, notify2) {
25368
25434
  let timer = null;
25369
25435
  const read = () => {
25370
25436
  timer = null;
25371
- const activity2 = readActivity(path70);
25437
+ const activity2 = readActivity(path71);
25372
25438
  if (!activity2) return;
25373
25439
  session.activity = activity2;
25374
- if (activity2.claudeSessionId)
25440
+ if (activity2.claudeSessionId) {
25375
25441
  session.claudeSessionId = activity2.claudeSessionId;
25442
+ onClaudeSessionId?.(session);
25443
+ }
25376
25444
  applyReviewPause(session, activity2);
25377
25445
  void seedRunningMsFromUsage(session, notify2);
25378
25446
  notify2();
25379
25447
  };
25380
25448
  session.activityWatcher = watch(dir, (_event, filename) => {
25381
- if (filename && !path70.endsWith(filename)) return;
25449
+ if (filename && !path71.endsWith(filename)) return;
25382
25450
  if (timer) clearTimeout(timer);
25383
25451
  timer = setTimeout(read, DEBOUNCE_MS);
25384
25452
  });
25385
- if (existsSync58(path70)) read();
25453
+ if (existsSync58(path71)) read();
25386
25454
  }
25387
25455
  function refreshActivity(session) {
25388
25456
  if (session.commandType !== "assist" || !session.cwd) return;
@@ -25445,7 +25513,6 @@ function wirePtyEvents(session, clients, onStatusChange) {
25445
25513
  if (!session.pty) return;
25446
25514
  session.pty.onData((data) => {
25447
25515
  appendScrollback(session, data);
25448
- noteOutputForEscInterrupt(session, onStatusChange);
25449
25516
  broadcast(clients, { type: "output", sessionId: session.id, data });
25450
25517
  });
25451
25518
  session.pty.onExit(
@@ -25613,6 +25680,222 @@ function errorSession(id, persisted, error) {
25613
25680
  };
25614
25681
  }
25615
25682
 
25683
+ // src/commands/sessions/shared/normalizeUser.ts
25684
+ var INTERRUPT_PREFIX = "[Request interrupted";
25685
+ function normalizeUser(entry) {
25686
+ const content = asRecord(entry.message)?.content;
25687
+ if (typeof content === "string")
25688
+ return isInterruptText(content) ? { kind: "interrupt" } : { kind: "user" };
25689
+ if (!Array.isArray(content)) return { kind: "user" };
25690
+ const toolResultIds = [];
25691
+ let hasInterrupt = false;
25692
+ let hasNonToolResult = false;
25693
+ for (const block of content) {
25694
+ const b = asRecord(block);
25695
+ if (!b) continue;
25696
+ if (b.type === "tool_result") {
25697
+ if (typeof b.tool_use_id === "string") toolResultIds.push(b.tool_use_id);
25698
+ } else if (b.type === "text" && isInterruptText(b.text)) {
25699
+ hasInterrupt = true;
25700
+ } else {
25701
+ hasNonToolResult = true;
25702
+ }
25703
+ }
25704
+ if (hasInterrupt) return { kind: "interrupt" };
25705
+ if (hasNonToolResult) return { kind: "user" };
25706
+ return { kind: "toolResult", ids: toolResultIds };
25707
+ }
25708
+ function asRecord(value) {
25709
+ return value && typeof value === "object" ? value : null;
25710
+ }
25711
+ function isInterruptText(value) {
25712
+ return typeof value === "string" && value.startsWith(INTERRUPT_PREFIX);
25713
+ }
25714
+
25715
+ // src/commands/sessions/shared/normalizeTranscriptEvents.ts
25716
+ function normalizeTranscriptEvents(entries) {
25717
+ return entries.map(normalizeEntry).filter((event) => event !== null);
25718
+ }
25719
+ function normalizeEntry(entry) {
25720
+ if (entry.isSidechain || entry.isMeta) return null;
25721
+ if (entry.type === "assistant") return normalizeAssistant(entry);
25722
+ if (entry.type === "user") return normalizeUser(entry);
25723
+ return null;
25724
+ }
25725
+ function normalizeAssistant(entry) {
25726
+ const message = asRecord2(entry.message);
25727
+ const stopReason = typeof message?.stop_reason === "string" ? message.stop_reason : null;
25728
+ const content = message?.content;
25729
+ const toolUses = [];
25730
+ if (Array.isArray(content))
25731
+ for (const block of content) {
25732
+ const b = asRecord2(block);
25733
+ if (b?.type === "tool_use")
25734
+ toolUses.push({
25735
+ id: typeof b.id === "string" ? b.id : "",
25736
+ name: typeof b.name === "string" ? b.name : ""
25737
+ });
25738
+ }
25739
+ return { kind: "assistant", stopReason, toolUses };
25740
+ }
25741
+ function asRecord2(value) {
25742
+ return value && typeof value === "object" ? value : null;
25743
+ }
25744
+
25745
+ // src/commands/sessions/shared/deriveTranscriptStatus.ts
25746
+ var ASK_USER_QUESTION2 = "AskUserQuestion";
25747
+ var TURN_END_STOP_REASONS = /* @__PURE__ */ new Set(["end_turn", "stop_sequence"]);
25748
+ function deriveTranscriptStatus(entries, opts = {}) {
25749
+ const events = normalizeTranscriptEvents(entries);
25750
+ const lastIdx = lastDecisiveIndex(events);
25751
+ if (lastIdx === -1) return null;
25752
+ const ev = events[lastIdx];
25753
+ if (ev.kind === "interrupt") return "waiting";
25754
+ if (ev.kind === "user") return "running";
25755
+ if (ev.kind === "toolResult") return null;
25756
+ if (ev.stopReason != null && TURN_END_STOP_REASONS.has(ev.stopReason))
25757
+ return "waiting";
25758
+ const resolved = resolvedToolUseIds(events, lastIdx);
25759
+ const pending = ev.toolUses.filter((tool) => !resolved.has(tool.id));
25760
+ if (pending.length === 0) return "running";
25761
+ if (pending.some((tool) => tool.name === ASK_USER_QUESTION2))
25762
+ return "waiting";
25763
+ if (opts.permissionActive) return "waiting";
25764
+ return "running";
25765
+ }
25766
+ function lastDecisiveIndex(events) {
25767
+ for (let i = events.length - 1; i >= 0; i--)
25768
+ if (events[i].kind !== "toolResult") return i;
25769
+ return -1;
25770
+ }
25771
+ function resolvedToolUseIds(events, afterIdx) {
25772
+ const ids = /* @__PURE__ */ new Set();
25773
+ for (let i = afterIdx + 1; i < events.length; i++) {
25774
+ const event = events[i];
25775
+ if (event.kind === "toolResult") for (const id of event.ids) ids.add(id);
25776
+ }
25777
+ return ids;
25778
+ }
25779
+
25780
+ // src/commands/sessions/shared/readTranscriptTail.ts
25781
+ import * as fs37 from "fs";
25782
+ var DEFAULT_MAX_BYTES = 256 * 1024;
25783
+ function parseTailEntries(raw) {
25784
+ const entries = [];
25785
+ for (const line of raw.split("\n")) {
25786
+ const trimmed = line.trim();
25787
+ if (!trimmed) continue;
25788
+ try {
25789
+ const parsed = JSON.parse(trimmed);
25790
+ if (parsed && typeof parsed === "object")
25791
+ entries.push(parsed);
25792
+ } catch {
25793
+ }
25794
+ }
25795
+ return entries;
25796
+ }
25797
+ function dropPartialFirstLine(raw, sliced) {
25798
+ if (!sliced) return raw;
25799
+ const newline = raw.indexOf("\n");
25800
+ return newline === -1 ? "" : raw.slice(newline + 1);
25801
+ }
25802
+ async function readTranscriptTail(filePath, maxBytes = DEFAULT_MAX_BYTES) {
25803
+ let handle;
25804
+ try {
25805
+ handle = await fs37.promises.open(filePath, "r");
25806
+ const { size } = await handle.stat();
25807
+ const start3 = Math.max(0, size - maxBytes);
25808
+ const length = size - start3;
25809
+ if (length === 0) return [];
25810
+ const buf = Buffer.alloc(length);
25811
+ await handle.read(buf, 0, length, start3);
25812
+ return parseTailEntries(
25813
+ dropPartialFirstLine(buf.toString("utf8"), start3 > 0)
25814
+ );
25815
+ } catch {
25816
+ return [];
25817
+ } finally {
25818
+ await handle?.close();
25819
+ }
25820
+ }
25821
+ function readTranscriptTailSync(filePath, maxBytes = DEFAULT_MAX_BYTES) {
25822
+ let fd;
25823
+ try {
25824
+ fd = fs37.openSync(filePath, "r");
25825
+ const { size } = fs37.fstatSync(fd);
25826
+ const start3 = Math.max(0, size - maxBytes);
25827
+ const length = size - start3;
25828
+ if (length === 0) return [];
25829
+ const buf = Buffer.alloc(length);
25830
+ fs37.readSync(fd, buf, 0, length, start3);
25831
+ return parseTailEntries(
25832
+ dropPartialFirstLine(buf.toString("utf8"), start3 > 0)
25833
+ );
25834
+ } catch {
25835
+ return [];
25836
+ } finally {
25837
+ if (fd !== void 0) fs37.closeSync(fd);
25838
+ }
25839
+ }
25840
+
25841
+ // src/commands/sessions/shared/findTranscriptPathSync.ts
25842
+ import * as fs38 from "fs";
25843
+ import * as os4 from "os";
25844
+ import * as path60 from "path";
25845
+ function projectDirForCwd(cwd) {
25846
+ return path60.join(
25847
+ os4.homedir(),
25848
+ ".claude",
25849
+ "projects",
25850
+ cwd.replace(/[^a-zA-Z0-9]/g, "-")
25851
+ );
25852
+ }
25853
+ function transcriptPathFor(cwd, claudeSessionId) {
25854
+ return path60.join(projectDirForCwd(cwd), `${claudeSessionId}.jsonl`);
25855
+ }
25856
+ function findTranscriptPathSync(cwd, claudeSessionId) {
25857
+ const direct = transcriptPathFor(cwd, claudeSessionId);
25858
+ if (fs38.existsSync(direct)) return direct;
25859
+ const dir = projectDirForCwd(cwd);
25860
+ let files;
25861
+ try {
25862
+ files = fs38.readdirSync(dir);
25863
+ } catch {
25864
+ return null;
25865
+ }
25866
+ for (const file of files) {
25867
+ if (!file.endsWith(".jsonl")) continue;
25868
+ if (headContainsSessionId(path60.join(dir, file), claudeSessionId))
25869
+ return path60.join(dir, file);
25870
+ }
25871
+ return null;
25872
+ }
25873
+ function headContainsSessionId(filePath, claudeSessionId) {
25874
+ let fd;
25875
+ try {
25876
+ fd = fs38.openSync(filePath, "r");
25877
+ const buf = Buffer.alloc(16384);
25878
+ const bytesRead = fs38.readSync(fd, buf, 0, buf.length, 0);
25879
+ return buf.toString("utf8", 0, bytesRead).includes(claudeSessionId);
25880
+ } catch {
25881
+ return false;
25882
+ } finally {
25883
+ if (fd !== void 0) fs38.closeSync(fd);
25884
+ }
25885
+ }
25886
+
25887
+ // src/commands/sessions/daemon/deriveRestoreStatus.ts
25888
+ function deriveRestoreStatus(persisted) {
25889
+ if (!persisted.claudeSessionId) return "waiting";
25890
+ const filePath = findTranscriptPathSync(
25891
+ persisted.cwd,
25892
+ persisted.claudeSessionId
25893
+ );
25894
+ if (!filePath) return "waiting";
25895
+ const entries = readTranscriptTailSync(filePath);
25896
+ return deriveTranscriptStatus(entries) === "running" ? "running" : "waiting";
25897
+ }
25898
+
25616
25899
  // src/commands/sessions/daemon/runningSession.ts
25617
25900
  function runningSession(base, persisted, pty2) {
25618
25901
  return restoredSession(base, persisted, pty2, "running");
@@ -25636,17 +25919,16 @@ function restoredSession(base, persisted, pty2, status3) {
25636
25919
  }
25637
25920
 
25638
25921
  // src/commands/sessions/daemon/restoreInteractiveSession.ts
25639
- function restoreInteractiveSession(id, persisted, base) {
25922
+ function restoreInteractiveSession(id, persisted, base, idle) {
25640
25923
  if (persisted.commandType !== "run" && persisted.claudeSessionId) {
25641
- return resumeViaClaude(id, persisted, base);
25924
+ return resumeViaClaude(id, persisted, base, idle);
25642
25925
  }
25643
25926
  if (persisted.commandType === "claude") {
25644
25927
  return unrecoverableClaude(id, persisted);
25645
25928
  }
25646
25929
  return notRestoredStub(base, persisted);
25647
25930
  }
25648
- function resumeViaClaude(id, persisted, base) {
25649
- const idle = persisted.status !== "running";
25931
+ function resumeViaClaude(id, persisted, base, idle) {
25650
25932
  const pty2 = spawnClaude2({
25651
25933
  resumeSessionId: persisted.claudeSessionId,
25652
25934
  prompt: idle ? void 0 : buildResumePrompt(),
@@ -25695,8 +25977,8 @@ function isUpdate(persisted) {
25695
25977
  function restoreSession(id, persisted) {
25696
25978
  const base = restoreBase(id, persisted);
25697
25979
  if (isUpdate(persisted)) return updatedSession(id, persisted);
25980
+ const idle = deriveRestoreStatus(persisted) !== "running";
25698
25981
  if (needsWrapperRelaunch(persisted)) {
25699
- const idle = persisted.status !== "running";
25700
25982
  const pty2 = spawnPty(
25701
25983
  assistResumeArgs(persisted),
25702
25984
  persisted.cwd,
@@ -25705,7 +25987,7 @@ function restoreSession(id, persisted) {
25705
25987
  );
25706
25988
  return idle ? waitingSession(base, persisted, pty2) : runningSession(base, persisted, pty2);
25707
25989
  }
25708
- return restoreInteractiveSession(id, persisted, base);
25990
+ return restoreInteractiveSession(id, persisted, base, idle);
25709
25991
  }
25710
25992
  function needsWrapperRelaunch(persisted) {
25711
25993
  return isBacklogRun(persisted) || isOnceLaunch(persisted) && !!persisted.claudeSessionId;
@@ -25846,6 +26128,77 @@ function shutdownSessions(sessions) {
25846
26128
  }
25847
26129
  }
25848
26130
 
26131
+ // src/commands/sessions/daemon/watchTranscript.ts
26132
+ import { existsSync as existsSync60, watch as watch2 } from "fs";
26133
+
26134
+ // src/commands/sessions/daemon/reconcileTranscriptStatus.ts
26135
+ async function resolveTranscriptPath(session) {
26136
+ if (session.transcriptPath) return session.transcriptPath;
26137
+ if (!session.claudeSessionId) return null;
26138
+ const direct = session.cwd ? findTranscriptPathSync(session.cwd, session.claudeSessionId) : null;
26139
+ const filePath = direct ?? await findSessionJsonlPath(session.claudeSessionId);
26140
+ if (filePath) session.transcriptPath = filePath;
26141
+ return filePath;
26142
+ }
26143
+ async function reconcileTranscriptStatus(session, onStatusChange) {
26144
+ if (session.status === "done" || session.status === "error") return;
26145
+ const filePath = await resolveTranscriptPath(session);
26146
+ if (!filePath) return;
26147
+ const entries = await readTranscriptTail(filePath);
26148
+ const derived = deriveTranscriptStatus(entries, {
26149
+ permissionActive: session.permissionActive
26150
+ });
26151
+ if (!derived) return;
26152
+ if (derived === "running") session.permissionActive = false;
26153
+ if (derived === session.status) return;
26154
+ daemonLog(
26155
+ `session ${session.id} transcript reconcile: ${session.status} -> ${derived}`
26156
+ );
26157
+ onStatusChange(session, derived);
26158
+ }
26159
+
26160
+ // src/commands/sessions/daemon/watchTranscript.ts
26161
+ var DEBOUNCE_MS2 = 100;
26162
+ function watchTranscript(session, onStatusChange) {
26163
+ if (!session.cwd || !session.claudeSessionId) return;
26164
+ if (session.watchedTranscriptId === session.claudeSessionId) return;
26165
+ const dir = projectDirForCwd(session.cwd);
26166
+ if (!existsSync60(dir)) return;
26167
+ if (session.transcriptWatcher) {
26168
+ session.transcriptWatcher.close();
26169
+ session.transcriptWatcher = void 0;
26170
+ }
26171
+ session.transcriptPath = void 0;
26172
+ const fileName = `${session.claudeSessionId}.jsonl`;
26173
+ let timer = null;
26174
+ const run4 = () => {
26175
+ timer = null;
26176
+ void reconcileTranscriptStatus(session, onStatusChange);
26177
+ };
26178
+ try {
26179
+ session.transcriptWatcher = watch2(dir, (_event, changed) => {
26180
+ if (changed && changed !== fileName) return;
26181
+ if (timer) clearTimeout(timer);
26182
+ timer = setTimeout(run4, DEBOUNCE_MS2);
26183
+ });
26184
+ } catch (error) {
26185
+ daemonLog(
26186
+ `session ${session.id} transcript watch failed: ${error instanceof Error ? error.message : String(error)}`
26187
+ );
26188
+ return;
26189
+ }
26190
+ session.watchedTranscriptId = session.claudeSessionId;
26191
+ daemonLog(`session ${session.id} watching transcript ${fileName}`);
26192
+ run4();
26193
+ }
26194
+
26195
+ // src/commands/sessions/daemon/wireSessionWatchers.ts
26196
+ function wireSessionWatchers(session, notify2, onStatusChange) {
26197
+ const wireTranscript = (s) => watchTranscript(s, onStatusChange);
26198
+ watchActivity(session, notify2, wireTranscript);
26199
+ wireTranscript(session);
26200
+ }
26201
+
25849
26202
  // src/commands/sessions/daemon/connectToWindowsDaemon.ts
25850
26203
  import * as net2 from "net";
25851
26204
 
@@ -25961,13 +26314,13 @@ async function defaultConnect() {
25961
26314
  }
25962
26315
 
25963
26316
  // src/commands/sessions/daemon/hasPersistedWindowsSessions.ts
25964
- import { existsSync as existsSync59, readFileSync as readFileSync49 } from "fs";
26317
+ import { existsSync as existsSync61, readFileSync as readFileSync49 } from "fs";
25965
26318
  import { posix } from "path";
25966
26319
  function hasPersistedWindowsSessions() {
25967
26320
  const sessionsFile = windowsSessionsFileFromWsl();
25968
26321
  if (!sessionsFile) return false;
25969
26322
  try {
25970
- if (!existsSync59(sessionsFile)) return false;
26323
+ if (!existsSync61(sessionsFile)) return false;
25971
26324
  const data = JSON.parse(readFileSync49(sessionsFile, "utf8"));
25972
26325
  return Array.isArray(data) && data.length > 0;
25973
26326
  } catch (error) {
@@ -26528,7 +26881,6 @@ function writeToSession(sessions, id, data, onStatusChange) {
26528
26881
  const s = sessions.get(id);
26529
26882
  if (!s || s.status === "done") return;
26530
26883
  s.pty?.write(data);
26531
- watchEscInterrupt(s, data, onStatusChange);
26532
26884
  watchPromptSubmit(s, data, onStatusChange);
26533
26885
  }
26534
26886
  function resizeSession(sessions, id, cols, rows) {
@@ -26608,7 +26960,7 @@ var SessionManager = class {
26608
26960
  drain = () => drainSessions(this.sessions, this.notify);
26609
26961
  add(session) {
26610
26962
  this.wire(session);
26611
- watchActivity(session, this.notify);
26963
+ wireSessionWatchers(session, this.notify, this.onStatusChange);
26612
26964
  logSpawnedSession(session);
26613
26965
  return session.id;
26614
26966
  }
@@ -26671,27 +27023,20 @@ var SessionManager = class {
26671
27023
  setStarred(id, starred) {
26672
27024
  if (setStarred2(this.sessions, id, starred)) this.notify();
26673
27025
  }
26674
- setStatus(id, status3) {
26675
- const session = this.sessions.get(id);
26676
- if (!session) {
26677
- daemonLog(
26678
- `set-status for unknown session id=${id} status=${status3} (no live session; ignoring)`
26679
- );
26680
- return;
26681
- }
26682
- this.onStatusChange(session, status3);
27026
+ setStatus(id, status3, source) {
27027
+ applySetStatus(this.sessions, id, status3, source, this.onStatusChange);
26683
27028
  }
26684
27029
  /* why: the status line relays token totals keyed by Claude's session id; join
26685
27030
  * it to the running backlog phase so the spend accumulates against that row. */
26686
27031
  recordUsage(claudeSessionId, transcriptPath, usedPct) {
26687
- if (recordSessionUsage(
27032
+ applyUsageRecord(
26688
27033
  this.sessions.values(),
27034
+ this.clients.currentWindows(),
27035
+ this.notify,
26689
27036
  claudeSessionId,
26690
27037
  transcriptPath,
26691
- usedPct,
26692
- this.clients.currentWindows()
26693
- ))
26694
- this.notify();
27038
+ usedPct
27039
+ );
26695
27040
  }
26696
27041
  listSessions = () => {
26697
27042
  const local = [...this.sessions.values()].map(toSessionInfo);
@@ -26712,8 +27057,30 @@ import * as net3 from "net";
26712
27057
  // src/commands/sessions/daemon/handleConnection.ts
26713
27058
  import { createInterface as createInterface9 } from "readline";
26714
27059
 
27060
+ // src/commands/sessions/daemon/creator.ts
27061
+ function creator(isNew, spawn12) {
27062
+ return (client, m, d) => {
27063
+ if (m.windowsProxy.route(client, d)) return;
27064
+ sendTo(client, { type: "created", sessionId: spawn12(m, d), isNew });
27065
+ };
27066
+ }
27067
+
27068
+ // src/commands/sessions/daemon/handleSetStatus.ts
27069
+ function handleSetStatus(client, m, d) {
27070
+ daemonLog(
27071
+ `set-status received: id=${d.sessionId} status=${d.status}${d.source ? ` source=${d.source}` : ""}`
27072
+ );
27073
+ if (m.windowsProxy.route(client, d)) return;
27074
+ m.setStatus(
27075
+ d.sessionId,
27076
+ d.status,
27077
+ d.source
27078
+ );
27079
+ if (d.ack) sendTo(client, { type: "ack", sessionId: d.sessionId });
27080
+ }
27081
+
26715
27082
  // src/commands/sessions/shared/parseTranscript.ts
26716
- import * as fs37 from "fs";
27083
+ import * as fs39 from "fs";
26717
27084
 
26718
27085
  // src/commands/sessions/shared/toolTarget.ts
26719
27086
  function toolTarget(input) {
@@ -26765,7 +27132,7 @@ async function parseTranscript(sessionId) {
26765
27132
  const filePath = await findSessionJsonlPath(sessionId);
26766
27133
  if (!filePath) return [];
26767
27134
  try {
26768
- const raw = await fs37.promises.readFile(filePath, "utf8");
27135
+ const raw = await fs39.promises.readFile(filePath, "utf8");
26769
27136
  return parseTranscriptLines(raw.split("\n"));
26770
27137
  } catch {
26771
27138
  return [];
@@ -26829,12 +27196,6 @@ function spawnCreate(m, d) {
26829
27196
  }
26830
27197
 
26831
27198
  // src/commands/sessions/daemon/messageHandlers.ts
26832
- function creator(isNew, spawn12) {
26833
- return (client, m, d) => {
26834
- if (m.windowsProxy.route(client, d)) return;
26835
- sendTo(client, { type: "created", sessionId: spawn12(m, d), isNew });
26836
- };
26837
- }
26838
27199
  function routed(local) {
26839
27200
  return (client, m, d) => {
26840
27201
  if (!m.windowsProxy.route(client, d)) local(client, m, d);
@@ -26903,11 +27264,7 @@ var messageHandlers = {
26903
27264
  (_client, m, d) => m.setStarred(d.sessionId, d.starred)
26904
27265
  ),
26905
27266
  "set-active": (_client, m, d) => m.active.set(d.cwd, d.sessionId),
26906
- "set-status": (client, m, d) => {
26907
- daemonLog(`set-status received: id=${d.sessionId} status=${d.status}`);
26908
- if (!m.windowsProxy.route(client, d))
26909
- m.setStatus(d.sessionId, d.status);
26910
- },
27267
+ "set-status": handleSetStatus,
26911
27268
  "ui-status": (_client, _m, d) => daemonLog(`ui rendered: id=${d.sessionId} status=${d.status}`)
26912
27269
  };
26913
27270
 
@@ -27093,18 +27450,33 @@ function registerDaemon(program2) {
27093
27450
  ).action(drainDaemon);
27094
27451
  }
27095
27452
 
27453
+ // src/commands/sessions/registerSetStatusCommand.ts
27454
+ function registerSetStatusCommand(cmd) {
27455
+ cmd.command("set-status <status>").description(
27456
+ "Report the current session's status to the sessions daemon (used by Claude Code hooks)"
27457
+ ).option(
27458
+ "--source <source>",
27459
+ "Originating hook (permission, stop, notification, prompt, pretool, posttool)"
27460
+ ).option(
27461
+ "--ack",
27462
+ "Wait for the daemon to acknowledge delivery, retrying on failure"
27463
+ ).action(
27464
+ (status3, options2) => setSessionStatus(status3, { source: options2.source, ack: options2.ack })
27465
+ );
27466
+ }
27467
+
27096
27468
  // src/commands/sessions/summarise/index.ts
27097
- import * as fs39 from "fs";
27469
+ import * as fs41 from "fs";
27098
27470
  import chalk200 from "chalk";
27099
27471
 
27100
27472
  // src/commands/sessions/summarise/shared.ts
27101
- import * as fs38 from "fs";
27473
+ import * as fs40 from "fs";
27102
27474
  function writeSummary(jsonlPath2, summary) {
27103
- fs38.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
27475
+ fs40.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
27104
27476
  `, "utf8");
27105
27477
  }
27106
27478
  function hasSummary(jsonlPath2) {
27107
- return fs38.existsSync(summaryPathFor(jsonlPath2));
27479
+ return fs40.existsSync(summaryPathFor(jsonlPath2));
27108
27480
  }
27109
27481
  function summaryPathFor(jsonlPath2) {
27110
27482
  return jsonlPath2.replace(/\.jsonl$/, ".summary");
@@ -27191,7 +27563,7 @@ function selectCandidates(files, options2) {
27191
27563
  const candidates = options2.force ? files : files.filter((f) => !hasSummary(f));
27192
27564
  candidates.sort((a, b) => {
27193
27565
  try {
27194
- return fs39.statSync(b).mtimeMs - fs39.statSync(a).mtimeMs;
27566
+ return fs41.statSync(b).mtimeMs - fs41.statSync(a).mtimeMs;
27195
27567
  } catch {
27196
27568
  return 0;
27197
27569
  }
@@ -27229,9 +27601,7 @@ function registerSessions(program2) {
27229
27601
  (options2, command) => web({ ...options2, open: command.optsWithGlobals().open })
27230
27602
  );
27231
27603
  cmd.command("summarise").description("Generate one-line summaries for Claude sessions").option("-f, --force", "Re-generate all summaries, even existing ones").option("-n, --limit <count>", "Maximum number of sessions to summarise").action(summarise2);
27232
- cmd.command("set-status <status>").description(
27233
- "Report the current session's status to the sessions daemon (used by Claude Code hooks)"
27234
- ).action(setSessionStatus);
27604
+ registerSetStatusCommand(cmd);
27235
27605
  configHelp(cmd, [
27236
27606
  {
27237
27607
  key: "sessions.windowsProjectsRoot",
@@ -27332,9 +27702,9 @@ function buildLimitsSegment(rateLimits) {
27332
27702
 
27333
27703
  // src/commands/readGitBranch.ts
27334
27704
  import { readFileSync as readFileSync52, statSync as statSync11 } from "fs";
27335
- import { isAbsolute as isAbsolute2, join as join68, resolve as resolve17 } from "path";
27705
+ import { isAbsolute as isAbsolute2, join as join69, resolve as resolve17 } from "path";
27336
27706
  function resolveGitDir(cwd) {
27337
- const dotGit = join68(cwd, ".git");
27707
+ const dotGit = join69(cwd, ".git");
27338
27708
  let stat2;
27339
27709
  try {
27340
27710
  stat2 = statSync11(dotGit);
@@ -27364,7 +27734,7 @@ function readGitBranch(cwd) {
27364
27734
  }
27365
27735
  let head;
27366
27736
  try {
27367
- head = readFileSync52(join68(gitDir, "HEAD"), "utf8");
27737
+ head = readFileSync52(join69(gitDir, "HEAD"), "utf8");
27368
27738
  } catch {
27369
27739
  return null;
27370
27740
  }
@@ -27432,21 +27802,21 @@ async function statusLine() {
27432
27802
  }
27433
27803
 
27434
27804
  // src/commands/sync.ts
27435
- import * as fs46 from "fs";
27436
- import * as os4 from "os";
27437
- import * as path68 from "path";
27805
+ import * as fs48 from "fs";
27806
+ import * as os5 from "os";
27807
+ import * as path69 from "path";
27438
27808
  import { fileURLToPath as fileURLToPath9 } from "url";
27439
27809
 
27440
27810
  // src/commands/sync/syncClaudeMd.ts
27441
- import * as fs40 from "fs";
27442
- import * as path60 from "path";
27811
+ import * as fs42 from "fs";
27812
+ import * as path61 from "path";
27443
27813
  import chalk203 from "chalk";
27444
27814
  async function syncClaudeMd(claudeDir, targetBase, options2) {
27445
- const source = path60.join(claudeDir, "CLAUDE.md");
27446
- const target = path60.join(targetBase, "CLAUDE.md");
27447
- const sourceContent = fs40.readFileSync(source, "utf8");
27448
- if (fs40.existsSync(target)) {
27449
- const targetContent = fs40.readFileSync(target, "utf8");
27815
+ const source = path61.join(claudeDir, "CLAUDE.md");
27816
+ const target = path61.join(targetBase, "CLAUDE.md");
27817
+ const sourceContent = fs42.readFileSync(source, "utf8");
27818
+ if (fs42.existsSync(target)) {
27819
+ const targetContent = fs42.readFileSync(target, "utf8");
27450
27820
  if (sourceContent !== targetContent) {
27451
27821
  console.log(
27452
27822
  chalk203.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
@@ -27463,38 +27833,38 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
27463
27833
  }
27464
27834
  }
27465
27835
  }
27466
- fs40.copyFileSync(source, target);
27836
+ fs42.copyFileSync(source, target);
27467
27837
  console.log("Copied CLAUDE.md to ~/.claude/CLAUDE.md");
27468
27838
  }
27469
27839
 
27470
27840
  // src/commands/sync/syncCodex.ts
27471
- import * as path63 from "path";
27841
+ import * as path64 from "path";
27472
27842
 
27473
27843
  // src/commands/sync/installHarnessCommands.ts
27474
- import * as fs41 from "fs";
27475
- import * as path61 from "path";
27844
+ import * as fs43 from "fs";
27845
+ import * as path62 from "path";
27476
27846
  function installHarnessCommands(claudeDir, harness, transform) {
27477
- const commandsSource = path61.join(claudeDir, "commands");
27478
- const files = fs41.readdirSync(commandsSource);
27847
+ const commandsSource = path62.join(claudeDir, "commands");
27848
+ const files = fs43.readdirSync(commandsSource);
27479
27849
  let synced = 0;
27480
27850
  for (const file of files) {
27481
27851
  if (!file.endsWith(".md")) continue;
27482
27852
  const name = file.replace(/\.md$/, "");
27483
- const content = fs41.readFileSync(path61.join(commandsSource, file), "utf8");
27484
- const target = path61.join(harness.homeDir, harness.sync.commandDest(name));
27485
- fs41.mkdirSync(path61.dirname(target), { recursive: true });
27486
- fs41.writeFileSync(target, transform(name, content));
27853
+ const content = fs43.readFileSync(path62.join(commandsSource, file), "utf8");
27854
+ const target = path62.join(harness.homeDir, harness.sync.commandDest(name));
27855
+ fs43.mkdirSync(path62.dirname(target), { recursive: true });
27856
+ fs43.writeFileSync(target, transform(name, content));
27487
27857
  synced++;
27488
27858
  }
27489
- const agentsTarget = path61.join(harness.homeDir, harness.sync.agentsFile);
27490
- fs41.mkdirSync(path61.dirname(agentsTarget), { recursive: true });
27491
- fs41.copyFileSync(path61.join(claudeDir, "CLAUDE.md"), agentsTarget);
27859
+ const agentsTarget = path62.join(harness.homeDir, harness.sync.agentsFile);
27860
+ fs43.mkdirSync(path62.dirname(agentsTarget), { recursive: true });
27861
+ fs43.copyFileSync(path62.join(claudeDir, "CLAUDE.md"), agentsTarget);
27492
27862
  return { total: files.length, synced };
27493
27863
  }
27494
27864
 
27495
27865
  // src/commands/sync/syncCodexHooks.ts
27496
- import * as fs42 from "fs";
27497
- import * as path62 from "path";
27866
+ import * as fs44 from "fs";
27867
+ import * as path63 from "path";
27498
27868
  var BEGIN = "# >>> assist codex hooks (managed) \u2014 do not edit >>>";
27499
27869
  var END = "# <<< assist codex hooks (managed) <<<";
27500
27870
  function upsertManagedBlock(existing, body) {
@@ -27524,11 +27894,11 @@ ${rest}
27524
27894
  `;
27525
27895
  }
27526
27896
  function syncCodexHooks(sourcePath) {
27527
- const body = fs42.readFileSync(sourcePath, "utf8");
27528
- const configPath = path62.join(harnesses.codex.homeDir, "config.toml");
27529
- const existing = fs42.existsSync(configPath) ? fs42.readFileSync(configPath, "utf8") : "";
27530
- fs42.mkdirSync(path62.dirname(configPath), { recursive: true });
27531
- fs42.writeFileSync(configPath, upsertManagedBlock(existing, body));
27897
+ const body = fs44.readFileSync(sourcePath, "utf8");
27898
+ const configPath = path63.join(harnesses.codex.homeDir, "config.toml");
27899
+ const existing = fs44.existsSync(configPath) ? fs44.readFileSync(configPath, "utf8") : "";
27900
+ fs44.mkdirSync(path63.dirname(configPath), { recursive: true });
27901
+ fs44.writeFileSync(configPath, upsertManagedBlock(existing, body));
27532
27902
  console.log(
27533
27903
  "Registered assist codex-hook in ~/.codex/config.toml (PreToolUse, PermissionRequest)"
27534
27904
  );
@@ -27559,50 +27929,50 @@ function syncCodex(claudeDir) {
27559
27929
  harnesses.codex,
27560
27930
  commandToSkill
27561
27931
  );
27562
- syncCodexHooks(path63.join(claudeDir, "..", "codex", "config.toml"));
27932
+ syncCodexHooks(path64.join(claudeDir, "..", "codex", "config.toml"));
27563
27933
  console.log(
27564
27934
  `Synced ${total} skill(s) to ~/.codex/skills and CLAUDE.md to ~/.codex/AGENTS.md`
27565
27935
  );
27566
27936
  }
27567
27937
 
27568
27938
  // src/commands/sync/syncDesign.ts
27569
- import * as fs43 from "fs";
27570
- import * as path64 from "path";
27939
+ import * as fs45 from "fs";
27940
+ import * as path65 from "path";
27571
27941
  function syncDesign(claudeDir, targetBase) {
27572
- const systemPromptSource = path64.join(claudeDir, "system-prompt.md");
27573
- const systemPromptTarget = path64.join(targetBase, "system-prompt.md");
27574
- fs43.copyFileSync(systemPromptSource, systemPromptTarget);
27942
+ const systemPromptSource = path65.join(claudeDir, "system-prompt.md");
27943
+ const systemPromptTarget = path65.join(targetBase, "system-prompt.md");
27944
+ fs45.copyFileSync(systemPromptSource, systemPromptTarget);
27575
27945
  console.log("Copied system-prompt.md to ~/.claude/system-prompt.md");
27576
- const skillsSource = path64.join(claudeDir, "skills");
27577
- const skillsTarget = path64.join(targetBase, "skills");
27578
- fs43.mkdirSync(skillsTarget, { recursive: true });
27579
- const files = fs43.readdirSync(skillsSource);
27946
+ const skillsSource = path65.join(claudeDir, "skills");
27947
+ const skillsTarget = path65.join(targetBase, "skills");
27948
+ fs45.mkdirSync(skillsTarget, { recursive: true });
27949
+ const files = fs45.readdirSync(skillsSource);
27580
27950
  for (const file of files) {
27581
- fs43.copyFileSync(
27582
- path64.join(skillsSource, file),
27583
- path64.join(skillsTarget, file)
27951
+ fs45.copyFileSync(
27952
+ path65.join(skillsSource, file),
27953
+ path65.join(skillsTarget, file)
27584
27954
  );
27585
27955
  }
27586
27956
  console.log(`Synced ${files.length} design skill(s) to ~/.claude/skills`);
27587
27957
  }
27588
27958
 
27589
27959
  // src/commands/sync/syncPi.ts
27590
- import * as path66 from "path";
27960
+ import * as path67 from "path";
27591
27961
 
27592
27962
  // src/commands/sync/syncPiHooks.ts
27593
- import * as fs44 from "fs";
27594
- import * as path65 from "path";
27963
+ import * as fs46 from "fs";
27964
+ import * as path66 from "path";
27595
27965
  function piExtensionsDir() {
27596
- return path65.join(harnesses.pi.homeDir, "extensions");
27966
+ return path66.join(harnesses.pi.homeDir, "extensions");
27597
27967
  }
27598
27968
  function syncPiHooks(sourceDir) {
27599
27969
  const target = piExtensionsDir();
27600
- fs44.mkdirSync(target, { recursive: true });
27601
- const files = fs44.readdirSync(sourceDir).filter((f) => f.endsWith(".ts"));
27970
+ fs46.mkdirSync(target, { recursive: true });
27971
+ const files = fs46.readdirSync(sourceDir).filter((f) => f.endsWith(".ts"));
27602
27972
  for (const file of files) {
27603
- fs44.copyFileSync(
27604
- path65.join(sourceDir, file),
27605
- path65.join(target, `assist-${file}`)
27973
+ fs46.copyFileSync(
27974
+ path66.join(sourceDir, file),
27975
+ path66.join(target, `assist-${file}`)
27606
27976
  );
27607
27977
  }
27608
27978
  console.log(
@@ -27639,23 +28009,23 @@ function syncPi(claudeDir) {
27639
28009
  harnesses.pi,
27640
28010
  commandToPrompt
27641
28011
  );
27642
- syncPiHooks(path66.join(claudeDir, "..", "pi"));
28012
+ syncPiHooks(path67.join(claudeDir, "..", "pi"));
27643
28013
  console.log(
27644
28014
  `Synced ${synced} prompt(s) to ~/.pi/agent/prompts and CLAUDE.md to ~/.pi/agent/AGENTS.md`
27645
28015
  );
27646
28016
  }
27647
28017
 
27648
28018
  // src/commands/sync/syncSettings.ts
27649
- import * as fs45 from "fs";
27650
- import * as path67 from "path";
28019
+ import * as fs47 from "fs";
28020
+ import * as path68 from "path";
27651
28021
  import chalk204 from "chalk";
27652
28022
  async function syncSettings(claudeDir, targetBase, options2) {
27653
- const source = path67.join(claudeDir, "settings.json");
27654
- const target = path67.join(targetBase, "settings.json");
27655
- const sourceContent = fs45.readFileSync(source, "utf8");
28023
+ const source = path68.join(claudeDir, "settings.json");
28024
+ const target = path68.join(targetBase, "settings.json");
28025
+ const sourceContent = fs47.readFileSync(source, "utf8");
27656
28026
  const sourceSettings = JSON.parse(sourceContent);
27657
- const targetExists = fs45.existsSync(target);
27658
- const targetContent = targetExists ? fs45.readFileSync(target, "utf8") : "";
28027
+ const targetExists = fs47.existsSync(target);
28028
+ const targetContent = targetExists ? fs47.readFileSync(target, "utf8") : "";
27659
28029
  const preservedUserSettings = targetExists ? JSON.parse(targetContent) : {};
27660
28030
  const mergedContent = JSON.stringify(
27661
28031
  { ...preservedUserSettings, ...sourceSettings },
@@ -27684,18 +28054,18 @@ async function syncSettings(claudeDir, targetBase, options2) {
27684
28054
  }
27685
28055
  }
27686
28056
  }
27687
- fs45.writeFileSync(target, mergedContent);
28057
+ fs47.writeFileSync(target, mergedContent);
27688
28058
  console.log("Copied settings.json to ~/.claude/settings.json");
27689
28059
  }
27690
28060
 
27691
28061
  // src/commands/sync.ts
27692
28062
  var __filename5 = fileURLToPath9(import.meta.url);
27693
- var __dirname7 = path68.dirname(__filename5);
28063
+ var __dirname7 = path69.dirname(__filename5);
27694
28064
  async function sync(options2) {
27695
28065
  const config = loadConfig();
27696
28066
  const yes = options2?.yes ?? config.sync.autoConfirm;
27697
- const claudeDir = path68.join(__dirname7, "..", "claude");
27698
- const targetBase = path68.join(os4.homedir(), ".claude");
28067
+ const claudeDir = path69.join(__dirname7, "..", "claude");
28068
+ const targetBase = path69.join(os5.homedir(), ".claude");
27699
28069
  syncCommands(claudeDir, targetBase);
27700
28070
  syncDesign(claudeDir, targetBase);
27701
28071
  await syncSettings(claudeDir, targetBase, { yes });
@@ -27704,12 +28074,12 @@ async function sync(options2) {
27704
28074
  syncPi(claudeDir);
27705
28075
  }
27706
28076
  function syncCommands(claudeDir, targetBase) {
27707
- const sourceDir = path68.join(claudeDir, "commands");
27708
- const targetDir = path68.join(targetBase, "commands");
27709
- fs46.mkdirSync(targetDir, { recursive: true });
27710
- const files = fs46.readdirSync(sourceDir);
28077
+ const sourceDir = path69.join(claudeDir, "commands");
28078
+ const targetDir = path69.join(targetBase, "commands");
28079
+ fs48.mkdirSync(targetDir, { recursive: true });
28080
+ const files = fs48.readdirSync(sourceDir);
27711
28081
  for (const file of files) {
27712
- fs46.copyFileSync(path68.join(sourceDir, file), path68.join(targetDir, file));
28082
+ fs48.copyFileSync(path69.join(sourceDir, file), path69.join(targetDir, file));
27713
28083
  console.log(`Copied ${file} to ${targetDir}`);
27714
28084
  }
27715
28085
  console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
@@ -27717,7 +28087,7 @@ function syncCommands(claudeDir, targetBase) {
27717
28087
 
27718
28088
  // src/commands/update.ts
27719
28089
  import { execSync as execSync59 } from "child_process";
27720
- import * as path69 from "path";
28090
+ import * as path70 from "path";
27721
28091
 
27722
28092
  // src/commands/restartDaemonAfterUpdate.ts
27723
28093
  async function restartDaemonAfterUpdate() {
@@ -27736,12 +28106,12 @@ async function restartDaemonAfterUpdate() {
27736
28106
  // src/commands/update.ts
27737
28107
  function isGlobalNpmInstall(dir) {
27738
28108
  try {
27739
- const resolved = path69.resolve(dir);
27740
- if (resolved.split(path69.sep).includes("node_modules")) {
28109
+ const resolved = path70.resolve(dir);
28110
+ if (resolved.split(path70.sep).includes("node_modules")) {
27741
28111
  return true;
27742
28112
  }
27743
28113
  const globalPrefix = execSync59("npm prefix -g", { stdio: "pipe" }).toString().trim();
27744
- return resolved.toLowerCase().startsWith(path69.resolve(globalPrefix).toLowerCase());
28114
+ return resolved.toLowerCase().startsWith(path70.resolve(globalPrefix).toLowerCase());
27745
28115
  } catch {
27746
28116
  return false;
27747
28117
  }