@staff0rd/assist 0.306.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.306.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 {};
@@ -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
@@ -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
  }
@@ -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;
@@ -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
  }
@@ -11411,25 +11420,18 @@ function createNetcapHandler(options2) {
11411
11420
  };
11412
11421
  }
11413
11422
 
11414
- // src/commands/netcap/defaultCapturePath.ts
11415
- import { homedir as homedir12 } from "os";
11416
- import { join as join34 } from "path";
11417
- function defaultCapturePath() {
11418
- return join34(homedir12(), ".assist", "netcap", "capture.jsonl");
11419
- }
11420
-
11421
11423
  // src/commands/netcap/prepareExtensionForLoad.ts
11422
11424
  import { cp, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
11423
11425
  import { networkInterfaces } from "os";
11424
- import { join as join36 } from "path";
11426
+ import { join as join35 } from "path";
11425
11427
  import chalk123 from "chalk";
11426
11428
 
11427
11429
  // src/commands/netcap/netcapExtensionDir.ts
11428
- import { dirname as dirname19, join as join35 } from "path";
11430
+ import { dirname as dirname19, join as join34 } from "path";
11429
11431
  import { fileURLToPath as fileURLToPath5 } from "url";
11430
11432
  var moduleDir = dirname19(fileURLToPath5(import.meta.url));
11431
11433
  function netcapExtensionDir() {
11432
- return join35(moduleDir, "commands", "netcap", "netcap-extension");
11434
+ return join34(moduleDir, "commands", "netcap", "netcap-extension");
11433
11435
  }
11434
11436
 
11435
11437
  // src/commands/netcap/prepareExtensionForLoad.ts
@@ -11443,21 +11445,24 @@ function lanIPv4() {
11443
11445
  }
11444
11446
  return void 0;
11445
11447
  }
11446
- async function setReceiverHost(dir, host, port) {
11447
- const file = join36(dir, "background.js");
11448
+ async function configureBackground(dir, host, port, filter) {
11449
+ const file = join35(dir, "background.js");
11448
11450
  const source = await readFile2(file, "utf8");
11449
11451
  await writeFile2(
11450
11452
  file,
11451
11453
  source.replace(
11452
11454
  /const RECEIVER = "[^"]*";/,
11453
11455
  `const RECEIVER = "http://${host}:${port}/";`
11456
+ ).replace(
11457
+ /const FILTER = "[^"]*";/,
11458
+ `const FILTER = ${JSON.stringify(filter)};`
11454
11459
  )
11455
11460
  );
11456
11461
  }
