@staff0rd/assist 0.285.0 → 0.287.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.285.0",
9
+ version: "0.287.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -5003,18 +5003,28 @@ function getCwdParam(req, res) {
5003
5003
  return cwd;
5004
5004
  }
5005
5005
 
5006
+ // src/commands/sessions/web/windowsCwdToWslPath.ts
5007
+ function windowsCwdToWslPath(cwd) {
5008
+ const match = /^([A-Za-z]):[\\/](.*)$/.exec(cwd);
5009
+ if (!match) return cwd;
5010
+ const drive = match[1].toLowerCase();
5011
+ const rest = match[2].replace(/\\/g, "/");
5012
+ return `/mnt/${drive}/${rest}`;
5013
+ }
5014
+
5006
5015
  // src/commands/sessions/web/githubUrl.ts
5007
5016
  function githubUrl(req, res) {
5008
5017
  const cwd = getCwdParam(req, res);
5009
5018
  if (!cwd) return;
5010
- const repo = getPreferredRemoteRepo(cwd);
5019
+ const repo = getPreferredRemoteRepo(windowsCwdToWslPath(cwd));
5011
5020
  respondJson(res, 200, {
5012
5021
  url: repo ? `https://github.com/${repo.org}/${repo.repo}` : null
5013
5022
  });
5014
5023
  }
5015
5024
 
5016
5025
  // src/commands/sessions/web/gitStatus.ts
5017
- import { execSync as execSync22 } from "child_process";
5026
+ import { execFile } from "child_process";
5027
+ import { promisify } from "util";
5018
5028
 
5019
5029
  // src/commands/sessions/web/parseGitStatus.ts
