@staff0rd/assist 0.307.0 → 0.308.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.307.0",
9
+ version: "0.308.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -124,10 +124,10 @@ import { stringify as stringifyYaml } from "yaml";
124
124
  // src/shared/loadRawYaml.ts
125
125
  import { existsSync, readFileSync } from "fs";
126
126
  import { parse as parseYaml } from "yaml";
127
- function loadRawYaml(path58) {
128
- if (!existsSync(path58)) return {};
127
+ function loadRawYaml(path57) {
128
+ if (!existsSync(path57)) return {};
129
129
  try {
130
- const content = readFileSync(path58, "utf8");
130
+ const content = readFileSync(path57, "utf8");
131
131
  return parseYaml(content) || {};
132
132
  } catch {
133
133
  return {};
@@ -2178,7 +2178,7 @@ function flushIfFailed(exitCode, chunks) {
2178
2178
 
2179
2179
  // src/commands/verify/run/runAllEntries.ts
2180
2180
  function runEntry(entry, onComplete) {
2181
- return new Promise((resolve17) => {
2181
+ return new Promise((resolve16) => {
2182
2182
  const child = spawnCommand(
2183
2183
  entry.fullCommand,
2184
2184
  entry.cwd,
@@ -2190,7 +2190,7 @@ function runEntry(entry, onComplete) {
2190
2190
  const exitCode = code ?? 1;
2191
2191
  flushIfFailed(exitCode, chunks);
2192
2192
  onComplete?.(exitCode);
2193
- resolve17({ script: entry.name, code: exitCode });
2193
+ resolve16({ script: entry.name, code: exitCode });
2194
2194
  });
2195
2195
  });
2196
2196
  }
@@ -2912,10 +2912,10 @@ var hooksSettings = {
2912
2912
  }
2913
2913
  };
2914
2914
  function ensureHooksSettings() {
2915
- const path58 = daemonPaths.hooksSettings;
2916
- mkdirSync5(dirname12(path58), { recursive: true });
2917
- writeFileSync14(path58, JSON.stringify(hooksSettings, null, 2));
2918
- return path58;
2915
+ const path57 = daemonPaths.hooksSettings;
2916
+ mkdirSync5(dirname12(path57), { recursive: true });
2917
+ writeFileSync14(path57, JSON.stringify(hooksSettings, null, 2));
2918
+ return path57;
2919
2919
  }
2920
2920
 
2921
2921
  // src/shared/spawnClaude.ts
@@ -2943,8 +2943,8 @@ function spawnClaude(prompt, options2 = {}) {
2943
2943
  stdio: "inherit",
2944
2944
  env
2945
2945
  });
2946
- const done2 = new Promise((resolve17, reject) => {
2947
- child.on("close", (code) => resolve17(code ?? 0));
2946
+ const done2 = new Promise((resolve16, reject) => {
2947
+ child.on("close", (code) => resolve16(code ?? 0));
2948
2948
  child.on("error", reject);
2949
2949
  });
2950
2950
  return { child, done: done2 };
@@ -2974,9 +2974,9 @@ var LOCAL_FILES = ["backlog.jsonl", "backlog.db"];
2974
2974
  function backupLocalBacklogFiles(dir) {
2975
2975
  const moved = [];
2976
2976
  for (const name of LOCAL_FILES) {
2977
- const path58 = join12(dir, ".assist", name);
2978
- if (existsSync15(path58)) {
2979
- renameSync(path58, `${path58}.bak`);
2977
+ const path57 = join12(dir, ".assist", name);
2978
+ if (existsSync15(path57)) {
2979
+ renameSync(path57, `${path57}.bak`);
2980
2980
  moved.push(`${name} \u2192 ${name}.bak`);
2981
2981
  }
2982
2982
  }
@@ -3393,8 +3393,8 @@ var backlogItemSchema = z3.strictObject({
3393
3393
  var backlogFileSchema = z3.array(backlogItemSchema);
3394
3394
 
3395
3395
  // src/commands/backlog/parseBacklogJsonl.ts
3396
- function parseBacklogJsonl(path58) {
3397
- const content = readFileSync12(path58, "utf8").trim();
3396
+ function parseBacklogJsonl(path57) {
3397
+ const content = readFileSync12(path57, "utf8").trim();
3398
3398
  if (content.length === 0) return [];
3399
3399
  return content.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => backlogItemSchema.parse(JSON.parse(line)));
3400
3400
  }
@@ -3674,8 +3674,8 @@ function findBacklogUp(startDir) {
3674
3674
 
3675
3675
  // src/commands/backlog/getCurrentOrigin.ts
3676
3676
  import { execFileSync } from "child_process";
3677
- function stripLeadingSlashes(path58) {
3678
- return path58.replace(/^\/+/, "");
3677
+ function stripLeadingSlashes(path57) {
3678
+ return path57.replace(/^\/+/, "");
3679
3679
  }
3680
3680
  function normalizeOrigin(raw) {
3681
3681
  const trimmed = raw.trim().replace(/\.git$/i, "").replace(/\/+$/, "");
@@ -3958,13 +3958,13 @@ function activityPath(sessionId) {
3958
3958
  function emitActivity(activity2) {
3959
3959
  const sessionId = process.env.ASSIST_ACTIVITY_ID;
3960
3960
  if (!sessionId) return;
3961
- const path58 = activityPath(sessionId);
3962
- mkdirSync7(dirname14(path58), { recursive: true });
3963
- writeFileSync16(path58, JSON.stringify({ ...activity2, startedAt: Date.now() }));
3961
+ const path57 = activityPath(sessionId);
3962
+ mkdirSync7(dirname14(path57), { recursive: true });
3963
+ writeFileSync16(path57, JSON.stringify({ ...activity2, startedAt: Date.now() }));
3964
3964
  }
3965
- function readActivity(path58) {
3965
+ function readActivity(path57) {
3966
3966
  try {
3967
- return JSON.parse(readFileSync13(path58, "utf8"));
3967
+ return JSON.parse(readFileSync13(path57, "utf8"));
3968
3968
  } catch {
3969
3969
  return void 0;
3970
3970
  }
@@ -3974,9 +3974,9 @@ function reconcileActivity(sessionId, activity2) {
3974
3974
  removeActivity(sessionId);
3975
3975
  return;
3976
3976
  }
3977
- const path58 = activityPath(sessionId);
3978
- mkdirSync7(dirname14(path58), { recursive: true });
3979
- writeFileSync16(path58, JSON.stringify(activity2));
3977
+ const path57 = activityPath(sessionId);
3978
+ mkdirSync7(dirname14(path57), { recursive: true });
3979
+ writeFileSync16(path57, JSON.stringify(activity2));
3980
3980
  }
3981
3981
  function removeActivity(sessionId) {
3982
3982
  try {
@@ -4133,10 +4133,10 @@ function writeSignal(event, data) {
4133
4133
 
4134
4134
  // src/commands/backlog/readSignal.ts
4135
4135
  function readSignal() {
4136
- const path58 = getSignalPath();
4137
- if (!existsSync19(path58)) return void 0;
4136
+ const path57 = getSignalPath();
4137
+ if (!existsSync19(path57)) return void 0;
4138
4138
  try {
4139
- return JSON.parse(readFileSync14(path58, "utf8"));
4139
+ return JSON.parse(readFileSync14(path57, "utf8"));
4140
4140
  } catch {
4141
4141
  return void 0;
4142
4142
  }
@@ -4752,9 +4752,9 @@ import {
4752
4752
  // src/commands/sessions/daemon/connectToDaemon.ts
4753
4753
  import * as net from "net";
4754
4754
  function connectToDaemon() {
4755
- return new Promise((resolve17, reject) => {
4755
+ return new Promise((resolve16, reject) => {
4756
4756
  const socket = net.connect(daemonPaths.socket);
4757
- socket.once("connect", () => resolve17(socket));
4757
+ socket.once("connect", () => resolve16(socket));
4758
4758
  socket.once("error", reject);
4759
4759
  });
4760
4760
  }
@@ -4834,7 +4834,7 @@ function spawnDaemon(reason) {
4834
4834
  child.unref();
4835
4835
  }
4836
4836
  function delay(ms) {
4837
- return new Promise((resolve17) => setTimeout(resolve17, ms));
4837
+ return new Promise((resolve16) => setTimeout(resolve16, ms));
4838
4838
  }
4839
4839
 
4840
4840
  // src/commands/sessions/web/handleRequest.ts
@@ -4974,12 +4974,12 @@ async function loadVisibleItems(req) {
4974
4974
 
4975
4975
  // src/commands/backlog/web/parseStatusBody.ts
4976
4976
  function readBody(req) {
4977
- return new Promise((resolve17, reject) => {
4977
+ return new Promise((resolve16, reject) => {
4978
4978
  let body = "";
4979
4979
  req.on("data", (chunk) => {
4980
4980
  body += chunk.toString();
4981
4981
  });
4982
- req.on("end", () => resolve17(body));
4982
+ req.on("end", () => resolve16(body));
4983
4983
  req.on("error", reject);
4984
4984
  });
4985
4985
  }
@@ -5503,17 +5503,17 @@ async function stopDaemon() {
5503
5503
  }
5504
5504
  }
5505
5505
  function closedBeforeTimeout(socket) {
5506
- return new Promise((resolve17) => {
5506
+ return new Promise((resolve16) => {
5507
5507
  const timer = setTimeout(() => {
5508
5508
  socket.destroy();
5509
- resolve17(false);
5509
+ resolve16(false);
5510
5510
  }, STOP_TIMEOUT_MS);
5511
5511
  socket.resume();
5512
5512
  socket.on("error", () => {
5513
5513
  });
5514
5514
  socket.once("close", () => {
5515
5515
  clearTimeout(timer);
5516
- resolve17(true);
5516
+ resolve16(true);
5517
5517
  });
5518
5518
  });
5519
5519
  }
@@ -5564,8 +5564,8 @@ async function restartWeb(req, res, deps2 = {}) {
5564
5564
  respondJson(res, 400, { error: "Invalid target" });
5565
5565
  return;
5566
5566
  }
5567
- await new Promise((resolve17) => {
5568
- res.once("finish", resolve17);
5567
+ await new Promise((resolve16) => {
5568
+ res.once("finish", resolve16);
5569
5569
  respondJson(res, 200, { ok: true });
5570
5570
  });
5571
5571
  if (target === "daemon" || target === "both") {
@@ -6553,8 +6553,8 @@ import chalk59 from "chalk";
6553
6553
  // src/commands/backlog/originDisplayName.ts
6554
6554
  function originDisplayName(origin) {
6555
6555
  if (origin.startsWith("local:")) {
6556
- const path58 = origin.slice("local:".length).replace(/\/+$/, "");
6557
- const segments = path58.split("/").filter(Boolean);
6556
+ const path57 = origin.slice("local:".length).replace(/\/+$/, "");
6557
+ const segments = path57.split("/").filter(Boolean);
6558
6558
  return segments[segments.length - 1] ?? origin;
6559
6559
  }
6560
6560
  const firstSlash = origin.indexOf("/");
@@ -6849,6 +6849,9 @@ function registerPlanCommands(cmd) {
6849
6849
  import chalk67 from "chalk";
6850
6850
  import enquirer7 from "enquirer";
6851
6851
 
6852
+ // src/commands/backlog/launchMode.ts
6853
+ import { randomUUID as randomUUID2 } from "crypto";
6854
+
6852
6855
  // src/commands/backlog/handleLaunchSignal.ts
6853
6856
  import chalk66 from "chalk";
6854
6857
 
@@ -6923,15 +6926,17 @@ function buildSlashCommand(slashCommand, description) {
6923
6926
  async function launchMode(slashCommand, options2) {
6924
6927
  pullIfConfigured();
6925
6928
  process.env.ASSIST_SESSION_ID ??= String(process.pid);
6929
+ const claudeSessionId = randomUUID2();
6926
6930
  emitActivity({
6927
6931
  kind: "command",
6928
6932
  name: slashCommand,
6929
6933
  itemId: options2?.itemId,
6930
- itemName: options2?.itemName
6934
+ itemName: options2?.itemName,
6935
+ claudeSessionId
6931
6936
  });
6932
6937
  const { child, done: done2 } = spawnClaude(
6933
6938
  buildSlashCommand(slashCommand, options2?.description),
6934
- { allowEdits: true }
6939
+ { allowEdits: true, sessionId: claudeSessionId }
6935
6940
  );
6936
6941
  watchForMarker(child, { actOnDone: options2?.once });
6937
6942
  const launched = await awaitClaude(done2, `/${slashCommand}`);
@@ -7892,9 +7897,9 @@ var __dirname4 = dirname17(__filename3);
7892
7897
  function packageRoot() {
7893
7898
  return __dirname4;
7894
7899
  }
7895
- function readLines(path58) {
7896
- if (!existsSync22(path58)) return [];
7897
- return readFileSync18(path58, "utf8").split("\n").filter((line) => line.trim() !== "");
7900
+ function readLines(path57) {
7901
+ if (!existsSync22(path57)) return [];
7902
+ return readFileSync18(path57, "utf8").split("\n").filter((line) => line.trim() !== "");
7898
7903
  }
7899
7904
  var cachedReads;
7900
7905
  var cachedWrites;
@@ -8339,12 +8344,12 @@ function hasSubcommands(helpText) {
8339
8344
  // src/commands/permitCliReads/runHelp.ts
8340
8345
  import { exec as exec2 } from "child_process";
8341
8346
  function runHelp(args) {
8342
- return new Promise((resolve17) => {
8347
+ return new Promise((resolve16) => {
8343
8348
  exec2(
8344
8349
  `${args.join(" ")} --help`,
8345
8350
  { encoding: "utf8", timeout: 3e4 },
8346
8351
  (_err, stdout, stderr) => {
8347
- resolve17(stdout || stderr || "");
8352
+ resolve16(stdout || stderr || "");
8348
8353
  }
8349
8354
  );
8350
8355
  });
@@ -8359,14 +8364,14 @@ function showProgress(p, label2) {
8359
8364
  const pct = Math.round(p.done / p.total * 100);
8360
8365
  process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
8361
8366
  }
8362
- async function resolveCommand(cli, path58, description, depth, p) {
8363
- showProgress(p, path58.join(" "));
8364
- const subHelp = await runHelp([cli, ...path58]);
8367
+ async function resolveCommand(cli, path57, description, depth, p) {
8368
+ showProgress(p, path57.join(" "));
8369
+ const subHelp = await runHelp([cli, ...path57]);
8365
8370
  if (!subHelp || !hasSubcommands(subHelp)) {
8366
- return [{ path: path58, description }];
8371
+ return [{ path: path57, description }];
8367
8372
  }
8368
- const children = await discoverAt(cli, path58, depth + 1, p);
8369
- return children.length > 0 ? children : [{ path: path58, description }];
8373
+ const children = await discoverAt(cli, path57, depth + 1, p);
8374
+ return children.length > 0 ? children : [{ path: path57, description }];
8370
8375
  }
8371
8376
  async function discoverAt(cli, parentPath, depth, p) {
8372
8377
  if (depth > SAFETY_DEPTH) return [];
@@ -8514,9 +8519,9 @@ function logPath(cli) {
8514
8519
  return join22(homedir9(), ".assist", `cli-discover-${safeName}.log`);
8515
8520
  }
8516
8521
  function readCache(cli) {
8517
- const path58 = logPath(cli);
8518
- if (!existsSync24(path58)) return void 0;
8519
- return readFileSync20(path58, "utf8");
8522
+ const path57 = logPath(cli);
8523
+ if (!existsSync24(path57)) return void 0;
8524
+ return readFileSync20(path57, "utf8");
8520
8525
  }
8521
8526
  function writeCache(cli, output) {
8522
8527
  const dir = join22(homedir9(), ".assist");
@@ -9211,8 +9216,8 @@ function stepIntoNested(container, key, nextKey) {
9211
9216
  }
9212
9217
  return ensureObject(container, resolved);
9213
9218
  }
9214
- function setNestedValue(obj, path58, value) {
9215
- const keys = path58.split(".");
9219
+ function setNestedValue(obj, path57, value) {
9220
+ const keys = path57.split(".");
9216
9221
  const result = { ...obj };
9217
9222
  let current = result;
9218
9223
  for (let i = 0; i < keys.length - 1; i++) {
@@ -9292,9 +9297,9 @@ function isTraversable(value) {
9292
9297
  function stepInto(current, key) {
9293
9298
  return isTraversable(current) ? current[key] : void 0;
9294
9299
  }
9295
- function getNestedValue(obj, path58) {
9300
+ function getNestedValue(obj, path57) {
9296
9301
  let current = obj;
9297
- for (const key of path58.split(".")) current = stepInto(current, key);
9302
+ for (const key of path57.split(".")) current = stepInto(current, key);
9298
9303
  return current;
9299
9304
  }
9300
9305
 
@@ -11076,10 +11081,10 @@ function getStorePath(filename) {
11076
11081
  return join33(getStoreDir(), filename);
11077
11082
  }
11078
11083
  function loadJson(filename) {
11079
- const path58 = getStorePath(filename);
11080
- if (existsSync32(path58)) {
11084
+ const path57 = getStorePath(filename);
11085
+ if (existsSync32(path57)) {
11081
11086
  try {
11082
- return JSON.parse(readFileSync28(path58, "utf8"));
11087
+ return JSON.parse(readFileSync28(path57, "utf8"));
11083
11088
  } catch {
11084
11089
  return {};
11085
11090
  }
@@ -11179,6 +11184,7 @@ function registerJira(program2) {
11179
11184
 
11180
11185
  // src/commands/reviewComments.ts
11181
11186
  import { execFileSync as execFileSync5 } from "child_process";
11187
+ import { randomUUID as randomUUID3 } from "crypto";
11182
11188
  import chalk119 from "chalk";
11183
11189
  async function reviewComments(number) {
11184
11190
  if (number) {
@@ -11189,8 +11195,11 @@ async function reviewComments(number) {
11189
11195
  process.exit(1);
11190
11196
  }
11191
11197
  }
11198
+ const claudeSessionId = randomUUID3();
11199
+ emitActivity({ kind: "command", name: "review-comments", claudeSessionId });
11192
11200
  const { done: done2 } = spawnClaude("/review-comments", {
11193
- permissionMode: "acceptEdits"
11201
+ permissionMode: "acceptEdits",
11202
+ sessionId: claudeSessionId
11194
11203
  });
11195
11204
  await done2;
11196
11205
  }
@@ -11563,9 +11572,9 @@ function parseRscRows(flight) {
11563
11572
  }
11564
11573
  function makeRscResolver(rows) {
11565
11574
  return (ref) => {
11566
- const [id2, ...path58] = ref.slice(1).replace(/^[L@]/, "").split(":");
11575
+ const [id2, ...path57] = ref.slice(1).replace(/^[L@]/, "").split(":");
11567
11576
  let v = rows[id2];
11568
- for (const key of path58) {
11577
+ for (const key of path57) {
11569
11578
  if (v == null || typeof v !== "object") return void 0;
11570
11579
  v = v[key];
11571
11580
  }
@@ -11580,25 +11589,25 @@ function isVisibleText(t) {
11580
11589
  return /[a-zA-Z]{3,}/.test(t);
11581
11590
  }
11582
11591
  var isHashtag = (t) => /^#[A-Za-z0-9_]+$/.test(t);
11583
- function collectRscText(v, resolve17, sink, seen) {
11592
+ function collectRscText(v, resolve16, sink, seen) {
11584
11593
  if (v == null) return;
11585
11594
  if (typeof v === "string") {
11586
11595
  if (isRscRef(v)) {
11587
11596
  if (!seen.has(v)) {
11588
11597
  seen.add(v);
11589
- collectRscText(resolve17(v), resolve17, sink, seen);
11598
+ collectRscText(resolve16(v), resolve16, sink, seen);
11590
11599
  }
11591
11600
  } else if (isHashtag(v)) sink.hashtags.push(v);
11592
11601
  else if (isVisibleText(v)) sink.text.push(v);
11593
11602
  return;
11594
11603
  }
11595
11604
  if (Array.isArray(v)) {
11596
- for (const x of v) collectRscText(x, resolve17, sink, seen);
11605
+ for (const x of v) collectRscText(x, resolve16, sink, seen);
11597
11606
  return;
11598
11607
  }
11599
11608
  if (typeof v === "object") {
11600
11609
  for (const val of Object.values(v)) {
11601
- collectRscText(val, resolve17, sink, seen);
11610
+ collectRscText(val, resolve16, sink, seen);
11602
11611
  }
11603
11612
  }
11604
11613
  }
@@ -11630,7 +11639,7 @@ function visitObjects(root, fn) {
11630
11639
  }
11631
11640
  }
11632
11641
  }
11633
- function buildMentionMap(rows, resolve17) {
11642
+ function buildMentionMap(rows, resolve16) {
11634
11643
  const map = /* @__PURE__ */ new Map();
11635
11644
  visitObjects(rows, (o) => {
11636
11645
  const url = profileActionUrl(o);
@@ -11638,7 +11647,7 @@ function buildMentionMap(rows, resolve17) {
11638
11647
  const slug = slugFromProfileUrl(url);
11639
11648
  if (!slug || map.has(slug)) return;
11640
11649
  const sink = { text: [], hashtags: [] };
11641
- collectRscText(o.children, resolve17, sink, /* @__PURE__ */ new Set());
11650
+ collectRscText(o.children, resolve16, sink, /* @__PURE__ */ new Set());
11642
11651
  const name = sink.text.join(" ").replace(/\s+/g, " ").trim();
11643
11652
  map.set(slug, name ? { slug, name, url } : { slug, url });
11644
11653
  });
@@ -11718,10 +11727,10 @@ function buildPost(raw, mentionMap, author) {
11718
11727
 
11719
11728
  // src/commands/netcap/walkPostRow.ts
11720
11729
  var isCommentary = (o) => asObject(o.viewTrackingSpecs)?.viewName === "feed-commentary";
11721
- function walkPostRow(v, resolve17, raw) {
11730
+ function walkPostRow(v, resolve16, raw) {
11722
11731
  if (v == null || typeof v !== "object") return;
11723
11732
  if (Array.isArray(v)) {
11724
- for (const x of v) walkPostRow(x, resolve17, raw);
11733
+ for (const x of v) walkPostRow(x, resolve16, raw);
11725
11734
  return;
11726
11735
  }
11727
11736
  const o = v;
@@ -11735,9 +11744,9 @@ function walkPostRow(v, resolve17, raw) {
11735
11744
  }
11736
11745
  if (isCommentary(o)) {
11737
11746
  const sink = { text: raw.text, hashtags: raw.hashtags };
11738
- collectRscText(o.children, resolve17, sink, /* @__PURE__ */ new Set());
11747
+ collectRscText(o.children, resolve16, sink, /* @__PURE__ */ new Set());
11739
11748
  }
11740
- for (const val of Object.values(o)) walkPostRow(val, resolve17, raw);
11749
+ for (const val of Object.values(o)) walkPostRow(val, resolve16, raw);
11741
11750
  }
11742
11751
 
11743
11752
  // src/commands/netcap/extractLinkedInPosts.ts
@@ -11751,8 +11760,8 @@ function findCommentaryRows(rows) {
11751
11760
  }
11752
11761
  function extractLinkedInPosts(flight, author = findAuthorSlug(flight)) {
11753
11762
  const rows = parseRscRows(flight);
11754
- const resolve17 = makeRscResolver(rows);
11755
- const mentionMap = buildMentionMap(rows, resolve17);
11763
+ const resolve16 = makeRscResolver(rows);
11764
+ const mentionMap = buildMentionMap(rows, resolve16);
11756
11765
  const posts = [];
11757
11766
  for (const id2 of findCommentaryRows(rows)) {
11758
11767
  const raw = {
@@ -11762,7 +11771,7 @@ function extractLinkedInPosts(flight, author = findAuthorSlug(flight)) {
11762
11771
  links: [],
11763
11772
  related: []
11764
11773
  };
11765
- walkPostRow(rows[id2], resolve17, raw);
11774
+ walkPostRow(rows[id2], resolve16, raw);
11766
11775
  const post = buildPost(raw, mentionMap, author);
11767
11776
  if (post) posts.push(post);
11768
11777
  }
@@ -12195,15 +12204,15 @@ function postComment(vars) {
12195
12204
  const stdout = startLine === void 0 ? runGhGraphql(MUTATION_SINGLE, base) : runGhGraphql(MUTATION_MULTI, { ...base, startLine });
12196
12205
  assertThreadCreated(stdout);
12197
12206
  }
12198
- function comment2(path58, line, body, startLine) {
12207
+ function comment2(path57, line, body, startLine) {
12199
12208
  validateBody(body);
12200
12209
  validateLine(line);
12201
12210
  if (startLine !== void 0) validateLine(startLine);
12202
12211
  try {
12203
12212
  const prId = getCurrentPrNodeId();
12204
- postComment({ prId, body, path: path58, line, startLine });
12213
+ postComment({ prId, body, path: path57, line, startLine });
12205
12214
  const range = startLine !== void 0 ? `${startLine}-${line}` : `${line}`;
12206
- console.log(`Added review comment on ${path58}:${range}`);
12215
+ console.log(`Added review comment on ${path57}:${range}`);
12207
12216
  } catch (error) {
12208
12217
  if (isGhNotInstalled(error)) {
12209
12218
  console.error("Error: GitHub CLI (gh) is not installed.");
@@ -12395,10 +12404,10 @@ function edit(options2) {
12395
12404
  }
12396
12405
 
12397
12406
  // src/commands/prs/fixed.ts
12398
- import { execSync as execSync33 } from "child_process";
12407
+ import { execSync as execSync34 } from "child_process";
12399
12408
 
12400
12409
  // src/commands/prs/resolveCommentWithReply.ts
12401
- import { execSync as execSync32 } from "child_process";
12410
+ import { execSync as execSync33 } from "child_process";
12402
12411
  import { unlinkSync as unlinkSync10, writeFileSync as writeFileSync27 } from "fs";
12403
12412
  import { tmpdir as tmpdir5 } from "os";
12404
12413
  import { join as join40 } from "path";
@@ -12426,19 +12435,22 @@ function deleteCommentsCache(prNumber) {
12426
12435
  }
12427
12436
  }
12428
12437
 
12429
- // src/commands/prs/resolveCommentWithReply.ts
12438
+ // src/commands/prs/replyToComment.ts
12439
+ import { execSync as execSync32 } from "child_process";
12430
12440
  function replyToComment(org, repo, prNumber, commentId, message) {
12431
12441
  execSync32(
12432
12442
  `gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message.replace(/"/g, String.raw`\"`)}" -F in_reply_to=${commentId}`,
12433
12443
  { stdio: ["inherit", "pipe", "inherit"] }
12434
12444
  );
12435
12445
  }
12446
+
12447
+ // src/commands/prs/resolveCommentWithReply.ts
12436
12448
  function resolveThread(threadId) {
12437
12449
  const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
12438
12450
  const queryFile = join40(tmpdir5(), `gh-mutation-${Date.now()}.graphql`);
12439
12451
  writeFileSync27(queryFile, mutation);
12440
12452
  try {
12441
- execSync32(
12453
+ execSync33(
12442
12454
  `gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
12443
12455
  { stdio: ["inherit", "pipe", "inherit"] }
12444
12456
  );
@@ -12490,7 +12502,7 @@ function resolveCommentWithReply(commentId, message) {
12490
12502
  // src/commands/prs/fixed.ts
12491
12503
  function verifySha(sha) {
12492
12504
  try {
12493
- return execSync33(`git rev-parse --verify ${sha}`, {
12505
+ return execSync34(`git rev-parse --verify ${sha}`, {
12494
12506
  encoding: "utf8"
12495
12507
  }).trim();
12496
12508
  } catch {
@@ -12504,7 +12516,7 @@ function fixed(commentId, sha) {
12504
12516
  const { org, repo } = getRepoInfo();
12505
12517
  const repoUrl = `https://github.com/${org}/${repo}`;
12506
12518
  const message = `Fixed in [${fullSha}](${repoUrl}/commit/${fullSha})`;
12507
- execSync33("git push", { stdio: "inherit" });
12519
+ execSync34("git push", { stdio: "inherit" });
12508
12520
  resolveCommentWithReply(commentId, message);
12509
12521
  } catch (error) {
12510
12522
  if (isGhNotInstalled(error)) {
@@ -12522,7 +12534,7 @@ import { join as join42 } from "path";
12522
12534
  import { stringify } from "yaml";
12523
12535
 
12524
12536
  // src/commands/prs/fetchThreadIds.ts
12525
- import { execSync as execSync34 } from "child_process";
12537
+ import { execSync as execSync35 } from "child_process";
12526
12538
  import { unlinkSync as unlinkSync11, writeFileSync as writeFileSync28 } from "fs";
12527
12539
  import { tmpdir as tmpdir6 } from "os";
12528
12540
  import { join as join41 } from "path";
@@ -12531,7 +12543,7 @@ function fetchThreadIds(org, repo, prNumber) {
12531
12543
  const queryFile = join41(tmpdir6(), `gh-query-${Date.now()}.graphql`);
12532
12544
  writeFileSync28(queryFile, THREAD_QUERY);
12533
12545
  try {
12534
- const result = execSync34(
12546
+ const result = execSync35(
12535
12547
  `gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
12536
12548
  { encoding: "utf8" }
12537
12549
  );
@@ -12553,9 +12565,9 @@ function fetchThreadIds(org, repo, prNumber) {
12553
12565
  }
12554
12566
 
12555
12567
  // src/commands/prs/listComments/fetchReviewComments.ts
12556
- import { execSync as execSync35 } from "child_process";
12568
+ import { execSync as execSync36 } from "child_process";
12557
12569
  function fetchJson(endpoint) {
12558
- const result = execSync35(`gh api --paginate ${endpoint}`, {
12570
+ const result = execSync36(`gh api --paginate ${endpoint}`, {
12559
12571
  encoding: "utf8"
12560
12572
  });
12561
12573
  if (!result.trim()) return [];
@@ -12694,7 +12706,7 @@ async function listComments() {
12694
12706
  }
12695
12707
 
12696
12708
  // src/commands/prs/prs/index.ts
12697
- import { execSync as execSync36 } from "child_process";
12709
+ import { execSync as execSync37 } from "child_process";
12698
12710
 
12699
12711
  // src/commands/prs/prs/displayPaginated/index.ts
12700
12712
  import enquirer9 from "enquirer";
@@ -12801,7 +12813,7 @@ async function prs(options2) {
12801
12813
  const state = options2.open ? "open" : options2.closed ? "closed" : "all";
12802
12814
  try {
12803
12815
  const { org, repo } = getRepoInfo();
12804
- const result = execSync36(
12816
+ const result = execSync37(
12805
12817
  `gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100 -R ${org}/${repo}`,
12806
12818
  { encoding: "utf8" }
12807
12819
  );
@@ -12824,7 +12836,7 @@ async function prs(options2) {
12824
12836
  }
12825
12837
 
12826
12838
  // src/commands/prs/raise.ts
12827
- import { execSync as execSync37 } from "child_process";
12839
+ import { execSync as execSync38 } from "child_process";
12828
12840
 
12829
12841
  // src/commands/prs/buildCreateArgs.ts
12830
12842
  function buildCreateArgs(title, body, options2) {
@@ -12884,14 +12896,39 @@ function raise(options2) {
12884
12896
  `--body ${shellQuote(body)}`
12885
12897
  ] : buildCreateArgs(options2.title, body, options2);
12886
12898
  try {
12887
- execSync37(args.join(" "), { stdio: "inherit" });
12899
+ execSync38(args.join(" "), { stdio: "inherit" });
12888
12900
  } catch {
12889
12901
  process.exit(1);
12890
12902
  }
12891
12903
  }
12892
12904
 
12905
+ // src/commands/prs/reply.ts
12906
+ function validateBody2(body) {
12907
+ const lowerBody = body.toLowerCase();
12908
+ if (lowerBody.includes("claude") || lowerBody.includes("opus")) {
12909
+ console.error('Error: Body must not contain "claude" or "opus"');
12910
+ process.exit(1);
12911
+ }
12912
+ }
12913
+ function reply(commentId, body) {
12914
+ validateBody2(body);
12915
+ try {
12916
+ const prNumber = getCurrentPrNumber();
12917
+ const { org, repo } = getRepoInfo();
12918
+ replyToComment(org, repo, prNumber, commentId, body);
12919
+ console.log("Reply posted successfully.");
12920
+ } catch (error) {
12921
+ if (isGhNotInstalled(error)) {
12922
+ console.error("Error: GitHub CLI (gh) is not installed.");
12923
+ console.error("Install it from https://cli.github.com/");
12924
+ process.exit(1);
12925
+ }
12926
+ throw error;
12927
+ }
12928
+ }
12929
+
12893
12930
  // src/commands/prs/wontfix.ts
12894
- import { execSync as execSync38 } from "child_process";
12931
+ import { execSync as execSync39 } from "child_process";
12895
12932
  function validateReason(reason) {
12896
12933
  const lowerReason = reason.toLowerCase();
12897
12934
  if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
@@ -12908,7 +12945,7 @@ function validateShaReferences(reason) {
12908
12945
  const invalidShas = [];
12909
12946
  for (const sha of shas) {
12910
12947
  try {
12911
- execSync38(`git cat-file -t ${sha}`, { stdio: "pipe" });
12948
+ execSync39(`git cat-file -t ${sha}`, { stdio: "pipe" });
12912
12949
  } catch {
12913
12950
  invalidShas.push(sha);
12914
12951
  }
@@ -12992,8 +13029,11 @@ function registerPrs(program2) {
12992
13029
  prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason) => {
12993
13030
  wontfix(Number.parseInt(commentId, 10), reason);
12994
13031
  });
12995
- prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path58, line, body) => {
12996
- comment2(path58, Number.parseInt(line, 10), body);
13032
+ prsCommand.command("reply <comment-id> <body>").description("Reply to a comment thread without resolving it").action((commentId, body) => {
13033
+ reply(Number.parseInt(commentId, 10), body);
13034
+ });
13035
+ prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path57, line, body) => {
13036
+ comment2(path57, Number.parseInt(line, 10), body);
12997
13037
  });
12998
13038
  }
12999
13039
 
@@ -13067,10 +13107,10 @@ import chalk132 from "chalk";
13067
13107
  import Enquirer2 from "enquirer";
13068
13108
 
13069
13109
  // src/commands/ravendb/searchItems.ts
13070
- import { execSync as execSync39 } from "child_process";
13110
+ import { execSync as execSync40 } from "child_process";
13071
13111
  import chalk131 from "chalk";
13072
13112
  function opExec(args) {
13073
- return execSync39(`op ${args}`, {
13113
+ return execSync40(`op ${args}`, {
13074
13114
  encoding: "utf8",
13075
13115
  stdio: ["pipe", "pipe", "pipe"]
13076
13116
  }).trim();
@@ -13222,7 +13262,7 @@ ${errorText}`
13222
13262
  }
13223
13263
 
13224
13264
  // src/commands/ravendb/resolveOpSecret.ts
13225
- import { execSync as execSync40 } from "child_process";
13265
+ import { execSync as execSync41 } from "child_process";
13226
13266
  import chalk136 from "chalk";
13227
13267
  function resolveOpSecret(reference) {
13228
13268
  if (!reference.startsWith("op://")) {
@@ -13230,7 +13270,7 @@ function resolveOpSecret(reference) {
13230
13270
  process.exit(1);
13231
13271
  }
13232
13272
  try {
13233
- return execSync40(`op read "${reference}"`, {
13273
+ return execSync41(`op read "${reference}"`, {
13234
13274
  encoding: "utf8",
13235
13275
  stdio: ["pipe", "pipe", "pipe"]
13236
13276
  }).trim();
@@ -13245,10 +13285,10 @@ function resolveOpSecret(reference) {
13245
13285
  }
13246
13286
 
13247
13287
  // src/commands/ravendb/ravenFetch.ts
13248
- async function ravenFetch(connection, path58) {
13288
+ async function ravenFetch(connection, path57) {
13249
13289
  const apiKey = resolveOpSecret(connection.apiKeyRef);
13250
13290
  let accessToken = await getAccessToken(apiKey);
13251
- const url = `${connection.url}${path58}`;
13291
+ const url = `${connection.url}${path57}`;
13252
13292
  const headers = {
13253
13293
  Authorization: `Bearer ${accessToken}`,
13254
13294
  "Content-Type": "application/json"
@@ -13338,16 +13378,16 @@ import chalk140 from "chalk";
13338
13378
  // src/commands/ravendb/buildQueryPath.ts
13339
13379
  function buildQueryPath(opts) {
13340
13380
  const db = encodeURIComponent(opts.db);
13341
- let path58;
13381
+ let path57;
13342
13382
  if (opts.collection) {
13343
- path58 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
13383
+ path57 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
13344
13384
  } else {
13345
- path58 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
13385
+ path57 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
13346
13386
  }
13347
13387
  if (opts.query) {
13348
- path58 += `&query=${encodeURIComponent(opts.query)}`;
13388
+ path57 += `&query=${encodeURIComponent(opts.query)}`;
13349
13389
  }
13350
- return path58;
13390
+ return path57;
13351
13391
  }
13352
13392
 
13353
13393
  // src/commands/ravendb/fetchAllPages.ts
@@ -13356,7 +13396,7 @@ async function fetchAllPages(connection, opts) {
13356
13396
  let start3 = 0;
13357
13397
  while (true) {
13358
13398
  const effectivePageSize = opts.limit !== void 0 ? Math.min(opts.pageSize, opts.limit - allResults.length) : opts.pageSize;
13359
- const path58 = buildQueryPath({
13399
+ const path57 = buildQueryPath({
13360
13400
  db: connection.database,
13361
13401
  collection: opts.collection,
13362
13402
  start: start3,
@@ -13364,7 +13404,7 @@ async function fetchAllPages(connection, opts) {
13364
13404
  sort: opts.sort,
13365
13405
  query: opts.query
13366
13406
  });
13367
- const data = await ravenFetch(connection, path58);
13407
+ const data = await ravenFetch(connection, path57);
13368
13408
  const results = data.Results ?? [];
13369
13409
  const totalResults = data.TotalResults ?? 0;
13370
13410
  if (results.length === 0) break;
@@ -13479,7 +13519,7 @@ Refactor check failed:
13479
13519
  }
13480
13520
 
13481
13521
  // src/commands/refactor/check/getViolations/index.ts
13482
- import { execSync as execSync41 } from "child_process";
13522
+ import { execSync as execSync42 } from "child_process";
13483
13523
  import fs20 from "fs";
13484
13524
  import { minimatch as minimatch5 } from "minimatch";
13485
13525
 
@@ -13529,7 +13569,7 @@ function getGitFiles(options2) {
13529
13569
  }
13530
13570
  const files = /* @__PURE__ */ new Set();
13531
13571
  if (options2.staged || options2.modified) {
13532
- const staged = execSync41("git diff --cached --name-only", {
13572
+ const staged = execSync42("git diff --cached --name-only", {
13533
13573
  encoding: "utf8"
13534
13574
  });
13535
13575
  for (const file of staged.trim().split("\n").filter(Boolean)) {
@@ -13537,7 +13577,7 @@ function getGitFiles(options2) {
13537
13577
  }
13538
13578
  }
13539
13579
  if (options2.unstaged || options2.modified) {
13540
- const unstaged = execSync41("git diff --name-only", { encoding: "utf8" });
13580
+ const unstaged = execSync42("git diff --name-only", { encoding: "utf8" });
13541
13581
  for (const file of unstaged.trim().split("\n").filter(Boolean)) {
13542
13582
  files.add(file);
13543
13583
  }
@@ -13567,7 +13607,7 @@ function getViolations(pattern2, options2 = {}, maxLines = DEFAULT_MAX_LINES) {
13567
13607
 
13568
13608
  // src/commands/refactor/check/index.ts
13569
13609
  function runScript(script, cwd) {
13570
- return new Promise((resolve17) => {
13610
+ return new Promise((resolve16) => {
13571
13611
  const child = spawn5("npm", ["run", script], {
13572
13612
  stdio: "pipe",
13573
13613
  shell: true,
@@ -13581,7 +13621,7 @@ function runScript(script, cwd) {
13581
13621
  output += data.toString();
13582
13622
  });
13583
13623
  child.on("close", (code) => {
13584
- resolve17({ script, code: code ?? 1, output });
13624
+ resolve16({ script, code: code ?? 1, output });
13585
13625
  });
13586
13626
  });
13587
13627
  }
@@ -15181,9 +15221,9 @@ function buildReviewPaths(repoRoot, key) {
15181
15221
  }
15182
15222
 
15183
15223
  // src/commands/review/fetchExistingComments.ts
15184
- import { execSync as execSync42 } from "child_process";
15224
+ import { execSync as execSync43 } from "child_process";
15185
15225
  function fetchRawComments(org, repo, prNumber) {
15186
- const out = execSync42(
15226
+ const out = execSync43(
15187
15227
  `gh api --paginate repos/${org}/${repo}/pulls/${prNumber}/comments`,
15188
15228
  { encoding: "utf8", maxBuffer: 64 * 1024 * 1024 }
15189
15229
  );
@@ -15214,14 +15254,14 @@ function fetchExistingComments() {
15214
15254
  }
15215
15255
 
15216
15256
  // src/commands/review/gatherContext.ts
15217
- import { execSync as execSync45 } from "child_process";
15257
+ import { execSync as execSync46 } from "child_process";
15218
15258
 
15219
15259
  // src/commands/review/fetchPrDiff.ts
15220
- import { execSync as execSync43 } from "child_process";
15260
+ import { execSync as execSync44 } from "child_process";
15221
15261
  function fetchPrDiff(prNumber, baseSha, headSha) {
15222
15262
  const { org, repo } = getRepoInfo();
15223
15263
  try {
15224
- return execSync43(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
15264
+ return execSync44(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
15225
15265
  encoding: "utf8",
15226
15266
  maxBuffer: 256 * 1024 * 1024,
15227
15267
  stdio: ["ignore", "pipe", "pipe"]
@@ -15236,19 +15276,19 @@ function isDiffTooLarge(error) {
15236
15276
  }
15237
15277
  function fetchDiffViaGit(baseSha, headSha) {
15238
15278
  try {
15239
- execSync43(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
15279
+ execSync44(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
15240
15280
  } catch {
15241
15281
  }
15242
- return execSync43(`git diff ${baseSha}...${headSha}`, {
15282
+ return execSync44(`git diff ${baseSha}...${headSha}`, {
15243
15283
  encoding: "utf8",
15244
15284
  maxBuffer: 256 * 1024 * 1024
15245
15285
  });
15246
15286
  }
15247
15287
 
15248
15288
  // src/commands/review/fetchPrDiffInfo.ts
15249
- import { execSync as execSync44 } from "child_process";
15289
+ import { execSync as execSync45 } from "child_process";
15250
15290
  function getCurrentBranch2() {
15251
- return execSync44("git rev-parse --abbrev-ref HEAD", {
15291
+ return execSync45("git rev-parse --abbrev-ref HEAD", {
15252
15292
  encoding: "utf8"
15253
15293
  }).trim();
15254
15294
  }
@@ -15258,7 +15298,7 @@ function fetchPrDiffInfo() {
15258
15298
  const fields = "number,baseRefName,baseRefOid,headRefName,headRefOid";
15259
15299
  let raw;
15260
15300
  try {
15261
- raw = execSync44(`gh pr view ${branch} --json ${fields} -R ${org}/${repo}`, {
15301
+ raw = execSync45(`gh pr view ${branch} --json ${fields} -R ${org}/${repo}`, {
15262
15302
  encoding: "utf8",
15263
15303
  stdio: ["ignore", "pipe", "pipe"]
15264
15304
  });
@@ -15282,7 +15322,7 @@ function fetchPrDiffInfo() {
15282
15322
  }
15283
15323
  function fetchPrChangedFiles(prNumber) {
15284
15324
  const { org, repo } = getRepoInfo();
15285
- const out = execSync44(
15325
+ const out = execSync45(
15286
15326
  `gh api repos/${org}/${repo}/pulls/${prNumber}/files --paginate --jq ".[].filename"`,
15287
15327
  {
15288
15328
  encoding: "utf8",
@@ -15294,11 +15334,11 @@ function fetchPrChangedFiles(prNumber) {
15294
15334
 
15295
15335
  // src/commands/review/gatherContext.ts
15296
15336
  function gatherContext() {
15297
- const branch = execSync45("git rev-parse --abbrev-ref HEAD", {
15337
+ const branch = execSync46("git rev-parse --abbrev-ref HEAD", {
15298
15338
  encoding: "utf8"
15299
15339
  }).trim();
15300
- const sha = execSync45("git rev-parse HEAD", { encoding: "utf8" }).trim();
15301
- const shortSha = execSync45("git rev-parse --short=7 HEAD", {
15340
+ const sha = execSync46("git rev-parse HEAD", { encoding: "utf8" }).trim();
15341
+ const shortSha = execSync46("git rev-parse --short=7 HEAD", {
15302
15342
  encoding: "utf8"
15303
15343
  }).trim();
15304
15344
  const prInfo = fetchPrDiffInfo();
@@ -15713,8 +15753,8 @@ async function handlePostSynthesis(synthesisPath, options2) {
15713
15753
  // src/commands/review/prepareReviewDir.ts
15714
15754
  import { existsSync as existsSync35, mkdirSync as mkdirSync14, unlinkSync as unlinkSync12, writeFileSync as writeFileSync30 } from "fs";
15715
15755
  function clearReviewFiles(paths) {
15716
- for (const path58 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
15717
- if (existsSync35(path58)) unlinkSync12(path58);
15756
+ for (const path57 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
15757
+ if (existsSync35(path57)) unlinkSync12(path57);
15718
15758
  }
15719
15759
  }
15720
15760
  function prepareReviewDir(paths, requestBody, force) {
@@ -16323,12 +16363,12 @@ function onCloseResult(ctx, code) {
16323
16363
  return { ...closed, stderr: ctx.stderr.value, stdout: ctx.stdout.value };
16324
16364
  }
16325
16365
  function waitForChildExit(ctx) {
16326
- return new Promise((resolve17) => {
16366
+ return new Promise((resolve16) => {
16327
16367
  let settled = false;
16328
16368
  const settle = (result) => {
16329
16369
  if (settled) return;
16330
16370
  settled = true;
16331
- resolve17(result);
16371
+ resolve16(result);
16332
16372
  };
16333
16373
  ctx.child.on("error", (err) => settle(onErrorResult(ctx, err)));
16334
16374
  ctx.child.on("close", (code) => settle(onCloseResult(ctx, code)));
@@ -16847,8 +16887,8 @@ import chalk161 from "chalk";
16847
16887
 
16848
16888
  // src/commands/seq/fetchSeq.ts
16849
16889
  import chalk158 from "chalk";
16850
- async function fetchSeq(conn, path58, params) {
16851
- const url = `${conn.url}${path58}?${params}`;
16890
+ async function fetchSeq(conn, path57, params) {
16891
+ const url = `${conn.url}${path57}?${params}`;
16852
16892
  const response = await fetch(url, {
16853
16893
  headers: {
16854
16894
  Accept: "application/json",
@@ -17447,9 +17487,9 @@ function createReadlineInterface() {
17447
17487
  });
17448
17488
  }
17449
17489
  function askQuestion(rl, question) {
17450
- return new Promise((resolve17) => {
17490
+ return new Promise((resolve16) => {
17451
17491
  rl.question(question, (answer) => {
17452
- resolve17(answer.trim());
17492
+ resolve16(answer.trim());
17453
17493
  });
17454
17494
  });
17455
17495
  }
@@ -18136,7 +18176,7 @@ import { mkdirSync as mkdirSync18 } from "fs";
18136
18176
  import { join as join53 } from "path";
18137
18177
 
18138
18178
  // src/commands/voice/checkLockFile.ts
18139
- import { execSync as execSync46 } from "child_process";
18179
+ import { execSync as execSync47 } from "child_process";
18140
18180
  import { existsSync as existsSync44, mkdirSync as mkdirSync17, readFileSync as readFileSync37, writeFileSync as writeFileSync33 } from "fs";
18141
18181
  import { join as join52 } from "path";
18142
18182
  function isProcessAlive2(pid) {
@@ -18165,7 +18205,7 @@ function bootstrapVenv() {
18165
18205
  if (existsSync44(getVenvPython())) return;
18166
18206
  console.log("Setting up Python environment...");
18167
18207
  const pythonDir = getPythonDir();
18168
- execSync46(
18208
+ execSync47(
18169
18209
  `uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
18170
18210
  {
18171
18211
  stdio: "inherit",
@@ -18350,7 +18390,7 @@ function extractCode(url, expectedState) {
18350
18390
  return code;
18351
18391
  }
18352
18392
  function waitForCallback(port, expectedState) {
18353
- return new Promise((resolve17, reject) => {
18393
+ return new Promise((resolve16, reject) => {
18354
18394
  const timeout = setTimeout(() => {
18355
18395
  server.close();
18356
18396
  reject(new Error("Authorization timed out after 120 seconds"));
@@ -18367,7 +18407,7 @@ function waitForCallback(port, expectedState) {
18367
18407
  const code = extractCode(url, expectedState);
18368
18408
  respondHtml(res, 200, "Authorization successful!");
18369
18409
  server.close();
18370
- resolve17(code);
18410
+ resolve16(code);
18371
18411
  } catch (error) {
18372
18412
  respondHtml(res, 400, error.message);
18373
18413
  server.close();
@@ -18498,9 +18538,9 @@ function findPortFile(roamDir) {
18498
18538
  return void 0;
18499
18539
  }
18500
18540
  const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
18501
- const path58 = join55(roamDir, name);
18541
+ const path57 = join55(roamDir, name);
18502
18542
  try {
18503
- return { path: path58, mtimeMs: statSync6(path58).mtimeMs };
18543
+ return { path: path57, mtimeMs: statSync6(path57).mtimeMs };
18504
18544
  } catch {
18505
18545
  return void 0;
18506
18546
  }
@@ -18642,11 +18682,11 @@ function resolveParams(params, cliArgs) {
18642
18682
  }
18643
18683
 
18644
18684
  // src/commands/run/runPreCommands.ts
18645
- import { execSync as execSync47 } from "child_process";
18685
+ import { execSync as execSync48 } from "child_process";
18646
18686
  function runPreCommands(pre, cwd) {
18647
18687
  for (const cmd of pre) {
18648
18688
  try {
18649
- execSync47(cmd, { stdio: "inherit", cwd });
18689
+ execSync48(cmd, { stdio: "inherit", cwd });
18650
18690
  } catch (error) {
18651
18691
  const code = error && typeof error === "object" && "status" in error ? error.status : 1;
18652
18692
  process.exit(code);
@@ -18843,11 +18883,11 @@ function findLinkIndex() {
18843
18883
  function parseLinkArgs() {
18844
18884
  const idx = findLinkIndex();
18845
18885
  if (idx === -1) return null;
18846
- const path58 = process.argv[idx + 1];
18886
+ const path57 = process.argv[idx + 1];
18847
18887
  const rest = process.argv.slice(idx + 2);
18848
18888
  const { value: prefix2 } = extractOption(rest, "--prefix");
18849
18889
  if (!prefix2) return null;
18850
- return { path: path58, prefix: prefix2 };
18890
+ return { path: path57, prefix: prefix2 };
18851
18891
  }
18852
18892
  function hasDuplicateLink(runList, linkPath) {
18853
18893
  return runList.some(
@@ -18930,7 +18970,7 @@ function registerRun(program2) {
18930
18970
  }
18931
18971
 
18932
18972
  // src/commands/screenshot/index.ts
18933
- import { execSync as execSync48 } from "child_process";
18973
+ import { execSync as execSync49 } from "child_process";
18934
18974
  import { existsSync as existsSync49, mkdirSync as mkdirSync21, unlinkSync as unlinkSync17, writeFileSync as writeFileSync36 } from "fs";
18935
18975
  import { tmpdir as tmpdir7 } from "os";
18936
18976
  import { join as join59, resolve as resolve14 } from "path";
@@ -19073,7 +19113,7 @@ function runPowerShellScript(processName, outputPath) {
19073
19113
  const scriptPath = join59(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
19074
19114
  writeFileSync36(scriptPath, captureWindowPs1, "utf8");
19075
19115
  try {
19076
- execSync48(
19116
+ execSync49(
19077
19117
  `powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
19078
19118
  { stdio: ["ignore", "pipe", "pipe"], encoding: "utf8" }
19079
19119
  );
@@ -19116,10 +19156,10 @@ var STATUS_TIMEOUT_MS = 5e3;
19116
19156
  function queryDaemon(socket) {
19117
19157
  socket.write(`${JSON.stringify({ type: "ping" })}
19118
19158
  `);
19119
- return new Promise((resolve17) => {
19159
+ return new Promise((resolve16) => {
19120
19160
  const result = { sessions: [] };
19121
19161
  const pending = /* @__PURE__ */ new Set(["sessions", "pong"]);
19122
- const timer = setTimeout(() => resolve17(result), STATUS_TIMEOUT_MS);
19162
+ const timer = setTimeout(() => resolve16(result), STATUS_TIMEOUT_MS);
19123
19163
  const lines = createInterface4({ input: socket });
19124
19164
  lines.on("error", () => {
19125
19165
  });
@@ -19127,7 +19167,7 @@ function queryDaemon(socket) {
19127
19167
  applyLine(result, pending, line);
19128
19168
  if (pending.size === 0) {
19129
19169
  clearTimeout(timer);
19130
- resolve17(result);
19170
+ resolve16(result);
19131
19171
  }
19132
19172
  });
19133
19173
  });
@@ -19487,6 +19527,9 @@ function createAssistSession(id2, assistArgs, cwd) {
19487
19527
  };
19488
19528
  }
19489
19529
 
19530
+ // src/commands/sessions/daemon/createSession.ts
19531
+ import { randomUUID as randomUUID4 } from "crypto";
19532
+
19490
19533
  // src/commands/sessions/daemon/spawnClaude.ts
19491
19534
  function spawnClaude2(opts = {}) {
19492
19535
  return spawnPty(buildArgs3(opts), opts.cwd, opts.sessionId);
@@ -19496,6 +19539,7 @@ function buildArgs3(opts) {
19496
19539
  if (opts.resumeSessionId) {
19497
19540
  return opts.prompt ? [...base, "--resume", opts.resumeSessionId, opts.prompt] : [...base, "--resume", opts.resumeSessionId];
19498
19541
  }
19542
+ if (opts.claudeSessionId) base.push("--session-id", opts.claudeSessionId);
19499
19543
  if (opts.prompt) return [...base, opts.prompt];
19500
19544
  return base;
19501
19545
  }
@@ -19506,33 +19550,34 @@ function spawnRun(opts) {
19506
19550
  }
19507
19551
 
19508
19552
  // src/commands/sessions/daemon/createSession.ts
19509
- function createSession(id2, prompt, cwd) {
19553
+ function runningBase(id2) {
19510
19554
  const startedAt = Date.now();
19511
19555
  return {
19512
19556
  id: id2,
19513
- name: prompt?.slice(0, 40) || `Session ${id2}`,
19514
- commandType: "claude",
19515
19557
  status: "running",
19516
19558
  startedAt,
19517
19559
  runningMs: 0,
19518
19560
  runningSince: startedAt,
19519
- pty: spawnClaude2({ prompt, cwd, sessionId: id2 }),
19520
- scrollback: "",
19521
- cwd
19561
+ scrollback: ""
19562
+ };
19563
+ }
19564
+ function createSession(id2, prompt, cwd) {
19565
+ const claudeSessionId = randomUUID4();
19566
+ return {
19567
+ ...runningBase(id2),
19568
+ name: prompt?.slice(0, 40) || `Session ${id2}`,
19569
+ commandType: "claude",
19570
+ pty: spawnClaude2({ prompt, cwd, sessionId: id2, claudeSessionId }),
19571
+ cwd,
19572
+ claudeSessionId
19522
19573
  };
19523
19574
  }
19524
19575
  function createRunSession(id2, runName, runArgs, cwd) {
19525
- const startedAt = Date.now();
19526
19576
  return {
19527
- id: id2,
19577
+ ...runningBase(id2),
19528
19578
  name: `run: ${runName}`,
19529
19579
  commandType: "run",
19530
- status: "running",
19531
- startedAt,
19532
- runningMs: 0,
19533
- runningSince: startedAt,
19534
19580
  pty: spawnRun({ name: runName, args: runArgs, cwd }),
19535
- scrollback: "",
19536
19581
  runName,
19537
19582
  runArgs,
19538
19583
  cwd
@@ -19596,10 +19641,14 @@ function disarmEscInterrupt(session) {
19596
19641
 
19597
19642
  // src/commands/sessions/daemon/shouldAutoDismiss.ts
19598
19643
  function shouldAutoDismiss(session, exitCode) {
19599
- const args = session.assistArgs;
19600
- if (session.status !== "done" || exitCode !== 0 || args === void 0) {
19644
+ if (session.status !== "done" || exitCode !== 0) {
19601
19645
  return false;
19602
19646
  }
19647
+ if (session.reviewStarted) {
19648
+ return session.autoAdvance === true;
19649
+ }
19650
+ const args = session.assistArgs;
19651
+ if (args === void 0) return false;
19603
19652
  if (args[0] === "update") return true;
19604
19653
  return args.includes("--once") && args[0] !== "next";
19605
19654
  }
@@ -19684,9 +19733,25 @@ function runningSession(base, persisted, pty2) {
19684
19733
  };
19685
19734
  }
19686
19735
 
19736
+ // src/commands/sessions/daemon/updatedSession.ts
19737
+ function updatedSession(id2, persisted) {
19738
+ return {
19739
+ ...restoreBase(id2, persisted),
19740
+ status: "done",
19741
+ startedAt: persisted.startedAt,
19742
+ runningMs: persisted.runningMs ?? 0,
19743
+ runningSince: null,
19744
+ pty: null
19745
+ };
19746
+ }
19747
+ function isUpdate(persisted) {
19748
+ return persisted.commandType === "assist" && persisted.assistArgs?.[0] === "update";
19749
+ }
19750
+
19687
19751
  // src/commands/sessions/daemon/restoreSession.ts
19688
19752
  function restoreSession(id2, persisted) {
19689
19753
  const base = restoreBase(id2, persisted);
19754
+ if (isUpdate(persisted)) return updatedSession(id2, persisted);
19690
19755
  if (isBacklogRun(persisted)) {
19691
19756
  const pty2 = spawnPty(backlogRunArgs(persisted), persisted.cwd, id2);
19692
19757
  return runningSession(base, persisted, pty2);
@@ -19766,18 +19831,35 @@ function resumeSession(id2, sessionId, cwd, name) {
19766
19831
  runningSince: startedAt,
19767
19832
  pty: spawnClaude2({ resumeSessionId: sessionId, cwd, sessionId: id2 }),
19768
19833
  scrollback: "",
19769
- cwd
19834
+ cwd,
19835
+ /* why: bind the card to the conversation it is resuming so a daemon restart
19836
+ * re-resumes this same transcript, not whichever .jsonl a cwd poller would
19837
+ * have re-discovered (#413). */
19838
+ claudeSessionId: sessionId
19770
19839
  };
19771
19840
  }
19772
19841
 
19773
19842
  // src/commands/sessions/daemon/watchActivity.ts
19774
19843
  import { existsSync as existsSync51, mkdirSync as mkdirSync22, watch } from "fs";
19775
19844
  import { dirname as dirname28 } from "path";
19845
+
19846
+ // src/commands/sessions/daemon/applyReviewPause.ts
19847
+ function applyReviewPause(session, activity2) {
19848
+ const inReview = activity2.kind === "backlog" && activity2.phase !== void 0 && activity2.phase === activity2.totalPhases;
19849
+ if (inReview && !session.reviewStarted) {
19850
+ session.autoAdvance = false;
19851
+ session.reviewStarted = true;
19852
+ } else if (!inReview && session.reviewStarted) {
19853
+ session.reviewStarted = false;
19854
+ }
19855
+ }
19856
+
19857
+ // src/commands/sessions/daemon/watchActivity.ts
19776
19858
  var DEBOUNCE_MS = 50;
19777
19859
  function watchActivity(session, notify2) {
19778
19860
  if (session.commandType !== "assist" || !session.cwd) return;
19779
- const path58 = activityPath(session.id);
19780
- const dir = dirname28(path58);
19861
+ const path57 = activityPath(session.id);
19862
+ const dir = dirname28(path57);
19781
19863
  try {
19782
19864
  mkdirSync22(dir, { recursive: true });
19783
19865
  } catch {
@@ -19787,19 +19869,20 @@ function watchActivity(session, notify2) {
19787
19869
  let timer = null;
19788
19870
  const read = () => {
19789
19871
  timer = null;
19790
- const activity2 = readActivity(path58);
19872
+ const activity2 = readActivity(path57);
19791
19873
  if (!activity2) return;
19792
19874
  session.activity = activity2;
19793
19875
  if (activity2.claudeSessionId)
19794
19876
  session.claudeSessionId = activity2.claudeSessionId;
19877
+ applyReviewPause(session, activity2);
19795
19878
  notify2();
19796
19879
  };
19797
19880
  session.activityWatcher = watch(dir, (_event, filename) => {
19798
- if (filename && !path58.endsWith(filename)) return;
19881
+ if (filename && !path57.endsWith(filename)) return;
19799
19882
  if (timer) clearTimeout(timer);
19800
19883
  timer = setTimeout(read, DEBOUNCE_MS);
19801
19884
  });
19802
- if (existsSync51(path58)) read();
19885
+ if (existsSync51(path57)) read();
19803
19886
  }
19804
19887
  function refreshActivity(session) {
19805
19888
  if (session.commandType !== "assist" || !session.cwd) return;
@@ -19901,10 +19984,10 @@ function windowsDaemonHost() {
19901
19984
 
19902
19985
  // src/commands/sessions/daemon/connectToWindowsDaemon.ts
19903
19986
  function connectToWindowsDaemon() {
19904
- return new Promise((resolve17, reject) => {
19987
+ return new Promise((resolve16, reject) => {
19905
19988
  const socket = net2.connect(windowsDaemonPort(), windowsDaemonHost());
19906
19989
  socket.setKeepAlive(true, 1e4);
19907
- socket.once("connect", () => resolve17(socket));
19990
+ socket.once("connect", () => resolve16(socket));
19908
19991
  socket.once("error", reject);
19909
19992
  });
19910
19993
  }
@@ -19981,7 +20064,7 @@ async function waitForWindowsDaemon() {
19981
20064
  );
19982
20065
  }
19983
20066
  function delay2(ms) {
19984
- return new Promise((resolve17) => setTimeout(resolve17, ms));
20067
+ return new Promise((resolve16) => setTimeout(resolve16, ms));
19985
20068
  }
19986
20069
 
19987
20070
  // src/commands/sessions/daemon/defaultConnect.ts
@@ -20148,7 +20231,7 @@ async function healWindowsDaemon() {
20148
20231
  daemonLog("windows daemon: auto-heal: stale daemon stopped");
20149
20232
  }
20150
20233
  function runOnWindowsHost(command, timeoutMs) {
20151
- return new Promise((resolve17, reject) => {
20234
+ return new Promise((resolve16, reject) => {
20152
20235
  const child = spawn11("pwsh.exe", ["-Command", command], {
20153
20236
  stdio: ["ignore", "pipe", "pipe"]
20154
20237
  });
@@ -20168,7 +20251,7 @@ function runOnWindowsHost(command, timeoutMs) {
20168
20251
  });
20169
20252
  child.on("exit", (code) => {
20170
20253
  clearTimeout(timer);
20171
- if (code === 0) resolve17();
20254
+ if (code === 0) resolve16();
20172
20255
  else
20173
20256
  reject(
20174
20257
  new Error(
@@ -20416,9 +20499,144 @@ var WindowsProxy = class {
20416
20499
  }
20417
20500
  };
20418
20501
 
20419
- // src/commands/sessions/daemon/watchClaudeSessionId.ts
20420
- import * as fs31 from "fs";
20421
- import * as path52 from "path";
20502
+ // src/commands/sessions/daemon/writeToSession.ts
20503
+ function writeToSession(sessions, id2, data, onStatusChange) {
20504
+ const s = sessions.get(id2);
20505
+ if (!s || s.status === "done") return;
20506
+ s.pty?.write(data);
20507
+ watchEscInterrupt(s, data, onStatusChange);
20508
+ }
20509
+ function resizeSession(sessions, id2, cols, rows) {
20510
+ const s = sessions.get(id2);
20511
+ if (s && s.status !== "done") s.pty?.resize(cols, rows);
20512
+ }
20513
+ function setAutoRun(sessions, id2, enabled) {
20514
+ const s = sessions.get(id2);
20515
+ if (!s) return false;
20516
+ s.autoRun = enabled;
20517
+ return true;
20518
+ }
20519
+ function setAutoAdvance(sessions, id2, enabled) {
20520
+ const s = sessions.get(id2);
20521
+ if (!s) return false;
20522
+ s.autoAdvance = enabled;
20523
+ const itemId = s.activity?.itemId;
20524
+ if (itemId != null) {
20525
+ if (enabled) clearPause(itemId);
20526
+ else requestPause(itemId);
20527
+ }
20528
+ return true;
20529
+ }
20530
+ function dismissSession(sessions, id2) {
20531
+ const s = sessions.get(id2);
20532
+ if (!s) return false;
20533
+ if (s.status !== "done") s.pty?.kill();
20534
+ s.activityWatcher?.close();
20535
+ removeActivity(s.id);
20536
+ if (s.activity?.itemId != null) releaseLock(s.activity.itemId);
20537
+ sessions.delete(id2);
20538
+ return true;
20539
+ }
20540
+
20541
+ // src/commands/sessions/daemon/SessionManager.ts
20542
+ var SessionManager = class {
20543
+ constructor(onIdleChange) {
20544
+ this.onIdleChange = onIdleChange;
20545
+ }
20546
+ sessions = /* @__PURE__ */ new Map();
20547
+ // why: dispatch calls active.set() on card click; broadcasts include active.toJSON()
20548
+ active = new ActiveSelection(() => this.notify());
20549
+ clients = new ClientHub(persistUsagePeak);
20550
+ nextId = 1;
20551
+ shuttingDown = false;
20552
+ // why: dispatch calls windowsProxy.route() to forward windows-origin sessions
20553
+ windowsProxy = new WindowsProxy(this.clients, () => this.notify());
20554
+ addClient(client) {
20555
+ this.clients.add(client);
20556
+ this.notify();
20557
+ greetClient(client, this.sessions, this.windowsProxy);
20558
+ }
20559
+ removeClient(client) {
20560
+ this.clients.delete(client);
20561
+ this.onIdleChange?.(this.isIdle());
20562
+ }
20563
+ isIdle = () => this.sessions.size === 0 && this.clients.size === 0;
20564
+ shutdown() {
20565
+ this.shuttingDown = true;
20566
+ shutdownSessions(this.sessions);
20567
+ }
20568
+ restore() {
20569
+ return restoreAll(this.spawnWith, this.sessions);
20570
+ }
20571
+ add(session) {
20572
+ this.wire(session);
20573
+ watchActivity(session, this.notify);
20574
+ return session.id;
20575
+ }
20576
+ spawnWith = (create) => this.add(create(String(this.nextId++)));
20577
+ spawn(prompt, cwd) {
20578
+ return this.spawnWith((id2) => createSession(id2, prompt, cwd));
20579
+ }
20580
+ spawnRun(runName, runArgs, cwd) {
20581
+ return this.spawnWith((id2) => createRunSession(id2, runName, runArgs, cwd));
20582
+ }
20583
+ spawnAssist(assistArgs, cwd) {
20584
+ return this.spawnWith((id2) => createAssistSession(id2, assistArgs, cwd));
20585
+ }
20586
+ resume(sessionId, cwd, name) {
20587
+ return this.spawnWith((id2) => resumeSession(id2, sessionId, cwd, name));
20588
+ }
20589
+ onStatusChange = makeStatusChangeHandler(
20590
+ (id2) => this.dismissSession(id2),
20591
+ () => this.notify(),
20592
+ (session, itemId) => reuseSessionForRun(session, itemId, this.clients, this.onStatusChange)
20593
+ );
20594
+ wire(session) {
20595
+ this.sessions.set(session.id, session);
20596
+ wirePtyEvents(session, this.clients, this.onStatusChange);
20597
+ this.notify();
20598
+ }
20599
+ writeToSession(id2, data) {
20600
+ writeToSession(this.sessions, id2, data, this.onStatusChange);
20601
+ }
20602
+ resizeSession(id2, cols, rows) {
20603
+ resizeSession(this.sessions, id2, cols, rows);
20604
+ }
20605
+ retrySession(id2) {
20606
+ const s = this.sessions.get(id2);
20607
+ if (s && retrySession(s, this.clients, this.onStatusChange)) this.notify();
20608
+ }
20609
+ dismissSession = (id2) => {
20610
+ if (dismissSession(this.sessions, id2)) this.notify();
20611
+ };
20612
+ setAutoRun(id2, enabled) {
20613
+ if (setAutoRun(this.sessions, id2, enabled)) this.notify();
20614
+ }
20615
+ setAutoAdvance(id2, enabled) {
20616
+ if (setAutoAdvance(this.sessions, id2, enabled)) this.notify();
20617
+ }
20618
+ setStatus(id2, status2) {
20619
+ const session = this.sessions.get(id2);
20620
+ if (session) this.onStatusChange(session, status2);
20621
+ }
20622
+ listSessions = () => {
20623
+ const local = [...this.sessions.values()].map(toSessionInfo);
20624
+ return local.concat(this.windowsProxy.sessions());
20625
+ };
20626
+ notify = () => {
20627
+ if (this.shuttingDown) return;
20628
+ const windows = this.windowsProxy.sessions();
20629
+ broadcastSessions(this.sessions, this.clients, windows, this.active);
20630
+ this.onIdleChange?.(this.isIdle());
20631
+ };
20632
+ };
20633
+
20634
+ // src/commands/sessions/daemon/startDaemonServer.ts
20635
+ import { unlinkSync as unlinkSync19 } from "fs";
20636
+ import * as net3 from "net";
20637
+
20638
+ // src/commands/sessions/daemon/handleConnection.ts
20639
+ import { createInterface as createInterface7 } from "readline";
20422
20640
 
20423
20641
  // src/commands/sessions/shared/discoverSessions.ts
20424
20642
  import * as fs30 from "fs";
@@ -20606,211 +20824,8 @@ async function discoverSessions() {
20606
20824
  return sessions;
20607
20825
  }
20608
20826
 
20609
- // src/commands/sessions/daemon/watchClaudeSessionId.ts
20610
- var POLL_MS = 3e3;
20611
- async function watchClaudeSessionId(options2) {
20612
- let adoptedMs = 0;
20613
- while (options2.isActive()) {
20614
- const latest = await findLatestSessionId(options2);
20615
- if (latest && latest.createdMs > adoptedMs) {
20616
- adoptedMs = latest.createdMs;
20617
- options2.onSessionId(latest.sessionId);
20618
- }
20619
- await sleep(options2.pollMs ?? POLL_MS);
20620
- }
20621
- }
20622
- async function findLatestSessionId(options2) {
20623
- const paths = await discoverSessionJsonlPaths();
20624
- let latest = null;
20625
- for (const { path: filePath, origin } of paths) {
20626
- const createdMs = await createdSince(filePath, options2.sinceMs);
20627
- if (createdMs === null) continue;
20628
- const meta = await parseSessionFile(filePath, origin);
20629
- if (!meta?.cwd || options2.isClaimed(meta.sessionId)) continue;
20630
- if (path52.resolve(meta.cwd) !== path52.resolve(options2.cwd)) continue;
20631
- if (!latest || createdMs > latest.createdMs)
20632
- latest = { sessionId: meta.sessionId, createdMs };
20633
- }
20634
- return latest;
20635
- }
20636
- async function createdSince(filePath, sinceMs) {
20637
- try {
20638
- const stat = await fs31.promises.stat(filePath);
20639
- const createdMs = stat.birthtimeMs || stat.mtimeMs;
20640
- return createdMs >= sinceMs ? createdMs : null;
20641
- } catch {
20642
- return null;
20643
- }
20644
- }
20645
- function sleep(ms) {
20646
- return new Promise((resolve17) => setTimeout(resolve17, ms));
20647
- }
20648
-
20649
- // src/commands/sessions/daemon/watchForClaudeSessionId.ts
20650
- function watchForClaudeSessionId(session, sessions, onDiscovered) {
20651
- if (session.commandType === "run" || !session.pty) return;
20652
- if (isBacklogRun2(session)) return;
20653
- void watchClaudeSessionId({
20654
- cwd: session.cwd ?? process.cwd(),
20655
- sinceMs: session.startedAt,
20656
- isClaimed: (sessionId) => [...sessions.values()].some((s) => s.claudeSessionId === sessionId),
20657
- isActive: () => {
20658
- const s = sessions.get(session.id);
20659
- return !!s && s.status !== "done";
20660
- },
20661
- onSessionId: (sessionId) => {
20662
- if (!sessions.has(session.id)) return;
20663
- session.claudeSessionId = sessionId;
20664
- onDiscovered();
20665
- }
20666
- });
20667
- }
20668
- function isBacklogRun2(session) {
20669
- return session.commandType === "assist" && session.assistArgs?.[0] === "backlog" && session.assistArgs?.[1] === "run";
20670
- }
20671
-
20672
- // src/commands/sessions/daemon/writeToSession.ts
20673
- function writeToSession(sessions, id2, data, onStatusChange) {
20674
- const s = sessions.get(id2);
20675
- if (!s || s.status === "done") return;
20676
- s.pty?.write(data);
20677
- watchEscInterrupt(s, data, onStatusChange);
20678
- }
20679
- function resizeSession(sessions, id2, cols, rows) {
20680
- const s = sessions.get(id2);
20681
- if (s && s.status !== "done") s.pty?.resize(cols, rows);
20682
- }
20683
- function setAutoRun(sessions, id2, enabled) {
20684
- const s = sessions.get(id2);
20685
- if (!s) return false;
20686
- s.autoRun = enabled;
20687
- return true;
20688
- }
20689
- function setAutoAdvance(sessions, id2, enabled) {
20690
- const s = sessions.get(id2);
20691
- if (!s) return false;
20692
- s.autoAdvance = enabled;
20693
- const itemId = s.activity?.itemId;
20694
- if (itemId != null) {
20695
- if (enabled) clearPause(itemId);
20696
- else requestPause(itemId);
20697
- }
20698
- return true;
20699
- }
20700
- function dismissSession(sessions, id2) {
20701
- const s = sessions.get(id2);
20702
- if (!s) return false;
20703
- if (s.status !== "done") s.pty?.kill();
20704
- s.activityWatcher?.close();
20705
- removeActivity(s.id);
20706
- if (s.activity?.itemId != null) releaseLock(s.activity.itemId);
20707
- sessions.delete(id2);
20708
- return true;
20709
- }
20710
-
20711
- // src/commands/sessions/daemon/SessionManager.ts
20712
- var SessionManager = class {
20713
- constructor(onIdleChange) {
20714
- this.onIdleChange = onIdleChange;
20715
- }
20716
- sessions = /* @__PURE__ */ new Map();
20717
- // why: dispatch calls active.set() on card click; broadcasts include active.toJSON()
20718
- active = new ActiveSelection(() => this.notify());
20719
- clients = new ClientHub(persistUsagePeak);
20720
- nextId = 1;
20721
- shuttingDown = false;
20722
- // why: dispatch calls windowsProxy.route() to forward windows-origin sessions
20723
- windowsProxy = new WindowsProxy(this.clients, () => this.notify());
20724
- addClient(client) {
20725
- this.clients.add(client);
20726
- this.notify();
20727
- greetClient(client, this.sessions, this.windowsProxy);
20728
- }
20729
- removeClient(client) {
20730
- this.clients.delete(client);
20731
- this.onIdleChange?.(this.isIdle());
20732
- }
20733
- isIdle = () => this.sessions.size === 0 && this.clients.size === 0;
20734
- shutdown() {
20735
- this.shuttingDown = true;
20736
- shutdownSessions(this.sessions);
20737
- }
20738
- restore() {
20739
- return restoreAll(this.spawnWith, this.sessions);
20740
- }
20741
- add(session) {
20742
- this.wire(session);
20743
- watchForClaudeSessionId(session, this.sessions, this.notify);
20744
- watchActivity(session, this.notify);
20745
- return session.id;
20746
- }
20747
- spawnWith = (create) => this.add(create(String(this.nextId++)));
20748
- spawn(prompt, cwd) {
20749
- return this.spawnWith((id2) => createSession(id2, prompt, cwd));
20750
- }
20751
- spawnRun(runName, runArgs, cwd) {
20752
- return this.spawnWith((id2) => createRunSession(id2, runName, runArgs, cwd));
20753
- }
20754
- spawnAssist(assistArgs, cwd) {
20755
- return this.spawnWith((id2) => createAssistSession(id2, assistArgs, cwd));
20756
- }
20757
- resume(sessionId, cwd, name) {
20758
- return this.spawnWith((id2) => resumeSession(id2, sessionId, cwd, name));
20759
- }
20760
- onStatusChange = makeStatusChangeHandler(
20761
- (id2) => this.dismissSession(id2),
20762
- () => this.notify(),
20763
- (session, itemId) => reuseSessionForRun(session, itemId, this.clients, this.onStatusChange)
20764
- );
20765
- wire(session) {
20766
- this.sessions.set(session.id, session);
20767
- wirePtyEvents(session, this.clients, this.onStatusChange);
20768
- this.notify();
20769
- }
20770
- writeToSession(id2, data) {
20771
- writeToSession(this.sessions, id2, data, this.onStatusChange);
20772
- }
20773
- resizeSession(id2, cols, rows) {
20774
- resizeSession(this.sessions, id2, cols, rows);
20775
- }
20776
- retrySession(id2) {
20777
- const s = this.sessions.get(id2);
20778
- if (s && retrySession(s, this.clients, this.onStatusChange)) this.notify();
20779
- }
20780
- dismissSession = (id2) => {
20781
- if (dismissSession(this.sessions, id2)) this.notify();
20782
- };
20783
- setAutoRun(id2, enabled) {
20784
- if (setAutoRun(this.sessions, id2, enabled)) this.notify();
20785
- }
20786
- setAutoAdvance(id2, enabled) {
20787
- if (setAutoAdvance(this.sessions, id2, enabled)) this.notify();
20788
- }
20789
- setStatus(id2, status2) {
20790
- const session = this.sessions.get(id2);
20791
- if (session) this.onStatusChange(session, status2);
20792
- }
20793
- listSessions = () => {
20794
- const local = [...this.sessions.values()].map(toSessionInfo);
20795
- return local.concat(this.windowsProxy.sessions());
20796
- };
20797
- notify = () => {
20798
- if (this.shuttingDown) return;
20799
- const windows = this.windowsProxy.sessions();
20800
- broadcastSessions(this.sessions, this.clients, windows, this.active);
20801
- this.onIdleChange?.(this.isIdle());
20802
- };
20803
- };
20804
-
20805
- // src/commands/sessions/daemon/startDaemonServer.ts
20806
- import { unlinkSync as unlinkSync19 } from "fs";
20807
- import * as net3 from "net";
20808
-
20809
- // src/commands/sessions/daemon/handleConnection.ts
20810
- import { createInterface as createInterface7 } from "readline";
20811
-
20812
20827
  // src/commands/sessions/shared/parseTranscript.ts
20813
- import * as fs32 from "fs";
20828
+ import * as fs31 from "fs";
20814
20829
 
20815
20830
  // src/commands/sessions/shared/toolTarget.ts
20816
20831
  function toolTarget(input) {
@@ -20858,11 +20873,11 @@ function cleanUserText(value) {
20858
20873
  }
20859
20874
 
20860
20875
  // src/commands/sessions/shared/findSessionJsonlPath.ts
20861
- import * as path53 from "path";
20876
+ import * as path52 from "path";
20862
20877
  async function findSessionJsonlPath(sessionId) {
20863
20878
  const paths = await discoverSessionJsonlPaths();
20864
20879
  const direct = paths.find(
20865
- (p) => path53.basename(p.path, ".jsonl") === sessionId
20880
+ (p) => path52.basename(p.path, ".jsonl") === sessionId
20866
20881
  );
20867
20882
  if (direct) return direct.path;
20868
20883
  for (const p of paths) {
@@ -20877,7 +20892,7 @@ async function parseTranscript(sessionId) {
20877
20892
  const filePath = await findSessionJsonlPath(sessionId);
20878
20893
  if (!filePath) return [];
20879
20894
  try {
20880
- const raw = await fs32.promises.readFile(filePath, "utf8");
20895
+ const raw = await fs31.promises.readFile(filePath, "utf8");
20881
20896
  return parseTranscriptLines(raw.split("\n"));
20882
20897
  } catch {
20883
20898
  return [];
@@ -21177,17 +21192,17 @@ async function setSessionStatus(status2) {
21177
21192
  }
21178
21193
 
21179
21194
  // src/commands/sessions/summarise/index.ts
21180
- import * as fs35 from "fs";
21195
+ import * as fs34 from "fs";
21181
21196
  import chalk171 from "chalk";
21182
21197
 
21183
21198
  // src/commands/sessions/summarise/shared.ts
21184
- import * as fs33 from "fs";
21199
+ import * as fs32 from "fs";
21185
21200
  function writeSummary(jsonlPath2, summary) {
21186
- fs33.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
21201
+ fs32.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
21187
21202
  `, "utf8");
21188
21203
  }
21189
21204
  function hasSummary(jsonlPath2) {
21190
- return fs33.existsSync(summaryPathFor(jsonlPath2));
21205
+ return fs32.existsSync(summaryPathFor(jsonlPath2));
21191
21206
  }
21192
21207
  function summaryPathFor(jsonlPath2) {
21193
21208
  return jsonlPath2.replace(/\.jsonl$/, ".summary");
@@ -21197,7 +21212,7 @@ function summaryPathFor(jsonlPath2) {
21197
21212
  import { execFileSync as execFileSync10 } from "child_process";
21198
21213
 
21199
21214
  // src/commands/sessions/summarise/iterateUserMessages.ts
21200
- import * as fs34 from "fs";
21215
+ import * as fs33 from "fs";
21201
21216
 
21202
21217
  // src/commands/sessions/summarise/parseUserLine.ts
21203
21218
  function parseUserLine(line) {
@@ -21228,13 +21243,13 @@ function parseUserLine(line) {
21228
21243
  function* iterateUserMessages(filePath, maxBytes = 65536) {
21229
21244
  let content;
21230
21245
  try {
21231
- const fd = fs34.openSync(filePath, "r");
21246
+ const fd = fs33.openSync(filePath, "r");
21232
21247
  try {
21233
21248
  const buf = Buffer.alloc(maxBytes);
21234
- const bytesRead = fs34.readSync(fd, buf, 0, buf.length, 0);
21249
+ const bytesRead = fs33.readSync(fd, buf, 0, buf.length, 0);
21235
21250
  content = buf.toString("utf8", 0, bytesRead);
21236
21251
  } finally {
21237
- fs34.closeSync(fd);
21252
+ fs33.closeSync(fd);
21238
21253
  }
21239
21254
  } catch {
21240
21255
  return;
@@ -21354,7 +21369,7 @@ function selectCandidates(files, options2) {
21354
21369
  const candidates = options2.force ? files : files.filter((f) => !hasSummary(f));
21355
21370
  candidates.sort((a, b) => {
21356
21371
  try {
21357
- return fs35.statSync(b).mtimeMs - fs35.statSync(a).mtimeMs;
21372
+ return fs34.statSync(b).mtimeMs - fs34.statSync(a).mtimeMs;
21358
21373
  } catch {
21359
21374
  return 0;
21360
21375
  }
@@ -21493,21 +21508,21 @@ async function statusLine() {
21493
21508
  }
21494
21509
 
21495
21510
  // src/commands/sync.ts
21496
- import * as fs38 from "fs";
21511
+ import * as fs37 from "fs";
21497
21512
  import * as os2 from "os";
21498
- import * as path56 from "path";
21513
+ import * as path55 from "path";
21499
21514
  import { fileURLToPath as fileURLToPath7 } from "url";
21500
21515
 
21501
21516
  // src/commands/sync/syncClaudeMd.ts
21502
- import * as fs36 from "fs";
21503
- import * as path54 from "path";
21517
+ import * as fs35 from "fs";
21518
+ import * as path53 from "path";
21504
21519
  import chalk174 from "chalk";
21505
21520
  async function syncClaudeMd(claudeDir, targetBase, options2) {
21506
- const source = path54.join(claudeDir, "CLAUDE.md");
21507
- const target = path54.join(targetBase, "CLAUDE.md");
21508
- const sourceContent = fs36.readFileSync(source, "utf8");
21509
- if (fs36.existsSync(target)) {
21510
- const targetContent = fs36.readFileSync(target, "utf8");
21521
+ const source = path53.join(claudeDir, "CLAUDE.md");
21522
+ const target = path53.join(targetBase, "CLAUDE.md");
21523
+ const sourceContent = fs35.readFileSync(source, "utf8");
21524
+ if (fs35.existsSync(target)) {
21525
+ const targetContent = fs35.readFileSync(target, "utf8");
21511
21526
  if (sourceContent !== targetContent) {
21512
21527
  console.log(
21513
21528
  chalk174.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
@@ -21524,21 +21539,21 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
21524
21539
  }
21525
21540
  }
21526
21541
  }
21527
- fs36.copyFileSync(source, target);
21542
+ fs35.copyFileSync(source, target);
21528
21543
  console.log("Copied CLAUDE.md to ~/.claude/CLAUDE.md");
21529
21544
  }
21530
21545
 
21531
21546
  // src/commands/sync/syncSettings.ts
21532
- import * as fs37 from "fs";
21533
- import * as path55 from "path";
21547
+ import * as fs36 from "fs";
21548
+ import * as path54 from "path";
21534
21549
  import chalk175 from "chalk";
21535
21550
  async function syncSettings(claudeDir, targetBase, options2) {
21536
- const source = path55.join(claudeDir, "settings.json");
21537
- const target = path55.join(targetBase, "settings.json");
21538
- const sourceContent = fs37.readFileSync(source, "utf8");
21551
+ const source = path54.join(claudeDir, "settings.json");
21552
+ const target = path54.join(targetBase, "settings.json");
21553
+ const sourceContent = fs36.readFileSync(source, "utf8");
21539
21554
  const mergedContent = JSON.stringify(JSON.parse(sourceContent), null, " ");
21540
- if (fs37.existsSync(target)) {
21541
- const targetContent = fs37.readFileSync(target, "utf8");
21555
+ if (fs36.existsSync(target)) {
21556
+ const targetContent = fs36.readFileSync(target, "utf8");
21542
21557
  const normalizedTarget = JSON.stringify(
21543
21558
  JSON.parse(targetContent),
21544
21559
  null,
@@ -21564,37 +21579,37 @@ async function syncSettings(claudeDir, targetBase, options2) {
21564
21579
  }
21565
21580
  }
21566
21581
  }
21567
- fs37.writeFileSync(target, mergedContent);
21582
+ fs36.writeFileSync(target, mergedContent);
21568
21583
  console.log("Copied settings.json to ~/.claude/settings.json");
21569
21584
  }
21570
21585
 
21571
21586
  // src/commands/sync.ts
21572
21587
  var __filename4 = fileURLToPath7(import.meta.url);
21573
- var __dirname6 = path56.dirname(__filename4);
21588
+ var __dirname6 = path55.dirname(__filename4);
21574
21589
  async function sync(options2) {
21575
21590
  const config = loadConfig();
21576
21591
  const yes = options2?.yes ?? config.sync.autoConfirm;
21577
- const claudeDir = path56.join(__dirname6, "..", "claude");
21578
- const targetBase = path56.join(os2.homedir(), ".claude");
21592
+ const claudeDir = path55.join(__dirname6, "..", "claude");
21593
+ const targetBase = path55.join(os2.homedir(), ".claude");
21579
21594
  syncCommands(claudeDir, targetBase);
21580
21595
  await syncSettings(claudeDir, targetBase, { yes });
21581
21596
  await syncClaudeMd(claudeDir, targetBase, { yes });
21582
21597
  }
21583
21598
  function syncCommands(claudeDir, targetBase) {
21584
- const sourceDir = path56.join(claudeDir, "commands");
21585
- const targetDir = path56.join(targetBase, "commands");
21586
- fs38.mkdirSync(targetDir, { recursive: true });
21587
- const files = fs38.readdirSync(sourceDir);
21599
+ const sourceDir = path55.join(claudeDir, "commands");
21600
+ const targetDir = path55.join(targetBase, "commands");
21601
+ fs37.mkdirSync(targetDir, { recursive: true });
21602
+ const files = fs37.readdirSync(sourceDir);
21588
21603
  for (const file of files) {
21589
- fs38.copyFileSync(path56.join(sourceDir, file), path56.join(targetDir, file));
21604
+ fs37.copyFileSync(path55.join(sourceDir, file), path55.join(targetDir, file));
21590
21605
  console.log(`Copied ${file} to ${targetDir}`);
21591
21606
  }
21592
21607
  console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
21593
21608
  }
21594
21609
 
21595
21610
  // src/commands/update.ts
21596
- import { execSync as execSync49 } from "child_process";
21597
- import * as path57 from "path";
21611
+ import { execSync as execSync50 } from "child_process";
21612
+ import * as path56 from "path";
21598
21613
 
21599
21614
  // src/commands/restartDaemonAfterUpdate.ts
21600
21615
  async function restartDaemonAfterUpdate() {
@@ -21613,12 +21628,12 @@ async function restartDaemonAfterUpdate() {
21613
21628
  // src/commands/update.ts
21614
21629
  function isGlobalNpmInstall(dir) {
21615
21630
  try {
21616
- const resolved = path57.resolve(dir);
21617
- if (resolved.split(path57.sep).includes("node_modules")) {
21631
+ const resolved = path56.resolve(dir);
21632
+ if (resolved.split(path56.sep).includes("node_modules")) {
21618
21633
  return true;
21619
21634
  }
21620
- const globalPrefix = execSync49("npm prefix -g", { stdio: "pipe" }).toString().trim();
21621
- return resolved.toLowerCase().startsWith(path57.resolve(globalPrefix).toLowerCase());
21635
+ const globalPrefix = execSync50("npm prefix -g", { stdio: "pipe" }).toString().trim();
21636
+ return resolved.toLowerCase().startsWith(path56.resolve(globalPrefix).toLowerCase());
21622
21637
  } catch {
21623
21638
  return false;
21624
21639
  }
@@ -21628,18 +21643,18 @@ async function update2() {
21628
21643
  console.log(`Assist is installed at: ${installDir}`);
21629
21644
  if (isGitRepo(installDir)) {
21630
21645
  console.log("Detected git repo installation, pulling latest...");
21631
- execSync49("git pull", { cwd: installDir, stdio: "inherit" });
21646
+ execSync50("git pull", { cwd: installDir, stdio: "inherit" });
21632
21647
  console.log("Installing dependencies...");
21633
- execSync49("npm i", { cwd: installDir, stdio: "inherit" });
21648
+ execSync50("npm i", { cwd: installDir, stdio: "inherit" });
21634
21649
  console.log("Building...");
21635
- execSync49("npm run build", { cwd: installDir, stdio: "inherit" });
21650
+ execSync50("npm run build", { cwd: installDir, stdio: "inherit" });
21636
21651
  console.log("Syncing commands...");
21637
- execSync49("assist sync", { stdio: "inherit" });
21652
+ execSync50("assist sync", { stdio: "inherit" });
21638
21653
  } else if (isGlobalNpmInstall(installDir)) {
21639
21654
  console.log("Detected global npm installation, updating...");
21640
- execSync49("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
21655
+ execSync50("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
21641
21656
  console.log("Syncing commands...");
21642
- execSync49("assist sync", { stdio: "inherit" });
21657
+ execSync50("assist sync", { stdio: "inherit" });
21643
21658
  } else {
21644
21659
  console.error(
21645
21660
  "Could not determine installation method. Expected a git repo or global npm install."