11457
- async function prepareExtensionForLoad(port) {
11462
+ async function prepareExtensionForLoad(port, filter = "") {
11458
11463
  const source = netcapExtensionDir();
11459
11464
  if (detectPlatform() !== "wsl") {
11460
- await setReceiverHost(source, "127.0.0.1", port);
11465
+ await configureBackground(source, "127.0.0.1", port, filter);
11461
11466
  return source;
11462
11467
  }
11463
11468
  const host = lanIPv4();
@@ -11465,12 +11470,12 @@ async function prepareExtensionForLoad(port) {
11465
11470
  console.log(
11466
11471
  chalk123.yellow("could not determine the WSL IP for the extension")
11467
11472
  );
11468
- await setReceiverHost(source, "127.0.0.1", port);
11473
+ await configureBackground(source, "127.0.0.1", port, filter);
11469
11474
  return source;
11470
11475
  }
11471
11476
  try {
11472
11477
  await cp(source, WSL_WINDOWS_DIR, { recursive: true });
11473
- await setReceiverHost(WSL_WINDOWS_DIR, host, port);
11478
+ await configureBackground(WSL_WINDOWS_DIR, host, port, filter);
11474
11479
  return WSL_WINDOWS_PATH;
11475
11480
  } catch {
11476
11481
  console.log(
@@ -11480,12 +11485,30 @@ async function prepareExtensionForLoad(port) {
11480
11485
  }
11481
11486
  }
11482
11487
 
11488
+ // src/commands/netcap/resolveNetcapOutPath.ts
11489
+ import { isAbsolute, join as join37, resolve as resolve11 } from "path";
11490
+
11491
+ // src/commands/netcap/defaultCapturePath.ts
11492
+ import { homedir as homedir12 } from "os";
11493
+ import { join as join36 } from "path";
11494
+ function defaultCapturePath() {
11495
+ return join36(homedir12(), ".assist", "netcap", "capture.jsonl");
11496
+ }
11497
+
11498
+ // src/commands/netcap/resolveNetcapOutPath.ts
11499
+ function resolveNetcapOutPath(out) {
11500
+ if (!out) return defaultCapturePath();
11501
+ const dir = isAbsolute(out) ? out : resolve11(process.cwd(), out);
11502
+ return join37(dir, "capture.jsonl");
11503
+ }
11504
+
11483
11505
  // src/commands/netcap/netcap.ts
11484
11506
  async function netcap(options2) {
11485
11507
  const port = Number(options2.port);
11486
- const outPath = defaultCapturePath();
11508
+ const outPath = resolveNetcapOutPath(options2.out);
11509
+ const filter = options2.filter ?? "";
11487
11510
  await mkdir(dirname20(outPath), { recursive: true });
11488
- const extensionPath = await prepareExtensionForLoad(port);
11511
+ const extensionPath = await prepareExtensionForLoad(port, filter);
11489
11512
  let count6 = 0;
11490
11513
  const handler = createNetcapHandler({
11491
11514
  outPath,
@@ -11504,24 +11527,480 @@ async function netcap(options2) {
11504
11527
  chalk124.bold(`netcap receiver listening on http://127.0.0.1:${port}`)
11505
11528
  );
11506
11529
  console.log(chalk124.dim(`appending captures to ${outPath}`));
11530
+ if (filter)
11531
+ console.log(chalk124.dim(`forwarding only URLs matching "${filter}"`));
11507
11532
  console.log(chalk124.dim(`load the unpacked extension from ${extensionPath}`));
11508
11533
  console.log(chalk124.dim("press Ctrl-C to stop"));
11509
11534
  });
11510
11535
  process.on("SIGINT", () => {
11511
11536
  server.close();
11537
+ console.log(
11538
+ chalk124.bold(
11539
+ `
11540
+ netcap stopped \u2014 captured ${count6} ${count6 === 1 ? "entry" : "entries"} to ${outPath}`
11541
+ )
11542
+ );
11512
11543
  process.exit(0);
11513
11544
  });
11514
11545
  }
11515
11546
 
11547
+ // src/commands/netcap/netcapExtract.ts
11548
+ import { writeFileSync as writeFileSync26 } from "fs";
11549
+ import { join as join38 } from "path";
11550
+ import chalk125 from "chalk";
11551
+
11552
+ // src/commands/netcap/extractPostsFromCapture.ts
11553
+ import { readFileSync as readFileSync30 } from "fs";
11554
+
11555
+ // src/commands/netcap/parseRscRows.ts
11556
+ var isRscRef = (v) => typeof v === "string" && /^\$[0-9a-fL@]/.test(v);
11557
+ function parseRscRows(flight) {
11558
+ const rows = {};
11559
+ for (const line of flight.split("\n")) {
11560
+ const m = line.match(/^([0-9a-f]+):(.*)$/s);
11561
+ if (!m) continue;
11562
+ let payload = m[2];
11563
+ if (payload && !/^[[{"\d\-tfn]/.test(payload[0]))
11564
+ payload = payload.slice(1);
11565
+ try {
11566
+ rows[m[1]] = JSON.parse(payload);
11567
+ } catch {
11568
+ rows[m[1]] = m[2];
11569
+ }
11570
+ }
11571
+ return rows;
11572
+ }
11573
+ function makeRscResolver(rows) {
11574
+ return (ref) => {
11575
+ const [id2, ...path57] = ref.slice(1).replace(/^[L@]/, "").split(":");
11576
+ let v = rows[id2];
11577
+ for (const key of path57) {
11578
+ if (v == null || typeof v !== "object") return void 0;
11579
+ v = v[key];
11580
+ }
11581
+ return v;
11582
+ };
11583
+ }
11584
+
11585
+ // src/commands/netcap/collectRscText.ts
11586
+ function isVisibleText(t) {
11587
+ if (/^(proto\.|com\.linkedin|react\.)/.test(t)) return false;
11588
+ if (!/\s/.test(t.trim())) return false;
11589
+ return /[a-zA-Z]{3,}/.test(t);
11590
+ }
11591
+ var isHashtag = (t) => /^#[A-Za-z0-9_]+$/.test(t);
11592
+ function collectRscText(v, resolve16, sink, seen) {
11593
+ if (v == null) return;
11594
+ if (typeof v === "string") {
11595
+ if (isRscRef(v)) {
11596
+ if (!seen.has(v)) {
11597
+ seen.add(v);
11598
+ collectRscText(resolve16(v), resolve16, sink, seen);
11599
+ }
11600
+ } else if (isHashtag(v)) sink.hashtags.push(v);
11601
+ else if (isVisibleText(v)) sink.text.push(v);
11602
+ return;
11603
+ }
11604
+ if (Array.isArray(v)) {
11605
+ for (const x of v) collectRscText(x, resolve16, sink, seen);
11606
+ return;
11607
+ }
11608
+ if (typeof v === "object") {
11609
+ for (const val of Object.values(v)) {
11610
+ collectRscText(val, resolve16, sink, seen);
11611
+ }
11612
+ }
11613
+ }
11614
+
11615
+ // src/commands/netcap/buildMentionMap.ts
11616
+ function asObject(v) {
11617
+ return v != null && typeof v === "object" && !Array.isArray(v) ? v : void 0;
11618
+ }
11619
+ function profileActionUrl(o) {
11620
+ const actions = asObject(o.action)?.actions;
11621
+ if (!Array.isArray(actions)) return void 0;
11622
+ for (const a of actions) {
11623
+ const url = asObject(asObject(asObject(a)?.value)?.content)?.url;
11624
+ const target = asObject(url)?.url;
11625
+ if (typeof target === "string" && /\/in\//.test(target)) return target;
11626
+ }
11627
+ return void 0;
11628
+ }
11629
+ var slugFromProfileUrl = (url) => url.match(/\/in\/([^/?]+)/)?.[1];
11630
+ function visitObjects(root, fn) {
11631
+ const stack = [root];
11632
+ while (stack.length) {
11633
+ const v = stack.pop();
11634
+ if (v == null || typeof v !== "object") continue;
11635
+ const o = asObject(v);
11636
+ if (o) fn(o);
11637
+ for (const child of Array.isArray(v) ? v : Object.values(v)) {
11638
+ if (child && typeof child === "object") stack.push(child);
11639
+ }
11640
+ }
11641
+ }
11642
+ function buildMentionMap(rows, resolve16) {
11643
+ const map = /* @__PURE__ */ new Map();
11644
+ visitObjects(rows, (o) => {
11645
+ const url = profileActionUrl(o);
11646
+ if (!url || o.children == null) return;
11647
+ const slug = slugFromProfileUrl(url);
11648
+ if (!slug || map.has(slug)) return;
11649
+ const sink = { text: [], hashtags: [] };
11650
+ collectRscText(o.children, resolve16, sink, /* @__PURE__ */ new Set());
11651
+ const name = sink.text.join(" ").replace(/\s+/g, " ").trim();
11652
+ map.set(slug, name ? { slug, name, url } : { slug, url });
11653
+ });
11654
+ return map;
11655
+ }
11656
+
11657
+ // src/commands/netcap/activityUrnDate.ts
11658
+ function activityUrnDate(urn) {
11659
+ if (!urn) return void 0;
11660
+ const id2 = urn.split(":").pop();
11661
+ if (!id2 || !/^\d+$/.test(id2)) return void 0;
11662
+ return new Date(Number(BigInt(id2) >> 22n)).toISOString();
11663
+ }
11664
+
11665
+ // src/commands/netcap/dedupeLinks.ts
11666
+ function decodeSafetyLink(url) {
11667
+ try {
11668
+ const wrapped = new URL(url).searchParams.get("url");
11669
+ return wrapped ? decodeURIComponent(wrapped) : url;
11670
+ } catch {
11671
+ return url;
11672
+ }
11673
+ }
11674
+ function dedupeLinks(links2) {
11675
+ return [
11676
+ ...new Set(
11677
+ links2.map((l) => /\/safety\/go\//.test(l) ? decodeSafetyLink(l) : l)
11678
+ )
11679
+ ];
11680
+ }
11681
+
11682
+ // src/commands/netcap/linkifyMentions.ts
11683
+ function linkifyMentions(text5, mentions) {
11684
+ let out = text5;
11685
+ for (const m of mentions) {
11686
+ if (m.name && out.includes(m.name)) {
11687
+ out = out.replace(m.name, `[${m.name}](${m.url})`);
11688
+ }
11689
+ }
11690
+ return out;
11691
+ }
11692
+
11693
+ // src/commands/netcap/buildPost.ts
11694
+ var profileUrl = (slug) => `https://www.linkedin.com/in/${slug}/`;
11695
+ var joinText = (parts) => parts.join(" ").replace(/\s+/g, " ").replace(/\s+([.,!?])/g, "$1").trim();
11696
+ function resolveMentions(raw, mentionMap, author) {
11697
+ const slugs = /* @__PURE__ */ new Set();
11698
+ for (const url of raw.profileUrls) {
11699
+ const slug = slugFromProfileUrl(url);
11700
+ if (slug && slug !== author) slugs.add(slug);
11701
+ }
11702
+ return [...slugs].map(
11703
+ (slug) => mentionMap.get(slug) ?? { slug, url: profileUrl(slug) }
11704
+ );
11705
+ }
11706
+ function resolveAuthor(mentionMap, author) {
11707
+ if (!author) return void 0;
11708
+ return mentionMap.get(author) ?? { slug: author, url: profileUrl(author) };
11709
+ }
11710
+ function buildPost(raw, mentionMap, author) {
11711
+ const text5 = joinText(raw.text);
11712
+ if (!text5) return void 0;
11713
+ const mentions = resolveMentions(raw, mentionMap, author);
11714
+ const relatedPosts = [...new Set(raw.related)];
11715
+ return {
11716
+ text: text5,
11717
+ markdown: linkifyMentions(text5, mentions),
11718
+ mentions,
11719
+ hashtags: [...new Set(raw.hashtags)],
11720
+ links: dedupeLinks(raw.links),
11721
+ relatedPosts,
11722
+ activityUrn: relatedPosts[0],
11723
+ postedAt: activityUrnDate(relatedPosts[0]),
11724
+ author: resolveAuthor(mentionMap, author)
11725
+ };
11726
+ }
11727
+
11728
+ // src/commands/netcap/walkPostRow.ts
11729
+ var isCommentary = (o) => asObject(o.viewTrackingSpecs)?.viewName === "feed-commentary";
11730
+ function walkPostRow(v, resolve16, raw) {
11731
+ if (v == null || typeof v !== "object") return;
11732
+ if (Array.isArray(v)) {
11733
+ for (const x of v) walkPostRow(x, resolve16, raw);
11734
+ return;
11735
+ }
11736
+ const o = v;
11737
+ if (o.$type === "proto.sdui.actions.core.NavigateToUrl" && typeof o.url === "string") {
11738
+ if (/\/in\//.test(o.url)) raw.profileUrls.push(o.url);
11739
+ else raw.links.push(o.url);
11740
+ }
11741
+ if (o.$type === "proto.sdui.actions.requests.RequestedArguments") {
11742
+ const a = JSON.stringify(o).match(/urn:li:activity:\d+/);
11743
+ if (a) raw.related.push(a[0]);
11744
+ }
11745
+ if (isCommentary(o)) {
11746
+ const sink = { text: raw.text, hashtags: raw.hashtags };
11747
+ collectRscText(o.children, resolve16, sink, /* @__PURE__ */ new Set());
11748
+ }
11749
+ for (const val of Object.values(o)) walkPostRow(val, resolve16, raw);
11750
+ }
11751
+
11752
+ // src/commands/netcap/extractLinkedInPosts.ts
11753
+ function findAuthorSlug(flight) {
11754
+ return flight.match(/profile-activity-load-([A-Za-z0-9-]+)/)?.[1];
11755
+ }
11756
+ function findCommentaryRows(rows) {
11757
+ return Object.keys(rows).filter(
11758
+ (id2) => /"componentkey":"feed-commentary_/.test(JSON.stringify(rows[id2]))
11759
+ );
11760
+ }
11761
+ function extractLinkedInPosts(flight, author = findAuthorSlug(flight)) {
11762
+ const rows = parseRscRows(flight);
11763
+ const resolve16 = makeRscResolver(rows);
11764
+ const mentionMap = buildMentionMap(rows, resolve16);
11765
+ const posts = [];
11766
+ for (const id2 of findCommentaryRows(rows)) {
11767
+ const raw = {
11768
+ text: [],
11769
+ hashtags: [],
11770
+ profileUrls: [],
11771
+ links: [],
11772
+ related: []
11773
+ };
11774
+ walkPostRow(rows[id2], resolve16, raw);
11775
+ const post = buildPost(raw, mentionMap, author);
11776
+ if (post) posts.push(post);
11777
+ }
11778
+ return posts;
11779
+ }
11780
+
11781
+ // src/commands/netcap/collectVoyagerAttributes.ts
11782
+ function attributeDetails(update3) {
11783
+ const attrs = asObject(asObject(update3.commentary)?.text)?.attributesV2;
11784
+ if (!Array.isArray(attrs)) return [];
11785
+ return attrs.map((a) => asObject(asObject(a)?.detailData)).filter((d) => d !== void 0);
11786
+ }
11787
+ function mentionsFrom(details, profiles, authorSlug) {
11788
+ const bySlug = /* @__PURE__ */ new Map();
11789
+ for (const detail of details) {
11790
+ const urn = detail["*profileMention"];
11791
+ if (typeof urn !== "string") continue;
11792
+ const mention = profiles.get(urn);
11793
+ if (mention && mention.slug !== authorSlug)
11794
+ bySlug.set(mention.slug, mention);
11795
+ }
11796
+ return [...bySlug.values()];
11797
+ }
11798
+ function hashtagsFrom(details) {
11799
+ const tags = [];
11800
+ for (const detail of details) {
11801
+ const urn = detail["*hashtag"];
11802
+ const tag = typeof urn === "string" ? urn.match(/\(([^,]+),/)?.[1] : void 0;
11803
+ if (tag) tags.push(`#${tag}`);
11804
+ }
11805
+ return [...new Set(tags)];
11806
+ }
11807
+ function linksFrom(details) {
11808
+ const links2 = details.map((detail) => asObject(detail.textLink)?.url).filter((url) => typeof url === "string");
11809
+ return dedupeLinks(links2);
11810
+ }
11811
+ function collectVoyagerAttributes(update3, profiles, authorSlug) {
11812
+ const details = attributeDetails(update3);
11813
+ return {
11814
+ mentions: mentionsFrom(details, profiles, authorSlug),
11815
+ hashtags: hashtagsFrom(details),
11816
+ links: linksFrom(details)
11817
+ };
11818
+ }
11819
+
11820
+ // src/commands/netcap/resolveVoyagerAuthor.ts
11821
+ var profileUrl2 = (slug) => `https://www.linkedin.com/in/${slug}/`;
11822
+ function profileSlug(actor) {
11823
+ const target = asObject(actor?.navigationContext)?.actionTarget;
11824
+ if (typeof target !== "string") return void 0;
11825
+ return target.match(/\/in\/([^/?]+)/)?.[1];
11826
+ }
11827
+ function resolveVoyagerAuthor(update3) {
11828
+ const actor = asObject(update3.actor);
11829
+ const slug = profileSlug(actor);
11830
+ if (!slug) return void 0;
11831
+ const name = asObject(actor?.name)?.text;
11832
+ const mention = { slug, url: profileUrl2(slug) };
11833
+ if (typeof name === "string" && name.trim()) mention.name = name.trim();
11834
+ return mention;
11835
+ }
11836
+
11837
+ // src/commands/netcap/buildVoyagerPost.ts
11838
+ function commentaryText(update3) {
11839
+ const body = asObject(asObject(update3.commentary)?.text)?.text;
11840
+ return typeof body === "string" && body.trim() ? body.trim() : void 0;
11841
+ }
11842
+ function activityUrnOf(update3) {
11843
+ const urn = asObject(update3.metadata)?.backendUrn;
11844
+ return typeof urn === "string" ? urn : void 0;
11845
+ }
11846
+ function buildVoyagerPost(update3, profiles) {
11847
+ const text5 = commentaryText(update3);
11848
+ if (!text5) return void 0;
11849
+ const author = resolveVoyagerAuthor(update3);
11850
+ const { mentions, hashtags, links: links2 } = collectVoyagerAttributes(
11851
+ update3,
11852
+ profiles,
11853
+ author?.slug
11854
+ );
11855
+ const activityUrn = activityUrnOf(update3);
11856
+ return {
11857
+ text: text5,
11858
+ markdown: linkifyMentions(text5, mentions),
11859
+ mentions,
11860
+ hashtags,
11861
+ links: links2,
11862
+ relatedPosts: activityUrn ? [activityUrn] : [],
11863
+ activityUrn,
11864
+ postedAt: activityUrnDate(activityUrn),
11865
+ author
11866
+ };
11867
+ }
11868
+
11869
+ // src/commands/netcap/voyagerProfileMentions.ts
11870
+ var PROFILE_TYPE = "com.linkedin.voyager.dash.identity.profile.Profile";
11871
+ var profileUrl3 = (slug) => `https://www.linkedin.com/in/${slug}/`;
11872
+ function profileName(o) {
11873
+ return [o.firstName, o.lastName].filter((s) => typeof s === "string" && s.length > 0).join(" ");
11874
+ }
11875
+ function voyagerProfileMentions(included) {
11876
+ const map = /* @__PURE__ */ new Map();
11877
+ for (const o of included) {
11878
+ const urn = o.entityUrn;
11879
+ const slug = o.publicIdentifier;
11880
+ if (o.$type !== PROFILE_TYPE) continue;
11881
+ if (typeof urn !== "string" || typeof slug !== "string") continue;
11882
+ const name = profileName(o);
11883
+ const url = profileUrl3(slug);
11884
+ map.set(urn, name ? { slug, name, url } : { slug, url });
11885
+ }
11886
+ return map;
11887
+ }
11888
+
11889
+ // src/commands/netcap/extractVoyagerPosts.ts
11890
+ function includedObjects(root) {
11891
+ const included = root.included;
11892
+ if (!Array.isArray(included)) return [];
11893
+ return included.map((item) => asObject(item)).filter((o) => o !== void 0);
11894
+ }
11895
+ function elementUrns(root) {
11896
+ const data = asObject(asObject(root.data)?.data);
11897
+ if (!data) return [];
11898
+ for (const value of Object.values(data)) {
11899
+ const elements = asObject(value)?.["*elements"];
11900
+ if (Array.isArray(elements))
11901
+ return elements.filter((e) => typeof e === "string");
11902
+ }
11903
+ return [];
11904
+ }
11905
+ function extractVoyagerPosts(body) {
11906
+ let root;
11907
+ try {
11908
+ root = JSON.parse(body);
11909
+ } catch {
11910
+ return [];
11911
+ }
11912
+ const rootObj = asObject(root);
11913
+ if (!rootObj) return [];
11914
+ const included = includedObjects(rootObj);
11915
+ const byUrn = /* @__PURE__ */ new Map();
11916
+ for (const o of included) {
11917
+ if (typeof o.entityUrn === "string") byUrn.set(o.entityUrn, o);
11918
+ }
11919
+ const profiles = voyagerProfileMentions(included);
11920
+ const posts = [];
11921
+ for (const ref of elementUrns(rootObj)) {
11922
+ const update3 = byUrn.get(ref);
11923
+ if (!update3) continue;
11924
+ const post = buildVoyagerPost(update3, profiles);
11925
+ if (post) posts.push(post);
11926
+ }
11927
+ return posts;
11928
+ }
11929
+
11930
+ // src/commands/netcap/extractPostsFromCapture.ts
11931
+ function captureEntries(captureFile) {
11932
+ const lines = readFileSync30(captureFile, "utf8").split("\n").filter(Boolean);
11933
+ const entries = [];
11934
+ for (const line of lines) {
11935
+ let entry;
11936
+ try {
11937
+ entry = JSON.parse(line);
11938
+ } catch {
11939
+ continue;
11940
+ }
11941
+ if (typeof entry.url !== "string" || typeof entry.responseBody !== "string")
11942
+ continue;
11943
+ entries.push({ url: entry.url, responseBody: entry.responseBody });
11944
+ }
11945
+ return entries;
11946
+ }
11947
+ function dedupeByActivity(posts) {
11948
+ const byUrn = /* @__PURE__ */ new Map();
11949
+ const noUrn = [];
11950
+ for (const post of posts) {
11951
+ if (!post.activityUrn) {
11952
+ noUrn.push(post);
11953
+ continue;
11954
+ }
11955
+ const existing = byUrn.get(post.activityUrn);
11956
+ if (!existing || post.text.length > existing.text.length)
11957
+ byUrn.set(post.activityUrn, post);
11958
+ }
11959
+ return [...byUrn.values(), ...noUrn];
11960
+ }
11961
+ function extractPostsFromCapture(captureFile) {
11962
+ const entries = captureEntries(captureFile);
11963
+ const rscBodies = entries.filter((e) => /rsc-action/.test(e.url)).map((e) => e.responseBody);
11964
+ const voyagerBodies = entries.filter((e) => /voyagerFeedDashProfileUpdates/.test(e.url)).map((e) => e.responseBody);
11965
+ const author = rscBodies.map(findAuthorSlug).find(Boolean);
11966
+ const all = [
11967
+ ...rscBodies.flatMap((body) => extractLinkedInPosts(body, author)),
11968
+ ...voyagerBodies.flatMap(extractVoyagerPosts)
11969
+ ];
11970
+ return dedupeByActivity(all);
11971
+ }
11972
+
11973
+ // src/commands/netcap/netcapExtract.ts
11974
+ function netcapExtract(file) {
11975
+ const captureFile = file ?? defaultCapturePath();
11976
+ const posts = extractPostsFromCapture(captureFile);
11977
+ const outFile = join38(captureFile, "..", "posts.json");
11978
+ writeFileSync26(outFile, `${JSON.stringify(posts, null, 2)}
11979
+ `);
11980
+ console.log(
11981
+ chalk125.green(`extracted ${posts.length} posts`),
11982
+ chalk125.dim(`-> ${outFile}`)
11983
+ );
11984
+ }
11985
+
11516
11986
  // src/commands/registerNetcap.ts
11517
11987
  function registerNetcap(program2) {
11518
- program2.command("netcap").description(
11988
+ const command = program2.command("netcap").description(
11519
11989
  "Start a local receiver that captures browser network traffic (fetch/XHR) to a JSONL file via the netcap browser extension"
11520
- ).option("-p, --port <port>", "Port to listen on", "8723").action((options2) => netcap(options2));
11990
+ ).option("-p, --port <port>", "Port to listen on", "8723").option(
11991
+ "-o, --out <dir>",
11992
+ "Directory to write the capture file into (default ~/.assist/netcap)"
11993
+ ).option(
11994
+ "-f, --filter <pattern>",
11995
+ "Only forward requests whose URL contains this substring"
11996
+ ).action((options2) => netcap(options2));
11997
+ command.command("extract [file]").description(
11998
+ "Extract LinkedIn posts (text, author, mentions, links) from a netcap capture file to posts.json"
11999
+ ).action((file) => netcapExtract(file));
11521
12000
  }
11522
12001
 
11523
12002
  // src/commands/news/add/index.ts
11524
- import chalk125 from "chalk";
12003
+ import chalk126 from "chalk";
11525
12004
  import enquirer8 from "enquirer";
11526
12005
  async function add2(url) {
11527
12006
  if (!url) {
@@ -11543,10 +12022,10 @@ async function add2(url) {
11543
12022
  const { orm } = await getReady();
11544
12023
  const added = await addFeed(orm, url);
11545
12024
  if (!added) {
11546
- console.log(chalk125.yellow("Feed already exists"));
12025
+ console.log(chalk126.yellow("Feed already exists"));
11547
12026
  return;
11548
12027
  }
11549
- console.log(chalk125.green(`Added feed: ${url}`));
12028
+ console.log(chalk126.green(`Added feed: ${url}`));
11550
12029
  }
11551
12030
 
11552
12031
  // src/commands/registerNews.ts
@@ -11556,7 +12035,7 @@ function registerNews(program2) {
11556
12035
  }
11557
12036
 
11558
12037
  // src/commands/prompts/printPromptsTable.ts
11559
- import chalk126 from "chalk";
12038
+ import chalk127 from "chalk";
11560
12039
  function truncate(str, max) {
11561
12040
  if (str.length <= max) return str;
11562
12041
  return `${str.slice(0, max - 1)}\u2026`;
@@ -11574,14 +12053,14 @@ function printPromptsTable(rows) {
11574
12053
  "Command".padEnd(commandWidth),
11575
12054
  "Repos"
11576
12055
  ].join(" ");
11577
- console.log(chalk126.dim(header));
11578
- console.log(chalk126.dim("-".repeat(header.length)));
12056
+ console.log(chalk127.dim(header));
12057
+ console.log(chalk127.dim("-".repeat(header.length)));
11579
12058
  for (const row of rows) {
11580
12059
  const count6 = String(row.count).padStart(countWidth);
11581
12060
  const tool = row.tool.padEnd(toolWidth);
11582
12061
  const command = truncate(row.command, 60).padEnd(commandWidth);
11583
12062
  console.log(
11584
- `${chalk126.yellow(count6)} ${tool} ${command} ${chalk126.dim(row.repos)}`
12063
+ `${chalk127.yellow(count6)} ${tool} ${command} ${chalk127.dim(row.repos)}`
11585
12064
  );
11586
12065
  }
11587
12066
  }
@@ -11725,15 +12204,15 @@ function postComment(vars) {
11725
12204
  const stdout = startLine === void 0 ? runGhGraphql(MUTATION_SINGLE, base) : runGhGraphql(MUTATION_MULTI, { ...base, startLine });
11726
12205
  assertThreadCreated(stdout);
11727
12206
  }
11728
- function comment2(path58, line, body, startLine) {
12207
+ function comment2(path57, line, body, startLine) {
11729
12208
  validateBody(body);
11730
12209
  validateLine(line);
11731
12210
  if (startLine !== void 0) validateLine(startLine);
11732
12211
  try {
11733
12212
  const prId = getCurrentPrNodeId();
11734
- postComment({ prId, body, path: path58, line, startLine });
12213
+ postComment({ prId, body, path: path57, line, startLine });
11735
12214
  const range = startLine !== void 0 ? `${startLine}-${line}` : `${line}`;
11736
- console.log(`Added review comment on ${path58}:${range}`);
12215
+ console.log(`Added review comment on ${path57}:${range}`);
11737
12216
  } catch (error) {
11738
12217
  if (isGhNotInstalled(error)) {
11739
12218
  console.error("Error: GitHub CLI (gh) is not installed.");
@@ -11925,27 +12404,27 @@ function edit(options2) {
11925
12404
  }
11926
12405
 
11927
12406
  // src/commands/prs/fixed.ts
11928
- import { execSync as execSync33 } from "child_process";
12407
+ import { execSync as execSync34 } from "child_process";
11929
12408
 
11930
12409
  // src/commands/prs/resolveCommentWithReply.ts
11931
- import { execSync as execSync32 } from "child_process";
11932
- import { unlinkSync as unlinkSync10, writeFileSync as writeFileSync26 } from "fs";
12410
+ import { execSync as execSync33 } from "child_process";
12411
+ import { unlinkSync as unlinkSync10, writeFileSync as writeFileSync27 } from "fs";
11933
12412
  import { tmpdir as tmpdir5 } from "os";
11934
- import { join as join38 } from "path";
12413
+ import { join as join40 } from "path";
11935
12414
 
11936
12415
  // src/commands/prs/loadCommentsCache.ts
11937
- import { existsSync as existsSync33, readFileSync as readFileSync30, unlinkSync as unlinkSync9 } from "fs";
11938
- import { join as join37 } from "path";
12416
+ import { existsSync as existsSync33, readFileSync as readFileSync31, unlinkSync as unlinkSync9 } from "fs";
12417
+ import { join as join39 } from "path";
11939
12418
  import { parse as parse2 } from "yaml";
11940
12419
  function getCachePath(prNumber) {
11941
- return join37(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
12420
+ return join39(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
11942
12421
  }
11943
12422
  function loadCommentsCache(prNumber) {
11944
12423
  const cachePath = getCachePath(prNumber);
11945
12424
  if (!existsSync33(cachePath)) {
11946
12425
  return null;
11947
12426
  }
11948
- const content = readFileSync30(cachePath, "utf8");
12427
+ const content = readFileSync31(cachePath, "utf8");
11949
12428
  return parse2(content);
11950
12429
  }
11951
12430
  function deleteCommentsCache(prNumber) {
@@ -11956,19 +12435,22 @@ function deleteCommentsCache(prNumber) {
11956
12435
  }
11957
12436
  }
11958
12437
 
11959
- // src/commands/prs/resolveCommentWithReply.ts
12438
+ // src/commands/prs/replyToComment.ts
12439
+ import { execSync as execSync32 } from "child_process";
11960
12440
  function replyToComment(org, repo, prNumber, commentId, message) {
11961
12441
  execSync32(
11962
12442
  `gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message.replace(/"/g, String.raw`\"`)}" -F in_reply_to=${commentId}`,
11963
12443
  { stdio: ["inherit", "pipe", "inherit"] }
11964
12444
  );
11965
12445
  }
12446
+
12447
+ // src/commands/prs/resolveCommentWithReply.ts
11966
12448
  function resolveThread(threadId) {
11967
12449
  const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
11968
- const queryFile = join38(tmpdir5(), `gh-mutation-${Date.now()}.graphql`);
11969
- writeFileSync26(queryFile, mutation);
12450
+ const queryFile = join40(tmpdir5(), `gh-mutation-${Date.now()}.graphql`);
12451
+ writeFileSync27(queryFile, mutation);
11970
12452
  try {
11971
- execSync32(
12453
+ execSync33(
11972
12454
  `gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
11973
12455
  { stdio: ["inherit", "pipe", "inherit"] }
11974
12456
  );
@@ -12020,7 +12502,7 @@ function resolveCommentWithReply(commentId, message) {
12020
12502
  // src/commands/prs/fixed.ts
12021
12503
  function verifySha(sha) {
12022
12504
  try {
12023
- return execSync33(`git rev-parse --verify ${sha}`, {
12505
+ return execSync34(`git rev-parse --verify ${sha}`, {
12024
12506
  encoding: "utf8"
12025
12507
  }).trim();
12026
12508
  } catch {
@@ -12034,7 +12516,7 @@ function fixed(commentId, sha) {
12034
12516
  const { org, repo } = getRepoInfo();
12035
12517
  const repoUrl = `https://github.com/${org}/${repo}`;
12036
12518
  const message = `Fixed in [${fullSha}](${repoUrl}/commit/${fullSha})`;
12037
- execSync33("git push", { stdio: "inherit" });
12519
+ execSync34("git push", { stdio: "inherit" });
12038
12520
  resolveCommentWithReply(commentId, message);
12039
12521
  } catch (error) {
12040
12522
  if (isGhNotInstalled(error)) {
@@ -12047,21 +12529,21 @@ function fixed(commentId, sha) {
12047
12529
  }
12048
12530
 
12049
12531
  // src/commands/prs/listComments/index.ts
12050
- import { existsSync as existsSync34, mkdirSync as mkdirSync13, writeFileSync as writeFileSync28 } from "fs";
12051
- import { join as join40 } from "path";
12532
+ import { existsSync as existsSync34, mkdirSync as mkdirSync13, writeFileSync as writeFileSync29 } from "fs";
12533
+ import { join as join42 } from "path";
12052
12534
  import { stringify } from "yaml";
12053
12535
 
12054
12536
  // src/commands/prs/fetchThreadIds.ts
12055
- import { execSync as execSync34 } from "child_process";
12056
- import { unlinkSync as unlinkSync11, writeFileSync as writeFileSync27 } from "fs";
12537
+ import { execSync as execSync35 } from "child_process";
12538
+ import { unlinkSync as unlinkSync11, writeFileSync as writeFileSync28 } from "fs";
12057
12539
  import { tmpdir as tmpdir6 } from "os";
12058
- import { join as join39 } from "path";
12540
+ import { join as join41 } from "path";
12059
12541
  var THREAD_QUERY = `query($owner: String!, $repo: String!, $prNumber: Int!) { repository(owner: $owner, name: $repo) { pullRequest(number: $prNumber) { reviewThreads(first: 100) { nodes { id isResolved comments(first: 100) { nodes { databaseId } } } } } } }`;
12060
12542
  function fetchThreadIds(org, repo, prNumber) {
12061
- const queryFile = join39(tmpdir6(), `gh-query-${Date.now()}.graphql`);
12062
- writeFileSync27(queryFile, THREAD_QUERY);
12543
+ const queryFile = join41(tmpdir6(), `gh-query-${Date.now()}.graphql`);
12544
+ writeFileSync28(queryFile, THREAD_QUERY);
12063
12545
  try {
12064
- const result = execSync34(
12546
+ const result = execSync35(
12065
12547
  `gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
12066
12548
  { encoding: "utf8" }
12067
12549
  );
@@ -12083,9 +12565,9 @@ function fetchThreadIds(org, repo, prNumber) {
12083
12565
  }
12084
12566
 
12085
12567
  // src/commands/prs/listComments/fetchReviewComments.ts
12086
- import { execSync as execSync35 } from "child_process";
12568
+ import { execSync as execSync36 } from "child_process";
12087
12569
  function fetchJson(endpoint) {
12088
- const result = execSync35(`gh api --paginate ${endpoint}`, {
12570
+ const result = execSync36(`gh api --paginate ${endpoint}`, {
12089
12571
  encoding: "utf8"
12090
12572
  });
12091
12573
  if (!result.trim()) return [];
@@ -12127,20 +12609,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
12127
12609
  }
12128
12610
 
12129
12611
  // src/commands/prs/listComments/printComments.ts
12130
- import chalk127 from "chalk";
12612
+ import chalk128 from "chalk";
12131
12613
  function formatForHuman(comment3) {
12132
12614
  if (comment3.type === "review") {
12133
- const stateColor = comment3.state === "APPROVED" ? chalk127.green : comment3.state === "CHANGES_REQUESTED" ? chalk127.red : chalk127.yellow;
12615
+ const stateColor = comment3.state === "APPROVED" ? chalk128.green : comment3.state === "CHANGES_REQUESTED" ? chalk128.red : chalk128.yellow;
12134
12616
  return [
12135
- `${chalk127.cyan("Review")} by ${chalk127.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
12617
+ `${chalk128.cyan("Review")} by ${chalk128.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
12136
12618
  comment3.body,
12137
12619
  ""
12138
12620
  ].join("\n");
12139
12621
  }
12140
12622
  const location = comment3.line ? `:${comment3.line}` : "";
12141
12623
  return [
12142
- `${chalk127.cyan("Line comment")} by ${chalk127.bold(comment3.user)} on ${chalk127.dim(`${comment3.path}${location}`)}`,
12143
- chalk127.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
12624
+ `${chalk128.cyan("Line comment")} by ${chalk128.bold(comment3.user)} on ${chalk128.dim(`${comment3.path}${location}`)}`,
12625
+ chalk128.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
12144
12626
  comment3.body,
12145
12627
  ""
12146
12628
  ].join("\n");
@@ -12172,7 +12654,7 @@ function printComments2(result) {
12172
12654
 
12173
12655
  // src/commands/prs/listComments/index.ts
12174
12656
  function writeCommentsCache(prNumber, comments3) {
12175
- const assistDir = join40(process.cwd(), ".assist");
12657
+ const assistDir = join42(process.cwd(), ".assist");
12176
12658
  if (!existsSync34(assistDir)) {
12177
12659
  mkdirSync13(assistDir, { recursive: true });
12178
12660
  }
@@ -12181,8 +12663,8 @@ function writeCommentsCache(prNumber, comments3) {
12181
12663
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
12182
12664
  comments: comments3
12183
12665
  };
12184
- const cachePath = join40(assistDir, `pr-${prNumber}-comments.yaml`);
12185
- writeFileSync28(cachePath, stringify(cacheData));
12666
+ const cachePath = join42(assistDir, `pr-${prNumber}-comments.yaml`);
12667
+ writeFileSync29(cachePath, stringify(cacheData));
12186
12668
  }
12187
12669
  function handleKnownErrors(error) {
12188
12670
  if (isGhNotInstalled(error)) {
@@ -12214,7 +12696,7 @@ async function listComments() {
12214
12696
  ];
12215
12697
  updateCache(prNumber, allComments);
12216
12698
  const hasLineComments = allComments.some((c) => c.type === "line");
12217
- const cachePath = hasLineComments ? join40(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`) : null;
12699
+ const cachePath = hasLineComments ? join42(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`) : null;
12218
12700
  return { comments: allComments, cachePath };
12219
12701
  } catch (error) {
12220
12702
  const handled = handleKnownErrors(error);
@@ -12224,19 +12706,19 @@ async function listComments() {
12224
12706
  }
12225
12707
 
12226
12708
  // src/commands/prs/prs/index.ts
12227
- import { execSync as execSync36 } from "child_process";
12709
+ import { execSync as execSync37 } from "child_process";
12228
12710
 
12229
12711
  // src/commands/prs/prs/displayPaginated/index.ts
12230
12712
  import enquirer9 from "enquirer";
12231
12713
 
12232
12714
  // src/commands/prs/prs/displayPaginated/printPr.ts
12233
- import chalk128 from "chalk";
12715
+ import chalk129 from "chalk";
12234
12716
  var STATUS_MAP = {
12235
- MERGED: (pr) => pr.mergedAt ? { label: chalk128.magenta("merged"), date: pr.mergedAt } : null,
12236
- CLOSED: (pr) => pr.closedAt ? { label: chalk128.red("closed"), date: pr.closedAt } : null
12717
+ MERGED: (pr) => pr.mergedAt ? { label: chalk129.magenta("merged"), date: pr.mergedAt } : null,
12718
+ CLOSED: (pr) => pr.closedAt ? { label: chalk129.red("closed"), date: pr.closedAt } : null
12237
12719
  };
12238
12720
  function defaultStatus(pr) {
12239
- return { label: chalk128.green("opened"), date: pr.createdAt };
12721
+ return { label: chalk129.green("opened"), date: pr.createdAt };
12240
12722
  }
12241
12723
  function getStatus2(pr) {
12242
12724
  return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
@@ -12245,11 +12727,11 @@ function formatDate(dateStr) {
12245
12727
  return new Date(dateStr).toISOString().split("T")[0];
12246
12728
  }
12247
12729
  function formatPrHeader(pr, status2) {
12248
- return `${chalk128.cyan(`#${pr.number}`)} ${pr.title} ${chalk128.dim(`(${pr.author.login},`)} ${status2.label} ${chalk128.dim(`${formatDate(status2.date)})`)}`;
12730
+ return `${chalk129.cyan(`#${pr.number}`)} ${pr.title} ${chalk129.dim(`(${pr.author.login},`)} ${status2.label} ${chalk129.dim(`${formatDate(status2.date)})`)}`;
12249
12731
  }
12250
12732
  function logPrDetails(pr) {
12251
12733
  console.log(
12252
- chalk128.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
12734
+ chalk129.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
12253
12735
  );
12254
12736
  console.log();
12255
12737
  }
@@ -12331,7 +12813,7 @@ async function prs(options2) {
12331
12813
  const state = options2.open ? "open" : options2.closed ? "closed" : "all";
12332
12814
  try {
12333
12815
  const { org, repo } = getRepoInfo();
12334
- const result = execSync36(
12816
+ const result = execSync37(
12335
12817
  `gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100 -R ${org}/${repo}`,
12336
12818
  { encoding: "utf8" }
12337
12819
  );
@@ -12354,7 +12836,7 @@ async function prs(options2) {
12354
12836
  }
12355
12837
 
12356
12838
  // src/commands/prs/raise.ts
12357
- import { execSync as execSync37 } from "child_process";
12839
+ import { execSync as execSync38 } from "child_process";
12358
12840
 
12359
12841
  // src/commands/prs/buildCreateArgs.ts
12360
12842
  function buildCreateArgs(title, body, options2) {
@@ -12414,14 +12896,39 @@ function raise(options2) {
12414
12896
  `--body ${shellQuote(body)}`
12415
12897
  ] : buildCreateArgs(options2.title, body, options2);
12416
12898
  try {
12417
- execSync37(args.join(" "), { stdio: "inherit" });
12899
+ execSync38(args.join(" "), { stdio: "inherit" });
12418
12900
  } catch {
12419
12901
  process.exit(1);
12420
12902
  }
12421
12903
  }
12422
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
+
12423
12930
  // src/commands/prs/wontfix.ts
12424
- import { execSync as execSync38 } from "child_process";
12931
+ import { execSync as execSync39 } from "child_process";
12425
12932
  function validateReason(reason) {
12426
12933
  const lowerReason = reason.toLowerCase();
12427
12934
  if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
@@ -12438,7 +12945,7 @@ function validateShaReferences(reason) {
12438
12945
  const invalidShas = [];
12439
12946
  for (const sha of shas) {
12440
12947
  try {
12441
- execSync38(`git cat-file -t ${sha}`, { stdio: "pipe" });
12948
+ execSync39(`git cat-file -t ${sha}`, { stdio: "pipe" });
12442
12949
  } catch {
12443
12950
  invalidShas.push(sha);
12444
12951
  }
@@ -12522,16 +13029,19 @@ function registerPrs(program2) {
12522
13029
  prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason) => {
12523
13030
  wontfix(Number.parseInt(commentId, 10), reason);
12524
13031
  });
12525
- prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path58, line, body) => {
12526
- 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);
12527
13037
  });
12528
13038
  }
12529
13039
 
12530
13040
  // src/commands/ravendb/ravendbAuth.ts
12531
- import chalk134 from "chalk";
13041
+ import chalk135 from "chalk";
12532
13042
 
12533
13043
  // src/shared/createConnectionAuth.ts
12534
- import chalk129 from "chalk";
13044
+ import chalk130 from "chalk";
12535
13045
  function listConnections(connections, format2) {
12536
13046
  if (connections.length === 0) {
12537
13047
  console.log("No connections configured.");
@@ -12544,7 +13054,7 @@ function listConnections(connections, format2) {
12544
13054
  function removeConnection(connections, name, save) {
12545
13055
  const filtered = connections.filter((c) => c.name !== name);
12546
13056
  if (filtered.length === connections.length) {
12547
- console.error(chalk129.red(`Connection "${name}" not found.`));
13057
+ console.error(chalk130.red(`Connection "${name}" not found.`));
12548
13058
  process.exit(1);
12549
13059
  }
12550
13060
  save(filtered);
@@ -12590,17 +13100,17 @@ function saveConnections(connections) {
12590
13100
  }
12591
13101
 
12592
13102
  // src/commands/ravendb/promptConnection.ts
12593
- import chalk132 from "chalk";
13103
+ import chalk133 from "chalk";
12594
13104
 
12595
13105
  // src/commands/ravendb/selectOpSecret.ts
12596
- import chalk131 from "chalk";
13106
+ import chalk132 from "chalk";
12597
13107
  import Enquirer2 from "enquirer";
12598
13108
 
12599
13109
  // src/commands/ravendb/searchItems.ts
12600
- import { execSync as execSync39 } from "child_process";
12601
- import chalk130 from "chalk";
13110
+ import { execSync as execSync40 } from "child_process";
13111
+ import chalk131 from "chalk";
12602
13112
  function opExec(args) {
12603
- return execSync39(`op ${args}`, {
13113
+ return execSync40(`op ${args}`, {
12604
13114
  encoding: "utf8",
12605
13115
  stdio: ["pipe", "pipe", "pipe"]
12606
13116
  }).trim();
@@ -12611,7 +13121,7 @@ function searchItems(search2) {
12611
13121
  items2 = JSON.parse(opExec("item list --format=json"));
12612
13122
  } catch {
12613
13123
  console.error(
12614
- chalk130.red(
13124
+ chalk131.red(
12615
13125
  "Failed to search 1Password. Ensure the CLI is installed and you are signed in."
12616
13126
  )
12617
13127
  );
@@ -12625,7 +13135,7 @@ function getItemFields(itemId) {
12625
13135
  const item = JSON.parse(opExec(`item get "${itemId}" --format=json`));
12626
13136
  return item.fields.filter((f) => f.reference && f.label);
12627
13137
  } catch {
12628
- console.error(chalk130.red("Failed to get item details from 1Password."));
13138
+ console.error(chalk131.red("Failed to get item details from 1Password."));
12629
13139
  process.exit(1);
12630
13140
  }
12631
13141
  }
@@ -12644,7 +13154,7 @@ async function selectOpSecret(searchTerm) {
12644
13154
  }).run();
12645
13155
  const items2 = searchItems(search2);
12646
13156
  if (items2.length === 0) {
12647
- console.error(chalk131.red(`No items found matching "${search2}".`));
13157
+ console.error(chalk132.red(`No items found matching "${search2}".`));
12648
13158
  process.exit(1);
12649
13159
  }
12650
13160
  const itemId = await selectOne(
@@ -12653,7 +13163,7 @@ async function selectOpSecret(searchTerm) {
12653
13163
  );
12654
13164
  const fields = getItemFields(itemId);
12655
13165
  if (fields.length === 0) {
12656
- console.error(chalk131.red("No fields with references found on this item."));
13166
+ console.error(chalk132.red("No fields with references found on this item."));
12657
13167
  process.exit(1);
12658
13168
  }
12659
13169
  const ref = await selectOne(
@@ -12667,7 +13177,7 @@ async function selectOpSecret(searchTerm) {
12667
13177
  async function promptConnection(existingNames) {
12668
13178
  const name = await promptInput("name", "Connection name:");
12669
13179
  if (existingNames.includes(name)) {
12670
- console.error(chalk132.red(`Connection "${name}" already exists.`));
13180
+ console.error(chalk133.red(`Connection "${name}" already exists.`));
12671
13181
  process.exit(1);
12672
13182
  }
12673
13183
  const url = await promptInput(
@@ -12676,22 +13186,22 @@ async function promptConnection(existingNames) {
12676
13186
  );
12677
13187
  const database = await promptInput("database", "Database name:");
12678
13188
  if (!name || !url || !database) {
12679
- console.error(chalk132.red("All fields are required."));
13189
+ console.error(chalk133.red("All fields are required."));
12680
13190
  process.exit(1);
12681
13191
  }
12682
13192
  const apiKeyRef = await selectOpSecret();
12683
- console.log(chalk132.dim(`Using: ${apiKeyRef}`));
13193
+ console.log(chalk133.dim(`Using: ${apiKeyRef}`));
12684
13194
  return { name, url, database, apiKeyRef };
12685
13195
  }
12686
13196
 
12687
13197
  // src/commands/ravendb/ravendbSetConnection.ts
12688
- import chalk133 from "chalk";
13198
+ import chalk134 from "chalk";
12689
13199
  function ravendbSetConnection(name) {
12690
13200
  const raw = loadGlobalConfigRaw();
12691
13201
  const ravendb = raw.ravendb ?? {};
12692
13202
  const connections = ravendb.connections ?? [];
12693
13203
  if (!connections.some((c) => c.name === name)) {
12694
- console.error(chalk133.red(`Connection "${name}" not found.`));
13204
+ console.error(chalk134.red(`Connection "${name}" not found.`));
12695
13205
  console.error(
12696
13206
  `Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
12697
13207
  );
@@ -12707,16 +13217,16 @@ function ravendbSetConnection(name) {
12707
13217
  var ravendbAuth = createConnectionAuth({
12708
13218
  load: loadConnections,
12709
13219
  save: saveConnections,
12710
- format: (c) => `${chalk134.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
13220
+ format: (c) => `${chalk135.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
12711
13221
  promptNew: promptConnection,
12712
13222
  onFirst: (c) => ravendbSetConnection(c.name)
12713
13223
  });
12714
13224
 
12715
13225
  // src/commands/ravendb/ravendbCollections.ts
12716
- import chalk138 from "chalk";
13226
+ import chalk139 from "chalk";
12717
13227
 
12718
13228
  // src/commands/ravendb/ravenFetch.ts
12719
- import chalk136 from "chalk";
13229
+ import chalk137 from "chalk";
12720
13230
 
12721
13231
  // src/commands/ravendb/getAccessToken.ts
12722
13232
  var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
@@ -12752,21 +13262,21 @@ ${errorText}`
12752
13262
  }
12753
13263
 
12754
13264
  // src/commands/ravendb/resolveOpSecret.ts
12755
- import { execSync as execSync40 } from "child_process";
12756
- import chalk135 from "chalk";
13265
+ import { execSync as execSync41 } from "child_process";
13266
+ import chalk136 from "chalk";
12757
13267
  function resolveOpSecret(reference) {
12758
13268
  if (!reference.startsWith("op://")) {
12759
- console.error(chalk135.red(`Invalid secret reference: must start with op://`));
13269
+ console.error(chalk136.red(`Invalid secret reference: must start with op://`));
12760
13270
  process.exit(1);
12761
13271
  }
12762
13272
  try {
12763
- return execSync40(`op read "${reference}"`, {
13273
+ return execSync41(`op read "${reference}"`, {
12764
13274
  encoding: "utf8",
12765
13275
  stdio: ["pipe", "pipe", "pipe"]
12766
13276
  }).trim();
12767
13277
  } catch {
12768
13278
  console.error(
12769
- chalk135.red(
13279
+ chalk136.red(
12770
13280
  "Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
12771
13281
  )
12772
13282
  );
@@ -12775,10 +13285,10 @@ function resolveOpSecret(reference) {
12775
13285
  }
12776
13286
 
12777
13287
  // src/commands/ravendb/ravenFetch.ts
12778
- async function ravenFetch(connection, path58) {
13288
+ async function ravenFetch(connection, path57) {
12779
13289
  const apiKey = resolveOpSecret(connection.apiKeyRef);
12780
13290
  let accessToken = await getAccessToken(apiKey);
12781
- const url = `${connection.url}${path58}`;
13291
+ const url = `${connection.url}${path57}`;
12782
13292
  const headers = {
12783
13293
  Authorization: `Bearer ${accessToken}`,
12784
13294
  "Content-Type": "application/json"
@@ -12793,7 +13303,7 @@ async function ravenFetch(connection, path58) {
12793
13303
  if (!response.ok) {
12794
13304
  const body = await response.text();
12795
13305
  console.error(
12796
- chalk136.red(`RavenDB error: ${response.status} ${response.statusText}`)
13306
+ chalk137.red(`RavenDB error: ${response.status} ${response.statusText}`)
12797
13307
  );
12798
13308
  console.error(body.substring(0, 500));
12799
13309
  process.exit(1);
@@ -12802,7 +13312,7 @@ async function ravenFetch(connection, path58) {
12802
13312
  }
12803
13313
 
12804
13314
  // src/commands/ravendb/resolveConnection.ts
12805
- import chalk137 from "chalk";
13315
+ import chalk138 from "chalk";
12806
13316
  function loadRavendb() {
12807
13317
  const raw = loadGlobalConfigRaw();
12808
13318
  const ravendb = raw.ravendb;
@@ -12816,7 +13326,7 @@ function resolveConnection(name) {
12816
13326
  const connectionName = name ?? defaultConnection;
12817
13327
  if (!connectionName) {
12818
13328
  console.error(
12819
- chalk137.red(
13329
+ chalk138.red(
12820
13330
  "No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
12821
13331
  )
12822
13332
  );
@@ -12824,7 +13334,7 @@ function resolveConnection(name) {
12824
13334
  }
12825
13335
  const connection = connections.find((c) => c.name === connectionName);
12826
13336
  if (!connection) {
12827
- console.error(chalk137.red(`Connection "${connectionName}" not found.`));
13337
+ console.error(chalk138.red(`Connection "${connectionName}" not found.`));
12828
13338
  console.error(
12829
13339
  `Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
12830
13340
  );
@@ -12855,29 +13365,29 @@ async function ravendbCollections(connectionName) {
12855
13365
  return;
12856
13366
  }
12857
13367
  for (const c of collections) {
12858
- console.log(`${chalk138.bold(c.Name)} ${c.CountOfDocuments} docs`);
13368
+ console.log(`${chalk139.bold(c.Name)} ${c.CountOfDocuments} docs`);
12859
13369
  }
12860
13370
  }
12861
13371
 
12862
13372
  // src/commands/ravendb/ravendbQuery.ts
12863
- import chalk140 from "chalk";
13373
+ import chalk141 from "chalk";
12864
13374
 
12865
13375
  // src/commands/ravendb/fetchAllPages.ts
12866
- import chalk139 from "chalk";
13376
+ import chalk140 from "chalk";
12867
13377
 
12868
13378
  // src/commands/ravendb/buildQueryPath.ts
12869
13379
  function buildQueryPath(opts) {
12870
13380
  const db = encodeURIComponent(opts.db);
12871
- let path58;
13381
+ let path57;
12872
13382
  if (opts.collection) {
12873
- 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)}`;
12874
13384
  } else {
12875
- path58 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
13385
+ path57 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
12876
13386
  }
12877
13387
  if (opts.query) {
12878
- path58 += `&query=${encodeURIComponent(opts.query)}`;
13388
+ path57 += `&query=${encodeURIComponent(opts.query)}`;
12879
13389
  }
12880
- return path58;
13390
+ return path57;
12881
13391
  }
12882
13392
 
12883
13393
  // src/commands/ravendb/fetchAllPages.ts
@@ -12886,7 +13396,7 @@ async function fetchAllPages(connection, opts) {
12886
13396
  let start3 = 0;
12887
13397
  while (true) {
12888
13398
  const effectivePageSize = opts.limit !== void 0 ? Math.min(opts.pageSize, opts.limit - allResults.length) : opts.pageSize;
12889
- const path58 = buildQueryPath({
13399
+ const path57 = buildQueryPath({
12890
13400
  db: connection.database,
12891
13401
  collection: opts.collection,
12892
13402
  start: start3,
@@ -12894,14 +13404,14 @@ async function fetchAllPages(connection, opts) {
12894
13404
  sort: opts.sort,
12895
13405
  query: opts.query
12896
13406
  });
12897
- const data = await ravenFetch(connection, path58);
13407
+ const data = await ravenFetch(connection, path57);
12898
13408
  const results = data.Results ?? [];
12899
13409
  const totalResults = data.TotalResults ?? 0;
12900
13410
  if (results.length === 0) break;
12901
13411
  allResults.push(...results);
12902
13412
  start3 += results.length;
12903
13413
  process.stderr.write(
12904
- `\r${chalk139.dim(`Fetched ${allResults.length}/${totalResults}`)}`
13414
+ `\r${chalk140.dim(`Fetched ${allResults.length}/${totalResults}`)}`
12905
13415
  );
12906
13416
  if (start3 >= totalResults) break;
12907
13417
  if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
@@ -12916,7 +13426,7 @@ async function fetchAllPages(connection, opts) {
12916
13426
  async function ravendbQuery(connectionName, collection, options2) {
12917
13427
  const resolved = resolveArgs(connectionName, collection);
12918
13428
  if (!resolved.collection && !options2.query) {
12919
- console.error(chalk140.red("Provide a collection name or --query filter."));
13429
+ console.error(chalk141.red("Provide a collection name or --query filter."));
12920
13430
  process.exit(1);
12921
13431
  }
12922
13432
  const { collection: col } = resolved;
@@ -12954,7 +13464,7 @@ import { spawn as spawn5 } from "child_process";
12954
13464
  import * as path28 from "path";
12955
13465
 
12956
13466
  // src/commands/refactor/logViolations.ts
12957
- import chalk141 from "chalk";
13467
+ import chalk142 from "chalk";
12958
13468
  var DEFAULT_MAX_LINES = 100;
12959
13469
  function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
12960
13470
  if (violations.length === 0) {
@@ -12963,43 +13473,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
12963
13473
  }
12964
13474
  return;
12965
13475
  }
12966
- console.error(chalk141.red(`
13476
+ console.error(chalk142.red(`
12967
13477
  Refactor check failed:
12968
13478
  `));
12969
- console.error(chalk141.red(` The following files exceed ${maxLines} lines:
13479
+ console.error(chalk142.red(` The following files exceed ${maxLines} lines:
12970
13480
  `));
12971
13481
  for (const violation of violations) {
12972
- console.error(chalk141.red(` ${violation.file} (${violation.lines} lines)`));
13482
+ console.error(chalk142.red(` ${violation.file} (${violation.lines} lines)`));
12973
13483
  }
12974
13484
  console.error(
12975
- chalk141.yellow(
13485
+ chalk142.yellow(
12976
13486
  `
12977
13487
  Each file needs to be sensibly refactored, or if there is no sensible
12978
13488
  way to refactor it, ignore it with:
12979
13489
  `
12980
13490
  )
12981
13491
  );
12982
- console.error(chalk141.gray(` assist refactor ignore <file>
13492
+ console.error(chalk142.gray(` assist refactor ignore <file>
12983
13493
  `));
12984
13494
  if (process.env.CLAUDECODE) {
12985
- console.error(chalk141.cyan(`
13495
+ console.error(chalk142.cyan(`
12986
13496
  ## Extracting Code to New Files
12987
13497
  `));
12988
13498
  console.error(
12989
- chalk141.cyan(
13499
+ chalk142.cyan(
12990
13500
  ` When extracting logic from one file to another, consider where the extracted code belongs:
12991
13501
  `
12992
13502
  )
12993
13503
  );
12994
13504
  console.error(
12995
- chalk141.cyan(
13505
+ chalk142.cyan(
12996
13506
  ` 1. Keep related logic together: If the extracted code is tightly coupled to the
12997
13507
  original file's domain, create a new folder containing both the original and extracted files.
12998
13508
  `
12999
13509
  )
13000
13510
  );
13001
13511
  console.error(
13002
- chalk141.cyan(
13512
+ chalk142.cyan(
13003
13513
  ` 2. Share common utilities: If the extracted code can be reused across multiple
13004
13514
  domains, move it to a common/shared folder.
13005
13515
  `
@@ -13009,7 +13519,7 @@ Refactor check failed:
13009
13519
  }
13010
13520
 
13011
13521
  // src/commands/refactor/check/getViolations/index.ts
13012
- import { execSync as execSync41 } from "child_process";
13522
+ import { execSync as execSync42 } from "child_process";
13013
13523
  import fs20 from "fs";
13014
13524
  import { minimatch as minimatch5 } from "minimatch";
13015
13525
 
@@ -13059,7 +13569,7 @@ function getGitFiles(options2) {
13059
13569
  }
13060
13570
  const files = /* @__PURE__ */ new Set();
13061
13571
  if (options2.staged || options2.modified) {
13062
- const staged = execSync41("git diff --cached --name-only", {
13572
+ const staged = execSync42("git diff --cached --name-only", {
13063
13573
  encoding: "utf8"
13064
13574
  });
13065
13575
  for (const file of staged.trim().split("\n").filter(Boolean)) {
@@ -13067,7 +13577,7 @@ function getGitFiles(options2) {
13067
13577
  }
13068
13578
  }
13069
13579
  if (options2.unstaged || options2.modified) {
13070
- const unstaged = execSync41("git diff --name-only", { encoding: "utf8" });
13580
+ const unstaged = execSync42("git diff --name-only", { encoding: "utf8" });
13071
13581
  for (const file of unstaged.trim().split("\n").filter(Boolean)) {
13072
13582
  files.add(file);
13073
13583
  }
@@ -13155,7 +13665,7 @@ async function check(pattern2, options2) {
13155
13665
 
13156
13666
  // src/commands/refactor/extract/index.ts
13157
13667
  import path35 from "path";
13158
- import chalk144 from "chalk";
13668
+ import chalk145 from "chalk";
13159
13669
 
13160
13670
  // src/commands/refactor/extract/applyExtraction.ts
13161
13671
  import { SyntaxKind as SyntaxKind4 } from "ts-morph";
@@ -13730,23 +14240,23 @@ function buildPlan2(functionName, sourceFile, sourcePath, destPath, project) {
13730
14240
 
13731
14241
  // src/commands/refactor/extract/displayPlan.ts
13732
14242
  import path32 from "path";
13733
- import chalk142 from "chalk";
14243
+ import chalk143 from "chalk";
13734
14244
  function section(title) {
13735
14245
  return `
13736
- ${chalk142.cyan(title)}`;
14246
+ ${chalk143.cyan(title)}`;
13737
14247
  }
13738
14248
  function displayImporters(plan2, cwd) {
13739
14249
  if (plan2.importersToUpdate.length === 0) return;
13740
14250
  console.log(section("Update importers:"));
13741
14251
  for (const imp of plan2.importersToUpdate) {
13742
14252
  const rel = path32.relative(cwd, imp.file.getFilePath());
13743
- console.log(` ${chalk142.dim(rel)}: \u2192 import from "${imp.relPath}"`);
14253
+ console.log(` ${chalk143.dim(rel)}: \u2192 import from "${imp.relPath}"`);
13744
14254
  }
13745
14255
  }
13746
14256
  function displayPlan(functionName, relDest, plan2, cwd) {
13747
- console.log(chalk142.bold(`Extract: ${functionName} \u2192 ${relDest}
14257
+ console.log(chalk143.bold(`Extract: ${functionName} \u2192 ${relDest}
13748
14258
  `));
13749
- console.log(` ${chalk142.cyan("Functions to move:")}`);
14259
+ console.log(` ${chalk143.cyan("Functions to move:")}`);
13750
14260
  for (const name of plan2.extractedNames) {
13751
14261
  console.log(` ${name}`);
13752
14262
  }
@@ -13780,7 +14290,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
13780
14290
 
13781
14291
  // src/commands/refactor/extract/loadProjectFile.ts
13782
14292
  import path34 from "path";
13783
- import chalk143 from "chalk";
14293
+ import chalk144 from "chalk";
13784
14294
  import { Project as Project4 } from "ts-morph";
13785
14295
 
13786
14296
  // src/commands/refactor/extract/findTsConfig.ts
@@ -13840,7 +14350,7 @@ function loadProjectFile(file) {
13840
14350
  });
13841
14351
  const sourceFile = project.getSourceFile(sourcePath);
13842
14352
  if (!sourceFile) {
13843
- console.log(chalk143.red(`File not found in project: ${file}`));
14353
+ console.log(chalk144.red(`File not found in project: ${file}`));
13844
14354
  process.exit(1);
13845
14355
  }
13846
14356
  return { project, sourceFile };
@@ -13863,19 +14373,19 @@ async function extract(file, functionName, destination, options2 = {}) {
13863
14373
  displayPlan(functionName, relDest, plan2, cwd);
13864
14374
  if (options2.apply) {
13865
14375
  await applyExtraction(functionName, sourceFile, destPath, plan2, project);
13866
- console.log(chalk144.green("\nExtraction complete"));
14376
+ console.log(chalk145.green("\nExtraction complete"));
13867
14377
  } else {
13868
- console.log(chalk144.dim("\nDry run. Use --apply to execute."));
14378
+ console.log(chalk145.dim("\nDry run. Use --apply to execute."));
13869
14379
  }
13870
14380
  }
13871
14381
 
13872
14382
  // src/commands/refactor/ignore.ts
13873
14383
  import fs22 from "fs";
13874
- import chalk145 from "chalk";
14384
+ import chalk146 from "chalk";
13875
14385
  var REFACTOR_YML_PATH2 = "refactor.yml";
13876
14386
  function ignore(file) {
13877
14387
  if (!fs22.existsSync(file)) {
13878
- console.error(chalk145.red(`Error: File does not exist: ${file}`));
14388
+ console.error(chalk146.red(`Error: File does not exist: ${file}`));
13879
14389
  process.exit(1);
13880
14390
  }
13881
14391
  const content = fs22.readFileSync(file, "utf8");
@@ -13891,7 +14401,7 @@ function ignore(file) {
13891
14401
  fs22.writeFileSync(REFACTOR_YML_PATH2, entry);
13892
14402
  }
13893
14403
  console.log(
13894
- chalk145.green(
14404
+ chalk146.green(
13895
14405
  `Added ${file} to refactor ignore list (max ${maxLines} lines)`
13896
14406
  )
13897
14407
  );
@@ -13900,12 +14410,12 @@ function ignore(file) {
13900
14410
  // src/commands/refactor/rename/index.ts
13901
14411
  import fs25 from "fs";
13902
14412
  import path40 from "path";
13903
- import chalk148 from "chalk";
14413
+ import chalk149 from "chalk";
13904
14414
 
13905
14415
  // src/commands/refactor/rename/applyRename.ts
13906
14416
  import fs24 from "fs";
13907
14417
  import path37 from "path";
13908
- import chalk146 from "chalk";
14418
+ import chalk147 from "chalk";
13909
14419
 
13910
14420
  // src/commands/refactor/restructure/computeRewrites/index.ts
13911
14421
  import path36 from "path";
@@ -14010,13 +14520,13 @@ function applyRename(rewrites, sourcePath, destPath, cwd) {
14010
14520
  const updatedContents = applyRewrites(rewrites);
14011
14521
  for (const [file, content] of updatedContents) {
14012
14522
  fs24.writeFileSync(file, content, "utf8");
14013
- console.log(chalk146.cyan(` Updated imports in ${path37.relative(cwd, file)}`));
14523
+ console.log(chalk147.cyan(` Updated imports in ${path37.relative(cwd, file)}`));
14014
14524
  }
14015
14525
  const destDir = path37.dirname(destPath);
14016
14526
  if (!fs24.existsSync(destDir)) fs24.mkdirSync(destDir, { recursive: true });
14017
14527
  fs24.renameSync(sourcePath, destPath);
14018
14528
  console.log(
14019
- chalk146.white(
14529
+ chalk147.white(
14020
14530
  ` Moved ${path37.relative(cwd, sourcePath)} \u2192 ${path37.relative(cwd, destPath)}`
14021
14531
  )
14022
14532
  );
@@ -14103,16 +14613,16 @@ function computeRenameRewrites(sourcePath, destPath) {
14103
14613
 
14104
14614
  // src/commands/refactor/rename/printRenamePreview.ts
14105
14615
  import path39 from "path";
14106
- import chalk147 from "chalk";
14616
+ import chalk148 from "chalk";
14107
14617
  function printRenamePreview(rewrites, cwd) {
14108
14618
  for (const rewrite of rewrites) {
14109
14619
  console.log(
14110
- chalk147.dim(
14620
+ chalk148.dim(
14111
14621
  ` ${path39.relative(cwd, rewrite.file)}: ${rewrite.oldSpecifier} \u2192 ${rewrite.newSpecifier}`
14112
14622
  )
14113
14623
  );
14114
14624
  }
14115
- console.log(chalk147.dim("Dry run. Use --apply to execute."));
14625
+ console.log(chalk148.dim("Dry run. Use --apply to execute."));
14116
14626
  }
14117
14627
 
14118
14628
  // src/commands/refactor/rename/index.ts
@@ -14123,20 +14633,20 @@ async function rename(source, destination, options2 = {}) {
14123
14633
  const relSource = path40.relative(cwd, sourcePath);
14124
14634
  const relDest = path40.relative(cwd, destPath);
14125
14635
  if (!fs25.existsSync(sourcePath)) {
14126
- console.log(chalk148.red(`File not found: ${source}`));
14636
+ console.log(chalk149.red(`File not found: ${source}`));
14127
14637
  process.exit(1);
14128
14638
  }
14129
14639
  if (destPath !== sourcePath && fs25.existsSync(destPath)) {
14130
- console.log(chalk148.red(`Destination already exists: ${destination}`));
14640
+ console.log(chalk149.red(`Destination already exists: ${destination}`));
14131
14641
  process.exit(1);
14132
14642
  }
14133
- console.log(chalk148.bold(`Rename: ${relSource} \u2192 ${relDest}`));
14134
- console.log(chalk148.dim("Loading project..."));
14135
- console.log(chalk148.dim("Scanning imports across the project..."));
14643
+ console.log(chalk149.bold(`Rename: ${relSource} \u2192 ${relDest}`));
14644
+ console.log(chalk149.dim("Loading project..."));
14645
+ console.log(chalk149.dim("Scanning imports across the project..."));
14136
14646
  const rewrites = computeRenameRewrites(sourcePath, destPath);
14137
14647
  const affectedFiles = new Set(rewrites.map((r) => r.file)).size;
14138
14648
  console.log(
14139
- chalk148.dim(
14649
+ chalk149.dim(
14140
14650
  `${rewrites.length} import path(s) to update across ${affectedFiles} file(s)`
14141
14651
  )
14142
14652
  );
@@ -14145,11 +14655,11 @@ async function rename(source, destination, options2 = {}) {
14145
14655
  return;
14146
14656
  }
14147
14657
  applyRename(rewrites, sourcePath, destPath, cwd);
14148
- console.log(chalk148.green("Done"));
14658
+ console.log(chalk149.green("Done"));
14149
14659
  }
14150
14660
 
14151
14661
  // src/commands/refactor/renameSymbol/index.ts
14152
- import chalk149 from "chalk";
14662
+ import chalk150 from "chalk";
14153
14663
 
14154
14664
  // src/commands/refactor/renameSymbol/findSymbol.ts
14155
14665
  import { SyntaxKind as SyntaxKind14 } from "ts-morph";
@@ -14195,33 +14705,33 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
14195
14705
  const { project, sourceFile } = loadProjectFile(file);
14196
14706
  const symbol = findSymbol(sourceFile, oldName);
14197
14707
  if (!symbol) {
14198
- console.log(chalk149.red(`Symbol "${oldName}" not found in ${file}`));
14708
+ console.log(chalk150.red(`Symbol "${oldName}" not found in ${file}`));
14199
14709
  process.exit(1);
14200
14710
  }
14201
14711
  const grouped = groupReferences(symbol, cwd);
14202
14712
  const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
14203
14713
  console.log(
14204
- chalk149.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
14714
+ chalk150.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
14205
14715
  `)
14206
14716
  );
14207
14717
  for (const [refFile, lines] of grouped) {
14208
14718
  console.log(
14209
- ` ${chalk149.dim(refFile)}: lines ${chalk149.cyan(lines.join(", "))}`
14719
+ ` ${chalk150.dim(refFile)}: lines ${chalk150.cyan(lines.join(", "))}`
14210
14720
  );
14211
14721
  }
14212
14722
  if (options2.apply) {
14213
14723
  symbol.rename(newName);
14214
14724
  await project.save();
14215
- console.log(chalk149.green(`
14725
+ console.log(chalk150.green(`
14216
14726
  Renamed ${oldName} \u2192 ${newName}`));
14217
14727
  } else {
14218
- console.log(chalk149.dim("\nDry run. Use --apply to execute."));
14728
+ console.log(chalk150.dim("\nDry run. Use --apply to execute."));
14219
14729
  }
14220
14730
  }
14221
14731
 
14222
14732
  // src/commands/refactor/restructure/index.ts
14223
14733
  import path48 from "path";
14224
- import chalk152 from "chalk";
14734
+ import chalk153 from "chalk";
14225
14735
 
14226
14736
  // src/commands/refactor/restructure/clusterDirectories.ts
14227
14737
  import path42 from "path";
@@ -14300,50 +14810,50 @@ function clusterFiles(graph) {
14300
14810
 
14301
14811
  // src/commands/refactor/restructure/displayPlan.ts
14302
14812
  import path44 from "path";
14303
- import chalk150 from "chalk";
14813
+ import chalk151 from "chalk";
14304
14814
  function relPath(filePath) {
14305
14815
  return path44.relative(process.cwd(), filePath);
14306
14816
  }
14307
14817
  function displayMoves(plan2) {
14308
14818
  if (plan2.moves.length === 0) return;
14309
- console.log(chalk150.bold("\nFile moves:"));
14819
+ console.log(chalk151.bold("\nFile moves:"));
14310
14820
  for (const move of plan2.moves) {
14311
14821
  console.log(
14312
- ` ${chalk150.red(relPath(move.from))} \u2192 ${chalk150.green(relPath(move.to))}`
14822
+ ` ${chalk151.red(relPath(move.from))} \u2192 ${chalk151.green(relPath(move.to))}`
14313
14823
  );
14314
- console.log(chalk150.dim(` ${move.reason}`));
14824
+ console.log(chalk151.dim(` ${move.reason}`));
14315
14825
  }
14316
14826
  }
14317
14827
  function displayRewrites(rewrites) {
14318
14828
  if (rewrites.length === 0) return;
14319
14829
  const affectedFiles = new Set(rewrites.map((r) => r.file));
14320
- console.log(chalk150.bold(`
14830
+ console.log(chalk151.bold(`
14321
14831
  Import rewrites (${affectedFiles.size} files):`));
14322
14832
  for (const file of affectedFiles) {
14323
- console.log(` ${chalk150.cyan(relPath(file))}:`);
14833
+ console.log(` ${chalk151.cyan(relPath(file))}:`);
14324
14834
  for (const { oldSpecifier, newSpecifier } of rewrites.filter(
14325
14835
  (r) => r.file === file
14326
14836
  )) {
14327
14837
  console.log(
14328
- ` ${chalk150.red(`"${oldSpecifier}"`)} \u2192 ${chalk150.green(`"${newSpecifier}"`)}`
14838
+ ` ${chalk151.red(`"${oldSpecifier}"`)} \u2192 ${chalk151.green(`"${newSpecifier}"`)}`
14329
14839
  );
14330
14840
  }
14331
14841
  }
14332
14842
  }
14333
14843
  function displayPlan2(plan2) {
14334
14844
  if (plan2.warnings.length > 0) {
14335
- console.log(chalk150.yellow("\nWarnings:"));
14336
- for (const w of plan2.warnings) console.log(chalk150.yellow(` ${w}`));
14845
+ console.log(chalk151.yellow("\nWarnings:"));
14846
+ for (const w of plan2.warnings) console.log(chalk151.yellow(` ${w}`));
14337
14847
  }
14338
14848
  if (plan2.newDirectories.length > 0) {
14339
- console.log(chalk150.bold("\nNew directories:"));
14849
+ console.log(chalk151.bold("\nNew directories:"));
14340
14850
  for (const dir of plan2.newDirectories)
14341
- console.log(chalk150.green(` ${dir}/`));
14851
+ console.log(chalk151.green(` ${dir}/`));
14342
14852
  }
14343
14853
  displayMoves(plan2);
14344
14854
  displayRewrites(plan2.rewrites);
14345
14855
  console.log(
14346
- chalk150.dim(
14856
+ chalk151.dim(
14347
14857
  `
14348
14858
  Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
14349
14859
  )
@@ -14353,18 +14863,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
14353
14863
  // src/commands/refactor/restructure/executePlan.ts
14354
14864
  import fs26 from "fs";
14355
14865
  import path45 from "path";
14356
- import chalk151 from "chalk";
14866
+ import chalk152 from "chalk";
14357
14867
  function executePlan(plan2) {
14358
14868
  const updatedContents = applyRewrites(plan2.rewrites);
14359
14869
  for (const [file, content] of updatedContents) {
14360
14870
  fs26.writeFileSync(file, content, "utf8");
14361
14871
  console.log(
14362
- chalk151.cyan(` Rewrote imports in ${path45.relative(process.cwd(), file)}`)
14872
+ chalk152.cyan(` Rewrote imports in ${path45.relative(process.cwd(), file)}`)
14363
14873
  );
14364
14874
  }
14365
14875
  for (const dir of plan2.newDirectories) {
14366
14876
  fs26.mkdirSync(dir, { recursive: true });
14367
- console.log(chalk151.green(` Created ${path45.relative(process.cwd(), dir)}/`));
14877
+ console.log(chalk152.green(` Created ${path45.relative(process.cwd(), dir)}/`));
14368
14878
  }
14369
14879
  for (const move of plan2.moves) {
14370
14880
  const targetDir = path45.dirname(move.to);
@@ -14373,7 +14883,7 @@ function executePlan(plan2) {
14373
14883
  }
14374
14884
  fs26.renameSync(move.from, move.to);
14375
14885
  console.log(
14376
- chalk151.white(
14886
+ chalk152.white(
14377
14887
  ` Moved ${path45.relative(process.cwd(), move.from)} \u2192 ${path45.relative(process.cwd(), move.to)}`
14378
14888
  )
14379
14889
  );
@@ -14388,7 +14898,7 @@ function removeEmptyDirectories(dirs) {
14388
14898
  if (entries.length === 0) {
14389
14899
  fs26.rmdirSync(dir);
14390
14900
  console.log(
14391
- chalk151.dim(
14901
+ chalk152.dim(
14392
14902
  ` Removed empty directory ${path45.relative(process.cwd(), dir)}`
14393
14903
  )
14394
14904
  );
@@ -14521,22 +15031,22 @@ async function restructure(pattern2, options2 = {}) {
14521
15031
  const targetPattern = pattern2 ?? "src";
14522
15032
  const files = findSourceFiles2(targetPattern);
14523
15033
  if (files.length === 0) {
14524
- console.log(chalk152.yellow("No files found matching pattern"));
15034
+ console.log(chalk153.yellow("No files found matching pattern"));
14525
15035
  return;
14526
15036
  }
14527
15037
  const tsConfigPath = path48.resolve("tsconfig.json");
14528
15038
  const plan2 = buildPlan3(files, tsConfigPath);
14529
15039
  if (plan2.moves.length === 0) {
14530
- console.log(chalk152.green("No restructuring needed"));
15040
+ console.log(chalk153.green("No restructuring needed"));
14531
15041
  return;
14532
15042
  }
14533
15043
  displayPlan2(plan2);
14534
15044
  if (options2.apply) {
14535
- console.log(chalk152.bold("\nApplying changes..."));
15045
+ console.log(chalk153.bold("\nApplying changes..."));
14536
15046
  executePlan(plan2);
14537
- console.log(chalk152.green("\nRestructuring complete"));
15047
+ console.log(chalk153.green("\nRestructuring complete"));
14538
15048
  } else {
14539
- console.log(chalk152.dim("\nDry run. Use --apply to execute."));
15049
+ console.log(chalk153.dim("\nDry run. Use --apply to execute."));
14540
15050
  }
14541
15051
  }
14542
15052
 
@@ -14692,9 +15202,9 @@ ${annotateDiffWithLineNumbers(context.diff.trimEnd())}
14692
15202
 
14693
15203
  // src/commands/review/buildReviewPaths.ts
14694
15204
  import { homedir as homedir13 } from "os";
14695
- import { basename as basename7, join as join41 } from "path";
15205
+ import { basename as basename7, join as join43 } from "path";
14696
15206
  function buildReviewPaths(repoRoot, key) {
14697
- const reviewDir = join41(
15207
+ const reviewDir = join43(
14698
15208
  homedir13(),
14699
15209
  ".assist",
14700
15210
  "reviews",
@@ -14703,17 +15213,17 @@ function buildReviewPaths(repoRoot, key) {
14703
15213
  );
14704
15214
  return {
14705
15215
  reviewDir,
14706
- requestPath: join41(reviewDir, "request.md"),
14707
- claudePath: join41(reviewDir, "claude.md"),
14708
- codexPath: join41(reviewDir, "codex.md"),
14709
- synthesisPath: join41(reviewDir, "synthesis.md")
15216
+ requestPath: join43(reviewDir, "request.md"),
15217
+ claudePath: join43(reviewDir, "claude.md"),
15218
+ codexPath: join43(reviewDir, "codex.md"),
15219
+ synthesisPath: join43(reviewDir, "synthesis.md")
14710
15220
  };
14711
15221
  }
14712
15222
 
14713
15223
  // src/commands/review/fetchExistingComments.ts
14714
- import { execSync as execSync42 } from "child_process";
15224
+ import { execSync as execSync43 } from "child_process";
14715
15225
  function fetchRawComments(org, repo, prNumber) {
14716
- const out = execSync42(
15226
+ const out = execSync43(
14717
15227
  `gh api --paginate repos/${org}/${repo}/pulls/${prNumber}/comments`,
14718
15228
  { encoding: "utf8", maxBuffer: 64 * 1024 * 1024 }
14719
15229
  );
@@ -14744,14 +15254,14 @@ function fetchExistingComments() {
14744
15254
  }
14745
15255
 
14746
15256
  // src/commands/review/gatherContext.ts
14747
- import { execSync as execSync45 } from "child_process";
15257
+ import { execSync as execSync46 } from "child_process";
14748
15258
 
14749
15259
  // src/commands/review/fetchPrDiff.ts
14750
- import { execSync as execSync43 } from "child_process";
15260
+ import { execSync as execSync44 } from "child_process";
14751
15261
  function fetchPrDiff(prNumber, baseSha, headSha) {
14752
15262
  const { org, repo } = getRepoInfo();
14753
15263
  try {
14754
- return execSync43(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
15264
+ return execSync44(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
14755
15265
  encoding: "utf8",
14756
15266
  maxBuffer: 256 * 1024 * 1024,
14757
15267
  stdio: ["ignore", "pipe", "pipe"]
@@ -14766,19 +15276,19 @@ function isDiffTooLarge(error) {
14766
15276
  }
14767
15277
  function fetchDiffViaGit(baseSha, headSha) {
14768
15278
  try {
14769
- execSync43(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
15279
+ execSync44(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
14770
15280
  } catch {
14771
15281
  }
14772
- return execSync43(`git diff ${baseSha}...${headSha}`, {
15282
+ return execSync44(`git diff ${baseSha}...${headSha}`, {
14773
15283
  encoding: "utf8",
14774
15284
  maxBuffer: 256 * 1024 * 1024
14775
15285
  });
14776
15286
  }
14777
15287
 
14778
15288
  // src/commands/review/fetchPrDiffInfo.ts
14779
- import { execSync as execSync44 } from "child_process";
15289
+ import { execSync as execSync45 } from "child_process";
14780
15290
  function getCurrentBranch2() {
14781
- return execSync44("git rev-parse --abbrev-ref HEAD", {
15291
+ return execSync45("git rev-parse --abbrev-ref HEAD", {
14782
15292
  encoding: "utf8"
14783
15293
  }).trim();
14784
15294
  }
@@ -14788,7 +15298,7 @@ function fetchPrDiffInfo() {
14788
15298
  const fields = "number,baseRefName,baseRefOid,headRefName,headRefOid";
14789
15299
  let raw;
14790
15300
  try {
14791
- raw = execSync44(`gh pr view ${branch} --json ${fields} -R ${org}/${repo}`, {
15301
+ raw = execSync45(`gh pr view ${branch} --json ${fields} -R ${org}/${repo}`, {
14792
15302
  encoding: "utf8",
14793
15303
  stdio: ["ignore", "pipe", "pipe"]
14794
15304
  });
@@ -14812,7 +15322,7 @@ function fetchPrDiffInfo() {
14812
15322
  }
14813
15323
  function fetchPrChangedFiles(prNumber) {
14814
15324
  const { org, repo } = getRepoInfo();
14815
- const out = execSync44(
15325
+ const out = execSync45(
14816
15326
  `gh api repos/${org}/${repo}/pulls/${prNumber}/files --paginate --jq ".[].filename"`,
14817
15327
  {
14818
15328
  encoding: "utf8",
@@ -14824,11 +15334,11 @@ function fetchPrChangedFiles(prNumber) {
14824
15334
 
14825
15335
  // src/commands/review/gatherContext.ts
14826
15336
  function gatherContext() {
14827
- const branch = execSync45("git rev-parse --abbrev-ref HEAD", {
15337
+ const branch = execSync46("git rev-parse --abbrev-ref HEAD", {
14828
15338
  encoding: "utf8"
14829
15339
  }).trim();
14830
- const sha = execSync45("git rev-parse HEAD", { encoding: "utf8" }).trim();
14831
- 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", {
14832
15342
  encoding: "utf8"
14833
15343
  }).trim();
14834
15344
  const prInfo = fetchPrDiffInfo();
@@ -14849,7 +15359,7 @@ function gatherContext() {
14849
15359
  }
14850
15360
 
14851
15361
  // src/commands/review/postReviewToPr.ts
14852
- import { readFileSync as readFileSync31 } from "fs";
15362
+ import { readFileSync as readFileSync32 } from "fs";
14853
15363
 
14854
15364
  // src/commands/review/parseFindings.ts
14855
15365
  var SEVERITIES = ["blocker", "major", "minor", "nit"];
@@ -15105,18 +15615,18 @@ function partitionFindingsByDiff(findings, index3) {
15105
15615
  }
15106
15616
 
15107
15617
  // src/commands/review/warnOutOfDiff.ts
15108
- import chalk153 from "chalk";
15618
+ import chalk154 from "chalk";
15109
15619
  function warnOutOfDiff(outOfDiff) {
15110
15620
  if (outOfDiff.length === 0) return;
15111
15621
  console.warn(
15112
- chalk153.yellow(
15622
+ chalk154.yellow(
15113
15623
  `Skipped ${outOfDiff.length} finding(s) whose lines fall outside the PR diff (GitHub would silently drop these):`
15114
15624
  )
15115
15625
  );
15116
15626
  for (const finding of outOfDiff) {
15117
15627
  const range = finding.startLine !== void 0 ? `${finding.startLine}-${finding.line}` : `${finding.line}`;
15118
15628
  console.warn(
15119
- ` ${chalk153.yellow("\xB7")} ${finding.title} ${chalk153.dim(
15629
+ ` ${chalk154.yellow("\xB7")} ${finding.title} ${chalk154.dim(
15120
15630
  `(${finding.file}:${range})`
15121
15631
  )}`
15122
15632
  );
@@ -15135,18 +15645,18 @@ function selectInDiffFindings(lineBound, prDiff) {
15135
15645
  }
15136
15646
 
15137
15647
  // src/commands/review/warnUnlocated.ts
15138
- import chalk154 from "chalk";
15648
+ import chalk155 from "chalk";
15139
15649
  function warnUnlocated(unlocated) {
15140
15650
  if (unlocated.length === 0) return;
15141
15651
  console.warn(
15142
- chalk154.yellow(
15652
+ chalk155.yellow(
15143
15653
  `Skipped ${unlocated.length} finding(s) without a parseable file:line:`
15144
15654
  )
15145
15655
  );
15146
15656
  for (const finding of unlocated) {
15147
- const where = finding.location || chalk154.dim("missing");
15657
+ const where = finding.location || chalk155.dim("missing");
15148
15658
  console.warn(
15149
- ` ${chalk154.yellow("\xB7")} ${finding.title} ${chalk154.dim(`(${where})`)}`
15659
+ ` ${chalk155.yellow("\xB7")} ${finding.title} ${chalk155.dim(`(${where})`)}`
15150
15660
  );
15151
15661
  }
15152
15662
  }
@@ -15159,7 +15669,7 @@ async function confirmPost(prNumber, count6, options2) {
15159
15669
  async function postReviewToPr(synthesisPath, options2) {
15160
15670
  const prInfo = fetchPrDiffInfo();
15161
15671
  const prNumber = prInfo.prNumber;
15162
- const markdown = readFileSync31(synthesisPath, "utf8");
15672
+ const markdown = readFileSync32(synthesisPath, "utf8");
15163
15673
  const findings = parseFindings(markdown);
15164
15674
  if (findings.length === 0) {
15165
15675
  console.log("Synthesis contains no findings; nothing to post.");
@@ -15241,16 +15751,16 @@ async function handlePostSynthesis(synthesisPath, options2) {
15241
15751
  }
15242
15752
 
15243
15753
  // src/commands/review/prepareReviewDir.ts
15244
- import { existsSync as existsSync35, mkdirSync as mkdirSync14, unlinkSync as unlinkSync12, writeFileSync as writeFileSync29 } from "fs";
15754
+ import { existsSync as existsSync35, mkdirSync as mkdirSync14, unlinkSync as unlinkSync12, writeFileSync as writeFileSync30 } from "fs";
15245
15755
  function clearReviewFiles(paths) {
15246
- for (const path58 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
15247
- if (existsSync35(path58)) unlinkSync12(path58);
15756
+ for (const path57 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
15757
+ if (existsSync35(path57)) unlinkSync12(path57);
15248
15758
  }
15249
15759
  }
15250
15760
  function prepareReviewDir(paths, requestBody, force) {
15251
15761
  mkdirSync14(paths.reviewDir, { recursive: true });
15252
15762
  if (force) clearReviewFiles(paths);
15253
- writeFileSync29(paths.requestPath, requestBody);
15763
+ writeFileSync30(paths.requestPath, requestBody);
15254
15764
  }
15255
15765
 
15256
15766
  // src/commands/review/runApplySession.ts
@@ -15595,7 +16105,7 @@ The review request is at: ${requestPath}
15595
16105
  }
15596
16106
 
15597
16107
  // src/commands/review/runClaudeReviewer.ts
15598
- import { writeFileSync as writeFileSync30 } from "fs";
16108
+ import { writeFileSync as writeFileSync31 } from "fs";
15599
16109
 
15600
16110
  // src/commands/review/finaliseReviewerSpinner.ts
15601
16111
  var SUMMARY_MAX_LEN = 80;
@@ -15931,7 +16441,7 @@ async function runClaudeReviewer(spec) {
15931
16441
  }
15932
16442
  });
15933
16443
  if (result.exitCode === 0 && finalText)
15934
- writeFileSync30(spec.outputPath, finalText);
16444
+ writeFileSync31(spec.outputPath, finalText);
15935
16445
  return finaliseReviewerRun({ ...spec, command }, spinner, result);
15936
16446
  }
15937
16447
 
@@ -16043,7 +16553,7 @@ async function runReviewers(reviewDir, claudePath, codexPath, stdinPrompt, optio
16043
16553
  }
16044
16554
 
16045
16555
  // src/commands/review/synthesise.ts
16046
- import { readFileSync as readFileSync32 } from "fs";
16556
+ import { readFileSync as readFileSync33 } from "fs";
16047
16557
 
16048
16558
  // src/commands/review/buildSynthesisStdin.ts
16049
16559
  var SYNTHESIS_PROMPT = `You are consolidating two independent code reviews of the same change. The original review request is in request.md. The two reviews are in claude.md and codex.md in the current working directory.
@@ -16099,7 +16609,7 @@ Files:
16099
16609
 
16100
16610
  // src/commands/review/synthesise.ts
16101
16611
  function printSummary2(synthesisPath) {
16102
- const markdown = readFileSync32(synthesisPath, "utf8");
16612
+ const markdown = readFileSync33(synthesisPath, "utf8");
16103
16613
  console.log("");
16104
16614
  console.log(buildReviewSummary(markdown));
16105
16615
  console.log("");
@@ -16317,7 +16827,7 @@ function registerReview(program2) {
16317
16827
  }
16318
16828
 
16319
16829
  // src/commands/seq/seqAuth.ts
16320
- import chalk156 from "chalk";
16830
+ import chalk157 from "chalk";
16321
16831
 
16322
16832
  // src/commands/seq/loadConnections.ts
16323
16833
  function loadConnections2() {
@@ -16346,10 +16856,10 @@ function setDefaultConnection(name) {
16346
16856
  }
16347
16857
 
16348
16858
  // src/shared/assertUniqueName.ts
16349
- import chalk155 from "chalk";
16859
+ import chalk156 from "chalk";
16350
16860
  function assertUniqueName(existingNames, name) {
16351
16861
  if (existingNames.includes(name)) {
16352
- console.error(chalk155.red(`Connection "${name}" already exists.`));
16862
+ console.error(chalk156.red(`Connection "${name}" already exists.`));
16353
16863
  process.exit(1);
16354
16864
  }
16355
16865
  }
@@ -16367,18 +16877,18 @@ async function promptConnection2(existingNames) {
16367
16877
  var seqAuth = createConnectionAuth({
16368
16878
  load: loadConnections2,
16369
16879
  save: saveConnections2,
16370
- format: (c) => `${chalk156.bold(c.name)} ${c.url}`,
16880
+ format: (c) => `${chalk157.bold(c.name)} ${c.url}`,
16371
16881
  promptNew: promptConnection2,
16372
16882
  onFirst: (c) => setDefaultConnection(c.name)
16373
16883
  });
16374
16884
 
16375
16885
  // src/commands/seq/seqQuery.ts
16376
- import chalk160 from "chalk";
16886
+ import chalk161 from "chalk";
16377
16887
 
16378
16888
  // src/commands/seq/fetchSeq.ts
16379
- import chalk157 from "chalk";
16380
- async function fetchSeq(conn, path58, params) {
16381
- const url = `${conn.url}${path58}?${params}`;
16889
+ import chalk158 from "chalk";
16890
+ async function fetchSeq(conn, path57, params) {
16891
+ const url = `${conn.url}${path57}?${params}`;
16382
16892
  const response = await fetch(url, {
16383
16893
  headers: {
16384
16894
  Accept: "application/json",
@@ -16387,7 +16897,7 @@ async function fetchSeq(conn, path58, params) {
16387
16897
  });
16388
16898
  if (!response.ok) {
16389
16899
  const body = await response.text();
16390
- console.error(chalk157.red(`Seq returned ${response.status}: ${body}`));
16900
+ console.error(chalk158.red(`Seq returned ${response.status}: ${body}`));
16391
16901
  process.exit(1);
16392
16902
  }
16393
16903
  return response;
@@ -16446,23 +16956,23 @@ async function fetchSeqEvents(conn, params) {
16446
16956
  }
16447
16957
 
16448
16958
  // src/commands/seq/formatEvent.ts
16449
- import chalk158 from "chalk";
16959
+ import chalk159 from "chalk";
16450
16960
  function levelColor(level) {
16451
16961
  switch (level) {
16452
16962
  case "Fatal":
16453
- return chalk158.bgRed.white;
16963
+ return chalk159.bgRed.white;
16454
16964
  case "Error":
16455
- return chalk158.red;
16965
+ return chalk159.red;
16456
16966
  case "Warning":
16457
- return chalk158.yellow;
16967
+ return chalk159.yellow;
16458
16968
  case "Information":
16459
- return chalk158.cyan;
16969
+ return chalk159.cyan;
16460
16970
  case "Debug":
16461
- return chalk158.gray;
16971
+ return chalk159.gray;
16462
16972
  case "Verbose":
16463
- return chalk158.dim;
16973
+ return chalk159.dim;
16464
16974
  default:
16465
- return chalk158.white;
16975
+ return chalk159.white;
16466
16976
  }
16467
16977
  }
16468
16978
  function levelAbbrev(level) {
@@ -16503,12 +17013,12 @@ function formatTimestamp(iso) {
16503
17013
  function formatEvent(event) {
16504
17014
  const color = levelColor(event.Level);
16505
17015
  const abbrev = levelAbbrev(event.Level);
16506
- const ts8 = chalk158.dim(formatTimestamp(event.Timestamp));
17016
+ const ts8 = chalk159.dim(formatTimestamp(event.Timestamp));
16507
17017
  const msg = renderMessage(event);
16508
17018
  const lines = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
16509
17019
  if (event.Exception) {
16510
17020
  for (const line of event.Exception.split("\n")) {
16511
- lines.push(chalk158.red(` ${line}`));
17021
+ lines.push(chalk159.red(` ${line}`));
16512
17022
  }
16513
17023
  }
16514
17024
  return lines.join("\n");
@@ -16541,11 +17051,11 @@ function rejectTimestampFilter(filter) {
16541
17051
  }
16542
17052
 
16543
17053
  // src/shared/resolveNamedConnection.ts
16544
- import chalk159 from "chalk";
17054
+ import chalk160 from "chalk";
16545
17055
  function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
16546
17056
  if (connections.length === 0) {
16547
17057
  console.error(
16548
- chalk159.red(
17058
+ chalk160.red(
16549
17059
  `No ${kind} connections configured. Run '${authCommand}' first.`
16550
17060
  )
16551
17061
  );
@@ -16554,7 +17064,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
16554
17064
  const target = requested ?? defaultName ?? connections[0].name;
16555
17065
  const connection = connections.find((c) => c.name === target);
16556
17066
  if (!connection) {
16557
- console.error(chalk159.red(`${kind} connection "${target}" not found.`));
17067
+ console.error(chalk160.red(`${kind} connection "${target}" not found.`));
16558
17068
  process.exit(1);
16559
17069
  }
16560
17070
  return connection;
@@ -16583,7 +17093,7 @@ async function seqQuery(filter, options2) {
16583
17093
  new URLSearchParams({ filter, count: String(count6) })
16584
17094
  );
16585
17095
  if (events.length === 0) {
16586
- console.log(chalk160.yellow("No events found."));
17096
+ console.log(chalk161.yellow("No events found."));
16587
17097
  return;
16588
17098
  }
16589
17099
  if (options2.json) {
@@ -16594,11 +17104,11 @@ async function seqQuery(filter, options2) {
16594
17104
  for (const event of chronological) {
16595
17105
  console.log(formatEvent(event));
16596
17106
  }
16597
- console.log(chalk160.dim(`
17107
+ console.log(chalk161.dim(`
16598
17108
  ${events.length} events`));
16599
17109
  if (events.length >= count6) {
16600
17110
  console.log(
16601
- chalk160.yellow(
17111
+ chalk161.yellow(
16602
17112
  `Results limited to ${count6}. Use --count to retrieve more.`
16603
17113
  )
16604
17114
  );
@@ -16606,10 +17116,10 @@ ${events.length} events`));
16606
17116
  }
16607
17117
 
16608
17118
  // src/shared/setNamedDefaultConnection.ts
16609
- import chalk161 from "chalk";
17119
+ import chalk162 from "chalk";
16610
17120
  function setNamedDefaultConnection(connections, name, setDefault, kind) {
16611
17121
  if (!connections.find((c) => c.name === name)) {
16612
- console.error(chalk161.red(`Connection "${name}" not found.`));
17122
+ console.error(chalk162.red(`Connection "${name}" not found.`));
16613
17123
  process.exit(1);
16614
17124
  }
16615
17125
  setDefault(name);
@@ -16657,7 +17167,7 @@ function registerSignal(program2) {
16657
17167
  }
16658
17168
 
16659
17169
  // src/commands/sql/sqlAuth.ts
16660
- import chalk163 from "chalk";
17170
+ import chalk164 from "chalk";
16661
17171
 
16662
17172
  // src/commands/sql/loadConnections.ts
16663
17173
  function loadConnections3() {
@@ -16686,7 +17196,7 @@ function setDefaultConnection2(name) {
16686
17196
  }
16687
17197
 
16688
17198
  // src/commands/sql/promptConnection.ts
16689
- import chalk162 from "chalk";
17199
+ import chalk163 from "chalk";
16690
17200
  async function promptConnection3(existingNames) {
16691
17201
  const name = await promptInput("name", "Connection name:", "default");
16692
17202
  assertUniqueName(existingNames, name);
@@ -16694,7 +17204,7 @@ async function promptConnection3(existingNames) {
16694
17204
  const portStr = await promptInput("port", "Port:", "1433");
16695
17205
  const port = Number.parseInt(portStr, 10);
16696
17206
  if (!Number.isFinite(port)) {
16697
- console.error(chalk162.red(`Invalid port "${portStr}".`));
17207
+ console.error(chalk163.red(`Invalid port "${portStr}".`));
16698
17208
  process.exit(1);
16699
17209
  }
16700
17210
  const user = await promptInput("user", "User:");
@@ -16707,13 +17217,13 @@ async function promptConnection3(existingNames) {
16707
17217
  var sqlAuth = createConnectionAuth({
16708
17218
  load: loadConnections3,
16709
17219
  save: saveConnections3,
16710
- format: (c) => `${chalk163.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
17220
+ format: (c) => `${chalk164.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
16711
17221
  promptNew: promptConnection3,
16712
17222
  onFirst: (c) => setDefaultConnection2(c.name)
16713
17223
  });
16714
17224
 
16715
17225
  // src/commands/sql/printTable.ts
16716
- import chalk164 from "chalk";
17226
+ import chalk165 from "chalk";
16717
17227
  function formatCell(value) {
16718
17228
  if (value === null || value === void 0) return "";
16719
17229
  if (value instanceof Date) return value.toISOString();
@@ -16722,7 +17232,7 @@ function formatCell(value) {
16722
17232
  }
16723
17233
  function printTable(rows) {
16724
17234
  if (rows.length === 0) {
16725
- console.log(chalk164.yellow("(no rows)"));
17235
+ console.log(chalk165.yellow("(no rows)"));
16726
17236
  return;
16727
17237
  }
16728
17238
  const columns = Object.keys(rows[0]);
@@ -16730,13 +17240,13 @@ function printTable(rows) {
16730
17240
  (col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
16731
17241
  );
16732
17242
  const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
16733
- console.log(chalk164.dim(header));
16734
- console.log(chalk164.dim("-".repeat(header.length)));
17243
+ console.log(chalk165.dim(header));
17244
+ console.log(chalk165.dim("-".repeat(header.length)));
16735
17245
  for (const row of rows) {
16736
17246
  const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
16737
17247
  console.log(line);
16738
17248
  }
16739
- console.log(chalk164.dim(`
17249
+ console.log(chalk165.dim(`
16740
17250
  ${rows.length} row${rows.length === 1 ? "" : "s"}`));
16741
17251
  }
16742
17252
 
@@ -16796,7 +17306,7 @@ async function sqlColumns(table, connectionName) {
16796
17306
  }
16797
17307
 
16798
17308
  // src/commands/sql/sqlMutate.ts
16799
- import chalk165 from "chalk";
17309
+ import chalk166 from "chalk";
16800
17310
 
16801
17311
  // src/commands/sql/isMutation.ts
16802
17312
  var MUTATION_KEYWORDS = [
@@ -16830,7 +17340,7 @@ function isMutation(sql6) {
16830
17340
  async function sqlMutate(query, connectionName) {
16831
17341
  if (!isMutation(query)) {
16832
17342
  console.error(
16833
- chalk165.red(
17343
+ chalk166.red(
16834
17344
  "assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
16835
17345
  )
16836
17346
  );
@@ -16840,18 +17350,18 @@ async function sqlMutate(query, connectionName) {
16840
17350
  const pool = await sqlConnect(conn);
16841
17351
  try {
16842
17352
  const result = await pool.request().query(query);
16843
- console.log(chalk165.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
17353
+ console.log(chalk166.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
16844
17354
  } finally {
16845
17355
  await pool.close();
16846
17356
  }
16847
17357
  }
16848
17358
 
16849
17359
  // src/commands/sql/sqlQuery.ts
16850
- import chalk166 from "chalk";
17360
+ import chalk167 from "chalk";
16851
17361
  async function sqlQuery(query, connectionName) {
16852
17362
  if (isMutation(query)) {
16853
17363
  console.error(
16854
- chalk166.red(
17364
+ chalk167.red(
16855
17365
  "assist sql query refuses mutating statements. Use `assist sql mutate` instead."
16856
17366
  )
16857
17367
  );
@@ -16866,7 +17376,7 @@ async function sqlQuery(query, connectionName) {
16866
17376
  printTable(rows);
16867
17377
  } else {
16868
17378
  console.log(
16869
- chalk166.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
17379
+ chalk167.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
16870
17380
  );
16871
17381
  }
16872
17382
  } finally {
@@ -16927,7 +17437,7 @@ function registerSql(program2) {
16927
17437
 
16928
17438
  // src/commands/transcript/shared.ts
16929
17439
  import { existsSync as existsSync38, readdirSync as readdirSync7, statSync as statSync5 } from "fs";
16930
- import { basename as basename8, join as join42, relative as relative2 } from "path";
17440
+ import { basename as basename8, join as join44, relative as relative2 } from "path";
16931
17441
  import * as readline2 from "readline";
16932
17442
  var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
16933
17443
  function getDatePrefix(daysOffset = 0) {
@@ -16945,7 +17455,7 @@ function collectFiles(dir, extension) {
16945
17455
  if (!existsSync38(dir)) return [];
16946
17456
  const results = [];
16947
17457
  for (const entry of readdirSync7(dir)) {
16948
- const fullPath = join42(dir, entry);
17458
+ const fullPath = join44(dir, entry);
16949
17459
  if (statSync5(fullPath).isDirectory()) {
16950
17460
  results.push(...collectFiles(fullPath, extension));
16951
17461
  } else if (entry.endsWith(extension)) {
@@ -17042,11 +17552,11 @@ async function configure() {
17042
17552
  import { existsSync as existsSync40 } from "fs";
17043
17553
 
17044
17554
  // src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
17045
- import { dirname as dirname22, join as join44 } from "path";
17555
+ import { dirname as dirname22, join as join46 } from "path";
17046
17556
 
17047
17557
  // src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
17048
17558
  import { renameSync as renameSync2 } from "fs";
17049
- import { join as join43 } from "path";
17559
+ import { join as join45 } from "path";
17050
17560
  async function resolveDate(rl, choice) {
17051
17561
  if (choice === "1") return getDatePrefix(0);
17052
17562
  if (choice === "2") return getDatePrefix(-1);
@@ -17061,7 +17571,7 @@ async function resolveDate(rl, choice) {
17061
17571
  }
17062
17572
  function renameWithPrefix(vttDir, vttFile, prefix2) {
17063
17573
  const newFilename = `${prefix2}.${vttFile}`;
17064
- renameSync2(join43(vttDir, vttFile), join43(vttDir, newFilename));
17574
+ renameSync2(join45(vttDir, vttFile), join45(vttDir, newFilename));
17065
17575
  console.log(`Renamed to: ${newFilename}`);
17066
17576
  return newFilename;
17067
17577
  }
@@ -17095,12 +17605,12 @@ async function fixInvalidDatePrefixes(vttFiles) {
17095
17605
  const vttFileDir = dirname22(vttFile.absolutePath);
17096
17606
  const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
17097
17607
  if (newFilename) {
17098
- const newRelativePath = join44(
17608
+ const newRelativePath = join46(
17099
17609
  dirname22(vttFile.relativePath),
17100
17610
  newFilename
17101
17611
  );
17102
17612
  vttFiles[i] = {
17103
- absolutePath: join44(vttFileDir, newFilename),
17613
+ absolutePath: join46(vttFileDir, newFilename),
17104
17614
  relativePath: newRelativePath,
17105
17615
  filename: newFilename
17106
17616
  };
@@ -17113,8 +17623,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
17113
17623
  }
17114
17624
 
17115
17625
  // src/commands/transcript/format/processVttFile/index.ts
17116
- import { existsSync as existsSync39, mkdirSync as mkdirSync15, readFileSync as readFileSync33, writeFileSync as writeFileSync31 } from "fs";
17117
- import { basename as basename9, dirname as dirname23, join as join45 } from "path";
17626
+ import { existsSync as existsSync39, mkdirSync as mkdirSync15, readFileSync as readFileSync34, writeFileSync as writeFileSync32 } from "fs";
17627
+ import { basename as basename9, dirname as dirname23, join as join47 } from "path";
17118
17628
 
17119
17629
  // src/commands/transcript/cleanText.ts
17120
17630
  function cleanText(text5) {
@@ -17324,17 +17834,17 @@ function toMdFilename(vttFilename) {
17324
17834
  return `${basename9(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
17325
17835
  }
17326
17836
  function resolveOutputDir(relativeDir, transcriptsDir) {
17327
- return relativeDir === "." ? transcriptsDir : join45(transcriptsDir, relativeDir);
17837
+ return relativeDir === "." ? transcriptsDir : join47(transcriptsDir, relativeDir);
17328
17838
  }
17329
17839
  function buildOutputPaths(vttFile, transcriptsDir) {
17330
17840
  const mdFile = toMdFilename(vttFile.filename);
17331
17841
  const relativeDir = dirname23(vttFile.relativePath);
17332
17842
  const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
17333
- const outputPath = join45(outputDir, mdFile);
17843
+ const outputPath = join47(outputDir, mdFile);
17334
17844
  return { outputDir, outputPath, mdFile, relativeDir };
17335
17845
  }
17336
17846
  function logSkipped(relativeDir, mdFile) {
17337
- console.log(`Skipping (already exists): ${join45(relativeDir, mdFile)}`);
17847
+ console.log(`Skipping (already exists): ${join47(relativeDir, mdFile)}`);
17338
17848
  return "skipped";
17339
17849
  }
17340
17850
  function ensureDirectory(dir, label2) {
@@ -17361,10 +17871,10 @@ function logReduction(cueCount, messageCount) {
17361
17871
  }
17362
17872
  function readAndParseCues(inputPath) {
17363
17873
  console.log(`Reading: ${inputPath}`);
17364
- return processCues(readFileSync33(inputPath, "utf8"));
17874
+ return processCues(readFileSync34(inputPath, "utf8"));
17365
17875
  }
17366
17876
  function writeFormatted(outputPath, content) {
17367
- writeFileSync31(outputPath, content, "utf8");
17877
+ writeFileSync32(outputPath, content, "utf8");
17368
17878
  console.log(`Written: ${outputPath}`);
17369
17879
  }
17370
17880
  function convertVttToMarkdown(inputPath, outputPath) {
@@ -17433,27 +17943,27 @@ async function format() {
17433
17943
 
17434
17944
  // src/commands/transcript/summarise/index.ts
17435
17945
  import { existsSync as existsSync42 } from "fs";
17436
- import { basename as basename10, dirname as dirname25, join as join47, relative as relative3 } from "path";
17946
+ import { basename as basename10, dirname as dirname25, join as join49, relative as relative3 } from "path";
17437
17947
 
17438
17948
  // src/commands/transcript/summarise/processStagedFile/index.ts
17439
17949
  import {
17440
17950
  existsSync as existsSync41,
17441
17951
  mkdirSync as mkdirSync16,
17442
- readFileSync as readFileSync34,
17952
+ readFileSync as readFileSync35,
17443
17953
  renameSync as renameSync3,
17444
17954
  rmSync as rmSync4
17445
17955
  } from "fs";
17446
- import { dirname as dirname24, join as join46 } from "path";
17956
+ import { dirname as dirname24, join as join48 } from "path";
17447
17957
 
17448
17958
  // src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
17449
- import chalk167 from "chalk";
17959
+ import chalk168 from "chalk";
17450
17960
  var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
17451
17961
  function validateStagedContent(filename, content) {
17452
17962
  const firstLine = content.split("\n")[0];
17453
17963
  const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
17454
17964
  if (!match) {
17455
17965
  console.error(
17456
- chalk167.red(
17966
+ chalk168.red(
17457
17967
  `Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
17458
17968
  )
17459
17969
  );
@@ -17462,7 +17972,7 @@ function validateStagedContent(filename, content) {
17462
17972
  const contentAfterLink = content.slice(firstLine.length).trim();
17463
17973
  if (!contentAfterLink) {
17464
17974
  console.error(
17465
- chalk167.red(
17975
+ chalk168.red(
17466
17976
  `Staged file ${filename} has no summary content after the transcript link.`
17467
17977
  )
17468
17978
  );
@@ -17472,7 +17982,7 @@ function validateStagedContent(filename, content) {
17472
17982
  }
17473
17983
 
17474
17984
  // src/commands/transcript/summarise/processStagedFile/index.ts
17475
- var STAGING_DIR = join46(process.cwd(), ".assist", "transcript");
17985
+ var STAGING_DIR = join48(process.cwd(), ".assist", "transcript");
17476
17986
  function processStagedFile() {
17477
17987
  if (!existsSync41(STAGING_DIR)) {
17478
17988
  return false;
@@ -17483,7 +17993,7 @@ function processStagedFile() {
17483
17993
  }
17484
17994
  const { transcriptsDir, summaryDir } = getTranscriptConfig();
17485
17995
  const stagedFile = stagedFiles[0];
17486
- const content = readFileSync34(stagedFile.absolutePath, "utf8");
17996
+ const content = readFileSync35(stagedFile.absolutePath, "utf8");
17487
17997
  validateStagedContent(stagedFile.filename, content);
17488
17998
  const stagedBaseName = getTranscriptBaseName(stagedFile.filename);
17489
17999
  const transcriptFiles = findMdFilesRecursive(transcriptsDir);
@@ -17496,7 +18006,7 @@ function processStagedFile() {
17496
18006
  );
17497
18007
  process.exit(1);
17498
18008
  }
17499
- const destPath = join46(summaryDir, matchingTranscript.relativePath);
18009
+ const destPath = join48(summaryDir, matchingTranscript.relativePath);
17500
18010
  const destDir = dirname24(destPath);
17501
18011
  if (!existsSync41(destDir)) {
17502
18012
  mkdirSync16(destDir, { recursive: true });
@@ -17512,7 +18022,7 @@ function processStagedFile() {
17512
18022
  // src/commands/transcript/summarise/index.ts
17513
18023
  function buildRelativeKey(relativePath, baseName) {
17514
18024
  const relDir = dirname25(relativePath);
17515
- return relDir === "." ? baseName : join47(relDir, baseName);
18025
+ return relDir === "." ? baseName : join49(relDir, baseName);
17516
18026
  }
17517
18027
  function buildSummaryIndex(summaryDir) {
17518
18028
  const summaryFiles = findMdFilesRecursive(summaryDir);
@@ -17546,8 +18056,8 @@ function summarise2() {
17546
18056
  }
17547
18057
  const next3 = missing[0];
17548
18058
  const outputFilename = `${getTranscriptBaseName(next3.filename)}.md`;
17549
- const outputPath = join47(STAGING_DIR, outputFilename);
17550
- const summaryFileDir = join47(summaryDir, dirname25(next3.relativePath));
18059
+ const outputPath = join49(STAGING_DIR, outputFilename);
18060
+ const summaryFileDir = join49(summaryDir, dirname25(next3.relativePath));
17551
18061
  const relativeTranscriptPath = encodeURI(
17552
18062
  relative3(summaryFileDir, next3.absolutePath).replace(/\\/g, "/")
17553
18063
  );
@@ -17597,50 +18107,50 @@ function registerVerify(program2) {
17597
18107
 
17598
18108
  // src/commands/voice/devices.ts
17599
18109
  import { spawnSync as spawnSync5 } from "child_process";
17600
- import { join as join49 } from "path";
18110
+ import { join as join51 } from "path";
17601
18111
 
17602
18112
  // src/commands/voice/shared.ts
17603
18113
  import { homedir as homedir14 } from "os";
17604
- import { dirname as dirname26, join as join48 } from "path";
18114
+ import { dirname as dirname26, join as join50 } from "path";
17605
18115
  import { fileURLToPath as fileURLToPath6 } from "url";
17606
18116
  var __dirname5 = dirname26(fileURLToPath6(import.meta.url));
17607
- var VOICE_DIR = join48(homedir14(), ".assist", "voice");
18117
+ var VOICE_DIR = join50(homedir14(), ".assist", "voice");
17608
18118
  var voicePaths = {
17609
18119
  dir: VOICE_DIR,
17610
- pid: join48(VOICE_DIR, "voice.pid"),
17611
- log: join48(VOICE_DIR, "voice.log"),
17612
- venv: join48(VOICE_DIR, ".venv"),
17613
- lock: join48(VOICE_DIR, "voice.lock")
18120
+ pid: join50(VOICE_DIR, "voice.pid"),
18121
+ log: join50(VOICE_DIR, "voice.log"),
18122
+ venv: join50(VOICE_DIR, ".venv"),
18123
+ lock: join50(VOICE_DIR, "voice.lock")
17614
18124
  };
17615
18125
  function getPythonDir() {
17616
- return join48(__dirname5, "commands", "voice", "python");
18126
+ return join50(__dirname5, "commands", "voice", "python");
17617
18127
  }
17618
18128
  function getVenvPython() {
17619
- return process.platform === "win32" ? join48(voicePaths.venv, "Scripts", "python.exe") : join48(voicePaths.venv, "bin", "python");
18129
+ return process.platform === "win32" ? join50(voicePaths.venv, "Scripts", "python.exe") : join50(voicePaths.venv, "bin", "python");
17620
18130
  }
17621
18131
  function getLockDir() {
17622
18132
  const config = loadConfig();
17623
18133
  return config.voice?.lockDir ?? VOICE_DIR;
17624
18134
  }
17625
18135
  function getLockFile() {
17626
- return join48(getLockDir(), "voice.lock");
18136
+ return join50(getLockDir(), "voice.lock");
17627
18137
  }
17628
18138
 
17629
18139
  // src/commands/voice/devices.ts
17630
18140
  function devices() {
17631
- const script = join49(getPythonDir(), "list_devices.py");
18141
+ const script = join51(getPythonDir(), "list_devices.py");
17632
18142
  spawnSync5(getVenvPython(), [script], { stdio: "inherit" });
17633
18143
  }
17634
18144
 
17635
18145
  // src/commands/voice/logs.ts
17636
- import { existsSync as existsSync43, readFileSync as readFileSync35 } from "fs";
18146
+ import { existsSync as existsSync43, readFileSync as readFileSync36 } from "fs";
17637
18147
  function logs(options2) {
17638
18148
  if (!existsSync43(voicePaths.log)) {
17639
18149
  console.log("No voice log file found");
17640
18150
  return;
17641
18151
  }
17642
18152
  const count6 = Number.parseInt(options2.lines ?? "150", 10);
17643
- const content = readFileSync35(voicePaths.log, "utf8").trim();
18153
+ const content = readFileSync36(voicePaths.log, "utf8").trim();
17644
18154
  if (!content) {
17645
18155
  console.log("Voice log is empty");
17646
18156
  return;
@@ -17663,12 +18173,12 @@ function logs(options2) {
17663
18173
  // src/commands/voice/setup.ts
17664
18174
  import { spawnSync as spawnSync6 } from "child_process";
17665
18175
  import { mkdirSync as mkdirSync18 } from "fs";
17666
- import { join as join51 } from "path";
18176
+ import { join as join53 } from "path";
17667
18177
 
17668
18178
  // src/commands/voice/checkLockFile.ts
17669
- import { execSync as execSync46 } from "child_process";
17670
- import { existsSync as existsSync44, mkdirSync as mkdirSync17, readFileSync as readFileSync36, writeFileSync as writeFileSync32 } from "fs";
17671
- import { join as join50 } from "path";
18179
+ import { execSync as execSync47 } from "child_process";
18180
+ import { existsSync as existsSync44, mkdirSync as mkdirSync17, readFileSync as readFileSync37, writeFileSync as writeFileSync33 } from "fs";
18181
+ import { join as join52 } from "path";
17672
18182
  function isProcessAlive2(pid) {
17673
18183
  try {
17674
18184
  process.kill(pid, 0);
@@ -17681,7 +18191,7 @@ function checkLockFile() {
17681
18191
  const lockFile = getLockFile();
17682
18192
  if (!existsSync44(lockFile)) return;
17683
18193
  try {
17684
- const lock = JSON.parse(readFileSync36(lockFile, "utf8"));
18194
+ const lock = JSON.parse(readFileSync37(lockFile, "utf8"));
17685
18195
  if (lock.pid && isProcessAlive2(lock.pid)) {
17686
18196
  console.error(
17687
18197
  `Voice daemon already running (PID ${lock.pid}, env: ${lock.env}). Stop it first with: assist voice stop`
@@ -17695,7 +18205,7 @@ function bootstrapVenv() {
17695
18205
  if (existsSync44(getVenvPython())) return;
17696
18206
  console.log("Setting up Python environment...");
17697
18207
  const pythonDir = getPythonDir();
17698
- execSync46(
18208
+ execSync47(
17699
18209
  `uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
17700
18210
  {
17701
18211
  stdio: "inherit",
@@ -17705,8 +18215,8 @@ function bootstrapVenv() {
17705
18215
  }
17706
18216
  function writeLockFile(pid) {
17707
18217
  const lockFile = getLockFile();
17708
- mkdirSync17(join50(lockFile, ".."), { recursive: true });
17709
- writeFileSync32(
18218
+ mkdirSync17(join52(lockFile, ".."), { recursive: true });
18219
+ writeFileSync33(
17710
18220
  lockFile,
17711
18221
  JSON.stringify({
17712
18222
  pid,
@@ -17721,7 +18231,7 @@ function setup() {
17721
18231
  mkdirSync18(voicePaths.dir, { recursive: true });
17722
18232
  bootstrapVenv();
17723
18233
  console.log("\nDownloading models...\n");
17724
- const script = join51(getPythonDir(), "setup_models.py");
18234
+ const script = join53(getPythonDir(), "setup_models.py");
17725
18235
  const result = spawnSync6(getVenvPython(), [script], {
17726
18236
  stdio: "inherit",
17727
18237
  env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
@@ -17734,8 +18244,8 @@ function setup() {
17734
18244
 
17735
18245
  // src/commands/voice/start.ts
17736
18246
  import { spawn as spawn7 } from "child_process";
17737
- import { mkdirSync as mkdirSync19, writeFileSync as writeFileSync33 } from "fs";
17738
- import { join as join52 } from "path";
18247
+ import { mkdirSync as mkdirSync19, writeFileSync as writeFileSync34 } from "fs";
18248
+ import { join as join54 } from "path";
17739
18249
 
17740
18250
  // src/commands/voice/buildDaemonEnv.ts
17741
18251
  function buildDaemonEnv(options2) {
@@ -17763,7 +18273,7 @@ function spawnBackground(python, script, env) {
17763
18273
  console.error("Failed to start voice daemon");
17764
18274
  process.exit(1);
17765
18275
  }
17766
- writeFileSync33(voicePaths.pid, String(pid));
18276
+ writeFileSync34(voicePaths.pid, String(pid));
17767
18277
  writeLockFile(pid);
17768
18278
  console.log(`Voice daemon started (PID ${pid})`);
17769
18279
  }
@@ -17773,7 +18283,7 @@ function start2(options2) {
17773
18283
  bootstrapVenv();
17774
18284
  const debug = options2.debug || options2.foreground || process.platform === "win32";
17775
18285
  const env = buildDaemonEnv({ debug });
17776
- const script = join52(getPythonDir(), "voice_daemon.py");
18286
+ const script = join54(getPythonDir(), "voice_daemon.py");
17777
18287
  const python = getVenvPython();
17778
18288
  if (options2.foreground) {
17779
18289
  spawnForeground(python, script, env);
@@ -17783,7 +18293,7 @@ function start2(options2) {
17783
18293
  }
17784
18294
 
17785
18295
  // src/commands/voice/status.ts
17786
- import { existsSync as existsSync45, readFileSync as readFileSync37 } from "fs";
18296
+ import { existsSync as existsSync45, readFileSync as readFileSync38 } from "fs";
17787
18297
  function isProcessAlive3(pid) {
17788
18298
  try {
17789
18299
  process.kill(pid, 0);
@@ -17794,7 +18304,7 @@ function isProcessAlive3(pid) {
17794
18304
  }
17795
18305
  function readRecentLogs(count6) {
17796
18306
  if (!existsSync45(voicePaths.log)) return [];
17797
- const lines = readFileSync37(voicePaths.log, "utf8").trim().split("\n");
18307
+ const lines = readFileSync38(voicePaths.log, "utf8").trim().split("\n");
17798
18308
  return lines.slice(-count6);
17799
18309
  }
17800
18310
  function status() {
@@ -17802,7 +18312,7 @@ function status() {
17802
18312
  console.log("Voice daemon: not running (no PID file)");
17803
18313
  return;
17804
18314
  }
17805
- const pid = Number.parseInt(readFileSync37(voicePaths.pid, "utf8").trim(), 10);
18315
+ const pid = Number.parseInt(readFileSync38(voicePaths.pid, "utf8").trim(), 10);
17806
18316
  const alive = isProcessAlive3(pid);
17807
18317
  console.log(`Voice daemon: ${alive ? "running" : "dead"} (PID ${pid})`);
17808
18318
  const recent = readRecentLogs(5);
@@ -17821,13 +18331,13 @@ function status() {
17821
18331
  }
17822
18332
 
17823
18333
  // src/commands/voice/stop.ts
17824
- import { existsSync as existsSync46, readFileSync as readFileSync38, unlinkSync as unlinkSync15 } from "fs";
18334
+ import { existsSync as existsSync46, readFileSync as readFileSync39, unlinkSync as unlinkSync15 } from "fs";
17825
18335
  function stop2() {
17826
18336
  if (!existsSync46(voicePaths.pid)) {
17827
18337
  console.log("Voice daemon is not running (no PID file)");
17828
18338
  return;
17829
18339
  }
17830
- const pid = Number.parseInt(readFileSync38(voicePaths.pid, "utf8").trim(), 10);
18340
+ const pid = Number.parseInt(readFileSync39(voicePaths.pid, "utf8").trim(), 10);
17831
18341
  try {
17832
18342
  process.kill(pid, "SIGTERM");
17833
18343
  console.log(`Sent SIGTERM to voice daemon (PID ${pid})`);
@@ -17859,7 +18369,7 @@ function registerVoice(program2) {
17859
18369
 
17860
18370
  // src/commands/roam/auth.ts
17861
18371
  import { randomBytes } from "crypto";
17862
- import chalk168 from "chalk";
18372
+ import chalk169 from "chalk";
17863
18373
 
17864
18374
  // src/commands/roam/waitForCallback.ts
17865
18375
  import { createServer as createServer3 } from "http";
@@ -17990,13 +18500,13 @@ async function auth() {
17990
18500
  saveGlobalConfig(config);
17991
18501
  const state = randomBytes(16).toString("hex");
17992
18502
  console.log(
17993
- chalk168.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
18503
+ chalk169.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
17994
18504
  );
17995
- console.log(chalk168.white("http://localhost:14523/callback\n"));
17996
- console.log(chalk168.blue("Opening browser for authorization..."));
17997
- console.log(chalk168.dim("Waiting for authorization callback..."));
18505
+ console.log(chalk169.white("http://localhost:14523/callback\n"));
18506
+ console.log(chalk169.blue("Opening browser for authorization..."));
18507
+ console.log(chalk169.dim("Waiting for authorization callback..."));
17998
18508
  const { code, redirectUri } = await authorizeInBrowser(clientId, state);
17999
- console.log(chalk168.dim("Exchanging code for tokens..."));
18509
+ console.log(chalk169.dim("Exchanging code for tokens..."));
18000
18510
  const tokens = await exchangeToken({
18001
18511
  code,
18002
18512
  clientId,
@@ -18012,14 +18522,14 @@ async function auth() {
18012
18522
  };
18013
18523
  saveGlobalConfig(config);
18014
18524
  console.log(
18015
- chalk168.green("Roam credentials and tokens saved to ~/.assist.yml")
18525
+ chalk169.green("Roam credentials and tokens saved to ~/.assist.yml")
18016
18526
  );
18017
18527
  }
18018
18528
 
18019
18529
  // src/commands/roam/postRoamActivity.ts
18020
18530
  import { execFileSync as execFileSync7 } from "child_process";
18021
- import { readdirSync as readdirSync8, readFileSync as readFileSync39, statSync as statSync6 } from "fs";
18022
- import { join as join53 } from "path";
18531
+ import { readdirSync as readdirSync8, readFileSync as readFileSync40, statSync as statSync6 } from "fs";
18532
+ import { join as join55 } from "path";
18023
18533
  function findPortFile(roamDir) {
18024
18534
  let entries;
18025
18535
  try {
@@ -18028,9 +18538,9 @@ function findPortFile(roamDir) {
18028
18538
  return void 0;
18029
18539
  }
18030
18540
  const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
18031
- const path58 = join53(roamDir, name);
18541
+ const path57 = join55(roamDir, name);
18032
18542
  try {
18033
- return { path: path58, mtimeMs: statSync6(path58).mtimeMs };
18543
+ return { path: path57, mtimeMs: statSync6(path57).mtimeMs };
18034
18544
  } catch {
18035
18545
  return void 0;
18036
18546
  }
@@ -18040,11 +18550,11 @@ function findPortFile(roamDir) {
18040
18550
  function postRoamActivity(app, event) {
18041
18551
  const appData = process.env.APPDATA;
18042
18552
  if (!appData) return;
18043
- const portFile = findPortFile(join53(appData, "Roam"));
18553
+ const portFile = findPortFile(join55(appData, "Roam"));
18044
18554
  if (!portFile) return;
18045
18555
  let port;
18046
18556
  try {
18047
- port = readFileSync39(portFile, "utf8").trim();
18557
+ port = readFileSync40(portFile, "utf8").trim();
18048
18558
  } catch {
18049
18559
  return;
18050
18560
  }
@@ -18088,7 +18598,7 @@ function registerRoam(program2) {
18088
18598
  }
18089
18599
 
18090
18600
  // src/commands/run/index.ts
18091
- import { resolve as resolve12 } from "path";
18601
+ import { resolve as resolve13 } from "path";
18092
18602
 
18093
18603
  // src/commands/run/findRunConfig.ts
18094
18604
  function exitNoRunConfigs() {
@@ -18172,11 +18682,11 @@ function resolveParams(params, cliArgs) {
18172
18682
  }
18173
18683
 
18174
18684
  // src/commands/run/runPreCommands.ts
18175
- import { execSync as execSync47 } from "child_process";
18685
+ import { execSync as execSync48 } from "child_process";
18176
18686
  function runPreCommands(pre, cwd) {
18177
18687
  for (const cmd of pre) {
18178
18688
  try {
18179
- execSync47(cmd, { stdio: "inherit", cwd });
18689
+ execSync48(cmd, { stdio: "inherit", cwd });
18180
18690
  } catch (error) {
18181
18691
  const code = error && typeof error === "object" && "status" in error ? error.status : 1;
18182
18692
  process.exit(code);
@@ -18187,13 +18697,13 @@ function runPreCommands(pre, cwd) {
18187
18697
  // src/commands/run/spawnRunCommand.ts
18188
18698
  import { execFileSync as execFileSync8, spawn as spawn8 } from "child_process";
18189
18699
  import { existsSync as existsSync47 } from "fs";
18190
- import { dirname as dirname27, join as join54, resolve as resolve11 } from "path";
18700
+ import { dirname as dirname27, join as join56, resolve as resolve12 } from "path";
18191
18701
  function resolveCommand2(command) {
18192
18702
  if (process.platform !== "win32" || command !== "bash") return command;
18193
18703
  try {
18194
18704
  const gitPath = execFileSync8("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
18195
- const gitRoot = resolve11(dirname27(gitPath), "..");
18196
- const gitBash = join54(gitRoot, "bin", "bash.exe");
18705
+ const gitRoot = resolve12(dirname27(gitPath), "..");
18706
+ const gitBash = join56(gitRoot, "bin", "bash.exe");
18197
18707
  if (existsSync47(gitBash)) return gitBash;
18198
18708
  } catch {
18199
18709
  }
@@ -18240,7 +18750,7 @@ function listRunConfigs(verbose) {
18240
18750
  }
18241
18751
  }
18242
18752
  function execRunConfig(config, args) {
18243
- const cwd = config.cwd ? resolve12(getConfigDir(), config.cwd) : void 0;
18753
+ const cwd = config.cwd ? resolve13(getConfigDir(), config.cwd) : void 0;
18244
18754
  if (config.pre) runPreCommands(config.pre, cwd);
18245
18755
  const resolved = resolveParams(config.params, args);
18246
18756
  spawnRunCommand(
@@ -18279,8 +18789,8 @@ async function run3(name, args) {
18279
18789
  }
18280
18790
 
18281
18791
  // src/commands/run/add.ts
18282
- import { mkdirSync as mkdirSync20, writeFileSync as writeFileSync34 } from "fs";
18283
- import { join as join55 } from "path";
18792
+ import { mkdirSync as mkdirSync20, writeFileSync as writeFileSync35 } from "fs";
18793
+ import { join as join57 } from "path";
18284
18794
 
18285
18795
  // src/commands/run/extractOption.ts
18286
18796
  function extractOption(args, flag) {
@@ -18341,7 +18851,7 @@ function saveNewRunConfig(name, command, args, cwd) {
18341
18851
  saveConfig(config);
18342
18852
  }
18343
18853
  function createCommandFile(name) {
18344
- const dir = join55(".claude", "commands");
18854
+ const dir = join57(".claude", "commands");
18345
18855
  mkdirSync20(dir, { recursive: true });
18346
18856
  const content = `---
18347
18857
  description: Run ${name}
@@ -18349,8 +18859,8 @@ description: Run ${name}
18349
18859
 
18350
18860
  Run \`assist run ${name} $ARGUMENTS 2>&1\`.
18351
18861
  `;
18352
- const filePath = join55(dir, `${name}.md`);
18353
- writeFileSync34(filePath, content);
18862
+ const filePath = join57(dir, `${name}.md`);
18863
+ writeFileSync35(filePath, content);
18354
18864
  console.log(`Created command file: ${filePath}`);
18355
18865
  }
18356
18866
  function add3() {
@@ -18373,11 +18883,11 @@ function findLinkIndex() {
18373
18883
  function parseLinkArgs() {
18374
18884
  const idx = findLinkIndex();
18375
18885
  if (idx === -1) return null;
18376
- const path58 = process.argv[idx + 1];
18886
+ const path57 = process.argv[idx + 1];
18377
18887
  const rest = process.argv.slice(idx + 2);
18378
18888
  const { value: prefix2 } = extractOption(rest, "--prefix");
18379
18889
  if (!prefix2) return null;
18380
- return { path: path58, prefix: prefix2 };
18890
+ return { path: path57, prefix: prefix2 };
18381
18891
  }
18382
18892
  function hasDuplicateLink(runList, linkPath) {
18383
18893
  return runList.some(
@@ -18406,7 +18916,7 @@ function link2() {
18406
18916
 
18407
18917
  // src/commands/run/remove.ts
18408
18918
  import { existsSync as existsSync48, unlinkSync as unlinkSync16 } from "fs";
18409
- import { join as join56 } from "path";
18919
+ import { join as join58 } from "path";
18410
18920
  function findRemoveIndex() {
18411
18921
  const idx = process.argv.indexOf("remove");
18412
18922
  if (idx === -1 || idx + 1 >= process.argv.length) return -1;
@@ -18421,7 +18931,7 @@ function parseRemoveName() {
18421
18931
  return process.argv[idx + 1];
18422
18932
  }
18423
18933
  function deleteCommandFile(name) {
18424
- const filePath = join56(".claude", "commands", `${name}.md`);
18934
+ const filePath = join58(".claude", "commands", `${name}.md`);
18425
18935
  if (existsSync48(filePath)) {
18426
18936
  unlinkSync16(filePath);
18427
18937
  console.log(`Deleted command file: ${filePath}`);
@@ -18460,11 +18970,11 @@ function registerRun(program2) {
18460
18970
  }
18461
18971
 
18462
18972
  // src/commands/screenshot/index.ts
18463
- import { execSync as execSync48 } from "child_process";
18464
- import { existsSync as existsSync49, mkdirSync as mkdirSync21, unlinkSync as unlinkSync17, writeFileSync as writeFileSync35 } from "fs";
18973
+ import { execSync as execSync49 } from "child_process";
18974
+ import { existsSync as existsSync49, mkdirSync as mkdirSync21, unlinkSync as unlinkSync17, writeFileSync as writeFileSync36 } from "fs";
18465
18975
  import { tmpdir as tmpdir7 } from "os";
18466
- import { join as join57, resolve as resolve13 } from "path";
18467
- import chalk169 from "chalk";
18976
+ import { join as join59, resolve as resolve14 } from "path";
18977
+ import chalk170 from "chalk";
18468
18978
 
18469
18979
  // src/commands/screenshot/captureWindowPs1.ts
18470
18980
  var captureWindowPs1 = `
@@ -18597,13 +19107,13 @@ function buildOutputPath(outputDir, processName) {
18597
19107
  mkdirSync21(outputDir, { recursive: true });
18598
19108
  }
18599
19109
  const timestamp2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
18600
- return resolve13(outputDir, `${processName}-${timestamp2}.png`);
19110
+ return resolve14(outputDir, `${processName}-${timestamp2}.png`);
18601
19111
  }
18602
19112
  function runPowerShellScript(processName, outputPath) {
18603
- const scriptPath = join57(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
18604
- writeFileSync35(scriptPath, captureWindowPs1, "utf8");
19113
+ const scriptPath = join59(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
19114
+ writeFileSync36(scriptPath, captureWindowPs1, "utf8");
18605
19115
  try {
18606
- execSync48(
19116
+ execSync49(
18607
19117
  `powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
18608
19118
  { stdio: ["ignore", "pipe", "pipe"], encoding: "utf8" }
18609
19119
  );
@@ -18613,15 +19123,15 @@ function runPowerShellScript(processName, outputPath) {
18613
19123
  }
18614
19124
  function screenshot(processName) {
18615
19125
  const config = loadConfig();
18616
- const outputDir = resolve13(config.screenshot.outputDir);
19126
+ const outputDir = resolve14(config.screenshot.outputDir);
18617
19127
  const outputPath = buildOutputPath(outputDir, processName);
18618
- console.log(chalk169.gray(`Capturing window for process "${processName}" ...`));
19128
+ console.log(chalk170.gray(`Capturing window for process "${processName}" ...`));
18619
19129
  try {
18620
19130
  runPowerShellScript(processName, outputPath);
18621
- console.log(chalk169.green(`Screenshot saved: ${outputPath}`));
19131
+ console.log(chalk170.green(`Screenshot saved: ${outputPath}`));
18622
19132
  } catch (error) {
18623
19133
  const msg = error instanceof Error ? error.message : String(error);
18624
- console.error(chalk169.red(`Failed to capture screenshot: ${msg}`));
19134
+ console.error(chalk170.red(`Failed to capture screenshot: ${msg}`));
18625
19135
  process.exit(1);
18626
19136
  }
18627
19137
  }
@@ -18677,7 +19187,7 @@ function applyLine(result, pending, line) {
18677
19187
  }
18678
19188
 
18679
19189
  // src/commands/sessions/daemon/reportStolenSocket.ts
18680
- import { readFileSync as readFileSync40 } from "fs";
19190
+ import { readFileSync as readFileSync41 } from "fs";
18681
19191
  function reportStolenSocket(socketPid) {
18682
19192
  if (!socketPid) return;
18683
19193
  const filePid = readPidFile();
@@ -18689,7 +19199,7 @@ function reportStolenSocket(socketPid) {
18689
19199
  function readPidFile() {
18690
19200
  try {
18691
19201
  const pid = Number.parseInt(
18692
- readFileSync40(daemonPaths.pid, "utf8").trim(),
19202
+ readFileSync41(daemonPaths.pid, "utf8").trim(),
18693
19203
  10
18694
19204
  );
18695
19205
  return Number.isInteger(pid) ? pid : void 0;
@@ -19017,6 +19527,9 @@ function createAssistSession(id2, assistArgs, cwd) {
19017
19527
  };
19018
19528
  }
19019
19529
 
19530
+ // src/commands/sessions/daemon/createSession.ts
19531
+ import { randomUUID as randomUUID4 } from "crypto";
19532
+
19020
19533
  // src/commands/sessions/daemon/spawnClaude.ts
19021
19534
  function spawnClaude2(opts = {}) {
19022
19535
  return spawnPty(buildArgs3(opts), opts.cwd, opts.sessionId);
@@ -19026,6 +19539,7 @@ function buildArgs3(opts) {
19026
19539
  if (opts.resumeSessionId) {
19027
19540
  return opts.prompt ? [...base, "--resume", opts.resumeSessionId, opts.prompt] : [...base, "--resume", opts.resumeSessionId];
19028
19541
  }
19542
+ if (opts.claudeSessionId) base.push("--session-id", opts.claudeSessionId);
19029
19543
  if (opts.prompt) return [...base, opts.prompt];
19030
19544
  return base;
19031
19545
  }
@@ -19036,33 +19550,34 @@ function spawnRun(opts) {
19036
19550
  }
19037
19551
 
19038
19552
  // src/commands/sessions/daemon/createSession.ts
19039
- function createSession(id2, prompt, cwd) {
19553
+ function runningBase(id2) {
19040
19554
  const startedAt = Date.now();
19041
19555
  return {
19042
19556
  id: id2,
19043
- name: prompt?.slice(0, 40) || `Session ${id2}`,
19044
- commandType: "claude",
19045
19557
  status: "running",
19046
19558
  startedAt,
19047
19559
  runningMs: 0,
19048
19560
  runningSince: startedAt,
19049
- pty: spawnClaude2({ prompt, cwd, sessionId: id2 }),
19050
- scrollback: "",
19051
- 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
19052
19573
  };
19053
19574
  }
19054
19575
  function createRunSession(id2, runName, runArgs, cwd) {
19055
- const startedAt = Date.now();
19056
19576
  return {
19057
- id: id2,
19577
+ ...runningBase(id2),
19058
19578
  name: `run: ${runName}`,
19059
19579
  commandType: "run",
19060
- status: "running",
19061
- startedAt,
19062
- runningMs: 0,
19063
- runningSince: startedAt,
19064
19580
  pty: spawnRun({ name: runName, args: runArgs, cwd }),
19065
- scrollback: "",
19066
19581
  runName,
19067
19582
  runArgs,
19068
19583
  cwd
@@ -19126,10 +19641,14 @@ function disarmEscInterrupt(session) {
19126
19641
 
19127
19642
  // src/commands/sessions/daemon/shouldAutoDismiss.ts
19128
19643
  function shouldAutoDismiss(session, exitCode) {
19129
- const args = session.assistArgs;
19130
- if (session.status !== "done" || exitCode !== 0 || args === void 0) {
19644
+ if (session.status !== "done" || exitCode !== 0) {
19131
19645
  return false;
19132
19646
  }
19647
+ if (session.reviewStarted) {
19648
+ return session.autoAdvance === true;
19649
+ }
19650
+ const args = session.assistArgs;
19651
+ if (args === void 0) return false;
19133
19652
  if (args[0] === "update") return true;
19134
19653
  return args.includes("--once") && args[0] !== "next";
19135
19654
  }
@@ -19214,9 +19733,25 @@ function runningSession(base, persisted, pty2) {
19214
19733
  };
19215
19734
  }
19216
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
+
19217
19751
  // src/commands/sessions/daemon/restoreSession.ts
19218
19752
  function restoreSession(id2, persisted) {
19219
19753
  const base = restoreBase(id2, persisted);
19754
+ if (isUpdate(persisted)) return updatedSession(id2, persisted);
19220
19755
  if (isBacklogRun(persisted)) {
19221
19756
  const pty2 = spawnPty(backlogRunArgs(persisted), persisted.cwd, id2);
19222
19757
  return runningSession(base, persisted, pty2);
@@ -19296,18 +19831,35 @@ function resumeSession(id2, sessionId, cwd, name) {
19296
19831
  runningSince: startedAt,
19297
19832
  pty: spawnClaude2({ resumeSessionId: sessionId, cwd, sessionId: id2 }),
19298
19833
  scrollback: "",
19299
- 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
19300
19839
  };
19301
19840
  }
19302
19841
 
19303
19842
  // src/commands/sessions/daemon/watchActivity.ts
19304
19843
  import { existsSync as existsSync51, mkdirSync as mkdirSync22, watch } from "fs";
19305
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
19306
19858
  var DEBOUNCE_MS = 50;
19307
19859
  function watchActivity(session, notify2) {
19308
19860
  if (session.commandType !== "assist" || !session.cwd) return;
19309
- const path58 = activityPath(session.id);
19310
- const dir = dirname28(path58);
19861
+ const path57 = activityPath(session.id);
19862
+ const dir = dirname28(path57);
19311
19863
  try {
19312
19864
  mkdirSync22(dir, { recursive: true });
19313
19865
  } catch {
@@ -19317,19 +19869,20 @@ function watchActivity(session, notify2) {
19317
19869
  let timer = null;
19318
19870
  const read = () => {
19319
19871
  timer = null;
19320
- const activity2 = readActivity(path58);
19872
+ const activity2 = readActivity(path57);
19321
19873
  if (!activity2) return;
19322
19874
  session.activity = activity2;
19323
19875
  if (activity2.claudeSessionId)
19324
19876
  session.claudeSessionId = activity2.claudeSessionId;
19877
+ applyReviewPause(session, activity2);
19325
19878
  notify2();
19326
19879
  };
19327
19880
  session.activityWatcher = watch(dir, (_event, filename) => {
19328
- if (filename && !path58.endsWith(filename)) return;
19881
+ if (filename && !path57.endsWith(filename)) return;
19329
19882
  if (timer) clearTimeout(timer);
19330
19883
  timer = setTimeout(read, DEBOUNCE_MS);
19331
19884
  });
19332
- if (existsSync51(path58)) read();
19885
+ if (existsSync51(path57)) read();
19333
19886
  }
19334
19887
  function refreshActivity(session) {
19335
19888
  if (session.commandType !== "assist" || !session.cwd) return;
@@ -19946,9 +20499,144 @@ var WindowsProxy = class {
19946
20499
  }
19947
20500
  };
19948
20501
 
19949
- // src/commands/sessions/daemon/watchClaudeSessionId.ts
19950
- import * as fs31 from "fs";
19951
- 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";
19952
20640
 
19953
20641
  // src/commands/sessions/shared/discoverSessions.ts
19954
20642
  import * as fs30 from "fs";
@@ -20136,211 +20824,8 @@ async function discoverSessions() {
20136
20824
  return sessions;
20137
20825
  }
20138
20826
 
20139
- // src/commands/sessions/daemon/watchClaudeSessionId.ts
20140
- var POLL_MS = 3e3;
20141
- async function watchClaudeSessionId(options2) {
20142
- let adoptedMs = 0;
20143
- while (options2.isActive()) {
20144
- const latest = await findLatestSessionId(options2);
20145
- if (latest && latest.createdMs > adoptedMs) {
20146
- adoptedMs = latest.createdMs;
20147
- options2.onSessionId(latest.sessionId);
20148
- }
20149
- await sleep(options2.pollMs ?? POLL_MS);
20150
- }
20151
- }
20152
- async function findLatestSessionId(options2) {
20153
- const paths = await discoverSessionJsonlPaths();
20154
- let latest = null;
20155
- for (const { path: filePath, origin } of paths) {
20156
- const createdMs = await createdSince(filePath, options2.sinceMs);
20157
- if (createdMs === null) continue;
20158
- const meta = await parseSessionFile(filePath, origin);
20159
- if (!meta?.cwd || options2.isClaimed(meta.sessionId)) continue;
20160
- if (path52.resolve(meta.cwd) !== path52.resolve(options2.cwd)) continue;
20161
- if (!latest || createdMs > latest.createdMs)
20162
- latest = { sessionId: meta.sessionId, createdMs };
20163
- }
20164
- return latest;
20165
- }
20166
- async function createdSince(filePath, sinceMs) {
20167
- try {
20168
- const stat = await fs31.promises.stat(filePath);
20169
- const createdMs = stat.birthtimeMs || stat.mtimeMs;
20170
- return createdMs >= sinceMs ? createdMs : null;
20171
- } catch {
20172
- return null;
20173
- }
20174
- }
20175
- function sleep(ms) {
20176
- return new Promise((resolve16) => setTimeout(resolve16, ms));
20177
- }
20178
-
20179
- // src/commands/sessions/daemon/watchForClaudeSessionId.ts
20180
- function watchForClaudeSessionId(session, sessions, onDiscovered) {
20181
- if (session.commandType === "run" || !session.pty) return;
20182
- if (isBacklogRun2(session)) return;
20183
- void watchClaudeSessionId({
20184
- cwd: session.cwd ?? process.cwd(),
20185
- sinceMs: session.startedAt,
20186
- isClaimed: (sessionId) => [...sessions.values()].some((s) => s.claudeSessionId === sessionId),
20187
- isActive: () => {
20188
- const s = sessions.get(session.id);
20189
- return !!s && s.status !== "done";
20190
- },
20191
- onSessionId: (sessionId) => {
20192
- if (!sessions.has(session.id)) return;
20193
- session.claudeSessionId = sessionId;
20194
- onDiscovered();
20195
- }
20196
- });
20197
- }
20198
- function isBacklogRun2(session) {
20199
- return session.commandType === "assist" && session.assistArgs?.[0] === "backlog" && session.assistArgs?.[1] === "run";
20200
- }
20201
-
20202
- // src/commands/sessions/daemon/writeToSession.ts
20203
- function writeToSession(sessions, id2, data, onStatusChange) {
20204
- const s = sessions.get(id2);
20205
- if (!s || s.status === "done") return;
20206
- s.pty?.write(data);
20207
- watchEscInterrupt(s, data, onStatusChange);
20208
- }
20209
- function resizeSession(sessions, id2, cols, rows) {
20210
- const s = sessions.get(id2);
20211
- if (s && s.status !== "done") s.pty?.resize(cols, rows);
20212
- }
20213
- function setAutoRun(sessions, id2, enabled) {
20214
- const s = sessions.get(id2);
20215
- if (!s) return false;
20216
- s.autoRun = enabled;
20217
- return true;
20218
- }
20219
- function setAutoAdvance(sessions, id2, enabled) {
20220
- const s = sessions.get(id2);
20221
- if (!s) return false;
20222
- s.autoAdvance = enabled;
20223
- const itemId = s.activity?.itemId;
20224
- if (itemId != null) {
20225
- if (enabled) clearPause(itemId);
20226
- else requestPause(itemId);
20227
- }
20228
- return true;
20229
- }
20230
- function dismissSession(sessions, id2) {
20231
- const s = sessions.get(id2);
20232
- if (!s) return false;
20233
- if (s.status !== "done") s.pty?.kill();
20234
- s.activityWatcher?.close();
20235
- removeActivity(s.id);
20236
- if (s.activity?.itemId != null) releaseLock(s.activity.itemId);
20237
- sessions.delete(id2);
20238
- return true;
20239
- }
20240
-
20241
- // src/commands/sessions/daemon/SessionManager.ts
20242
- var SessionManager = class {
20243
- constructor(onIdleChange) {
20244
- this.onIdleChange = onIdleChange;
20245
- }
20246
- sessions = /* @__PURE__ */ new Map();
20247
- // why: dispatch calls active.set() on card click; broadcasts include active.toJSON()
20248
- active = new ActiveSelection(() => this.notify());
20249
- clients = new ClientHub(persistUsagePeak);
20250
- nextId = 1;
20251
- shuttingDown = false;
20252
- // why: dispatch calls windowsProxy.route() to forward windows-origin sessions
20253
- windowsProxy = new WindowsProxy(this.clients, () => this.notify());
20254
- addClient(client) {
20255
- this.clients.add(client);
20256
- this.notify();
20257
- greetClient(client, this.sessions, this.windowsProxy);
20258
- }
20259
- removeClient(client) {
20260
- this.clients.delete(client);
20261
- this.onIdleChange?.(this.isIdle());
20262
- }
20263
- isIdle = () => this.sessions.size === 0 && this.clients.size === 0;
20264
- shutdown() {
20265
- this.shuttingDown = true;
20266
- shutdownSessions(this.sessions);
20267
- }
20268
- restore() {
20269
- return restoreAll(this.spawnWith, this.sessions);
20270
- }
20271
- add(session) {
20272
- this.wire(session);
20273
- watchForClaudeSessionId(session, this.sessions, this.notify);
20274
- watchActivity(session, this.notify);
20275
- return session.id;
20276
- }
20277
- spawnWith = (create) => this.add(create(String(this.nextId++)));
20278
- spawn(prompt, cwd) {
20279
- return this.spawnWith((id2) => createSession(id2, prompt, cwd));
20280
- }
20281
- spawnRun(runName, runArgs, cwd) {
20282
- return this.spawnWith((id2) => createRunSession(id2, runName, runArgs, cwd));
20283
- }
20284
- spawnAssist(assistArgs, cwd) {
20285
- return this.spawnWith((id2) => createAssistSession(id2, assistArgs, cwd));
20286
- }
20287
- resume(sessionId, cwd, name) {
20288
- return this.spawnWith((id2) => resumeSession(id2, sessionId, cwd, name));
20289
- }
20290
- onStatusChange = makeStatusChangeHandler(
20291
- (id2) => this.dismissSession(id2),
20292
- () => this.notify(),
20293
- (session, itemId) => reuseSessionForRun(session, itemId, this.clients, this.onStatusChange)
20294
- );
20295
- wire(session) {
20296
- this.sessions.set(session.id, session);
20297
- wirePtyEvents(session, this.clients, this.onStatusChange);
20298
- this.notify();
20299
- }
20300
- writeToSession(id2, data) {
20301
- writeToSession(this.sessions, id2, data, this.onStatusChange);
20302
- }
20303
- resizeSession(id2, cols, rows) {
20304
- resizeSession(this.sessions, id2, cols, rows);
20305
- }
20306
- retrySession(id2) {
20307
- const s = this.sessions.get(id2);
20308
- if (s && retrySession(s, this.clients, this.onStatusChange)) this.notify();
20309
- }
20310
- dismissSession = (id2) => {
20311
- if (dismissSession(this.sessions, id2)) this.notify();
20312
- };
20313
- setAutoRun(id2, enabled) {
20314
- if (setAutoRun(this.sessions, id2, enabled)) this.notify();
20315
- }
20316
- setAutoAdvance(id2, enabled) {
20317
- if (setAutoAdvance(this.sessions, id2, enabled)) this.notify();
20318
- }
20319
- setStatus(id2, status2) {
20320
- const session = this.sessions.get(id2);
20321
- if (session) this.onStatusChange(session, status2);
20322
- }
20323
- listSessions = () => {
20324
- const local = [...this.sessions.values()].map(toSessionInfo);
20325
- return local.concat(this.windowsProxy.sessions());
20326
- };
20327
- notify = () => {
20328
- if (this.shuttingDown) return;
20329
- const windows = this.windowsProxy.sessions();
20330
- broadcastSessions(this.sessions, this.clients, windows, this.active);
20331
- this.onIdleChange?.(this.isIdle());
20332
- };
20333
- };
20334
-
20335
- // src/commands/sessions/daemon/startDaemonServer.ts
20336
- import { unlinkSync as unlinkSync19 } from "fs";
20337
- import * as net3 from "net";
20338
-
20339
- // src/commands/sessions/daemon/handleConnection.ts
20340
- import { createInterface as createInterface7 } from "readline";
20341
-
20342
20827
  // src/commands/sessions/shared/parseTranscript.ts
20343
- import * as fs32 from "fs";
20828
+ import * as fs31 from "fs";
20344
20829
 
20345
20830
  // src/commands/sessions/shared/toolTarget.ts
20346
20831
  function toolTarget(input) {
@@ -20388,11 +20873,11 @@ function cleanUserText(value) {
20388
20873
  }
20389
20874
 
20390
20875
  // src/commands/sessions/shared/findSessionJsonlPath.ts
20391
- import * as path53 from "path";
20876
+ import * as path52 from "path";
20392
20877
  async function findSessionJsonlPath(sessionId) {
20393
20878
  const paths = await discoverSessionJsonlPaths();
20394
20879
  const direct = paths.find(
20395
- (p) => path53.basename(p.path, ".jsonl") === sessionId
20880
+ (p) => path52.basename(p.path, ".jsonl") === sessionId
20396
20881
  );
20397
20882
  if (direct) return direct.path;
20398
20883
  for (const p of paths) {
@@ -20407,7 +20892,7 @@ async function parseTranscript(sessionId) {
20407
20892
  const filePath = await findSessionJsonlPath(sessionId);
20408
20893
  if (!filePath) return [];
20409
20894
  try {
20410
- const raw = await fs32.promises.readFile(filePath, "utf8");
20895
+ const raw = await fs31.promises.readFile(filePath, "utf8");
20411
20896
  return parseTranscriptLines(raw.split("\n"));
20412
20897
  } catch {
20413
20898
  return [];
@@ -20552,10 +21037,10 @@ function handleConnection(socket, manager) {
20552
21037
  }
20553
21038
 
20554
21039
  // src/commands/sessions/daemon/onListening.ts
20555
- import { unlinkSync as unlinkSync18, writeFileSync as writeFileSync36 } from "fs";
21040
+ import { unlinkSync as unlinkSync18, writeFileSync as writeFileSync37 } from "fs";
20556
21041
 
20557
21042
  // src/commands/sessions/daemon/startPidFileWatchdog.ts
20558
- import { readFileSync as readFileSync41 } from "fs";
21043
+ import { readFileSync as readFileSync42 } from "fs";
20559
21044
  var WATCHDOG_INTERVAL_MS = 5e3;
20560
21045
  function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
20561
21046
  const timer = setInterval(() => {
@@ -20566,7 +21051,7 @@ function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
20566
21051
  }
20567
21052
  function ownsPidFile() {
20568
21053
  try {
20569
- return readFileSync41(daemonPaths.pid, "utf8").trim() === String(process.pid);
21054
+ return readFileSync42(daemonPaths.pid, "utf8").trim() === String(process.pid);
20570
21055
  } catch {
20571
21056
  return false;
20572
21057
  }
@@ -20574,7 +21059,7 @@ function ownsPidFile() {
20574
21059
 
20575
21060
  // src/commands/sessions/daemon/onListening.ts
20576
21061
  function onListening(manager, checkAutoExit) {
20577
- writeFileSync36(daemonPaths.pid, String(process.pid));
21062
+ writeFileSync37(daemonPaths.pid, String(process.pid));
20578
21063
  startPidFileWatchdog(() => {
20579
21064
  daemonLog("lost daemon.pid ownership; shutting down sessions and exiting");
20580
21065
  manager.shutdown();
@@ -20707,17 +21192,17 @@ async function setSessionStatus(status2) {
20707
21192
  }
20708
21193
 
20709
21194
  // src/commands/sessions/summarise/index.ts
20710
- import * as fs35 from "fs";
20711
- import chalk170 from "chalk";
21195
+ import * as fs34 from "fs";
21196
+ import chalk171 from "chalk";
20712
21197
 
20713
21198
  // src/commands/sessions/summarise/shared.ts
20714
- import * as fs33 from "fs";
21199
+ import * as fs32 from "fs";
20715
21200
  function writeSummary(jsonlPath2, summary) {
20716
- fs33.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
21201
+ fs32.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
20717
21202
  `, "utf8");
20718
21203
  }
20719
21204
  function hasSummary(jsonlPath2) {
20720
- return fs33.existsSync(summaryPathFor(jsonlPath2));
21205
+ return fs32.existsSync(summaryPathFor(jsonlPath2));
20721
21206
  }
20722
21207
  function summaryPathFor(jsonlPath2) {
20723
21208
  return jsonlPath2.replace(/\.jsonl$/, ".summary");
@@ -20727,7 +21212,7 @@ function summaryPathFor(jsonlPath2) {
20727
21212
  import { execFileSync as execFileSync10 } from "child_process";
20728
21213
 
20729
21214
  // src/commands/sessions/summarise/iterateUserMessages.ts
20730
- import * as fs34 from "fs";
21215
+ import * as fs33 from "fs";
20731
21216
 
20732
21217
  // src/commands/sessions/summarise/parseUserLine.ts
20733
21218
  function parseUserLine(line) {
@@ -20758,13 +21243,13 @@ function parseUserLine(line) {
20758
21243
  function* iterateUserMessages(filePath, maxBytes = 65536) {
20759
21244
  let content;
20760
21245
  try {
20761
- const fd = fs34.openSync(filePath, "r");
21246
+ const fd = fs33.openSync(filePath, "r");
20762
21247
  try {
20763
21248
  const buf = Buffer.alloc(maxBytes);
20764
- const bytesRead = fs34.readSync(fd, buf, 0, buf.length, 0);
21249
+ const bytesRead = fs33.readSync(fd, buf, 0, buf.length, 0);
20765
21250
  content = buf.toString("utf8", 0, bytesRead);
20766
21251
  } finally {
20767
- fs34.closeSync(fd);
21252
+ fs33.closeSync(fd);
20768
21253
  }
20769
21254
  } catch {
20770
21255
  return;
@@ -20862,29 +21347,29 @@ ${firstMessage}`);
20862
21347
  async function summarise3(options2) {
20863
21348
  const files = await discoverSessionFiles();
20864
21349
  if (files.length === 0) {
20865
- console.log(chalk170.yellow("No sessions found."));
21350
+ console.log(chalk171.yellow("No sessions found."));
20866
21351
  return;
20867
21352
  }
20868
21353
  const toProcess = selectCandidates(files, options2);
20869
21354
  if (toProcess.length === 0) {
20870
- console.log(chalk170.green("All sessions already summarised."));
21355
+ console.log(chalk171.green("All sessions already summarised."));
20871
21356
  return;
20872
21357
  }
20873
21358
  console.log(
20874
- chalk170.cyan(
21359
+ chalk171.cyan(
20875
21360
  `Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
20876
21361
  )
20877
21362
  );
20878
21363
  const { succeeded, failed: failed2 } = processSessions(toProcess);
20879
21364
  console.log(
20880
- chalk170.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk170.yellow(`, ${failed2} skipped`) : "")
21365
+ chalk171.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk171.yellow(`, ${failed2} skipped`) : "")
20881
21366
  );
20882
21367
  }
20883
21368
  function selectCandidates(files, options2) {
20884
21369
  const candidates = options2.force ? files : files.filter((f) => !hasSummary(f));
20885
21370
  candidates.sort((a, b) => {
20886
21371
  try {
20887
- return fs35.statSync(b).mtimeMs - fs35.statSync(a).mtimeMs;
21372
+ return fs34.statSync(b).mtimeMs - fs34.statSync(a).mtimeMs;
20888
21373
  } catch {
20889
21374
  return 0;
20890
21375
  }
@@ -20897,16 +21382,16 @@ function processSessions(files) {
20897
21382
  let failed2 = 0;
20898
21383
  for (let i = 0; i < files.length; i++) {
20899
21384
  const file = files[i];
20900
- process.stdout.write(chalk170.dim(` [${i + 1}/${files.length}] `));
21385
+ process.stdout.write(chalk171.dim(` [${i + 1}/${files.length}] `));
20901
21386
  const summary = summariseSession(file);
20902
21387
  if (summary) {
20903
21388
  writeSummary(file, summary);
20904
21389
  succeeded++;
20905
- process.stdout.write(`${chalk170.green("\u2713")} ${summary}
21390
+ process.stdout.write(`${chalk171.green("\u2713")} ${summary}
20906
21391
  `);
20907
21392
  } else {
20908
21393
  failed2++;
20909
- process.stdout.write(` ${chalk170.yellow("skip")}
21394
+ process.stdout.write(` ${chalk171.yellow("skip")}
20910
21395
  `);
20911
21396
  }
20912
21397
  }
@@ -20924,10 +21409,10 @@ function registerSessions(program2) {
20924
21409
  }
20925
21410
 
20926
21411
  // src/commands/statusLine.ts
20927
- import chalk172 from "chalk";
21412
+ import chalk173 from "chalk";
20928
21413
 
20929
21414
  // src/commands/buildLimitsSegment.ts
20930
- import chalk171 from "chalk";
21415
+ import chalk172 from "chalk";
20931
21416
 
20932
21417
  // src/shared/rateLimitLevel.ts
20933
21418
  var FIVE_HOUR_SECONDS = 5 * 3600;
@@ -20958,9 +21443,9 @@ function rateLimitLevel(pct, resetsAt, windowSeconds, now) {
20958
21443
 
20959
21444
  // src/commands/buildLimitsSegment.ts
20960
21445
  var LEVEL_COLOR = {
20961
- ok: chalk171.green,
20962
- warn: chalk171.yellow,
20963
- over: chalk171.red
21446
+ ok: chalk172.green,
21447
+ warn: chalk172.yellow,
21448
+ over: chalk172.red
20964
21449
  };
20965
21450
  function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel, now) {
20966
21451
  const level = rateLimitLevel(pct, resetsAt, windowSeconds, now);
@@ -21000,14 +21485,14 @@ async function relayRateLimits(rateLimits) {
21000
21485
  }
21001
21486
 
21002
21487
  // src/commands/statusLine.ts
21003
- chalk172.level = 3;
21488
+ chalk173.level = 3;
21004
21489
  function formatNumber(num) {
21005
21490
  return num.toLocaleString("en-US");
21006
21491
  }
21007
21492
  function colorizePercent(pct) {
21008
21493
  const label2 = `${Math.round(pct)}%`;
21009
- if (pct > 80) return chalk172.red(label2);
21010
- if (pct > 40) return chalk172.yellow(label2);
21494
+ if (pct > 80) return chalk173.red(label2);
21495
+ if (pct > 40) return chalk173.yellow(label2);
21011
21496
  return label2;
21012
21497
  }
21013
21498
  async function statusLine() {
@@ -21023,29 +21508,29 @@ async function statusLine() {
21023
21508
  }
21024
21509
 
21025
21510
  // src/commands/sync.ts
21026
- import * as fs38 from "fs";
21511
+ import * as fs37 from "fs";
21027
21512
  import * as os2 from "os";
21028
- import * as path56 from "path";
21513
+ import * as path55 from "path";
21029
21514
  import { fileURLToPath as fileURLToPath7 } from "url";
21030
21515
 
21031
21516
  // src/commands/sync/syncClaudeMd.ts
21032
- import * as fs36 from "fs";
21033
- import * as path54 from "path";
21034
- import chalk173 from "chalk";
21517
+ import * as fs35 from "fs";
21518
+ import * as path53 from "path";
21519
+ import chalk174 from "chalk";
21035
21520
  async function syncClaudeMd(claudeDir, targetBase, options2) {
21036
- const source = path54.join(claudeDir, "CLAUDE.md");
21037
- const target = path54.join(targetBase, "CLAUDE.md");
21038
- const sourceContent = fs36.readFileSync(source, "utf8");
21039
- if (fs36.existsSync(target)) {
21040
- 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");
21041
21526
  if (sourceContent !== targetContent) {
21042
21527
  console.log(
21043
- chalk173.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
21528
+ chalk174.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
21044
21529
  );
21045
21530
  console.log();
21046
21531
  printDiff(targetContent, sourceContent);
21047
21532
  const confirm = options2?.yes || await promptConfirm(
21048
- chalk173.red("Overwrite existing CLAUDE.md?"),
21533
+ chalk174.red("Overwrite existing CLAUDE.md?"),
21049
21534
  false
21050
21535
  );
21051
21536
  if (!confirm) {
@@ -21054,21 +21539,21 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
21054
21539
  }
21055
21540
  }
21056
21541
  }
21057
- fs36.copyFileSync(source, target);
21542
+ fs35.copyFileSync(source, target);
21058
21543
  console.log("Copied CLAUDE.md to ~/.claude/CLAUDE.md");
21059
21544
  }
21060
21545
 
21061
21546
  // src/commands/sync/syncSettings.ts
21062
- import * as fs37 from "fs";
21063
- import * as path55 from "path";
21064
- import chalk174 from "chalk";
21547
+ import * as fs36 from "fs";
21548
+ import * as path54 from "path";
21549
+ import chalk175 from "chalk";
21065
21550
  async function syncSettings(claudeDir, targetBase, options2) {
21066
- const source = path55.join(claudeDir, "settings.json");
21067
- const target = path55.join(targetBase, "settings.json");
21068
- 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");
21069
21554
  const mergedContent = JSON.stringify(JSON.parse(sourceContent), null, " ");
21070
- if (fs37.existsSync(target)) {
21071
- const targetContent = fs37.readFileSync(target, "utf8");
21555
+ if (fs36.existsSync(target)) {
21556
+ const targetContent = fs36.readFileSync(target, "utf8");
21072
21557
  const normalizedTarget = JSON.stringify(
21073
21558
  JSON.parse(targetContent),
21074
21559
  null,
@@ -21077,14 +21562,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
21077
21562
  if (mergedContent !== normalizedTarget) {
21078
21563
  if (!options2?.yes) {
21079
21564
  console.log(
21080
- chalk174.yellow(
21565
+ chalk175.yellow(
21081
21566
  "\n\u26A0\uFE0F Warning: settings.json differs from existing file"
21082
21567
  )
21083
21568
  );
21084
21569
  console.log();
21085
21570
  printDiff(targetContent, mergedContent);
21086
21571
  const confirm = await promptConfirm(
21087
- chalk174.red("Overwrite existing settings.json?"),
21572
+ chalk175.red("Overwrite existing settings.json?"),
21088
21573
  false
21089
21574
  );
21090
21575
  if (!confirm) {
@@ -21094,37 +21579,37 @@ async function syncSettings(claudeDir, targetBase, options2) {
21094
21579
  }
21095
21580
  }
21096
21581
  }
21097
- fs37.writeFileSync(target, mergedContent);
21582
+ fs36.writeFileSync(target, mergedContent);
21098
21583
  console.log("Copied settings.json to ~/.claude/settings.json");
21099
21584
  }
21100
21585
 
21101
21586
  // src/commands/sync.ts
21102
21587
  var __filename4 = fileURLToPath7(import.meta.url);
21103
- var __dirname6 = path56.dirname(__filename4);
21588
+ var __dirname6 = path55.dirname(__filename4);
21104
21589
  async function sync(options2) {
21105
21590
  const config = loadConfig();
21106
21591
  const yes = options2?.yes ?? config.sync.autoConfirm;
21107
- const claudeDir = path56.join(__dirname6, "..", "claude");
21108
- const targetBase = path56.join(os2.homedir(), ".claude");
21592
+ const claudeDir = path55.join(__dirname6, "..", "claude");
21593
+ const targetBase = path55.join(os2.homedir(), ".claude");
21109
21594
  syncCommands(claudeDir, targetBase);
21110
21595
  await syncSettings(claudeDir, targetBase, { yes });
21111
21596
  await syncClaudeMd(claudeDir, targetBase, { yes });
21112
21597
  }
21113
21598
  function syncCommands(claudeDir, targetBase) {
21114
- const sourceDir = path56.join(claudeDir, "commands");
21115
- const targetDir = path56.join(targetBase, "commands");
21116
- fs38.mkdirSync(targetDir, { recursive: true });
21117
- 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);
21118
21603
  for (const file of files) {
21119
- fs38.copyFileSync(path56.join(sourceDir, file), path56.join(targetDir, file));
21604
+ fs37.copyFileSync(path55.join(sourceDir, file), path55.join(targetDir, file));
21120
21605
  console.log(`Copied ${file} to ${targetDir}`);
21121
21606
  }
21122
21607
  console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
21123
21608
  }
21124
21609
 
21125
21610
  // src/commands/update.ts
21126
- import { execSync as execSync49 } from "child_process";
21127
- import * as path57 from "path";
21611
+ import { execSync as execSync50 } from "child_process";
21612
+ import * as path56 from "path";
21128
21613
 
21129
21614
  // src/commands/restartDaemonAfterUpdate.ts
21130
21615
  async function restartDaemonAfterUpdate() {
@@ -21143,12 +21628,12 @@ async function restartDaemonAfterUpdate() {
21143
21628
  // src/commands/update.ts
21144
21629
  function isGlobalNpmInstall(dir) {
21145
21630
  try {
21146
- const resolved = path57.resolve(dir);
21147
- if (resolved.split(path57.sep).includes("node_modules")) {
21631
+ const resolved = path56.resolve(dir);
21632
+ if (resolved.split(path56.sep).includes("node_modules")) {
21148
21633
  return true;
21149
21634
  }
21150
- const globalPrefix = execSync49("npm prefix -g", { stdio: "pipe" }).toString().trim();
21151
- 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());
21152
21637
  } catch {
21153
21638
  return false;
21154
21639
  }
@@ -21158,18 +21643,18 @@ async function update2() {
21158
21643
  console.log(`Assist is installed at: ${installDir}`);
21159
21644
  if (isGitRepo(installDir)) {
21160
21645
  console.log("Detected git repo installation, pulling latest...");
21161
- execSync49("git pull", { cwd: installDir, stdio: "inherit" });
21646
+ execSync50("git pull", { cwd: installDir, stdio: "inherit" });
21162
21647
  console.log("Installing dependencies...");
21163
- execSync49("npm i", { cwd: installDir, stdio: "inherit" });
21648
+ execSync50("npm i", { cwd: installDir, stdio: "inherit" });
21164
21649
  console.log("Building...");
21165
- execSync49("npm run build", { cwd: installDir, stdio: "inherit" });
21650
+ execSync50("npm run build", { cwd: installDir, stdio: "inherit" });
21166
21651
  console.log("Syncing commands...");
21167
- execSync49("assist sync", { stdio: "inherit" });
21652
+ execSync50("assist sync", { stdio: "inherit" });
21168
21653
  } else if (isGlobalNpmInstall(installDir)) {
21169
21654
  console.log("Detected global npm installation, updating...");
21170
- execSync49("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
21655
+ execSync50("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
21171
21656
  console.log("Syncing commands...");
21172
- execSync49("assist sync", { stdio: "inherit" });
21657
+ execSync50("assist sync", { stdio: "inherit" });
21173
21658
  } else {
21174
21659
  console.error(
21175
21660
  "Could not determine installation method. Expected a git repo or global npm install."