5020
5030
  function extractPath(rest) {
@@ -5042,20 +5052,24 @@ function parseGitStatus(output) {
5042
5052
  }
5043
5053
 
5044
5054
  // src/commands/sessions/web/gitStatus.ts
5045
- function gitStatus(req, res) {
5055
+ var execFileAsync = promisify(execFile);
5056
+ async function gitStatus(req, res) {
5046
5057
  const cwd = getCwdParam(req, res);
5047
5058
  if (!cwd) return;
5048
5059
  try {
5049
- const output = execSync22("git status --porcelain", {
5050
- encoding: "utf-8",
5051
- stdio: ["pipe", "pipe", "pipe"],
5052
- cwd
5053
- });
5054
- respondJson(res, 200, parseGitStatus(output));
5060
+ respondJson(res, 200, parseGitStatus(await runGitStatus(cwd)));
5055
5061
  } catch {
5056
5062
  respondJson(res, 200, { new: [], modified: [], deleted: [] });
5057
5063
  }
5058
5064
  }
5065
+ function runGitStatus(cwd) {
5066
+ const args = ["status", "--porcelain"];
5067
+ const { file, argv } = /^[A-Za-z]:[\\/]/.test(cwd) ? { file: "git.exe", argv: ["-C", cwd, ...args] } : { file: "git", argv: args };
5068
+ return execFileAsync(file, argv, {
5069
+ encoding: "utf-8",
5070
+ ...file === "git" ? { cwd } : {}
5071
+ }).then((r) => r.stdout);
5072
+ }
5059
5073
 
5060
5074
  // src/commands/news/shared.ts
5061
5075
  import { decodeHTML } from "entities";
@@ -5182,13 +5196,14 @@ async function listNewsItems(_req, res) {
5182
5196
 
5183
5197
  // src/commands/sessions/web/openInCode.ts
5184
5198
  import { exec } from "child_process";
5185
- import { promisify } from "util";
5186
- var execAsync = promisify(exec);
5199
+ import { promisify as promisify2 } from "util";
5200
+ var execAsync = promisify2(exec);
5187
5201
  async function openInCode(req, res) {
5188
5202
  const cwd = getCwdParam(req, res);
5189
5203
  if (!cwd) return;
5190
5204
  try {
5191
- await execAsync(`code "${cwd}"`);
5205
+ const command = /^[A-Za-z]:[\\/]/.test(cwd) ? `cmd.exe /c code "${cwd}"` : `code "${cwd}"`;
5206
+ await execAsync(command);
5192
5207
  respondJson(res, 200, { ok: true });
5193
5208
  } catch {
5194
5209
  respondJson(res, 500, {
@@ -5235,6 +5250,79 @@ var handleRequest = createFallbackHandler(
5235
5250
 
5236
5251
  // src/commands/sessions/web/handleSocket.ts
5237
5252
  import { createInterface as createInterface2 } from "readline";
5253
+
5254
+ // src/commands/sessions/daemon/toWindowsSessionId.ts
5255
+ var PREFIX = "w-";
5256
+ function toWindowsSessionId(id) {
5257
+ return `${PREFIX}${id}`;
5258
+ }
5259
+ function isWindowsSessionId(id) {
5260
+ return id.startsWith(PREFIX);
5261
+ }
5262
+ function stripWindowsSessionId(id) {
5263
+ return id.startsWith(PREFIX) ? id.slice(PREFIX.length) : id;
5264
+ }
5265
+
5266
+ // src/commands/sessions/web/ui/repoLabel.ts
5267
+ function repoLabel(cwd) {
5268
+ if (!cwd) return "";
5269
+ const segments = cwd.split(/[/\\]/).filter(Boolean);
5270
+ return segments[segments.length - 1] ?? "";
5271
+ }
5272
+
5273
+ // src/commands/sessions/web/createSessionLifecycleLogger.ts
5274
+ function createSessionLifecycleLogger() {
5275
+ const known = /* @__PURE__ */ new Map();
5276
+ return (line) => {
5277
+ const sessions = parseSnapshot(line);
5278
+ if (sessions) applySnapshot(known, sessions);
5279
+ };
5280
+ }
5281
+ function parseSnapshot(line) {
5282
+ try {
5283
+ const data = JSON.parse(line);
5284
+ if (data.type === "sessions" && Array.isArray(data.sessions))
5285
+ return data.sessions;
5286
+ } catch {
5287
+ }
5288
+ return null;
5289
+ }
5290
+ function applySnapshot(known, sessions) {
5291
+ const present = /* @__PURE__ */ new Set();
5292
+ for (const session of sessions) {
5293
+ present.add(session.id);
5294
+ const previous = known.get(session.id);
5295
+ known.set(session.id, session);
5296
+ if (previous === void 0) logEvent("started", session);
5297
+ else if (isDone(session) && !isDone(previous)) logEvent("ended", session);
5298
+ }
5299
+ for (const [id, session] of [...known]) {
5300
+ if (present.has(id)) continue;
5301
+ known.delete(id);
5302
+ if (!isDone(session)) logEvent("ended", session);
5303
+ }
5304
+ }
5305
+ function isDone(session) {
5306
+ return session.status === "done";
5307
+ }
5308
+ function logEvent(event, session) {
5309
+ const origin = isWindowsSessionId(session.id) ? "windows" : "wsl";
5310
+ console.log(
5311
+ `${(/* @__PURE__ */ new Date()).toISOString()} session ${event}: ${session.id}${describe(session)} [${origin} daemon]`
5312
+ );
5313
+ }
5314
+ function describe(session) {
5315
+ const parts = [];
5316
+ const repo = repoLabel(session.cwd);
5317
+ if (repo) parts.push(repo);
5318
+ const { itemId, phase, totalPhases } = session.activity ?? {};
5319
+ if (itemId !== void 0) parts.push(`#${itemId}`);
5320
+ if (phase !== void 0)
5321
+ parts.push(`phase ${phase}${totalPhases ? `/${totalPhases}` : ""}`);
5322
+ return parts.length ? ` ${parts.join(" ")}` : "";
5323
+ }
5324
+
5325
+ // src/commands/sessions/web/handleSocket.ts
5238
5326
  var CWD_DEFAULTED_TYPES = /* @__PURE__ */ new Set(["create", "create-run", "create-assist"]);
5239
5327
  function handleSocket(ws, ctx) {
5240
5328
  const connection = openDaemonConnection(ws, ctx);
@@ -5266,6 +5354,7 @@ function relayDaemonLines(conn, ws, repoCwd) {
5266
5354
  lines.on("error", () => {
5267
5355
  });
5268
5356
  lines.on("line", (line) => {
5357
+ logSessionLifecycle(line);
5269
5358
  if (ws.readyState === ws.OPEN) ws.send(withRepoCwd(line, repoCwd));
5270
5359
  });
5271
5360
  conn.on("error", () => {
@@ -5292,6 +5381,7 @@ function withDefaultCwd(raw, serverCwd) {
5292
5381
  return raw;
5293
5382
  }
5294
5383
  }
5384
+ var logSessionLifecycle = createSessionLifecycleLogger();
5295
5385
  function withRepoCwd(line, repoCwd) {
5296
5386
  if (!repoCwd) return line;
5297
5387
  try {
@@ -7798,7 +7888,7 @@ import { homedir as homedir9 } from "os";
7798
7888
  import { join as join22 } from "path";
7799
7889
 
7800
7890
  // src/shared/checkCliAvailable.ts
7801
- import { execSync as execSync23 } from "child_process";
7891
+ import { execSync as execSync22 } from "child_process";
7802
7892
  function checkCliAvailable(cli) {
7803
7893
  const binary = cli.split(/\s+/)[0];
7804
7894
  const opts = {
@@ -7806,11 +7896,11 @@ function checkCliAvailable(cli) {
7806
7896
  stdio: ["ignore", "pipe", "pipe"]
7807
7897
  };
7808
7898
  try {
7809
- execSync23(`command -v ${binary}`, opts);
7899
+ execSync22(`command -v ${binary}`, opts);
7810
7900
  return true;
7811
7901
  } catch {
7812
7902
  try {
7813
- execSync23(`where ${binary}`, opts);
7903
+ execSync22(`where ${binary}`, opts);
7814
7904
  return true;
7815
7905
  } catch {
7816
7906
  return false;
@@ -8946,7 +9036,7 @@ function loadBlogSkipDays(repoName) {
8946
9036
  }
8947
9037
 
8948
9038
  // src/commands/devlog/shared.ts
8949
- import { execSync as execSync24 } from "child_process";
9039
+ import { execSync as execSync23 } from "child_process";
8950
9040
  import chalk92 from "chalk";
8951
9041
 
8952
9042
  // src/shared/getRepoName.ts
@@ -9038,7 +9128,7 @@ function loadAllDevlogLatestDates() {
9038
9128
  // src/commands/devlog/shared.ts
9039
9129
  function getCommitFiles(hash) {
9040
9130
  try {
9041
- const output = execSync24(`git show --name-only --format="" ${hash}`, {
9131
+ const output = execSync23(`git show --name-only --format="" ${hash}`, {
9042
9132
  encoding: "utf-8"
9043
9133
  });
9044
9134
  return output.trim().split("\n").filter(Boolean);
@@ -9134,11 +9224,11 @@ function list3(options2) {
9134
9224
  }
9135
9225
 
9136
9226
  // src/commands/devlog/getLastVersionInfo.ts
9137
- import { execFileSync as execFileSync2, execSync as execSync25 } from "child_process";
9227
+ import { execFileSync as execFileSync2, execSync as execSync24 } from "child_process";
9138
9228
  import semver from "semver";
9139
9229
  function getVersionAtCommit(hash) {
9140
9230
  try {
9141
- const content = execSync25(`git show ${hash}:package.json`, {
9231
+ const content = execSync24(`git show ${hash}:package.json`, {
9142
9232
  encoding: "utf-8"
9143
9233
  });
9144
9234
  const pkg = JSON.parse(content);
@@ -9311,7 +9401,7 @@ function next2(options2) {
9311
9401
  }
9312
9402
 
9313
9403
  // src/commands/devlog/repos/index.ts
9314
- import { execSync as execSync26 } from "child_process";
9404
+ import { execSync as execSync25 } from "child_process";
9315
9405
 
9316
9406
  // src/commands/devlog/repos/printReposTable.ts
9317
9407
  import chalk96 from "chalk";
@@ -9346,7 +9436,7 @@ function getStatus(lastPush, lastDevlog) {
9346
9436
  return lastDevlog < lastPush ? "outdated" : "ok";
9347
9437
  }
9348
9438
  function fetchRepos(days, all) {
9349
- const json = execSync26(
9439
+ const json = execSync25(
9350
9440
  "gh repo list staff0rd --json name,pushedAt,isArchived --limit 200",
9351
9441
  { encoding: "utf-8" }
9352
9442
  );
@@ -9706,7 +9796,7 @@ async function deps(csprojPath, options2) {
9706
9796
  }
9707
9797
 
9708
9798
  // src/commands/dotnet/getChangedCsFiles.ts
9709
- import { execSync as execSync27 } from "child_process";
9799
+ import { execSync as execSync26 } from "child_process";
9710
9800
  var SCOPE_ALL = "all";
9711
9801
  var SCOPE_BASE = "base:";
9712
9802
  var SCOPE_COMMIT = "commit:";
@@ -9730,7 +9820,7 @@ function getChangedCsFiles(scope) {
9730
9820
  } else {
9731
9821
  cmd = "git diff --name-only HEAD";
9732
9822
  }
9733
- const output = execSync27(cmd, { encoding: "utf-8" }).trim();
9823
+ const output = execSync26(cmd, { encoding: "utf-8" }).trim();
9734
9824
  if (output === "") return [];
9735
9825
  return output.split("\n").filter((f) => f.toLowerCase().endsWith(".cs"));
9736
9826
  }
@@ -9928,14 +10018,14 @@ function parseInspectReport(json) {
9928
10018
  }
9929
10019
 
9930
10020
  // src/commands/dotnet/runInspectCode.ts
9931
- import { execSync as execSync28 } from "child_process";
10021
+ import { execSync as execSync27 } from "child_process";
9932
10022
  import { existsSync as existsSync30, readFileSync as readFileSync24, unlinkSync as unlinkSync7 } from "fs";
9933
10023
  import { tmpdir as tmpdir3 } from "os";
9934
10024
  import path25 from "path";
9935
10025
  import chalk106 from "chalk";
9936
10026
  function assertJbInstalled() {
9937
10027
  try {
9938
- execSync28("jb inspectcode --version", { stdio: "pipe" });
10028
+ execSync27("jb inspectcode --version", { stdio: "pipe" });
9939
10029
  } catch {
9940
10030
  console.error(chalk106.red("jb is not installed. Install with:"));
9941
10031
  console.error(
@@ -9949,7 +10039,7 @@ function runInspectCode(slnPath, include, swea) {
9949
10039
  const includeFlag = include ? ` --include="${include}"` : "";
9950
10040
  const sweaFlag = swea ? " --swea" : "";
9951
10041
  try {
9952
- execSync28(
10042
+ execSync27(
9953
10043
  `jb inspectcode "${slnPath}" -o="${reportPath}"${includeFlag}${sweaFlag} --verbosity=OFF`,
9954
10044
  { stdio: "pipe" }
9955
10045
  );
@@ -9970,7 +10060,7 @@ function runInspectCode(slnPath, include, swea) {
9970
10060
  }
9971
10061
 
9972
10062
  // src/commands/dotnet/runRoslynInspect.ts
9973
- import { execSync as execSync29 } from "child_process";
10063
+ import { execSync as execSync28 } from "child_process";
9974
10064
  import chalk107 from "chalk";
9975
10065
  function resolveMsbuildPath() {
9976
10066
  const { run: run4 } = loadConfig();
@@ -9981,7 +10071,7 @@ function resolveMsbuildPath() {
9981
10071
  function assertMsbuildInstalled() {
9982
10072
  const msbuild = resolveMsbuildPath();
9983
10073
  try {
9984
- execSync29(`"${msbuild}" -version`, { stdio: "pipe" });
10074
+ execSync28(`"${msbuild}" -version`, { stdio: "pipe" });
9985
10075
  } catch {
9986
10076
  console.error(chalk107.red(`msbuild not found at: ${msbuild}`));
9987
10077
  console.error(
@@ -10007,7 +10097,7 @@ function runRoslynInspect(slnPath) {
10007
10097
  const msbuild = resolveMsbuildPath();
10008
10098
  let output;
10009
10099
  try {
10010
- output = execSync29(
10100
+ output = execSync28(
10011
10101
  `"${msbuild}" "${slnPath}" -t:Build -v:minimal -maxcpucount -p:EnforceCodeStyleInBuild=true -p:RunAnalyzersDuringBuild=true 2>&1`,
10012
10102
  { encoding: "utf-8", stdio: "pipe", maxBuffer: 50 * 1024 * 1024 }
10013
10103
  );
@@ -10585,12 +10675,12 @@ function adfToText(doc) {
10585
10675
  }
10586
10676
 
10587
10677
  // src/commands/jira/fetchIssue.ts
10588
- import { execSync as execSync30 } from "child_process";
10678
+ import { execSync as execSync29 } from "child_process";
10589
10679
  import chalk111 from "chalk";
10590
10680
  function fetchIssue(issueKey, fields) {
10591
10681
  let result;
10592
10682
  try {
10593
- result = execSync30(
10683
+ result = execSync29(
10594
10684
  `acli jira workitem view ${issueKey} -f ${fields} --json`,
10595
10685
  { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
10596
10686
  );
@@ -10636,7 +10726,7 @@ function acceptanceCriteria(issueKey) {
10636
10726
  }
10637
10727
 
10638
10728
  // src/commands/jira/jiraAuth.ts
10639
- import { execSync as execSync31 } from "child_process";
10729
+ import { execSync as execSync30 } from "child_process";
10640
10730
 
10641
10731
  // src/shared/loadJson.ts
10642
10732
  import { existsSync as existsSync33, mkdirSync as mkdirSync11, readFileSync as readFileSync27, writeFileSync as writeFileSync21 } from "fs";
@@ -10700,7 +10790,7 @@ async function jiraAuth() {
10700
10790
  console.error("All fields are required.");
10701
10791
  process.exit(1);
10702
10792
  }
10703
- execSync31(`acli jira auth login --site ${site} --email "${email}" --token`, {
10793
+ execSync30(`acli jira auth login --site ${site} --email "${email}" --token`, {
10704
10794
  encoding: "utf-8",
10705
10795
  input: token,
10706
10796
  stdio: ["pipe", "inherit", "inherit"]
@@ -10995,7 +11085,7 @@ function registerPrompts(program2) {
10995
11085
  }
10996
11086
 
10997
11087
  // src/commands/prs/shared.ts
10998
- import { execSync as execSync32 } from "child_process";
11088
+ import { execSync as execSync31 } from "child_process";
10999
11089
  function isGhNotInstalled(error) {
11000
11090
  if (error instanceof Error) {
11001
11091
  const msg = error.message.toLowerCase();
@@ -11013,12 +11103,12 @@ function getRepoInfo() {
11013
11103
  const preferred = getPreferredRemoteRepo();
11014
11104
  if (preferred) return preferred;
11015
11105
  const repoInfo = JSON.parse(
11016
- execSync32("gh repo view --json owner,name", { encoding: "utf-8" })
11106
+ execSync31("gh repo view --json owner,name", { encoding: "utf-8" })
11017
11107
  );
11018
11108
  return { org: repoInfo.owner.login, repo: repoInfo.name };
11019
11109
  }
11020
11110
  function getCurrentBranch() {
11021
- return execSync32("git rev-parse --abbrev-ref HEAD", {
11111
+ return execSync31("git rev-parse --abbrev-ref HEAD", {
11022
11112
  encoding: "utf-8"
11023
11113
  }).trim();
11024
11114
  }
@@ -11026,7 +11116,7 @@ function viewCurrentPr(fields) {
11026
11116
  const { org, repo } = getRepoInfo();
11027
11117
  const branch = getCurrentBranch();
11028
11118
  return JSON.parse(
11029
- execSync32(`gh pr view ${branch} --json ${fields} -R ${org}/${repo}`, {
11119
+ execSync31(`gh pr view ${branch} --json ${fields} -R ${org}/${repo}`, {
11030
11120
  encoding: "utf-8"
11031
11121
  })
11032
11122
  );
@@ -11130,7 +11220,7 @@ function comment2(path54, line, body, startLine) {
11130
11220
  }
11131
11221
 
11132
11222
  // src/commands/prs/edit.ts
11133
- import { execSync as execSync33 } from "child_process";
11223
+ import { execSync as execSync32 } from "child_process";
11134
11224
 
11135
11225
  // src/commands/prs/buildPrBody.ts
11136
11226
  function jiraBrowseUrl(key) {
@@ -11256,17 +11346,17 @@ function edit(options2) {
11256
11346
  if (options2.title) args.push(`--title ${shellQuote(options2.title)}`);
11257
11347
  args.push(`--body ${shellQuote(newBody)}`);
11258
11348
  try {
11259
- execSync33(args.join(" "), { stdio: "inherit" });
11349
+ execSync32(args.join(" "), { stdio: "inherit" });
11260
11350
  } catch (_error) {
11261
11351
  process.exit(1);
11262
11352
  }
11263
11353
  }
11264
11354
 
11265
11355
  // src/commands/prs/fixed.ts
11266
- import { execSync as execSync35 } from "child_process";
11356
+ import { execSync as execSync34 } from "child_process";
11267
11357
 
11268
11358
  // src/commands/prs/resolveCommentWithReply.ts
11269
- import { execSync as execSync34 } from "child_process";
11359
+ import { execSync as execSync33 } from "child_process";
11270
11360
  import { unlinkSync as unlinkSync10, writeFileSync as writeFileSync23 } from "fs";
11271
11361
  import { tmpdir as tmpdir5 } from "os";
11272
11362
  import { join as join34 } from "path";
@@ -11296,7 +11386,7 @@ function deleteCommentsCache(prNumber) {
11296
11386
 
11297
11387
  // src/commands/prs/resolveCommentWithReply.ts
11298
11388
  function replyToComment(org, repo, prNumber, commentId, message) {
11299
- execSync34(
11389
+ execSync33(
11300
11390
  `gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message.replace(/"/g, '\\"')}" -F in_reply_to=${commentId}`,
11301
11391
  { stdio: ["inherit", "pipe", "inherit"] }
11302
11392
  );
@@ -11306,7 +11396,7 @@ function resolveThread(threadId) {
11306
11396
  const queryFile = join34(tmpdir5(), `gh-mutation-${Date.now()}.graphql`);
11307
11397
  writeFileSync23(queryFile, mutation);
11308
11398
  try {
11309
- execSync34(
11399
+ execSync33(
11310
11400
  `gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
11311
11401
  { stdio: ["inherit", "pipe", "inherit"] }
11312
11402
  );
@@ -11358,7 +11448,7 @@ function resolveCommentWithReply(commentId, message) {
11358
11448
  // src/commands/prs/fixed.ts
11359
11449
  function verifySha(sha) {
11360
11450
  try {
11361
- return execSync35(`git rev-parse --verify ${sha}`, {
11451
+ return execSync34(`git rev-parse --verify ${sha}`, {
11362
11452
  encoding: "utf-8"
11363
11453
  }).trim();
11364
11454
  } catch {
@@ -11372,7 +11462,7 @@ function fixed(commentId, sha) {
11372
11462
  const { org, repo } = getRepoInfo();
11373
11463
  const repoUrl = `https://github.com/${org}/${repo}`;
11374
11464
  const message = `Fixed in [${fullSha}](${repoUrl}/commit/${fullSha})`;
11375
- execSync35("git push", { stdio: "inherit" });
11465
+ execSync34("git push", { stdio: "inherit" });
11376
11466
  resolveCommentWithReply(commentId, message);
11377
11467
  } catch (error) {
11378
11468
  if (isGhNotInstalled(error)) {
@@ -11390,7 +11480,7 @@ import { join as join36 } from "path";
11390
11480
  import { stringify } from "yaml";
11391
11481
 
11392
11482
  // src/commands/prs/fetchThreadIds.ts
11393
- import { execSync as execSync36 } from "child_process";
11483
+ import { execSync as execSync35 } from "child_process";
11394
11484
  import { unlinkSync as unlinkSync11, writeFileSync as writeFileSync24 } from "fs";
11395
11485
  import { tmpdir as tmpdir6 } from "os";
11396
11486
  import { join as join35 } from "path";
@@ -11399,7 +11489,7 @@ function fetchThreadIds(org, repo, prNumber) {
11399
11489
  const queryFile = join35(tmpdir6(), `gh-query-${Date.now()}.graphql`);
11400
11490
  writeFileSync24(queryFile, THREAD_QUERY);
11401
11491
  try {
11402
- const result = execSync36(
11492
+ const result = execSync35(
11403
11493
  `gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
11404
11494
  { encoding: "utf-8" }
11405
11495
  );
@@ -11421,9 +11511,9 @@ function fetchThreadIds(org, repo, prNumber) {
11421
11511
  }
11422
11512
 
11423
11513
  // src/commands/prs/listComments/fetchReviewComments.ts
11424
- import { execSync as execSync37 } from "child_process";
11514
+ import { execSync as execSync36 } from "child_process";
11425
11515
  function fetchJson(endpoint) {
11426
- const result = execSync37(`gh api --paginate ${endpoint}`, {
11516
+ const result = execSync36(`gh api --paginate ${endpoint}`, {
11427
11517
  encoding: "utf-8"
11428
11518
  });
11429
11519
  if (!result.trim()) return [];
@@ -11562,7 +11652,7 @@ async function listComments() {
11562
11652
  }
11563
11653
 
11564
11654
  // src/commands/prs/prs/index.ts
11565
- import { execSync as execSync38 } from "child_process";
11655
+ import { execSync as execSync37 } from "child_process";
11566
11656
 
11567
11657
  // src/commands/prs/prs/displayPaginated/index.ts
11568
11658
  import enquirer9 from "enquirer";
@@ -11669,7 +11759,7 @@ async function prs(options2) {
11669
11759
  const state = options2.open ? "open" : options2.closed ? "closed" : "all";
11670
11760
  try {
11671
11761
  const { org, repo } = getRepoInfo();
11672
- const result = execSync38(
11762
+ const result = execSync37(
11673
11763
  `gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100 -R ${org}/${repo}`,
11674
11764
  { encoding: "utf-8" }
11675
11765
  );
@@ -11692,7 +11782,7 @@ async function prs(options2) {
11692
11782
  }
11693
11783
 
11694
11784
  // src/commands/prs/raise.ts
11695
- import { execSync as execSync39 } from "child_process";
11785
+ import { execSync as execSync38 } from "child_process";
11696
11786
 
11697
11787
  // src/commands/prs/buildCreateArgs.ts
11698
11788
  function buildCreateArgs(title, body, options2) {
@@ -11752,14 +11842,14 @@ function raise(options2) {
11752
11842
  `--body ${shellQuote(body)}`
11753
11843
  ] : buildCreateArgs(options2.title, body, options2);
11754
11844
  try {
11755
- execSync39(args.join(" "), { stdio: "inherit" });
11845
+ execSync38(args.join(" "), { stdio: "inherit" });
11756
11846
  } catch (_error) {
11757
11847
  process.exit(1);
11758
11848
  }
11759
11849
  }
11760
11850
 
11761
11851
  // src/commands/prs/wontfix.ts
11762
- import { execSync as execSync40 } from "child_process";
11852
+ import { execSync as execSync39 } from "child_process";
11763
11853
  function validateReason(reason) {
11764
11854
  const lowerReason = reason.toLowerCase();
11765
11855
  if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
@@ -11776,7 +11866,7 @@ function validateShaReferences(reason) {
11776
11866
  const invalidShas = [];
11777
11867
  for (const sha of shas) {
11778
11868
  try {
11779
- execSync40(`git cat-file -t ${sha}`, { stdio: "pipe" });
11869
+ execSync39(`git cat-file -t ${sha}`, { stdio: "pipe" });
11780
11870
  } catch {
11781
11871
  invalidShas.push(sha);
11782
11872
  }
@@ -11935,10 +12025,10 @@ import chalk124 from "chalk";
11935
12025
  import Enquirer2 from "enquirer";
11936
12026
 
11937
12027
  // src/commands/ravendb/searchItems.ts
11938
- import { execSync as execSync41 } from "child_process";
12028
+ import { execSync as execSync40 } from "child_process";
11939
12029
  import chalk123 from "chalk";
11940
12030
  function opExec(args) {
11941
- return execSync41(`op ${args}`, {
12031
+ return execSync40(`op ${args}`, {
11942
12032
  encoding: "utf-8",
11943
12033
  stdio: ["pipe", "pipe", "pipe"]
11944
12034
  }).trim();
@@ -12077,10 +12167,10 @@ async function getAccessToken(apiKey) {
12077
12167
  }
12078
12168
  });
12079
12169
  if (!response.ok) {
12080
- const errorText2 = await response.text();
12170
+ const errorText = await response.text();
12081
12171
  throw new Error(
12082
12172
  `Failed to get access token: ${response.status} ${response.statusText}
12083
- ${errorText2}`
12173
+ ${errorText}`
12084
12174
  );
12085
12175
  }
12086
12176
  const tokenData = await response.json();
@@ -12090,7 +12180,7 @@ ${errorText2}`
12090
12180
  }
12091
12181
 
12092
12182
  // src/commands/ravendb/resolveOpSecret.ts
12093
- import { execSync as execSync42 } from "child_process";
12183
+ import { execSync as execSync41 } from "child_process";
12094
12184
  import chalk128 from "chalk";
12095
12185
  function resolveOpSecret(reference) {
12096
12186
  if (!reference.startsWith("op://")) {
@@ -12098,7 +12188,7 @@ function resolveOpSecret(reference) {
12098
12188
  process.exit(1);
12099
12189
  }
12100
12190
  try {
12101
- return execSync42(`op read "${reference}"`, {
12191
+ return execSync41(`op read "${reference}"`, {
12102
12192
  encoding: "utf-8",
12103
12193
  stdio: ["pipe", "pipe", "pipe"]
12104
12194
  }).trim();
@@ -12347,7 +12437,7 @@ Refactor check failed:
12347
12437
  }
12348
12438
 
12349
12439
  // src/commands/refactor/check/getViolations/index.ts
12350
- import { execSync as execSync43 } from "child_process";
12440
+ import { execSync as execSync42 } from "child_process";
12351
12441
  import fs18 from "fs";
12352
12442
  import { minimatch as minimatch5 } from "minimatch";
12353
12443
 
@@ -12397,7 +12487,7 @@ function getGitFiles(options2) {
12397
12487
  }
12398
12488
  const files = /* @__PURE__ */ new Set();
12399
12489
  if (options2.staged || options2.modified) {
12400
- const staged = execSync43("git diff --cached --name-only", {
12490
+ const staged = execSync42("git diff --cached --name-only", {
12401
12491
  encoding: "utf-8"
12402
12492
  });
12403
12493
  for (const file of staged.trim().split("\n").filter(Boolean)) {
@@ -12405,7 +12495,7 @@ function getGitFiles(options2) {
12405
12495
  }
12406
12496
  }
12407
12497
  if (options2.unstaged || options2.modified) {
12408
- const unstaged = execSync43("git diff --name-only", { encoding: "utf-8" });
12498
+ const unstaged = execSync42("git diff --name-only", { encoding: "utf-8" });
12409
12499
  for (const file of unstaged.trim().split("\n").filter(Boolean)) {
12410
12500
  files.add(file);
12411
12501
  }
@@ -13981,9 +14071,9 @@ function buildReviewPaths(repoRoot, key) {
13981
14071
  }
13982
14072
 
13983
14073
  // src/commands/review/fetchExistingComments.ts
13984
- import { execSync as execSync44 } from "child_process";
14074
+ import { execSync as execSync43 } from "child_process";
13985
14075
  function fetchRawComments(org, repo, prNumber) {
13986
- const out = execSync44(
14076
+ const out = execSync43(
13987
14077
  `gh api --paginate repos/${org}/${repo}/pulls/${prNumber}/comments`,
13988
14078
  { encoding: "utf-8", maxBuffer: 64 * 1024 * 1024 }
13989
14079
  );
@@ -14014,14 +14104,14 @@ function fetchExistingComments() {
14014
14104
  }
14015
14105
 
14016
14106
  // src/commands/review/gatherContext.ts
14017
- import { execSync as execSync47 } from "child_process";
14107
+ import { execSync as execSync46 } from "child_process";
14018
14108
 
14019
14109
  // src/commands/review/fetchPrDiff.ts
14020
- import { execSync as execSync45 } from "child_process";
14110
+ import { execSync as execSync44 } from "child_process";
14021
14111
  function fetchPrDiff(prNumber, baseSha, headSha) {
14022
14112
  const { org, repo } = getRepoInfo();
14023
14113
  try {
14024
- return execSync45(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
14114
+ return execSync44(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
14025
14115
  encoding: "utf-8",
14026
14116
  maxBuffer: 256 * 1024 * 1024,
14027
14117
  stdio: ["ignore", "pipe", "pipe"]
@@ -14036,19 +14126,19 @@ function isDiffTooLarge(error) {
14036
14126
  }
14037
14127
  function fetchDiffViaGit(baseSha, headSha) {
14038
14128
  try {
14039
- execSync45(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
14129
+ execSync44(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
14040
14130
  } catch {
14041
14131
  }
14042
- return execSync45(`git diff ${baseSha}...${headSha}`, {
14132
+ return execSync44(`git diff ${baseSha}...${headSha}`, {
14043
14133
  encoding: "utf-8",
14044
14134
  maxBuffer: 256 * 1024 * 1024
14045
14135
  });
14046
14136
  }
14047
14137
 
14048
14138
  // src/commands/review/fetchPrDiffInfo.ts
14049
- import { execSync as execSync46 } from "child_process";
14139
+ import { execSync as execSync45 } from "child_process";
14050
14140
  function getCurrentBranch2() {
14051
- return execSync46("git rev-parse --abbrev-ref HEAD", {
14141
+ return execSync45("git rev-parse --abbrev-ref HEAD", {
14052
14142
  encoding: "utf-8"
14053
14143
  }).trim();
14054
14144
  }
@@ -14058,7 +14148,7 @@ function fetchPrDiffInfo() {
14058
14148
  const fields = "number,baseRefName,baseRefOid,headRefName,headRefOid";
14059
14149
  let raw;
14060
14150
  try {
14061
- raw = execSync46(`gh pr view ${branch} --json ${fields} -R ${org}/${repo}`, {
14151
+ raw = execSync45(`gh pr view ${branch} --json ${fields} -R ${org}/${repo}`, {
14062
14152
  encoding: "utf-8",
14063
14153
  stdio: ["ignore", "pipe", "pipe"]
14064
14154
  });
@@ -14082,7 +14172,7 @@ function fetchPrDiffInfo() {
14082
14172
  }
14083
14173
  function fetchPrChangedFiles(prNumber) {
14084
14174
  const { org, repo } = getRepoInfo();
14085
- const out = execSync46(
14175
+ const out = execSync45(
14086
14176
  `gh api repos/${org}/${repo}/pulls/${prNumber}/files --paginate --jq ".[].filename"`,
14087
14177
  {
14088
14178
  encoding: "utf-8",
@@ -14094,11 +14184,11 @@ function fetchPrChangedFiles(prNumber) {
14094
14184
 
14095
14185
  // src/commands/review/gatherContext.ts
14096
14186
  function gatherContext() {
14097
- const branch = execSync47("git rev-parse --abbrev-ref HEAD", {
14187
+ const branch = execSync46("git rev-parse --abbrev-ref HEAD", {
14098
14188
  encoding: "utf-8"
14099
14189
  }).trim();
14100
- const sha = execSync47("git rev-parse HEAD", { encoding: "utf-8" }).trim();
14101
- const shortSha = execSync47("git rev-parse --short=7 HEAD", {
14190
+ const sha = execSync46("git rev-parse HEAD", { encoding: "utf-8" }).trim();
14191
+ const shortSha = execSync46("git rev-parse --short=7 HEAD", {
14102
14192
  encoding: "utf-8"
14103
14193
  }).trim();
14104
14194
  const prInfo = fetchPrDiffInfo();
@@ -16934,7 +17024,7 @@ import { mkdirSync as mkdirSync18 } from "fs";
16934
17024
  import { join as join47 } from "path";
16935
17025
 
16936
17026
  // src/commands/voice/checkLockFile.ts
16937
- import { execSync as execSync48 } from "child_process";
17027
+ import { execSync as execSync47 } from "child_process";
16938
17028
  import { existsSync as existsSync45, mkdirSync as mkdirSync17, readFileSync as readFileSync35, writeFileSync as writeFileSync29 } from "fs";
16939
17029
  import { join as join46 } from "path";
16940
17030
  function isProcessAlive2(pid) {
@@ -16963,7 +17053,7 @@ function bootstrapVenv() {
16963
17053
  if (existsSync45(getVenvPython())) return;
16964
17054
  console.log("Setting up Python environment...");
16965
17055
  const pythonDir = getPythonDir();
16966
- execSync48(
17056
+ execSync47(
16967
17057
  `uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
16968
17058
  {
16969
17059
  stdio: "inherit",
@@ -17440,11 +17530,11 @@ function resolveParams(params, cliArgs) {
17440
17530
  }
17441
17531
 
17442
17532
  // src/commands/run/runPreCommands.ts
17443
- import { execSync as execSync49 } from "child_process";
17533
+ import { execSync as execSync48 } from "child_process";
17444
17534
  function runPreCommands(pre, cwd) {
17445
17535
  for (const cmd of pre) {
17446
17536
  try {
17447
- execSync49(cmd, { stdio: "inherit", cwd });
17537
+ execSync48(cmd, { stdio: "inherit", cwd });
17448
17538
  } catch (err) {
17449
17539
  const code = err && typeof err === "object" && "status" in err ? err.status : 1;
17450
17540
  process.exit(code);
@@ -17728,7 +17818,7 @@ function registerRun(program2) {
17728
17818
  }
17729
17819
 
17730
17820
  // src/commands/screenshot/index.ts
17731
- import { execSync as execSync50 } from "child_process";
17821
+ import { execSync as execSync49 } from "child_process";
17732
17822
  import { existsSync as existsSync50, mkdirSync as mkdirSync21, unlinkSync as unlinkSync17, writeFileSync as writeFileSync32 } from "fs";
17733
17823
  import { tmpdir as tmpdir7 } from "os";
17734
17824
  import { join as join53, resolve as resolve13 } from "path";
@@ -17871,7 +17961,7 @@ function runPowerShellScript(processName, outputPath) {
17871
17961
  const scriptPath = join53(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
17872
17962
  writeFileSync32(scriptPath, captureWindowPs1, "utf-8");
17873
17963
  try {
17874
- execSync50(
17964
+ execSync49(
17875
17965
  `powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
17876
17966
  { stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }
17877
17967
  );
@@ -18240,6 +18330,7 @@ function greetClient(client, sessions, list4, windowsProxy) {
18240
18330
  sendTo(client, { type: "sessions", sessions: list4() });
18241
18331
  replayScrollback(sessions, client);
18242
18332
  windowsProxy.replayScrollback(client);
18333
+ void windowsProxy.discover();
18243
18334
  }
18244
18335
 
18245
18336
  // src/commands/sessions/daemon/shouldAutoDismiss.ts
@@ -18509,21 +18600,36 @@ async function isWindowsDaemonRunning() {
18509
18600
  }
18510
18601
  }
18511
18602
 
18603
+ // src/commands/sessions/daemon/discoverWindowsSessions.ts
18604
+ async function discoverWindowsSessions(conn) {
18605
+ if (conn.connected || !await isWindowsDaemonRunning()) return;
18606
+ daemonLog("windows proxy: discovering sessions on running windows daemon");
18607
+ try {
18608
+ await conn.ensure();
18609
+ } catch (e) {
18610
+ const message = e instanceof Error ? e.message : String(e);
18611
+ daemonLog(`windows proxy: discovery failed: ${message}`);
18612
+ }
18613
+ }
18614
+
18512
18615
  // src/commands/sessions/daemon/ensureWindowsDaemonRunning.ts
18513
18616
  import { spawn as spawn10 } from "child_process";
18514
18617
  var SPAWN_TIMEOUT_MS2 = 3e4;
18515
18618
  var RETRY_DELAY_MS2 = 300;
18516
18619
  async function ensureWindowsDaemonRunning() {
18517
- if (await isWindowsDaemonRunning()) return;
18620
+ if (await isWindowsDaemonRunning()) {
18621
+ daemonLog("windows daemon: already running");
18622
+ return;
18623
+ }
18624
+ daemonLog("windows daemon: not running, launching via pwsh.exe");
18518
18625
  launchWindowsDaemon();
18519
18626
  await waitForWindowsDaemon();
18520
18627
  }
18521
18628
  function launchWindowsDaemon() {
18522
- const child = spawn10(
18523
- "cmd.exe",
18524
- ["/c", "start", "", "assist", "daemon", "run"],
18525
- { detached: true, stdio: "ignore" }
18526
- );
18629
+ const child = spawn10("pwsh.exe", ["-Command", "assist daemon run"], {
18630
+ detached: true,
18631
+ stdio: "ignore"
18632
+ });
18527
18633
  child.on(
18528
18634
  "error",
18529
18635
  (e) => daemonLog(`failed to launch windows daemon: ${e.message}`)
@@ -18531,11 +18637,22 @@ function launchWindowsDaemon() {
18531
18637
  child.unref();
18532
18638
  }
18533
18639
  async function waitForWindowsDaemon() {
18534
- const deadline = Date.now() + SPAWN_TIMEOUT_MS2;
18640
+ const start3 = Date.now();
18641
+ const deadline = start3 + SPAWN_TIMEOUT_MS2;
18642
+ let attempts = 0;
18535
18643
  while (Date.now() < deadline) {
18536
18644
  await delay2(RETRY_DELAY_MS2);
18537
- if (await isWindowsDaemonRunning()) return;
18645
+ attempts++;
18646
+ if (await isWindowsDaemonRunning()) {
18647
+ daemonLog(
18648
+ `windows daemon: up after ${Date.now() - start3}ms (${attempts} attempts)`
18649
+ );
18650
+ return;
18651
+ }
18538
18652
  }
18653
+ daemonLog(
18654
+ `windows daemon: did NOT start within ${SPAWN_TIMEOUT_MS2}ms (${attempts} attempts)`
18655
+ );
18539
18656
  throw new Error(
18540
18657
  "Windows daemon did not start; is assist installed on the Windows host?"
18541
18658
  );
@@ -18544,6 +18661,24 @@ function delay2(ms) {
18544
18661
  return new Promise((resolve16) => setTimeout(resolve16, ms));
18545
18662
  }
18546
18663
 
18664
+ // src/commands/sessions/daemon/forwardWindowsCreate.ts
18665
+ async function forwardWindowsCreate(conn, state, client, data) {
18666
+ daemonLog(`windows proxy: routing ${data.type} (cwd=${data.cwd})`);
18667
+ try {
18668
+ await conn.ensure();
18669
+ daemonLog("windows proxy: connection ready, forwarding create");
18670
+ state.pendingCreators.push(client);
18671
+ conn.write(data);
18672
+ } catch (e) {
18673
+ const message = e instanceof Error ? e.message : String(e);
18674
+ daemonLog(`windows proxy: forwardCreate failed: ${message}`);
18675
+ sendTo(client, {
18676
+ type: "error",
18677
+ message: `Windows session unavailable: ${message}`
18678
+ });
18679
+ }
18680
+ }
18681
+
18547
18682
  // src/commands/sessions/daemon/buildHello.ts
18548
18683
  var ASSIST_VERSION = package_default.version;
18549
18684
  function buildHello() {
@@ -18556,18 +18691,6 @@ function versionsMatch(a, b) {
18556
18691
  return a === b;
18557
18692
  }
18558
18693
 
18559
- // src/commands/sessions/daemon/toWindowsSessionId.ts
18560
- var PREFIX = "w-";
18561
- function toWindowsSessionId(id) {
18562
- return `${PREFIX}${id}`;
18563
- }
18564
- function isWindowsSessionId(id) {
18565
- return id.startsWith(PREFIX);
18566
- }
18567
- function stripWindowsSessionId(id) {
18568
- return id.startsWith(PREFIX) ? id.slice(PREFIX.length) : id;
18569
- }
18570
-
18571
18694
  // src/commands/sessions/daemon/WindowsProxyState.ts
18572
18695
  var MAX_SCROLLBACK2 = 256 * 1024;
18573
18696
  function createState(broadcast2, onSessionsChanged) {
@@ -18612,7 +18735,10 @@ var inbound = {
18612
18735
  sessions: handleSessions,
18613
18736
  output: handleOutput,
18614
18737
  clear: relayWithSessionId,
18615
- error: (state, msg) => state.broadcast(msg)
18738
+ error: (state, msg) => {
18739
+ daemonLog(`windows daemon: inbound error: ${msg.message}`);
18740
+ state.broadcast(msg);
18741
+ }
18616
18742
  };
18617
18743
  function handleHello(msg) {
18618
18744
  if (isHello(msg) && !versionsMatch(msg.version, ASSIST_VERSION))
@@ -18621,8 +18747,10 @@ function handleHello(msg) {
18621
18747
  );
18622
18748
  }
18623
18749
  function handleCreated(state, msg) {
18750
+ daemonLog(`windows daemon: created session ${nsId(msg)}`);
18624
18751
  const client = state.pendingCreators.shift();
18625
18752
  if (client) sendTo(client, { type: "created", sessionId: nsId(msg) });
18753
+ else daemonLog("windows daemon: created with no pending creator (dropped)");
18626
18754
  }
18627
18755
  function handleSessions(state, msg) {
18628
18756
  state.windowsSessions = msg.sessions.map((s) => ({
@@ -18663,6 +18791,9 @@ var WindowsConnection = class {
18663
18791
  }
18664
18792
  connection = null;
18665
18793
  socket = null;
18794
+ get connected() {
18795
+ return this.connection !== null;
18796
+ }
18666
18797
  ensure() {
18667
18798
  if (this.connection) return this.connection;
18668
18799
  const connection = this.open();
@@ -18686,7 +18817,9 @@ var WindowsConnection = class {
18686
18817
  this.reset();
18687
18818
  }
18688
18819
  async open() {
18820
+ daemonLog("windows connection: opening (launch + tcp connect)");
18689
18821
  const socket = await this.deps.connect();
18822
+ daemonLog("windows connection: tcp connected, sending hello");
18690
18823
  this.socket = socket;
18691
18824
  const lines = createInterface5({ input: socket });
18692
18825
  lines.on("error", () => {
@@ -18725,6 +18858,9 @@ var WindowsProxy = class {
18725
18858
  sessions() {
18726
18859
  return this.state.windowsSessions;
18727
18860
  }
18861
+ discover() {
18862
+ return discoverWindowsSessions(this.conn);
18863
+ }
18728
18864
  replayScrollback(client) {
18729
18865
  replayScrollback2(this.state, client);
18730
18866
  }
@@ -18746,18 +18882,10 @@ var WindowsProxy = class {
18746
18882
  this.conn.dispose();
18747
18883
  }
18748
18884
  async forwardCreate(client, data) {
18749
- try {
18750
- await this.conn.ensure();
18751
- this.state.pendingCreators.push(client);
18752
- this.conn.write(data);
18753
- } catch (e) {
18754
- sendTo(client, {
18755
- type: "error",
18756
- message: `Windows session unavailable: ${errorText(e)}`
18757
- });
18758
- }
18885
+ await forwardWindowsCreate(this.conn, this.state, client, data);
18759
18886
  }
18760
18887
  handleClose() {
18888
+ daemonLog("windows proxy: connection to windows daemon closed");
18761
18889
  for (const client of this.state.pendingCreators)
18762
18890
  sendTo(client, {
18763
18891
  type: "error",
@@ -18777,9 +18905,6 @@ async function defaultConnect() {
18777
18905
  await ensureWindowsDaemonRunning();
18778
18906
  return connectToWindowsDaemon();
18779
18907
  }
18780
- function errorText(e) {
18781
- return e instanceof Error ? e.message : String(e);
18782
- }
18783
18908
 
18784
18909
  // src/commands/sessions/daemon/watchClaudeSessionId.ts
18785
18910
  import * as fs27 from "fs";
@@ -18878,23 +19003,20 @@ function matchMarker(text3, tag) {
18878
19003
  }
18879
19004
 
18880
19005
  // src/commands/sessions/shared/parseSessionFile.ts
18881
- async function parseSessionFile(filePath) {
19006
+ async function parseSessionFile(filePath, origin = "wsl") {
18882
19007
  let handle;
18883
19008
  try {
18884
19009
  handle = await fs25.promises.open(filePath, "r");
18885
- const buf = Buffer.alloc(16384);
18886
- const { bytesRead } = await handle.read(buf, 0, buf.length, 0);
18887
- const lines = buf.toString("utf8", 0, bytesRead).split("\n").filter(Boolean);
18888
- const meta = extractSessionMeta(lines);
19010
+ const meta = extractSessionMeta(await readHeadLines(handle));
18889
19011
  if (!meta.sessionId) return null;
18890
19012
  const timestamp = meta.timestamp || (await fs25.promises.stat(filePath)).mtime.toISOString();
18891
- const project = meta.cwd ? path46.basename(meta.cwd) : dirNameToProject(filePath);
18892
19013
  return {
18893
19014
  sessionId: meta.sessionId,
18894
19015
  name: meta.name || `Session ${meta.sessionId.slice(0, 8)}`,
18895
- project,
19016
+ project: deriveProject(meta.cwd, filePath, origin),
18896
19017
  cwd: meta.cwd,
18897
19018
  timestamp,
19019
+ origin,
18898
19020
  ...deriveHistoryFields(meta.commandName, meta.commandArgs, meta.name)
18899
19021
  };
18900
19022
  } catch {
@@ -18903,6 +19025,15 @@ async function parseSessionFile(filePath) {
18903
19025
  await handle?.close();
18904
19026
  }
18905
19027
  }
19028
+ async function readHeadLines(handle) {
19029
+ const buf = Buffer.alloc(16384);
19030
+ const { bytesRead } = await handle.read(buf, 0, buf.length, 0);
19031
+ return buf.toString("utf8", 0, bytesRead).split("\n").filter(Boolean);
19032
+ }
19033
+ function deriveProject(cwd, filePath, origin) {
19034
+ if (!cwd) return dirNameToProject(filePath);
19035
+ return origin === "windows" ? path46.win32.basename(cwd) : path46.basename(cwd);
19036
+ }
18906
19037
  function dirNameToProject(filePath) {
18907
19038
  const dirName = path46.basename(path46.dirname(filePath));
18908
19039
  const parts = dirName.split("--");
@@ -18910,38 +19041,52 @@ function dirNameToProject(filePath) {
18910
19041
  }
18911
19042
 
18912
19043
  // src/commands/sessions/shared/discoverSessions.ts
19044
+ function sessionRoots() {
19045
+ const roots = [
19046
+ { dir: path47.join(os.homedir(), ".claude", "projects"), origin: "wsl" }
19047
+ ];
19048
+ const windowsRoot = loadConfig().sessions?.windowsProjectsRoot;
19049
+ if (windowsRoot) roots.push({ dir: windowsRoot, origin: "windows" });
19050
+ return roots;
19051
+ }
18913
19052
  async function discoverSessionJsonlPaths() {
18914
- const projectsDir = path47.join(os.homedir(), ".claude", "projects");
18915
- let projectDirs;
18916
- try {
18917
- projectDirs = await fs26.promises.readdir(projectsDir);
18918
- } catch {
18919
- return [];
18920
- }
18921
- const paths = [];
19053
+ const results = [];
18922
19054
  await Promise.all(
18923
- projectDirs.map(async (dirName) => {
18924
- const dirPath = path47.join(projectsDir, dirName);
18925
- let entries;
19055
+ sessionRoots().map(async ({ dir, origin }) => {
19056
+ let projectDirs;
18926
19057
  try {
18927
- entries = await fs26.promises.readdir(dirPath);
19058
+ projectDirs = await fs26.promises.readdir(dir);
18928
19059
  } catch {
18929
19060
  return;
18930
19061
  }
18931
- const jsonlFiles = entries.filter((e) => e.endsWith(".jsonl"));
18932
- for (const file of jsonlFiles) {
18933
- paths.push(path47.join(dirPath, file));
18934
- }
19062
+ await Promise.all(
19063
+ projectDirs.map(async (dirName) => {
19064
+ const dirPath = path47.join(dir, dirName);
19065
+ let entries;
19066
+ try {
19067
+ entries = await fs26.promises.readdir(dirPath);
19068
+ } catch {
19069
+ return;
19070
+ }
19071
+ for (const file of entries) {
19072
+ if (file.endsWith(".jsonl"))
19073
+ results.push({ path: path47.join(dirPath, file), origin });
19074
+ }
19075
+ })
19076
+ );
18935
19077
  })
18936
19078
  );
18937
- return paths;
19079
+ return results;
19080
+ }
19081
+ async function discoverSessionFiles() {
19082
+ return (await discoverSessionJsonlPaths()).map((p) => p.path);
18938
19083
  }
18939
19084
  async function discoverSessions() {
18940
19085
  const paths = await discoverSessionJsonlPaths();
18941
19086
  const sessions = [];
18942
19087
  await Promise.all(
18943
- paths.map(async (filePath) => {
18944
- const session = await parseSessionFile(filePath);
19088
+ paths.map(async ({ path: filePath, origin }) => {
19089
+ const session = await parseSessionFile(filePath, origin);
18945
19090
  if (session) sessions.push(session);
18946
19091
  })
18947
19092
  );
@@ -18967,10 +19112,10 @@ async function watchClaudeSessionId(options2) {
18967
19112
  async function findLatestSessionId(options2) {
18968
19113
  const paths = await discoverSessionJsonlPaths();
18969
19114
  let latest = null;
18970
- for (const filePath of paths) {
19115
+ for (const { path: filePath, origin } of paths) {
18971
19116
  const createdMs = await createdSince(filePath, options2.sinceMs);
18972
19117
  if (createdMs === null) continue;
18973
- const meta = await parseSessionFile(filePath);
19118
+ const meta = await parseSessionFile(filePath, origin);
18974
19119
  if (!meta?.cwd || options2.isClaimed(meta.sessionId)) continue;
18975
19120
  if (path48.resolve(meta.cwd) !== path48.resolve(options2.cwd)) continue;
18976
19121
  if (!latest || createdMs > latest.createdMs)
@@ -19209,11 +19354,13 @@ function cleanUserText(value) {
19209
19354
  import * as path49 from "path";
19210
19355
  async function findSessionJsonlPath(sessionId) {
19211
19356
  const paths = await discoverSessionJsonlPaths();
19212
- const direct = paths.find((p) => path49.basename(p, ".jsonl") === sessionId);
19213
- if (direct) return direct;
19357
+ const direct = paths.find(
19358
+ (p) => path49.basename(p.path, ".jsonl") === sessionId
19359
+ );
19360
+ if (direct) return direct.path;
19214
19361
  for (const p of paths) {
19215
- const meta = await parseSessionFile(p);
19216
- if (meta?.sessionId === sessionId) return p;
19362
+ const meta = await parseSessionFile(p.path, p.origin);
19363
+ if (meta?.sessionId === sessionId) return p.path;
19217
19364
  }
19218
19365
  return null;
19219
19366
  }
@@ -19611,7 +19758,7 @@ ${firstMessage}`);
19611
19758
 
19612
19759
  // src/commands/sessions/summarise/index.ts
19613
19760
  async function summarise4(options2) {
19614
- const files = await discoverSessionJsonlPaths();
19761
+ const files = await discoverSessionFiles();
19615
19762
  if (files.length === 0) {
19616
19763
  console.log(chalk161.yellow("No sessions found."));
19617
19764
  return;
@@ -19849,7 +19996,7 @@ function syncCommands(claudeDir, targetBase) {
19849
19996
  }
19850
19997
 
19851
19998
  // src/commands/update.ts
19852
- import { execSync as execSync51 } from "child_process";
19999
+ import { execSync as execSync50 } from "child_process";
19853
20000
  import * as path53 from "path";
19854
20001
  function isGlobalNpmInstall(dir) {
19855
20002
  try {
@@ -19857,7 +20004,7 @@ function isGlobalNpmInstall(dir) {
19857
20004
  if (resolved.split(path53.sep).includes("node_modules")) {
19858
20005
  return true;
19859
20006
  }
19860
- const globalPrefix = execSync51("npm prefix -g", { stdio: "pipe" }).toString().trim();
20007
+ const globalPrefix = execSync50("npm prefix -g", { stdio: "pipe" }).toString().trim();
19861
20008
  return resolved.toLowerCase().startsWith(path53.resolve(globalPrefix).toLowerCase());
19862
20009
  } catch {
19863
20010
  return false;
@@ -19868,18 +20015,18 @@ async function update2() {
19868
20015
  console.log(`Assist is installed at: ${installDir}`);
19869
20016
  if (isGitRepo(installDir)) {
19870
20017
  console.log("Detected git repo installation, pulling latest...");
19871
- execSync51("git pull", { cwd: installDir, stdio: "inherit" });
20018
+ execSync50("git pull", { cwd: installDir, stdio: "inherit" });
19872
20019
  console.log("Installing dependencies...");
19873
- execSync51("npm i", { cwd: installDir, stdio: "inherit" });
20020
+ execSync50("npm i", { cwd: installDir, stdio: "inherit" });
19874
20021
  console.log("Building...");
19875
- execSync51("npm run build", { cwd: installDir, stdio: "inherit" });
20022
+ execSync50("npm run build", { cwd: installDir, stdio: "inherit" });
19876
20023
  console.log("Syncing commands...");
19877
- execSync51("assist sync", { stdio: "inherit" });
20024
+ execSync50("assist sync", { stdio: "inherit" });
19878
20025
  } else if (isGlobalNpmInstall(installDir)) {
19879
20026
  console.log("Detected global npm installation, updating...");
19880
- execSync51("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
20027
+ execSync50("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
19881
20028
  console.log("Syncing commands...");
19882
- execSync51("assist sync", { stdio: "inherit" });
20029
+ execSync50("assist sync", { stdio: "inherit" });
19883
20030
  } else {
19884
20031
  console.error(
19885
20032
  "Could not determine installation method. Expected a git repo or global npm install."