@adhdev/daemon-core 0.9.52 → 0.9.54

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.mjs CHANGED
@@ -265,7 +265,7 @@ var init_config = __esm({
265
265
 
266
266
  // src/logging/logger.ts
267
267
  import * as fs2 from "fs";
268
- import * as path6 from "path";
268
+ import * as path9 from "path";
269
269
  import * as os4 from "os";
270
270
  function setLogLevel(level) {
271
271
  currentLevel = level;
@@ -281,13 +281,13 @@ function getDaemonLogDir() {
281
281
  return LOG_DIR;
282
282
  }
283
283
  function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
284
- return path6.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
284
+ return path9.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
285
285
  }
286
286
  function checkDateRotation() {
287
287
  const today = getDateStr();
288
288
  if (today !== currentDate) {
289
289
  currentDate = today;
290
- currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
290
+ currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
291
291
  cleanOldLogs();
292
292
  }
293
293
  }
@@ -301,7 +301,7 @@ function cleanOldLogs() {
301
301
  const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
302
302
  if (dateMatch && dateMatch[1] < cutoffStr) {
303
303
  try {
304
- fs2.unlinkSync(path6.join(LOG_DIR, file));
304
+ fs2.unlinkSync(path9.join(LOG_DIR, file));
305
305
  } catch {
306
306
  }
307
307
  }
@@ -311,8 +311,8 @@ function cleanOldLogs() {
311
311
  }
312
312
  function rotateSizeIfNeeded() {
313
313
  try {
314
- const stat = fs2.statSync(currentLogFile);
315
- if (stat.size > MAX_LOG_SIZE) {
314
+ const stat2 = fs2.statSync(currentLogFile);
315
+ if (stat2.size > MAX_LOG_SIZE) {
316
316
  const backup = currentLogFile.replace(".log", ".1.log");
317
317
  try {
318
318
  fs2.unlinkSync(backup);
@@ -424,7 +424,7 @@ var init_logger = __esm({
424
424
  LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
425
425
  LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
426
426
  currentLevel = "info";
427
- LOG_DIR = process.platform === "win32" ? path6.join(process.env.LOCALAPPDATA || process.env.APPDATA || path6.join(os4.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path6.join(os4.homedir(), "Library", "Logs", "adhdev") : path6.join(os4.homedir(), ".local", "share", "adhdev", "logs");
427
+ LOG_DIR = process.platform === "win32" ? path9.join(process.env.LOCALAPPDATA || process.env.APPDATA || path9.join(os4.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path9.join(os4.homedir(), "Library", "Logs", "adhdev") : path9.join(os4.homedir(), ".local", "share", "adhdev", "logs");
428
428
  MAX_LOG_SIZE = 5 * 1024 * 1024;
429
429
  MAX_LOG_DAYS = 7;
430
430
  try {
@@ -432,16 +432,16 @@ var init_logger = __esm({
432
432
  } catch {
433
433
  }
434
434
  currentDate = getDateStr();
435
- currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
435
+ currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
436
436
  cleanOldLogs();
437
437
  try {
438
- const oldLog = path6.join(LOG_DIR, "daemon.log");
438
+ const oldLog = path9.join(LOG_DIR, "daemon.log");
439
439
  if (fs2.existsSync(oldLog)) {
440
- const stat = fs2.statSync(oldLog);
441
- const oldDate = stat.mtime.toISOString().slice(0, 10);
442
- fs2.renameSync(oldLog, path6.join(LOG_DIR, `daemon-${oldDate}.log`));
440
+ const stat2 = fs2.statSync(oldLog);
441
+ const oldDate = stat2.mtime.toISOString().slice(0, 10);
442
+ fs2.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
443
443
  }
444
- const oldLogBackup = path6.join(LOG_DIR, "daemon.log.old");
444
+ const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
445
445
  if (fs2.existsSync(oldLogBackup)) {
446
446
  fs2.unlinkSync(oldLogBackup);
447
447
  }
@@ -473,7 +473,7 @@ var init_logger = __esm({
473
473
  }
474
474
  };
475
475
  interceptorInstalled = false;
476
- LOG_PATH = path6.join(LOG_DIR, `daemon-${getDateStr()}.log`);
476
+ LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
477
477
  }
478
478
  });
479
479
 
@@ -1380,8 +1380,8 @@ var init_pty_transport = __esm({
1380
1380
  if (cwd) {
1381
1381
  try {
1382
1382
  const fs16 = __require("fs");
1383
- const stat = fs16.statSync(cwd);
1384
- if (!stat.isDirectory()) cwd = os8.homedir();
1383
+ const stat2 = fs16.statSync(cwd);
1384
+ if (!stat2.isDirectory()) cwd = os8.homedir();
1385
1385
  } catch {
1386
1386
  cwd = os8.homedir();
1387
1387
  }
@@ -1401,7 +1401,7 @@ var init_pty_transport = __esm({
1401
1401
 
1402
1402
  // src/cli-adapters/provider-cli-shared.ts
1403
1403
  import * as os9 from "os";
1404
- import * as path10 from "path";
1404
+ import * as path13 from "path";
1405
1405
  import { execSync as execSync3 } from "child_process";
1406
1406
  function stripAnsi(str) {
1407
1407
  return str.replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][\s\S]*?\x1B\\/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B\[\d*[A-HJKSTfG]/g, " ").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/ +/g, " ");
@@ -1466,9 +1466,9 @@ function buildCliScreenSnapshot(text) {
1466
1466
  function findBinary(name) {
1467
1467
  const trimmed = String(name || "").trim();
1468
1468
  if (!trimmed) return trimmed;
1469
- const expanded = trimmed.startsWith("~") ? path10.join(os9.homedir(), trimmed.slice(1)) : trimmed;
1470
- if (path10.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
1471
- return path10.isAbsolute(expanded) ? expanded : path10.resolve(expanded);
1469
+ const expanded = trimmed.startsWith("~") ? path13.join(os9.homedir(), trimmed.slice(1)) : trimmed;
1470
+ if (path13.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
1471
+ return path13.isAbsolute(expanded) ? expanded : path13.resolve(expanded);
1472
1472
  }
1473
1473
  const isWin = os9.platform() === "win32";
1474
1474
  try {
@@ -1484,7 +1484,7 @@ function findBinary(name) {
1484
1484
  }
1485
1485
  }
1486
1486
  function isScriptBinary(binaryPath) {
1487
- if (!path10.isAbsolute(binaryPath)) return false;
1487
+ if (!path13.isAbsolute(binaryPath)) return false;
1488
1488
  try {
1489
1489
  const fs16 = __require("fs");
1490
1490
  const resolved = fs16.realpathSync(binaryPath);
@@ -1500,7 +1500,7 @@ function isScriptBinary(binaryPath) {
1500
1500
  }
1501
1501
  }
1502
1502
  function looksLikeMachOOrElf(filePath) {
1503
- if (!path10.isAbsolute(filePath)) return false;
1503
+ if (!path13.isAbsolute(filePath)) return false;
1504
1504
  try {
1505
1505
  const fs16 = __require("fs");
1506
1506
  const resolved = fs16.realpathSync(filePath);
@@ -1961,7 +1961,7 @@ var init_provider_cli_config = __esm({
1961
1961
 
1962
1962
  // src/cli-adapters/provider-cli-runtime.ts
1963
1963
  import * as os10 from "os";
1964
- import * as path11 from "path";
1964
+ import * as path14 from "path";
1965
1965
  import { DEFAULT_SESSION_HOST_COLS, DEFAULT_SESSION_HOST_ROWS } from "@adhdev/session-host-core";
1966
1966
  function resolveCliSpawnPlan(options) {
1967
1967
  const { provider, runtimeSettings, workingDir, extraArgs } = options;
@@ -1972,9 +1972,9 @@ function resolveCliSpawnPlan(options) {
1972
1972
  const allArgs = [...spawnConfig.args, ...extraArgs];
1973
1973
  let shellCmd;
1974
1974
  let shellArgs;
1975
- const useShellUnix = !isWin && (!!spawnConfig.shell || !path11.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1975
+ const useShellUnix = !isWin && (!!spawnConfig.shell || !path14.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1976
1976
  const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
1977
- const useShellWin = !!spawnConfig.shell || isCmdShim || !path11.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
1977
+ const useShellWin = !!spawnConfig.shell || isCmdShim || !path14.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
1978
1978
  const useShell = isWin ? useShellWin : useShellUnix;
1979
1979
  if (useShell) {
1980
1980
  shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
@@ -2851,7 +2851,7 @@ var init_provider_cli_adapter = __esm({
2851
2851
  `[${this.cliType}] Waiting for interactive prompt: status=${status} stableMs=${stableMs} recentOutputMs=${recentlyOutput} screen=${JSON.stringify(summarizeCliTraceText(screenText, 220)).slice(0, 260)}`
2852
2852
  );
2853
2853
  }
2854
- await new Promise((resolve12) => setTimeout(resolve12, 50));
2854
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
2855
2855
  }
2856
2856
  const finalScreenText = this.terminalScreen.getText() || "";
2857
2857
  LOG.warn(
@@ -4039,7 +4039,7 @@ var init_provider_cli_adapter = __esm({
4039
4039
  const deadline = Date.now() + 1e4;
4040
4040
  while (this.startupParseGate && Date.now() < deadline) {
4041
4041
  this.resolveStartupState("send_wait");
4042
- await new Promise((resolve12) => setTimeout(resolve12, 50));
4042
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
4043
4043
  }
4044
4044
  }
4045
4045
  if (!allowInterventionPrompt) {
@@ -4120,13 +4120,13 @@ var init_provider_cli_adapter = __esm({
4120
4120
  }
4121
4121
  this.responseEpoch += 1;
4122
4122
  this.responseSettleIgnoreUntil = Date.now() + submitDelayMs + this.timeouts.outputSettle + 250;
4123
- await new Promise((resolve12, reject) => {
4123
+ await new Promise((resolve15, reject) => {
4124
4124
  let resolved = false;
4125
4125
  const completion = {
4126
4126
  resolveOnce: () => {
4127
4127
  if (resolved) return;
4128
4128
  resolved = true;
4129
- resolve12();
4129
+ resolve15();
4130
4130
  },
4131
4131
  rejectOnce: (error) => {
4132
4132
  if (resolved) return;
@@ -4288,17 +4288,17 @@ var init_provider_cli_adapter = __esm({
4288
4288
  }
4289
4289
  }
4290
4290
  waitForStopped(timeoutMs) {
4291
- return new Promise((resolve12) => {
4291
+ return new Promise((resolve15) => {
4292
4292
  const startedAt = Date.now();
4293
4293
  const timer = setInterval(() => {
4294
4294
  if (!this.ptyProcess || this.currentStatus === "stopped") {
4295
4295
  clearInterval(timer);
4296
- resolve12(true);
4296
+ resolve15(true);
4297
4297
  return;
4298
4298
  }
4299
4299
  if (Date.now() - startedAt >= timeoutMs) {
4300
4300
  clearInterval(timer);
4301
- resolve12(false);
4301
+ resolve15(false);
4302
4302
  }
4303
4303
  }, 100);
4304
4304
  });
@@ -4524,20 +4524,1137 @@ var init_provider_cli_adapter = __esm({
4524
4524
  }
4525
4525
  });
4526
4526
 
4527
+ // src/git/git-executor.ts
4528
+ import { execFile } from "child_process";
4529
+ import { constants } from "fs";
4530
+ import { access, realpath, stat } from "fs/promises";
4531
+ import * as path from "path";
4532
+ import { promisify } from "util";
4533
+ var execFileAsync = promisify(execFile);
4534
+ var DEFAULT_TIMEOUT_MS = 5e3;
4535
+ var DEFAULT_MAX_BUFFER = 1024 * 1024;
4536
+ var GitCommandError = class extends Error {
4537
+ reason;
4538
+ stdout;
4539
+ stderr;
4540
+ exitCode;
4541
+ signal;
4542
+ argv;
4543
+ cwd;
4544
+ constructor(reason, message, details = {}) {
4545
+ super(message);
4546
+ if (details.cause !== void 0) {
4547
+ this.cause = details.cause;
4548
+ }
4549
+ this.name = "GitCommandError";
4550
+ this.reason = reason;
4551
+ this.stdout = normalizeGitOutput(details.stdout);
4552
+ this.stderr = normalizeGitOutput(details.stderr);
4553
+ this.exitCode = details.exitCode;
4554
+ this.signal = details.signal;
4555
+ this.argv = details.argv ? [...details.argv] : void 0;
4556
+ this.cwd = details.cwd;
4557
+ }
4558
+ };
4559
+ async function resolveGitRepository(workspace, options = {}) {
4560
+ const normalizedWorkspace = await validateWorkspace(workspace);
4561
+ const result = await execGitRaw(normalizedWorkspace, ["rev-parse", "--show-toplevel"], options, {
4562
+ mapNotGitRepo: true
4563
+ });
4564
+ const repoRoot = path.resolve(result.stdout.trim());
4565
+ if (!repoRoot) {
4566
+ throw new GitCommandError("not_git_repo", "Git did not return a repository root", {
4567
+ stdout: result.stdout,
4568
+ stderr: result.stderr,
4569
+ argv: ["rev-parse", "--show-toplevel"],
4570
+ cwd: normalizedWorkspace
4571
+ });
4572
+ }
4573
+ return {
4574
+ workspace: normalizedWorkspace,
4575
+ repoRoot,
4576
+ isGitRepo: true
4577
+ };
4578
+ }
4579
+ async function runGit(repoOrWorkspace, argv, options = {}) {
4580
+ validateGitArgv(argv);
4581
+ const repo = typeof repoOrWorkspace === "string" ? await resolveGitRepository(repoOrWorkspace, options) : repoOrWorkspace;
4582
+ if (!repo.repoRoot || !repo.isGitRepo) {
4583
+ throw new GitCommandError("not_git_repo", "Workspace is not a Git repository", {
4584
+ argv,
4585
+ cwd: repo.workspace
4586
+ });
4587
+ }
4588
+ const cwd = options.cwd ? await validateWorkspace(options.cwd) : await validateWorkspace(repo.workspace);
4589
+ const canonicalRepoRoot = await realpath(repo.repoRoot);
4590
+ const canonicalCwd = await realpath(cwd);
4591
+ if (!isPathInside(canonicalRepoRoot, canonicalCwd)) {
4592
+ throw new GitCommandError("path_outside_repo", "Git cwd is outside the repository root", {
4593
+ argv,
4594
+ cwd
4595
+ });
4596
+ }
4597
+ return execGitRaw(cwd, argv, options);
4598
+ }
4599
+ function normalizeGitOutput(value) {
4600
+ if (typeof value === "string") return value.replace(/\r\n/g, "\n");
4601
+ if (Buffer.isBuffer(value)) return value.toString("utf8").replace(/\r\n/g, "\n");
4602
+ if (value == null) return "";
4603
+ return String(value).replace(/\r\n/g, "\n");
4604
+ }
4605
+ function isPathInside(parent, child) {
4606
+ const relative3 = path.relative(path.resolve(parent), path.resolve(child));
4607
+ return relative3 === "" || !relative3.startsWith("..") && !path.isAbsolute(relative3);
4608
+ }
4609
+ async function validateWorkspace(workspace) {
4610
+ if (typeof workspace !== "string" || workspace.length === 0 || workspace.includes("\0")) {
4611
+ throw new GitCommandError("invalid_args", "Workspace must be a non-empty path");
4612
+ }
4613
+ if (!path.isAbsolute(workspace)) {
4614
+ throw new GitCommandError("invalid_args", "Workspace must be an absolute path", { cwd: workspace });
4615
+ }
4616
+ const normalizedWorkspace = path.resolve(workspace);
4617
+ try {
4618
+ const info = await stat(normalizedWorkspace);
4619
+ if (!info.isDirectory()) {
4620
+ throw new GitCommandError("invalid_args", "Workspace must be an existing directory", {
4621
+ cwd: normalizedWorkspace
4622
+ });
4623
+ }
4624
+ await access(normalizedWorkspace, constants.R_OK);
4625
+ } catch (error) {
4626
+ if (error instanceof GitCommandError) throw error;
4627
+ throw new GitCommandError("invalid_args", "Workspace must be an existing directory", {
4628
+ cwd: normalizedWorkspace,
4629
+ cause: error
4630
+ });
4631
+ }
4632
+ return normalizedWorkspace;
4633
+ }
4634
+ function validateGitArgv(argv) {
4635
+ if (!Array.isArray(argv) || argv.length === 0) {
4636
+ throw new GitCommandError("invalid_args", "Git argv must be a non-empty string array", { argv });
4637
+ }
4638
+ for (const arg of argv) {
4639
+ if (typeof arg !== "string" || arg.length === 0 || arg.includes("\0")) {
4640
+ throw new GitCommandError("invalid_args", "Git argv contains an invalid argument", { argv });
4641
+ }
4642
+ }
4643
+ if (argv.includes("-C") || argv.some((arg) => arg.startsWith("--git-dir") || arg.startsWith("--work-tree"))) {
4644
+ throw new GitCommandError("invalid_args", "Git argv contains unsafe repository override arguments", {
4645
+ argv
4646
+ });
4647
+ }
4648
+ }
4649
+ async function execGitRaw(cwd, argv, options, behavior = {}) {
4650
+ validateGitArgv(argv);
4651
+ try {
4652
+ const result = await execFileAsync("git", [...argv], {
4653
+ cwd,
4654
+ encoding: "utf8",
4655
+ timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
4656
+ maxBuffer: options.maxBuffer ?? DEFAULT_MAX_BUFFER,
4657
+ windowsHide: true
4658
+ });
4659
+ return {
4660
+ stdout: normalizeGitOutput(result.stdout),
4661
+ stderr: normalizeGitOutput(result.stderr)
4662
+ };
4663
+ } catch (error) {
4664
+ throw mapExecError(error, cwd, argv, behavior);
4665
+ }
4666
+ }
4667
+ function mapExecError(error, cwd, argv, behavior) {
4668
+ const execError = error;
4669
+ const stdout = normalizeGitOutput(execError.stdout);
4670
+ const stderr = normalizeGitOutput(execError.stderr);
4671
+ const code = execError.code;
4672
+ const signal = execError.signal;
4673
+ const message = [stderr.trim(), execError.message].filter(Boolean).join("\n");
4674
+ if (code === "ENOENT") {
4675
+ return new GitCommandError("git_not_installed", "Git executable was not found", {
4676
+ stdout,
4677
+ stderr,
4678
+ exitCode: code,
4679
+ signal,
4680
+ argv,
4681
+ cwd,
4682
+ cause: error
4683
+ });
4684
+ }
4685
+ if (execError.killed || /timed out/i.test(execError.message)) {
4686
+ return new GitCommandError("timeout", "Git command timed out", {
4687
+ stdout,
4688
+ stderr,
4689
+ exitCode: code,
4690
+ signal,
4691
+ argv,
4692
+ cwd,
4693
+ cause: error
4694
+ });
4695
+ }
4696
+ if (behavior.mapNotGitRepo && /not a git repository/i.test(stderr + "\n" + execError.message)) {
4697
+ return new GitCommandError("not_git_repo", "Workspace is not a Git repository", {
4698
+ stdout,
4699
+ stderr,
4700
+ exitCode: code,
4701
+ signal,
4702
+ argv,
4703
+ cwd,
4704
+ cause: error
4705
+ });
4706
+ }
4707
+ return new GitCommandError("git_command_failed", message || "Git command failed", {
4708
+ stdout,
4709
+ stderr,
4710
+ exitCode: code,
4711
+ signal,
4712
+ argv,
4713
+ cwd,
4714
+ cause: error
4715
+ });
4716
+ }
4717
+
4718
+ // src/git/git-status.ts
4719
+ async function getGitRepoStatus(workspace, options = {}) {
4720
+ const lastCheckedAt = Date.now();
4721
+ try {
4722
+ const repo = await resolveGitRepository(workspace, options);
4723
+ const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
4724
+ const parsed = parsePorcelainV2Status(statusOutput.stdout);
4725
+ const head = await readHead(repo, options);
4726
+ const stashCount = await readStashCount(repo, options);
4727
+ return {
4728
+ workspace: repo.workspace,
4729
+ repoRoot: repo.repoRoot,
4730
+ isGitRepo: true,
4731
+ branch: parsed.branch,
4732
+ headCommit: head.commit,
4733
+ headMessage: head.message,
4734
+ upstream: parsed.upstream,
4735
+ ahead: parsed.ahead,
4736
+ behind: parsed.behind,
4737
+ staged: parsed.staged,
4738
+ modified: parsed.modified,
4739
+ untracked: parsed.untracked,
4740
+ deleted: parsed.deleted,
4741
+ renamed: parsed.renamed,
4742
+ hasConflicts: parsed.conflictFiles.length > 0,
4743
+ conflictFiles: parsed.conflictFiles,
4744
+ stashCount,
4745
+ lastCheckedAt
4746
+ };
4747
+ } catch (error) {
4748
+ if (error instanceof GitCommandError) {
4749
+ return emptyStatus(workspace, lastCheckedAt, error);
4750
+ }
4751
+ return emptyStatus(
4752
+ workspace,
4753
+ lastCheckedAt,
4754
+ new GitCommandError("git_command_failed", "Failed to read Git status", { cause: error })
4755
+ );
4756
+ }
4757
+ }
4758
+ function parsePorcelainV2Status(output) {
4759
+ const parsed = {
4760
+ branch: null,
4761
+ upstream: null,
4762
+ ahead: 0,
4763
+ behind: 0,
4764
+ staged: 0,
4765
+ modified: 0,
4766
+ untracked: 0,
4767
+ deleted: 0,
4768
+ renamed: 0,
4769
+ conflictFiles: []
4770
+ };
4771
+ for (const line of output.split("\n")) {
4772
+ if (!line) continue;
4773
+ if (line.startsWith("# branch.head ")) {
4774
+ const branch = line.slice("# branch.head ".length).trim();
4775
+ parsed.branch = branch && branch !== "(detached)" ? branch : null;
4776
+ continue;
4777
+ }
4778
+ if (line.startsWith("# branch.upstream ")) {
4779
+ parsed.upstream = line.slice("# branch.upstream ".length).trim() || null;
4780
+ continue;
4781
+ }
4782
+ if (line.startsWith("# branch.ab ")) {
4783
+ const match = line.match(/\+(-?\d+)\s+-(-?\d+)/);
4784
+ if (match) {
4785
+ parsed.ahead = Number.parseInt(match[1] ?? "0", 10) || 0;
4786
+ parsed.behind = Number.parseInt(match[2] ?? "0", 10) || 0;
4787
+ }
4788
+ continue;
4789
+ }
4790
+ if (line.startsWith("? ")) {
4791
+ parsed.untracked += 1;
4792
+ continue;
4793
+ }
4794
+ if (line.startsWith("u ")) {
4795
+ const fields = line.split(" ");
4796
+ const filePath = fields.slice(10).join(" ");
4797
+ if (filePath) parsed.conflictFiles.push(filePath);
4798
+ continue;
4799
+ }
4800
+ if (line.startsWith("1 ") || line.startsWith("2 ")) {
4801
+ const fields = line.split(" ");
4802
+ const xy = fields[1] ?? "..";
4803
+ const indexStatus = xy[0] ?? ".";
4804
+ const worktreeStatus = xy[1] ?? ".";
4805
+ if (isStagedStatus(indexStatus)) parsed.staged += 1;
4806
+ if (worktreeStatus === "M" || worktreeStatus === "T") parsed.modified += 1;
4807
+ if (indexStatus === "D" || worktreeStatus === "D") parsed.deleted += 1;
4808
+ if (indexStatus === "R" || worktreeStatus === "R") parsed.renamed += 1;
4809
+ if (xy.includes("U")) {
4810
+ const filePath = fields.slice(line.startsWith("2 ") ? 9 : 8).join(" ").split(" ")[0] ?? "";
4811
+ if (filePath) parsed.conflictFiles.push(filePath);
4812
+ }
4813
+ }
4814
+ }
4815
+ parsed.conflictFiles = Array.from(new Set(parsed.conflictFiles));
4816
+ return parsed;
4817
+ }
4818
+ async function readHead(repo, options) {
4819
+ try {
4820
+ const result = await runGit(repo, ["log", "-1", "--pretty=%h%x00%s"], options);
4821
+ const text = result.stdout.trimEnd();
4822
+ if (!text) return { commit: null, message: null };
4823
+ const [commit, ...messageParts] = text.split("\0");
4824
+ return {
4825
+ commit: commit || null,
4826
+ message: messageParts.join("\0") || null
4827
+ };
4828
+ } catch {
4829
+ return { commit: null, message: null };
4830
+ }
4831
+ }
4832
+ async function readStashCount(repo, options) {
4833
+ try {
4834
+ const result = await runGit(repo, ["stash", "list", "--format=%gd"], options);
4835
+ return result.stdout.split("\n").filter((line) => line.trim().length > 0).length;
4836
+ } catch {
4837
+ return 0;
4838
+ }
4839
+ }
4840
+ function isStagedStatus(status) {
4841
+ return status !== "." && status !== "?" && status !== "U";
4842
+ }
4843
+ function emptyStatus(workspace, lastCheckedAt, error) {
4844
+ return {
4845
+ workspace,
4846
+ repoRoot: null,
4847
+ isGitRepo: false,
4848
+ branch: null,
4849
+ headCommit: null,
4850
+ headMessage: null,
4851
+ upstream: null,
4852
+ ahead: 0,
4853
+ behind: 0,
4854
+ staged: 0,
4855
+ modified: 0,
4856
+ untracked: 0,
4857
+ deleted: 0,
4858
+ renamed: 0,
4859
+ hasConflicts: false,
4860
+ conflictFiles: [],
4861
+ stashCount: 0,
4862
+ lastCheckedAt,
4863
+ error: error.stderr || error.message,
4864
+ reason: error.reason
4865
+ };
4866
+ }
4867
+
4868
+ // src/git/git-diff.ts
4869
+ import { readFile, realpath as realpath2 } from "fs/promises";
4870
+ import * as path2 from "path";
4871
+ var DEFAULT_MAX_FILES = 200;
4872
+ var DEFAULT_MAX_BYTES = 2e5;
4873
+ async function getGitDiffSummary(workspace, options = {}) {
4874
+ const lastCheckedAt = Date.now();
4875
+ try {
4876
+ const repo = await resolveGitRepository(workspace, options);
4877
+ const repoRoot = repo.repoRoot;
4878
+ const [unstagedNameStatus, unstagedNumstat, stagedNameStatus, stagedNumstat, untracked] = await Promise.all([
4879
+ runGit(repo, ["diff", "--no-ext-diff", "--name-status"], { ...options, cwd: repoRoot }),
4880
+ runGit(repo, ["diff", "--no-ext-diff", "--numstat"], { ...options, cwd: repoRoot }),
4881
+ runGit(repo, ["diff", "--cached", "--no-ext-diff", "--name-status"], { ...options, cwd: repoRoot }),
4882
+ runGit(repo, ["diff", "--cached", "--no-ext-diff", "--numstat"], { ...options, cwd: repoRoot }),
4883
+ runGit(repo, ["ls-files", "--others", "--exclude-standard"], { ...options, cwd: repoRoot })
4884
+ ]);
4885
+ const outputBytes = byteLength(
4886
+ unstagedNameStatus.stdout + unstagedNumstat.stdout + stagedNameStatus.stdout + stagedNumstat.stdout + untracked.stdout
4887
+ );
4888
+ const changes = [
4889
+ ...combineDiffEntries(unstagedNameStatus.stdout, unstagedNumstat.stdout, false),
4890
+ ...combineDiffEntries(stagedNameStatus.stdout, stagedNumstat.stdout, true),
4891
+ ...parseUntrackedFiles(untracked.stdout)
4892
+ ];
4893
+ const maxFiles = normalizePositiveInteger(options.maxFiles, DEFAULT_MAX_FILES);
4894
+ const maxBytes = normalizePositiveInteger(options.maxBytes, DEFAULT_MAX_BYTES);
4895
+ const files = changes.slice(0, maxFiles);
4896
+ const truncated = changes.length > files.length || outputBytes > maxBytes;
4897
+ return {
4898
+ workspace: repo.workspace,
4899
+ repoRoot,
4900
+ isGitRepo: true,
4901
+ files,
4902
+ totalInsertions: files.reduce((sum, file) => sum + file.insertions, 0),
4903
+ totalDeletions: files.reduce((sum, file) => sum + file.deletions, 0),
4904
+ truncated,
4905
+ lastCheckedAt
4906
+ };
4907
+ } catch (error) {
4908
+ const gitError = error instanceof GitCommandError ? error : new GitCommandError("git_command_failed", "Failed to read Git diff summary", { cause: error });
4909
+ return {
4910
+ workspace,
4911
+ repoRoot: null,
4912
+ isGitRepo: false,
4913
+ files: [],
4914
+ totalInsertions: 0,
4915
+ totalDeletions: 0,
4916
+ truncated: false,
4917
+ lastCheckedAt,
4918
+ error: gitError.stderr || gitError.message,
4919
+ reason: gitError.reason
4920
+ };
4921
+ }
4922
+ }
4923
+ async function getGitFileDiff(workspace, filePath, options = {}) {
4924
+ const lastCheckedAt = Date.now();
4925
+ const repo = await resolveGitRepository(workspace, options);
4926
+ const repoRoot = repo.repoRoot;
4927
+ const selected = await resolveRepoFilePath(repoRoot, filePath);
4928
+ const maxBytes = normalizePositiveInteger(options.maxBytes, DEFAULT_MAX_BYTES);
4929
+ const [unstaged, staged] = await Promise.all([
4930
+ runGit(repo, ["diff", "--no-ext-diff", "--", selected.relativePath], { ...options, cwd: repoRoot }),
4931
+ runGit(repo, ["diff", "--cached", "--no-ext-diff", "--", selected.relativePath], { ...options, cwd: repoRoot })
4932
+ ]);
4933
+ let diff = [unstaged.stdout, staged.stdout].filter((part) => part.length > 0).join("\n");
4934
+ if (!diff) {
4935
+ const untracked = await runGit(repo, ["ls-files", "--others", "--exclude-standard", "--", selected.relativePath], {
4936
+ ...options,
4937
+ cwd: repoRoot
4938
+ });
4939
+ const untrackedFiles = untracked.stdout.split("\n").filter(Boolean);
4940
+ if (untrackedFiles.includes(selected.relativePath)) {
4941
+ diff = await buildUntrackedDiff(selected.absolutePath, selected.relativePath, maxBytes + 1);
4942
+ }
4943
+ }
4944
+ const bounded = truncateText(diff, maxBytes);
4945
+ return {
4946
+ workspace: repo.workspace,
4947
+ repoRoot,
4948
+ isGitRepo: true,
4949
+ path: selected.relativePath,
4950
+ diff: bounded.text,
4951
+ truncated: bounded.truncated,
4952
+ lastCheckedAt
4953
+ };
4954
+ }
4955
+ function combineDiffEntries(nameStatusOutput, numstatOutput, staged) {
4956
+ const statusEntries = parseNameStatus(nameStatusOutput);
4957
+ const numstatEntries = parseNumstat(numstatOutput);
4958
+ return statusEntries.map((entry, index) => {
4959
+ const stats = numstatEntries[index];
4960
+ return {
4961
+ path: entry.path,
4962
+ oldPath: entry.oldPath,
4963
+ status: entry.status,
4964
+ staged,
4965
+ insertions: stats?.insertions ?? 0,
4966
+ deletions: stats?.deletions ?? 0,
4967
+ binary: stats?.binary || void 0
4968
+ };
4969
+ });
4970
+ }
4971
+ function parseNameStatus(output) {
4972
+ return output.split("\n").filter(Boolean).map((line) => {
4973
+ const fields = line.split(" ");
4974
+ const code = fields[0] ?? "";
4975
+ const statusLetter = code[0] ?? "M";
4976
+ if (statusLetter === "R") {
4977
+ return {
4978
+ oldPath: fields[1] ?? "",
4979
+ path: fields[2] ?? fields[1] ?? "",
4980
+ status: "renamed"
4981
+ };
4982
+ }
4983
+ if (statusLetter === "C") {
4984
+ return {
4985
+ oldPath: fields[1] ?? "",
4986
+ path: fields[2] ?? fields[1] ?? "",
4987
+ status: "copied"
4988
+ };
4989
+ }
4990
+ return {
4991
+ path: fields[1] ?? "",
4992
+ status: mapNameStatus(statusLetter)
4993
+ };
4994
+ }).filter((entry) => entry.path.length > 0);
4995
+ }
4996
+ function parseNumstat(output) {
4997
+ return output.split("\n").filter(Boolean).map((line) => {
4998
+ const fields = line.split(" ");
4999
+ const insertionsText = fields[0] ?? "0";
5000
+ const deletionsText = fields[1] ?? "0";
5001
+ const binary = insertionsText === "-" || deletionsText === "-";
5002
+ return {
5003
+ path: fields.slice(2).join(" "),
5004
+ insertions: binary ? 0 : Number.parseInt(insertionsText, 10) || 0,
5005
+ deletions: binary ? 0 : Number.parseInt(deletionsText, 10) || 0,
5006
+ binary
5007
+ };
5008
+ });
5009
+ }
5010
+ function parseUntrackedFiles(output) {
5011
+ return output.split("\n").filter(Boolean).map((filePath) => ({
5012
+ path: filePath,
5013
+ status: "untracked",
5014
+ staged: false,
5015
+ insertions: 0,
5016
+ deletions: 0
5017
+ }));
5018
+ }
5019
+ function mapNameStatus(status) {
5020
+ switch (status) {
5021
+ case "A":
5022
+ return "added";
5023
+ case "D":
5024
+ return "deleted";
5025
+ case "R":
5026
+ return "renamed";
5027
+ case "C":
5028
+ return "copied";
5029
+ case "U":
5030
+ return "conflict";
5031
+ case "M":
5032
+ case "T":
5033
+ default:
5034
+ return "modified";
5035
+ }
5036
+ }
5037
+ async function resolveRepoFilePath(repoRoot, filePath) {
5038
+ if (typeof filePath !== "string" || filePath.length === 0 || filePath.includes("\0")) {
5039
+ throw new GitCommandError("invalid_args", "File path must be a non-empty path");
5040
+ }
5041
+ const canonicalRepoRoot = await realpath2(repoRoot).catch(() => path2.resolve(repoRoot));
5042
+ const absolutePath = path2.isAbsolute(filePath) ? path2.resolve(filePath) : path2.resolve(repoRoot, filePath);
5043
+ const checkPath = await realpath2(absolutePath).catch(() => absolutePath);
5044
+ const relativeBase = isPathInside(canonicalRepoRoot, checkPath) ? canonicalRepoRoot : path2.resolve(repoRoot);
5045
+ if (!isPathInside(canonicalRepoRoot, checkPath) && !isPathInside(repoRoot, absolutePath)) {
5046
+ throw new GitCommandError("path_outside_repo", "Selected file path is outside the repository root", {
5047
+ cwd: repoRoot
5048
+ });
5049
+ }
5050
+ const relativePath = path2.relative(relativeBase, checkPath).split(path2.sep).join("/");
5051
+ if (!relativePath || relativePath.startsWith("..") || path2.isAbsolute(relativePath)) {
5052
+ throw new GitCommandError("path_outside_repo", "Selected file path is outside the repository root", {
5053
+ cwd: repoRoot
5054
+ });
5055
+ }
5056
+ return { absolutePath, relativePath };
5057
+ }
5058
+ async function buildUntrackedDiff(absolutePath, relativePath, readLimit) {
5059
+ const content = await readFile(absolutePath, "utf8");
5060
+ const limitedContent = content.length > readLimit ? content.slice(0, readLimit) : content;
5061
+ const lines = limitedContent.length > 0 ? limitedContent.split("\n") : [];
5062
+ const plusLines = lines.filter((line, index) => index < lines.length - 1 || line.length > 0).map((line) => `+${line}`).join("\n");
5063
+ const lineCount = plusLines ? plusLines.split("\n").length : 0;
5064
+ return [
5065
+ `diff --git a/${relativePath} b/${relativePath}`,
5066
+ "new file mode 100644",
5067
+ "index 0000000..0000000",
5068
+ "--- /dev/null",
5069
+ `+++ b/${relativePath}`,
5070
+ `@@ -0,0 +1,${lineCount} @@`,
5071
+ plusLines
5072
+ ].filter((line) => line.length > 0).join("\n");
5073
+ }
5074
+ function truncateText(text, maxBytes) {
5075
+ if (byteLength(text) <= maxBytes) return { text, truncated: false };
5076
+ return { text: Buffer.from(text, "utf8").subarray(0, maxBytes).toString("utf8"), truncated: true };
5077
+ }
5078
+ function byteLength(text) {
5079
+ return Buffer.byteLength(text, "utf8");
5080
+ }
5081
+ function normalizePositiveInteger(value, fallback) {
5082
+ if (!Number.isFinite(value) || value == null || value <= 0) return fallback;
5083
+ return Math.floor(value);
5084
+ }
5085
+
5086
+ // src/git/git-summary.ts
5087
+ function countStatusChangedFiles(status) {
5088
+ const conflictCount = status.conflictFiles.length > 0 ? status.conflictFiles.length : status.hasConflicts ? 1 : 0;
5089
+ return status.staged + status.modified + status.untracked + status.deleted + status.renamed + conflictCount;
5090
+ }
5091
+ function createGitCompactSummary(status, diffSummary) {
5092
+ const statusChangedFiles = countStatusChangedFiles(status);
5093
+ const diffChangedFiles = diffSummary?.files.length ?? 0;
5094
+ const changedFiles = Math.max(statusChangedFiles, diffChangedFiles);
5095
+ const conflictCount = status.conflictFiles.length > 0 ? status.conflictFiles.length : status.hasConflicts ? 1 : 0;
5096
+ return {
5097
+ isGitRepo: status.isGitRepo,
5098
+ repoRoot: status.repoRoot,
5099
+ branch: status.branch,
5100
+ dirty: status.staged > 0 || status.modified > 0 || status.untracked > 0 || status.deleted > 0 || status.renamed > 0 || conflictCount > 0 || changedFiles > 0,
5101
+ changedFiles,
5102
+ ahead: status.ahead,
5103
+ behind: status.behind,
5104
+ hasConflicts: status.hasConflicts || conflictCount > 0,
5105
+ lastCheckedAt: Math.max(status.lastCheckedAt, diffSummary?.lastCheckedAt ?? status.lastCheckedAt),
5106
+ error: status.error ?? diffSummary?.error,
5107
+ reason: status.reason ?? diffSummary?.reason
5108
+ };
5109
+ }
5110
+ var summarizeGitStatus = createGitCompactSummary;
5111
+
5112
+ // src/git/git-snapshot-store.ts
5113
+ function normalizeCapacity(capacity) {
5114
+ return Math.max(1, Math.floor(capacity ?? 100));
5115
+ }
5116
+ function createEmptyDiffSummary(status) {
5117
+ return {
5118
+ workspace: status.workspace,
5119
+ repoRoot: status.repoRoot,
5120
+ isGitRepo: status.isGitRepo,
5121
+ files: [],
5122
+ totalInsertions: 0,
5123
+ totalDeletions: 0,
5124
+ truncated: false,
5125
+ lastCheckedAt: status.lastCheckedAt,
5126
+ error: status.error,
5127
+ reason: status.reason
5128
+ };
5129
+ }
5130
+ function changedFileKey(file) {
5131
+ return `${file.oldPath ?? ""}\0${file.path}`;
5132
+ }
5133
+ function uniqueSorted(values) {
5134
+ return Array.from(new Set(Array.from(values).filter(Boolean))).sort((a, b) => a.localeCompare(b));
5135
+ }
5136
+ function plural(count, singular, pluralText = `${singular}s`) {
5137
+ return count === 1 ? singular : pluralText;
5138
+ }
5139
+ function compareGitSnapshots(before, after) {
5140
+ const beforeFileKeys = new Set(before.diffSummary.files.map(changedFileKey));
5141
+ const changedAfterFiles = after.diffSummary.files.filter((file) => !beforeFileKeys.has(changedFileKey(file)));
5142
+ const addedFiles = [];
5143
+ const modifiedFiles = [];
5144
+ const deletedFiles = [];
5145
+ const renamedFiles = [];
5146
+ const untrackedFiles = [];
5147
+ const conflictFilesFromDiff = [];
5148
+ let totalInsertions = 0;
5149
+ let totalDeletions = 0;
5150
+ for (const file of changedAfterFiles) {
5151
+ totalInsertions += file.insertions;
5152
+ totalDeletions += file.deletions;
5153
+ switch (file.status) {
5154
+ case "added":
5155
+ case "copied":
5156
+ addedFiles.push(file.path);
5157
+ break;
5158
+ case "modified":
5159
+ modifiedFiles.push(file.path);
5160
+ break;
5161
+ case "deleted":
5162
+ deletedFiles.push(file.path);
5163
+ break;
5164
+ case "renamed":
5165
+ renamedFiles.push({ oldPath: file.oldPath ?? file.path, path: file.path });
5166
+ break;
5167
+ case "untracked":
5168
+ untrackedFiles.push(file.path);
5169
+ break;
5170
+ case "conflict":
5171
+ conflictFilesFromDiff.push(file.path);
5172
+ break;
5173
+ }
5174
+ }
5175
+ renamedFiles.sort((a, b) => `${a.oldPath}\0${a.path}`.localeCompare(`${b.oldPath}\0${b.path}`));
5176
+ const conflictFiles = uniqueSorted([...after.status.conflictFiles, ...conflictFilesFromDiff]);
5177
+ const changedFiles = changedAfterFiles.length;
5178
+ const hasConflicts = after.status.hasConflicts || conflictFiles.length > 0;
5179
+ const summaryParts = [];
5180
+ if (changedFiles > 0) summaryParts.push(`${changedFiles} ${plural(changedFiles, "file")} changed`);
5181
+ if (addedFiles.length > 0) summaryParts.push(`${addedFiles.length} added`);
5182
+ if (modifiedFiles.length > 0) summaryParts.push(`${modifiedFiles.length} modified`);
5183
+ if (deletedFiles.length > 0) summaryParts.push(`${deletedFiles.length} deleted`);
5184
+ if (renamedFiles.length > 0) summaryParts.push(`${renamedFiles.length} renamed`);
5185
+ if (untrackedFiles.length > 0) summaryParts.push(`${untrackedFiles.length} untracked`);
5186
+ if (hasConflicts) summaryParts.push(`${conflictFiles.length || 1} ${plural(conflictFiles.length || 1, "conflict")}`);
5187
+ return {
5188
+ beforeSnapshotId: before.id,
5189
+ afterSnapshotId: after.id,
5190
+ workspace: after.workspace,
5191
+ repoRoot: after.repoRoot,
5192
+ changedFiles,
5193
+ addedFiles: uniqueSorted(addedFiles),
5194
+ modifiedFiles: uniqueSorted(modifiedFiles),
5195
+ deletedFiles: uniqueSorted(deletedFiles),
5196
+ renamedFiles,
5197
+ untrackedFiles: uniqueSorted(untrackedFiles),
5198
+ conflictFiles,
5199
+ totalInsertions,
5200
+ totalDeletions,
5201
+ hasConflicts,
5202
+ currentStatus: after.status,
5203
+ summaryText: summaryParts.length > 0 ? summaryParts.join(", ") : "No file-set changes between snapshots."
5204
+ };
5205
+ }
5206
+ var InMemoryGitSnapshotStore = class {
5207
+ snapshots = /* @__PURE__ */ new Map();
5208
+ order = [];
5209
+ capacity;
5210
+ now;
5211
+ idPrefix;
5212
+ getStatusProvider;
5213
+ getDiffSummaryProvider;
5214
+ counter = 0;
5215
+ constructor(options = {}) {
5216
+ this.capacity = normalizeCapacity(options.capacity);
5217
+ this.now = options.now ?? Date.now;
5218
+ this.idPrefix = options.idPrefix ?? "git-snapshot";
5219
+ this.getStatusProvider = options.getStatus;
5220
+ this.getDiffSummaryProvider = options.getDiffSummary;
5221
+ }
5222
+ async create(input) {
5223
+ const getStatus = input.getStatus ?? this.getStatusProvider;
5224
+ if (!getStatus) {
5225
+ throw new Error("GitSnapshotStore requires an injected getStatus provider");
5226
+ }
5227
+ const status = await getStatus(input.workspace);
5228
+ const getDiffSummary = input.getDiffSummary ?? this.getDiffSummaryProvider;
5229
+ const diffSummary = getDiffSummary ? await getDiffSummary(input.workspace, status) : createEmptyDiffSummary(status);
5230
+ const createdAt = this.now();
5231
+ const id = `${this.idPrefix}-${createdAt}-${++this.counter}`;
5232
+ const snapshot = {
5233
+ id,
5234
+ workspace: input.workspace,
5235
+ repoRoot: status.repoRoot ?? input.workspace,
5236
+ sessionId: input.sessionId,
5237
+ turnId: input.turnId,
5238
+ reason: input.reason,
5239
+ status,
5240
+ diffSummary,
5241
+ createdAt
5242
+ };
5243
+ this.snapshots.set(id, snapshot);
5244
+ this.order.push(id);
5245
+ this.enforceCapacity();
5246
+ return snapshot;
5247
+ }
5248
+ get(id) {
5249
+ return this.snapshots.get(id);
5250
+ }
5251
+ compare(beforeSnapshotId, afterSnapshotId) {
5252
+ const before = this.snapshots.get(beforeSnapshotId);
5253
+ if (!before) throw new Error(`Unknown before snapshot: ${beforeSnapshotId}`);
5254
+ const after = this.snapshots.get(afterSnapshotId);
5255
+ if (!after) throw new Error(`Unknown after snapshot: ${afterSnapshotId}`);
5256
+ return compareGitSnapshots(before, after);
5257
+ }
5258
+ list(query = {}) {
5259
+ const limit = Math.max(1, Math.floor(query.limit ?? this.capacity));
5260
+ return this.order.map((id) => this.snapshots.get(id)).filter((snapshot) => Boolean(snapshot)).filter((snapshot) => !query.workspace || snapshot.workspace === query.workspace).filter((snapshot) => !query.sessionId || snapshot.sessionId === query.sessionId).slice(-limit);
5261
+ }
5262
+ clear() {
5263
+ this.snapshots.clear();
5264
+ this.order.splice(0, this.order.length);
5265
+ }
5266
+ enforceCapacity() {
5267
+ while (this.order.length > this.capacity) {
5268
+ const evictedId = this.order.shift();
5269
+ if (evictedId) this.snapshots.delete(evictedId);
5270
+ }
5271
+ }
5272
+ };
5273
+ function createGitSnapshotStore(options = {}) {
5274
+ return new InMemoryGitSnapshotStore(options);
5275
+ }
5276
+
5277
+ // src/git/git-monitor.ts
5278
+ var DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS = 5e3;
5279
+ var MIN_GIT_WORKSPACE_POLL_INTERVAL_MS = 1e3;
5280
+ function defaultStatusProvider(workspace) {
5281
+ return getGitRepoStatus(workspace);
5282
+ }
5283
+ function defaultDiffSummaryProvider(workspace) {
5284
+ return getGitDiffSummary(workspace);
5285
+ }
5286
+ function normalizeIntervalMs(value, defaultIntervalMs, minIntervalMs) {
5287
+ const requested = Number.isFinite(value) ? Math.floor(value) : defaultIntervalMs;
5288
+ return Math.max(minIntervalMs, requested > 0 ? requested : defaultIntervalMs);
5289
+ }
5290
+ function normalizeGitWorkspaceSubscriptionParams(params, options = {}) {
5291
+ const minIntervalMs = Math.max(1, Math.floor(options.minIntervalMs ?? MIN_GIT_WORKSPACE_POLL_INTERVAL_MS));
5292
+ const defaultIntervalMs = Math.max(minIntervalMs, Math.floor(options.defaultIntervalMs ?? DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS));
5293
+ return {
5294
+ workspace: params.workspace,
5295
+ includeDiffSummary: Boolean(params.includeDiffSummary),
5296
+ intervalMs: normalizeIntervalMs(params.intervalMs, defaultIntervalMs, minIntervalMs)
5297
+ };
5298
+ }
5299
+ var GitWorkspaceMonitor = class {
5300
+ getStatusProvider;
5301
+ getDiffSummaryProvider;
5302
+ now;
5303
+ minIntervalMs;
5304
+ defaultIntervalMs;
5305
+ keyPrefix;
5306
+ cache = /* @__PURE__ */ new Map();
5307
+ listeners = /* @__PURE__ */ new Set();
5308
+ seq = 0;
5309
+ constructor(options = {}) {
5310
+ this.getStatusProvider = options.getStatus ?? defaultStatusProvider;
5311
+ this.getDiffSummaryProvider = options.getDiffSummary ?? defaultDiffSummaryProvider;
5312
+ this.now = options.now ?? Date.now;
5313
+ this.minIntervalMs = Math.max(1, Math.floor(options.minIntervalMs ?? MIN_GIT_WORKSPACE_POLL_INTERVAL_MS));
5314
+ this.defaultIntervalMs = Math.max(
5315
+ this.minIntervalMs,
5316
+ Math.floor(options.defaultIntervalMs ?? DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS)
5317
+ );
5318
+ this.keyPrefix = options.keyPrefix ?? "git";
5319
+ }
5320
+ async refresh(params) {
5321
+ const normalized = this.normalize(typeof params === "string" ? { workspace: params } : params);
5322
+ const status = await this.getStatusProvider(normalized.workspace);
5323
+ const diffSummary = normalized.includeDiffSummary ? await this.getDiffSummaryProvider(normalized.workspace, status) : void 0;
5324
+ const compactSummary = createGitCompactSummary(status, diffSummary);
5325
+ const timestamp = this.now();
5326
+ const seq = ++this.seq;
5327
+ const key = this.keyForWorkspace(normalized.workspace);
5328
+ const update = {
5329
+ topic: "workspace.git",
5330
+ key,
5331
+ workspace: normalized.workspace,
5332
+ status,
5333
+ diffSummary,
5334
+ seq,
5335
+ timestamp
5336
+ };
5337
+ const cacheEntry = {
5338
+ key,
5339
+ workspace: normalized.workspace,
5340
+ status,
5341
+ diffSummary,
5342
+ compactSummary,
5343
+ seq,
5344
+ timestamp
5345
+ };
5346
+ this.cache.set(normalized.workspace, cacheEntry);
5347
+ this.emit(update, cacheEntry);
5348
+ return update;
5349
+ }
5350
+ poll(params) {
5351
+ return this.refresh(params);
5352
+ }
5353
+ getCached(workspace) {
5354
+ return this.cache.get(workspace);
5355
+ }
5356
+ getCompactSummary(workspace) {
5357
+ return this.cache.get(workspace)?.compactSummary;
5358
+ }
5359
+ onUpdate(listener) {
5360
+ this.listeners.add(listener);
5361
+ return () => {
5362
+ this.listeners.delete(listener);
5363
+ };
5364
+ }
5365
+ createSubscription(params, listener) {
5366
+ const normalized = this.normalize(params);
5367
+ const scopedListener = listener ? (update, cacheEntry) => {
5368
+ if (update.workspace === normalized.workspace) listener(update, cacheEntry);
5369
+ } : void 0;
5370
+ const unsubscribe = scopedListener ? this.onUpdate(scopedListener) : () => void 0;
5371
+ return {
5372
+ params: normalized,
5373
+ refresh: () => this.refresh(normalized),
5374
+ getCached: () => this.getCached(normalized.workspace),
5375
+ dispose: unsubscribe
5376
+ };
5377
+ }
5378
+ normalize(params) {
5379
+ return normalizeGitWorkspaceSubscriptionParams(params, {
5380
+ defaultIntervalMs: this.defaultIntervalMs,
5381
+ minIntervalMs: this.minIntervalMs
5382
+ });
5383
+ }
5384
+ keyForWorkspace(workspace) {
5385
+ return `${this.keyPrefix}:${workspace}`;
5386
+ }
5387
+ emit(update, cacheEntry) {
5388
+ for (const listener of this.listeners) {
5389
+ listener(update, cacheEntry);
5390
+ }
5391
+ }
5392
+ };
5393
+ function createGitWorkspaceMonitor(options = {}) {
5394
+ return new GitWorkspaceMonitor(options);
5395
+ }
5396
+
5397
+ // src/git/git-commands.ts
5398
+ import * as path3 from "path";
5399
+ var GIT_COMMAND_NAMES = /* @__PURE__ */ new Set([
5400
+ "git_status",
5401
+ "git_diff_summary",
5402
+ "git_diff_file",
5403
+ "git_snapshot_create",
5404
+ "git_snapshot_compare",
5405
+ "git_log",
5406
+ "git_checkpoint",
5407
+ "git_stash_push",
5408
+ "git_stash_pop",
5409
+ "git_checkout_files"
5410
+ ]);
5411
+ var MUTATING_COMMAND_NAMES = /* @__PURE__ */ new Set([
5412
+ "git_checkpoint",
5413
+ "git_stash_push",
5414
+ "git_stash_pop",
5415
+ "git_checkout_files"
5416
+ ]);
5417
+ var SNAPSHOT_REASONS = /* @__PURE__ */ new Set([
5418
+ "session_baseline",
5419
+ "before_user_input_dispatch",
5420
+ "before_agent_work",
5421
+ "after_agent_work",
5422
+ "manual"
5423
+ ]);
5424
+ var FAILURE_REASONS = /* @__PURE__ */ new Set([
5425
+ "not_git_repo",
5426
+ "git_not_installed",
5427
+ "timeout",
5428
+ "path_outside_repo",
5429
+ "dirty_index_required",
5430
+ "conflict",
5431
+ "invalid_args",
5432
+ "git_command_failed"
5433
+ ]);
5434
+ function failure(reason, error) {
5435
+ return { success: false, reason, error };
5436
+ }
5437
+ function serviceNotImplemented(command) {
5438
+ return failure("invalid_args", `${command} is not implemented: daemon-core Git service is not configured`);
5439
+ }
5440
+ var defaultSnapshotStore = createGitSnapshotStore({
5441
+ getStatus: (workspace) => getGitRepoStatus(workspace),
5442
+ getDiffSummary: (workspace) => getGitDiffSummary(workspace)
5443
+ });
5444
+ function createDefaultGitCommandServices() {
5445
+ return {
5446
+ getStatus: ({ workspace }) => getGitRepoStatus(workspace),
5447
+ getDiffSummary: ({ workspace }) => getGitDiffSummary(workspace),
5448
+ getDiffFile: ({ workspace, path: filePath }) => getGitFileDiff(workspace, filePath),
5449
+ createSnapshot: ({ workspace, reason, sessionId, turnId }) => defaultSnapshotStore.create({
5450
+ workspace,
5451
+ reason,
5452
+ sessionId,
5453
+ turnId
5454
+ }),
5455
+ compareSnapshots: ({ beforeSnapshotId, afterSnapshotId }) => defaultSnapshotStore.compare(beforeSnapshotId, afterSnapshotId),
5456
+ getLog: ({ workspace, limit, path: filePath, since, until }) => getGitLog(workspace, { limit, path: filePath, since, until })
5457
+ };
5458
+ }
5459
+ var defaultGitCommandServices = createDefaultGitCommandServices();
5460
+ function validateWorkspace2(args) {
5461
+ if (typeof args?.workspace !== "string") {
5462
+ return failure("invalid_args", "workspace must be a non-empty absolute path");
5463
+ }
5464
+ const workspace = args.workspace.trim();
5465
+ if (!workspace || !path3.isAbsolute(workspace)) {
5466
+ return failure("invalid_args", "workspace must be a non-empty absolute path");
5467
+ }
5468
+ return { workspace };
5469
+ }
5470
+ function validateRepoPath(args) {
5471
+ if (typeof args?.path !== "string" || !args.path.trim()) {
5472
+ return failure("invalid_args", "path must be a non-empty repository-relative path");
5473
+ }
5474
+ return { path: args.path.trim() };
5475
+ }
5476
+ function validateSnapshotId(args, key) {
5477
+ if (typeof args?.[key] !== "string" || !args[key].trim()) {
5478
+ return failure("invalid_args", `${key} must be a non-empty string`);
5479
+ }
5480
+ return args[key].trim();
5481
+ }
5482
+ function parseSnapshotReason(args) {
5483
+ if (args?.reason === void 0 || args?.reason === null || args?.reason === "") {
5484
+ return "manual";
5485
+ }
5486
+ if (typeof args.reason !== "string" || !SNAPSHOT_REASONS.has(args.reason)) {
5487
+ return failure("invalid_args", "reason must be a valid GitSnapshotReason");
5488
+ }
5489
+ return args.reason;
5490
+ }
5491
+ function optionalString(value) {
5492
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
5493
+ }
5494
+ function optionalBoolean(value) {
5495
+ return typeof value === "boolean" ? value : void 0;
5496
+ }
5497
+ function boundedLogLimit(value) {
5498
+ if (value === void 0 || value === null || value === "") return 50;
5499
+ const numeric = typeof value === "number" ? value : Number(value);
5500
+ if (!Number.isFinite(numeric)) return 50;
5501
+ return Math.max(1, Math.min(200, Math.floor(numeric)));
5502
+ }
5503
+ function failureReasonFromError(error) {
5504
+ return typeof error?.reason === "string" && FAILURE_REASONS.has(error.reason) ? error.reason : "git_command_failed";
5505
+ }
5506
+ async function runService(fn) {
5507
+ try {
5508
+ return await fn();
5509
+ } catch (error) {
5510
+ return failure(failureReasonFromError(error), error?.message || "Git command failed");
5511
+ }
5512
+ }
5513
+ function isGitCommandName(command) {
5514
+ return GIT_COMMAND_NAMES.has(command);
5515
+ }
5516
+ async function handleGitCommand(command, args, services = defaultGitCommandServices) {
5517
+ if (!isGitCommandName(command)) {
5518
+ return failure("invalid_args", `Unknown Git command: ${command}`);
5519
+ }
5520
+ if (MUTATING_COMMAND_NAMES.has(command)) {
5521
+ return failure("invalid_args", `${command} is not implemented in daemon-core read-only Git routing`);
5522
+ }
5523
+ const workspaceResult = validateWorkspace2(args);
5524
+ if ("success" in workspaceResult) return workspaceResult;
5525
+ const { workspace } = workspaceResult;
5526
+ switch (command) {
5527
+ case "git_status": {
5528
+ if (!services.getStatus) return serviceNotImplemented(command);
5529
+ const status = await runService(() => services.getStatus({ workspace }));
5530
+ return "success" in status ? status : { success: true, status };
5531
+ }
5532
+ case "git_diff_summary": {
5533
+ if (!services.getDiffSummary) return serviceNotImplemented(command);
5534
+ const diffSummary = await runService(() => services.getDiffSummary({ workspace, staged: optionalBoolean(args?.staged) }));
5535
+ return "success" in diffSummary ? diffSummary : { success: true, diffSummary };
5536
+ }
5537
+ case "git_diff_file": {
5538
+ if (!services.getDiffFile) return serviceNotImplemented(command);
5539
+ const pathResult = validateRepoPath(args);
5540
+ if (typeof pathResult !== "object" || "success" in pathResult) return pathResult;
5541
+ const diff = await runService(() => services.getDiffFile({
5542
+ workspace,
5543
+ path: pathResult.path,
5544
+ staged: optionalBoolean(args?.staged)
5545
+ }));
5546
+ return "success" in diff ? diff : { success: true, diff };
5547
+ }
5548
+ case "git_snapshot_create": {
5549
+ if (!services.createSnapshot) return serviceNotImplemented(command);
5550
+ const reason = parseSnapshotReason(args);
5551
+ if (typeof reason !== "string") return reason;
5552
+ const snapshot = await runService(() => services.createSnapshot({
5553
+ workspace,
5554
+ reason,
5555
+ sessionId: optionalString(args?.sessionId),
5556
+ turnId: optionalString(args?.turnId)
5557
+ }));
5558
+ return "success" in snapshot ? snapshot : { success: true, snapshot };
5559
+ }
5560
+ case "git_snapshot_compare": {
5561
+ if (!services.compareSnapshots) return serviceNotImplemented(command);
5562
+ const beforeSnapshotId = validateSnapshotId(args, "beforeSnapshotId");
5563
+ if (typeof beforeSnapshotId !== "string") return beforeSnapshotId;
5564
+ const afterSnapshotId = validateSnapshotId(args, "afterSnapshotId");
5565
+ if (typeof afterSnapshotId !== "string") return afterSnapshotId;
5566
+ const compare = await runService(() => services.compareSnapshots({ workspace, beforeSnapshotId, afterSnapshotId }));
5567
+ return "success" in compare ? compare : { success: true, compare };
5568
+ }
5569
+ case "git_log": {
5570
+ if (!services.getLog) {
5571
+ return failure("invalid_args", "git_log is not implemented: bounded daemon-core Git log service is not configured");
5572
+ }
5573
+ const log = await runService(() => services.getLog({
5574
+ workspace,
5575
+ limit: boundedLogLimit(args?.limit),
5576
+ path: optionalString(args?.path),
5577
+ since: optionalString(args?.since),
5578
+ until: optionalString(args?.until)
5579
+ }));
5580
+ return "success" in log ? log : { success: true, log };
5581
+ }
5582
+ default:
5583
+ return failure("invalid_args", `Unknown Git command: ${command}`);
5584
+ }
5585
+ }
5586
+ function formatOptionalGitLogRangeArg(flag, value) {
5587
+ return value ? [`${flag}=${value}`] : [];
5588
+ }
5589
+ async function getGitLog(workspace, options) {
5590
+ const lastCheckedAt = Date.now();
5591
+ const repo = await resolveGitRepository(workspace);
5592
+ const repoRoot = repo.repoRoot;
5593
+ const boundedLimit = Math.max(1, Math.min(200, Math.floor(options.limit || 50)));
5594
+ const selectedPath = options.path ? validateGitLogPath(repoRoot, options.path) : void 0;
5595
+ const result = await runGit(
5596
+ repo,
5597
+ [
5598
+ "log",
5599
+ `--max-count=${boundedLimit}`,
5600
+ "--format=%H%x00%an%x00%ae%x00%at%x00%ct%x00%s",
5601
+ ...formatOptionalGitLogRangeArg("--since", options.since),
5602
+ ...formatOptionalGitLogRangeArg("--until", options.until),
5603
+ "--",
5604
+ ...selectedPath ? [selectedPath] : []
5605
+ ],
5606
+ { cwd: repoRoot }
5607
+ );
5608
+ const entries = result.stdout.split("\n").filter((line) => line.trim().length > 0).map((line) => {
5609
+ const [commit = "", authorName, authorEmail, authoredAt, committedAt, ...messageParts] = line.split("\0");
5610
+ return {
5611
+ commit,
5612
+ message: messageParts.join("\0"),
5613
+ authorName: authorName || void 0,
5614
+ authorEmail: authorEmail || void 0,
5615
+ authoredAt: authoredAt ? Number.parseInt(authoredAt, 10) * 1e3 : void 0,
5616
+ committedAt: committedAt ? Number.parseInt(committedAt, 10) * 1e3 : void 0
5617
+ };
5618
+ }).filter((entry) => entry.commit.length > 0);
5619
+ return {
5620
+ workspace: repo.workspace,
5621
+ repoRoot,
5622
+ isGitRepo: true,
5623
+ entries,
5624
+ limit: boundedLimit,
5625
+ truncated: entries.length >= boundedLimit,
5626
+ lastCheckedAt
5627
+ };
5628
+ }
5629
+ function validateGitLogPath(repoRoot, filePath) {
5630
+ if (!filePath.trim() || filePath.includes("\0")) {
5631
+ throw new GitCommandError("invalid_args", "path must be a non-empty repository-relative path");
5632
+ }
5633
+ if (path3.isAbsolute(filePath)) {
5634
+ throw new GitCommandError("invalid_args", "path must be repository-relative");
5635
+ }
5636
+ const normalized = path3.normalize(filePath).split(path3.sep).join("/");
5637
+ const absolutePath = path3.resolve(repoRoot, normalized);
5638
+ if (!isPathInside(repoRoot, absolutePath) || normalized.startsWith("../") || normalized === "..") {
5639
+ throw new GitCommandError("path_outside_repo", "Git log path is outside the repository root");
5640
+ }
5641
+ return normalized;
5642
+ }
5643
+
4527
5644
  // src/index.ts
4528
5645
  init_config();
4529
5646
 
4530
5647
  // src/config/workspaces.ts
4531
5648
  import * as fs from "fs";
4532
5649
  import * as os from "os";
4533
- import * as path from "path";
5650
+ import * as path4 from "path";
4534
5651
  import { randomUUID as randomUUID2 } from "crypto";
4535
5652
  var MAX_WORKSPACES = 50;
4536
5653
  function expandPath(p) {
4537
5654
  const t = (p || "").trim();
4538
5655
  if (!t) return "";
4539
- if (t.startsWith("~")) return path.join(os.homedir(), t.slice(1).replace(/^\//, ""));
4540
- return path.resolve(t);
5656
+ if (t.startsWith("~")) return path4.join(os.homedir(), t.slice(1).replace(/^\//, ""));
5657
+ return path4.resolve(t);
4541
5658
  }
4542
5659
  function validateWorkspacePath(absPath) {
4543
5660
  try {
@@ -4551,7 +5668,7 @@ function validateWorkspacePath(absPath) {
4551
5668
  }
4552
5669
  }
4553
5670
  function defaultWorkspaceLabel(absPath) {
4554
- const base = path.basename(absPath) || absPath;
5671
+ const base = path4.basename(absPath) || absPath;
4555
5672
  return base;
4556
5673
  }
4557
5674
  function getDefaultWorkspacePath(config) {
@@ -4642,9 +5759,9 @@ function resolveIdeLaunchWorkspace(args, config) {
4642
5759
  return getDefaultWorkspacePath(config) || void 0;
4643
5760
  }
4644
5761
  function findWorkspaceByPath(config, rawPath) {
4645
- const abs = path.resolve(expandPath(rawPath));
5762
+ const abs = path4.resolve(expandPath(rawPath));
4646
5763
  if (!abs) return void 0;
4647
- return (config.workspaces || []).find((w) => path.resolve(expandPath(w.path)) === abs);
5764
+ return (config.workspaces || []).find((w) => path4.resolve(expandPath(w.path)) === abs);
4648
5765
  }
4649
5766
  function addWorkspaceEntry(config, rawPath, label, options) {
4650
5767
  const abs = expandPath(rawPath);
@@ -4660,7 +5777,7 @@ function addWorkspaceEntry(config, rawPath, label, options) {
4660
5777
  const v = validateWorkspacePath(abs);
4661
5778
  if (!v.ok) return { error: v.error };
4662
5779
  const list = [...config.workspaces || []];
4663
- if (list.some((w) => path.resolve(w.path) === abs)) {
5780
+ if (list.some((w) => path4.resolve(w.path) === abs)) {
4664
5781
  return { error: "Workspace already in list" };
4665
5782
  }
4666
5783
  if (list.length >= MAX_WORKSPACES) {
@@ -4694,7 +5811,7 @@ function setDefaultWorkspaceId(config, id) {
4694
5811
  }
4695
5812
 
4696
5813
  // src/config/recent-activity.ts
4697
- import * as path2 from "path";
5814
+ import * as path5 from "path";
4698
5815
 
4699
5816
  // src/providers/summary-metadata.ts
4700
5817
  function normalizeSummaryItem(item) {
@@ -4763,9 +5880,9 @@ var MAX_ACTIVITY = 30;
4763
5880
  function normalizeWorkspace(workspace) {
4764
5881
  if (!workspace) return "";
4765
5882
  try {
4766
- return path2.resolve(expandPath(workspace));
5883
+ return path5.resolve(expandPath(workspace));
4767
5884
  } catch {
4768
- return path2.resolve(workspace);
5885
+ return path5.resolve(workspace);
4769
5886
  }
4770
5887
  }
4771
5888
  function buildRecentActivityKey(entry) {
@@ -4933,14 +6050,14 @@ function markSessionSeen(state, sessionId, seenAt = Date.now(), completionMarker
4933
6050
  }
4934
6051
 
4935
6052
  // src/config/saved-sessions.ts
4936
- import * as path3 from "path";
6053
+ import * as path6 from "path";
4937
6054
  var MAX_SAVED_SESSIONS = 500;
4938
6055
  function normalizeWorkspace2(workspace) {
4939
6056
  if (!workspace) return "";
4940
6057
  try {
4941
- return path3.resolve(expandPath(workspace));
6058
+ return path6.resolve(expandPath(workspace));
4942
6059
  } catch {
4943
- return path3.resolve(workspace);
6060
+ return path6.resolve(workspace);
4944
6061
  }
4945
6062
  }
4946
6063
  function buildSavedProviderSessionKey(providerSessionId) {
@@ -5059,7 +6176,7 @@ function resetState() {
5059
6176
  import { execSync } from "child_process";
5060
6177
  import { existsSync as existsSync4 } from "fs";
5061
6178
  import { platform, homedir as homedir3 } from "os";
5062
- import * as path4 from "path";
6179
+ import * as path7 from "path";
5063
6180
  var BUILTIN_IDE_DEFINITIONS = [];
5064
6181
  var registeredIDEs = /* @__PURE__ */ new Map();
5065
6182
  function registerIDEDefinition(def) {
@@ -5078,9 +6195,9 @@ function getMergedDefinitions() {
5078
6195
  function findCliCommand(command) {
5079
6196
  const trimmed = String(command || "").trim();
5080
6197
  if (!trimmed) return null;
5081
- if (path4.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
5082
- const candidate = trimmed.startsWith("~") ? path4.join(homedir3(), trimmed.slice(1)) : trimmed;
5083
- const resolved = path4.isAbsolute(candidate) ? candidate : path4.resolve(candidate);
6198
+ if (path7.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
6199
+ const candidate = trimmed.startsWith("~") ? path7.join(homedir3(), trimmed.slice(1)) : trimmed;
6200
+ const resolved = path7.isAbsolute(candidate) ? candidate : path7.resolve(candidate);
5084
6201
  return existsSync4(resolved) ? resolved : null;
5085
6202
  }
5086
6203
  try {
@@ -5108,7 +6225,7 @@ function getIdeVersion(cliCommand) {
5108
6225
  function checkPathExists(paths) {
5109
6226
  const home = homedir3();
5110
6227
  for (const p of paths) {
5111
- const normalized = p.startsWith("~") ? path4.join(home, p.slice(1)) : p;
6228
+ const normalized = p.startsWith("~") ? path7.join(home, p.slice(1)) : p;
5112
6229
  if (normalized.includes("*")) {
5113
6230
  const username = home.split(/[\\/]/).pop() || "";
5114
6231
  const resolved = normalized.replace("*", username);
@@ -5166,7 +6283,7 @@ async function detectIDEs(providerLoader) {
5166
6283
  // src/detection/cli-detector.ts
5167
6284
  import { exec } from "child_process";
5168
6285
  import * as os2 from "os";
5169
- import * as path5 from "path";
6286
+ import * as path8 from "path";
5170
6287
  import { existsSync as existsSync5 } from "fs";
5171
6288
  function parseVersion(raw) {
5172
6289
  const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
@@ -5179,36 +6296,36 @@ function shellQuote(value) {
5179
6296
  function expandHome(value) {
5180
6297
  const trimmed = value.trim();
5181
6298
  if (!trimmed.startsWith("~")) return trimmed;
5182
- return path5.join(os2.homedir(), trimmed.slice(1));
6299
+ return path8.join(os2.homedir(), trimmed.slice(1));
5183
6300
  }
5184
6301
  function isExplicitCommandPath(command) {
5185
6302
  const trimmed = command.trim();
5186
- return path5.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
6303
+ return path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
5187
6304
  }
5188
6305
  function resolveCommandPath(command) {
5189
6306
  const trimmed = command.trim();
5190
6307
  if (!trimmed) return null;
5191
6308
  if (isExplicitCommandPath(trimmed)) {
5192
6309
  const expanded = expandHome(trimmed);
5193
- const candidate = path5.isAbsolute(expanded) ? expanded : path5.resolve(expanded);
6310
+ const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
5194
6311
  return existsSync5(candidate) ? candidate : null;
5195
6312
  }
5196
6313
  return null;
5197
6314
  }
5198
6315
  function execAsync(cmd, timeoutMs = 5e3) {
5199
- return new Promise((resolve12) => {
6316
+ return new Promise((resolve15) => {
5200
6317
  const child = exec(cmd, {
5201
6318
  encoding: "utf-8",
5202
6319
  timeout: timeoutMs,
5203
6320
  ...process.platform === "win32" ? { windowsHide: true } : {}
5204
6321
  }, (err, stdout) => {
5205
6322
  if (err || !stdout?.trim()) {
5206
- resolve12(null);
6323
+ resolve15(null);
5207
6324
  } else {
5208
- resolve12(stdout.trim());
6325
+ resolve15(stdout.trim());
5209
6326
  }
5210
6327
  });
5211
- child.on("error", () => resolve12(null));
6328
+ child.on("error", () => resolve15(null));
5212
6329
  });
5213
6330
  }
5214
6331
  async function detectCLIs(providerLoader, options) {
@@ -5573,7 +6690,7 @@ var DaemonCdpManager = class {
5573
6690
  * Returns multiple entries if multiple IDE windows are open on same port
5574
6691
  */
5575
6692
  static listAllTargets(port) {
5576
- return new Promise((resolve12) => {
6693
+ return new Promise((resolve15) => {
5577
6694
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
5578
6695
  let data = "";
5579
6696
  res.on("data", (chunk) => data += chunk.toString());
@@ -5589,16 +6706,16 @@ var DaemonCdpManager = class {
5589
6706
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
5590
6707
  );
5591
6708
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
5592
- resolve12(mainPages.length > 0 ? mainPages : fallbackPages);
6709
+ resolve15(mainPages.length > 0 ? mainPages : fallbackPages);
5593
6710
  } catch {
5594
- resolve12([]);
6711
+ resolve15([]);
5595
6712
  }
5596
6713
  });
5597
6714
  });
5598
- req.on("error", () => resolve12([]));
6715
+ req.on("error", () => resolve15([]));
5599
6716
  req.setTimeout(2e3, () => {
5600
6717
  req.destroy();
5601
- resolve12([]);
6718
+ resolve15([]);
5602
6719
  });
5603
6720
  });
5604
6721
  }
@@ -5638,7 +6755,7 @@ var DaemonCdpManager = class {
5638
6755
  }
5639
6756
  }
5640
6757
  findTargetOnPort(port) {
5641
- return new Promise((resolve12) => {
6758
+ return new Promise((resolve15) => {
5642
6759
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
5643
6760
  let data = "";
5644
6761
  res.on("data", (chunk) => data += chunk.toString());
@@ -5649,7 +6766,7 @@ var DaemonCdpManager = class {
5649
6766
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
5650
6767
  );
5651
6768
  if (pages.length === 0) {
5652
- resolve12(targets.find((t) => t.webSocketDebuggerUrl) || null);
6769
+ resolve15(targets.find((t) => t.webSocketDebuggerUrl) || null);
5653
6770
  return;
5654
6771
  }
5655
6772
  const titleFilteredPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -5668,25 +6785,25 @@ var DaemonCdpManager = class {
5668
6785
  this._targetId = selected.target.id;
5669
6786
  }
5670
6787
  this._pageTitle = selected.target.title || "";
5671
- resolve12(selected.target);
6788
+ resolve15(selected.target);
5672
6789
  return;
5673
6790
  }
5674
6791
  if (previousTargetId) {
5675
6792
  this.log(`[CDP] Target ${previousTargetId} not found in page list`);
5676
- resolve12(null);
6793
+ resolve15(null);
5677
6794
  return;
5678
6795
  }
5679
6796
  this._pageTitle = list[0]?.title || "";
5680
- resolve12(list[0]);
6797
+ resolve15(list[0]);
5681
6798
  } catch {
5682
- resolve12(null);
6799
+ resolve15(null);
5683
6800
  }
5684
6801
  });
5685
6802
  });
5686
- req.on("error", () => resolve12(null));
6803
+ req.on("error", () => resolve15(null));
5687
6804
  req.setTimeout(2e3, () => {
5688
6805
  req.destroy();
5689
- resolve12(null);
6806
+ resolve15(null);
5690
6807
  });
5691
6808
  });
5692
6809
  }
@@ -5697,7 +6814,7 @@ var DaemonCdpManager = class {
5697
6814
  this.extensionProviders = providers;
5698
6815
  }
5699
6816
  connectToTarget(wsUrl) {
5700
- return new Promise((resolve12) => {
6817
+ return new Promise((resolve15) => {
5701
6818
  this.ws = new WebSocket(wsUrl);
5702
6819
  this.ws.on("open", async () => {
5703
6820
  this._connected = true;
@@ -5707,17 +6824,17 @@ var DaemonCdpManager = class {
5707
6824
  }
5708
6825
  this.connectBrowserWs().catch(() => {
5709
6826
  });
5710
- resolve12(true);
6827
+ resolve15(true);
5711
6828
  });
5712
6829
  this.ws.on("message", (data) => {
5713
6830
  try {
5714
6831
  const msg = JSON.parse(data.toString());
5715
6832
  if (msg.id && this.pending.has(msg.id)) {
5716
- const { resolve: resolve13, reject } = this.pending.get(msg.id);
6833
+ const { resolve: resolve16, reject } = this.pending.get(msg.id);
5717
6834
  this.pending.delete(msg.id);
5718
6835
  this.failureCount = 0;
5719
6836
  if (msg.error) reject(new Error(msg.error.message));
5720
- else resolve13(msg.result);
6837
+ else resolve16(msg.result);
5721
6838
  } else if (msg.method === "Runtime.executionContextCreated") {
5722
6839
  this.contexts.add(msg.params.context.id);
5723
6840
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -5740,7 +6857,7 @@ var DaemonCdpManager = class {
5740
6857
  this.ws.on("error", (err) => {
5741
6858
  this.log(`[CDP] WebSocket error: ${err.message}`);
5742
6859
  this._connected = false;
5743
- resolve12(false);
6860
+ resolve15(false);
5744
6861
  });
5745
6862
  });
5746
6863
  }
@@ -5754,7 +6871,7 @@ var DaemonCdpManager = class {
5754
6871
  return;
5755
6872
  }
5756
6873
  this.log(`[CDP] Connecting browser WS for target discovery...`);
5757
- await new Promise((resolve12, reject) => {
6874
+ await new Promise((resolve15, reject) => {
5758
6875
  this.browserWs = new WebSocket(browserWsUrl);
5759
6876
  this.browserWs.on("open", async () => {
5760
6877
  this._browserConnected = true;
@@ -5764,16 +6881,16 @@ var DaemonCdpManager = class {
5764
6881
  } catch (e) {
5765
6882
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
5766
6883
  }
5767
- resolve12();
6884
+ resolve15();
5768
6885
  });
5769
6886
  this.browserWs.on("message", (data) => {
5770
6887
  try {
5771
6888
  const msg = JSON.parse(data.toString());
5772
6889
  if (msg.id && this.browserPending.has(msg.id)) {
5773
- const { resolve: resolve13, reject: reject2 } = this.browserPending.get(msg.id);
6890
+ const { resolve: resolve16, reject: reject2 } = this.browserPending.get(msg.id);
5774
6891
  this.browserPending.delete(msg.id);
5775
6892
  if (msg.error) reject2(new Error(msg.error.message));
5776
- else resolve13(msg.result);
6893
+ else resolve16(msg.result);
5777
6894
  }
5778
6895
  } catch {
5779
6896
  }
@@ -5793,31 +6910,31 @@ var DaemonCdpManager = class {
5793
6910
  }
5794
6911
  }
5795
6912
  getBrowserWsUrl() {
5796
- return new Promise((resolve12) => {
6913
+ return new Promise((resolve15) => {
5797
6914
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
5798
6915
  let data = "";
5799
6916
  res.on("data", (chunk) => data += chunk.toString());
5800
6917
  res.on("end", () => {
5801
6918
  try {
5802
6919
  const info = JSON.parse(data);
5803
- resolve12(info.webSocketDebuggerUrl || null);
6920
+ resolve15(info.webSocketDebuggerUrl || null);
5804
6921
  } catch {
5805
- resolve12(null);
6922
+ resolve15(null);
5806
6923
  }
5807
6924
  });
5808
6925
  });
5809
- req.on("error", () => resolve12(null));
6926
+ req.on("error", () => resolve15(null));
5810
6927
  req.setTimeout(3e3, () => {
5811
6928
  req.destroy();
5812
- resolve12(null);
6929
+ resolve15(null);
5813
6930
  });
5814
6931
  });
5815
6932
  }
5816
6933
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
5817
- return new Promise((resolve12, reject) => {
6934
+ return new Promise((resolve15, reject) => {
5818
6935
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
5819
6936
  const id = this.browserMsgId++;
5820
- this.browserPending.set(id, { resolve: resolve12, reject });
6937
+ this.browserPending.set(id, { resolve: resolve15, reject });
5821
6938
  this.browserWs.send(JSON.stringify({ id, method, params }));
5822
6939
  setTimeout(() => {
5823
6940
  if (this.browserPending.has(id)) {
@@ -5857,11 +6974,11 @@ var DaemonCdpManager = class {
5857
6974
  }
5858
6975
  // ─── CDP Protocol ────────────────────────────────────────
5859
6976
  sendInternal(method, params = {}, timeoutMs = 15e3) {
5860
- return new Promise((resolve12, reject) => {
6977
+ return new Promise((resolve15, reject) => {
5861
6978
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
5862
6979
  if (this.ws.readyState !== WebSocket.OPEN) return reject(new Error("WebSocket not open"));
5863
6980
  const id = this.msgId++;
5864
- this.pending.set(id, { resolve: resolve12, reject });
6981
+ this.pending.set(id, { resolve: resolve15, reject });
5865
6982
  this.ws.send(JSON.stringify({ id, method, params }));
5866
6983
  setTimeout(() => {
5867
6984
  if (this.pending.has(id)) {
@@ -6110,7 +7227,7 @@ var DaemonCdpManager = class {
6110
7227
  const browserWs = this.browserWs;
6111
7228
  let msgId = this.browserMsgId;
6112
7229
  const sendWs = (method, params = {}, sessionId) => {
6113
- return new Promise((resolve12, reject) => {
7230
+ return new Promise((resolve15, reject) => {
6114
7231
  const mid = msgId++;
6115
7232
  this.browserMsgId = msgId;
6116
7233
  const handler = (raw) => {
@@ -6119,7 +7236,7 @@ var DaemonCdpManager = class {
6119
7236
  if (msg.id === mid) {
6120
7237
  browserWs.removeListener("message", handler);
6121
7238
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
6122
- else resolve12(msg.result);
7239
+ else resolve15(msg.result);
6123
7240
  }
6124
7241
  } catch {
6125
7242
  }
@@ -6320,14 +7437,14 @@ var DaemonCdpManager = class {
6320
7437
  if (!ws || ws.readyState !== WebSocket.OPEN) {
6321
7438
  throw new Error("CDP not connected");
6322
7439
  }
6323
- return new Promise((resolve12, reject) => {
7440
+ return new Promise((resolve15, reject) => {
6324
7441
  const id = getNextId();
6325
7442
  pendingMap.set(id, {
6326
7443
  resolve: (result) => {
6327
7444
  if (result?.result?.subtype === "error") {
6328
7445
  reject(new Error(result.result.description));
6329
7446
  } else {
6330
- resolve12(result?.result?.value);
7447
+ resolve15(result?.result?.value);
6331
7448
  }
6332
7449
  },
6333
7450
  reject
@@ -6359,10 +7476,10 @@ var DaemonCdpManager = class {
6359
7476
  throw new Error("CDP not connected");
6360
7477
  }
6361
7478
  const sendViaSession = (method, params = {}) => {
6362
- return new Promise((resolve12, reject) => {
7479
+ return new Promise((resolve15, reject) => {
6363
7480
  const pendingMap = this._browserConnected ? this.browserPending : this.pending;
6364
7481
  const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
6365
- pendingMap.set(id, { resolve: resolve12, reject });
7482
+ pendingMap.set(id, { resolve: resolve15, reject });
6366
7483
  ws.send(JSON.stringify({ id, sessionId, method, params }));
6367
7484
  setTimeout(() => {
6368
7485
  if (pendingMap.has(id)) {
@@ -7109,9 +8226,9 @@ ${cleanBody}`;
7109
8226
  // src/config/chat-history.ts
7110
8227
  init_chat_message_normalization();
7111
8228
  import * as fs3 from "fs";
7112
- import * as path7 from "path";
8229
+ import * as path10 from "path";
7113
8230
  import * as os5 from "os";
7114
- var HISTORY_DIR = path7.join(os5.homedir(), ".adhdev", "history");
8231
+ var HISTORY_DIR = path10.join(os5.homedir(), ".adhdev", "history");
7115
8232
  var RETAIN_DAYS = 30;
7116
8233
  var SAVED_HISTORY_INDEX_VERSION = 1;
7117
8234
  var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
@@ -7274,8 +8391,8 @@ function extractSavedHistorySessionIdFromFile(file) {
7274
8391
  function buildSavedHistoryFileSignatureMap(dir, files) {
7275
8392
  return new Map(files.map((file) => {
7276
8393
  try {
7277
- const stat = fs3.statSync(path7.join(dir, file));
7278
- return [file, `${file}:${stat.size}:${Math.trunc(stat.mtimeMs)}`];
8394
+ const stat2 = fs3.statSync(path10.join(dir, file));
8395
+ return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
7279
8396
  } catch {
7280
8397
  return [file, `${file}:missing`];
7281
8398
  }
@@ -7285,7 +8402,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
7285
8402
  return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
7286
8403
  }
7287
8404
  function getSavedHistoryIndexFilePath(dir) {
7288
- return path7.join(dir, SAVED_HISTORY_INDEX_FILE);
8405
+ return path10.join(dir, SAVED_HISTORY_INDEX_FILE);
7289
8406
  }
7290
8407
  function getSavedHistoryIndexLockPath(dir) {
7291
8408
  return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
@@ -7338,8 +8455,8 @@ function acquireSavedHistoryIndexLock(dir) {
7338
8455
  } catch (error) {
7339
8456
  if (error?.code !== "EEXIST") return null;
7340
8457
  try {
7341
- const stat = fs3.statSync(lockPath);
7342
- if (Date.now() - stat.mtimeMs > SAVED_HISTORY_INDEX_LOCK_STALE_MS) {
8458
+ const stat2 = fs3.statSync(lockPath);
8459
+ if (Date.now() - stat2.mtimeMs > SAVED_HISTORY_INDEX_LOCK_STALE_MS) {
7343
8460
  fs3.rmSync(lockPath, { recursive: true, force: true });
7344
8461
  continue;
7345
8462
  }
@@ -7387,7 +8504,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
7387
8504
  }
7388
8505
  for (const file of Array.from(currentEntries.keys())) {
7389
8506
  if (incomingFiles.has(file)) continue;
7390
- if (!fs3.existsSync(path7.join(dir, file))) {
8507
+ if (!fs3.existsSync(path10.join(dir, file))) {
7391
8508
  currentEntries.delete(file);
7392
8509
  }
7393
8510
  }
@@ -7402,8 +8519,8 @@ function invalidatePersistedSavedHistoryIndex(agentType, dir) {
7402
8519
  }
7403
8520
  function buildSavedHistoryIndexFileSignature(dir) {
7404
8521
  try {
7405
- const stat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
7406
- return `index:${stat.size}:${Math.trunc(stat.mtimeMs)}`;
8522
+ const stat2 = fs3.statSync(getSavedHistoryIndexFilePath(dir));
8523
+ return `index:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
7407
8524
  } catch {
7408
8525
  return "index:missing";
7409
8526
  }
@@ -7413,8 +8530,8 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
7413
8530
  const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
7414
8531
  const files = listHistoryFiles(dir);
7415
8532
  for (const file of files) {
7416
- const stat = fs3.statSync(path7.join(dir, file));
7417
- if (stat.mtimeMs > indexStat.mtimeMs) return true;
8533
+ const stat2 = fs3.statSync(path10.join(dir, file));
8534
+ if (stat2.mtimeMs > indexStat.mtimeMs) return true;
7418
8535
  }
7419
8536
  return false;
7420
8537
  } catch {
@@ -7423,14 +8540,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
7423
8540
  }
7424
8541
  function buildSavedHistoryFileSignature(dir, file) {
7425
8542
  try {
7426
- const stat = fs3.statSync(path7.join(dir, file));
7427
- return `${file}:${stat.size}:${Math.trunc(stat.mtimeMs)}`;
8543
+ const stat2 = fs3.statSync(path10.join(dir, file));
8544
+ return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
7428
8545
  } catch {
7429
8546
  return `${file}:missing`;
7430
8547
  }
7431
8548
  }
7432
8549
  function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
7433
- const filePath = path7.join(dir, file);
8550
+ const filePath = path10.join(dir, file);
7434
8551
  const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
7435
8552
  const currentEntry = entries.get(file) || null;
7436
8553
  const nextSummary = updater(currentEntry?.summary || null);
@@ -7503,7 +8620,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
7503
8620
  function computeSavedHistoryFileSummary(dir, file) {
7504
8621
  const historySessionId = extractSavedHistorySessionIdFromFile(file);
7505
8622
  if (!historySessionId) return null;
7506
- const filePath = path7.join(dir, file);
8623
+ const filePath = path10.join(dir, file);
7507
8624
  const content = fs3.readFileSync(filePath, "utf-8");
7508
8625
  const lines = content.split("\n").filter(Boolean);
7509
8626
  let messageCount = 0;
@@ -7590,7 +8707,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
7590
8707
  const summaryBySessionId = /* @__PURE__ */ new Map();
7591
8708
  const nextPersistedEntries = /* @__PURE__ */ new Map();
7592
8709
  for (const file of files.slice().sort()) {
7593
- const filePath = path7.join(dir, file);
8710
+ const filePath = path10.join(dir, file);
7594
8711
  const signature = fileSignatures.get(file) || `${file}:missing`;
7595
8712
  const cached = savedHistoryFileSummaryCache.get(filePath);
7596
8713
  const persisted = persistedEntries.get(file);
@@ -7710,12 +8827,12 @@ var ChatHistoryWriter = class {
7710
8827
  });
7711
8828
  }
7712
8829
  if (newMessages.length === 0) return;
7713
- const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
8830
+ const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
7714
8831
  fs3.mkdirSync(dir, { recursive: true });
7715
8832
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
7716
8833
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
7717
8834
  const fileName = `${filePrefix}${date}.jsonl`;
7718
- const filePath = path7.join(dir, fileName);
8835
+ const filePath = path10.join(dir, fileName);
7719
8836
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
7720
8837
  fs3.appendFileSync(filePath, lines, "utf-8");
7721
8838
  updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
@@ -7806,11 +8923,11 @@ var ChatHistoryWriter = class {
7806
8923
  const ws = String(workspace || "").trim();
7807
8924
  if (!id || !ws) return;
7808
8925
  try {
7809
- const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
8926
+ const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
7810
8927
  fs3.mkdirSync(dir, { recursive: true });
7811
8928
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
7812
8929
  const fileName = `${this.sanitize(id)}_${date}.jsonl`;
7813
- const filePath = path7.join(dir, fileName);
8930
+ const filePath = path10.join(dir, fileName);
7814
8931
  const record = {
7815
8932
  ts: (/* @__PURE__ */ new Date()).toISOString(),
7816
8933
  receivedAt: Date.now(),
@@ -7856,14 +8973,14 @@ var ChatHistoryWriter = class {
7856
8973
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
7857
8974
  this.lastSeenCounts.delete(fromDedupKey);
7858
8975
  }
7859
- const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
8976
+ const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
7860
8977
  if (!fs3.existsSync(dir)) return;
7861
8978
  const fromPrefix = `${this.sanitize(fromId)}_`;
7862
8979
  const toPrefix = `${this.sanitize(toId)}_`;
7863
8980
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
7864
8981
  for (const file of files) {
7865
- const sourcePath = path7.join(dir, file);
7866
- const targetPath = path7.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
8982
+ const sourcePath = path10.join(dir, file);
8983
+ const targetPath = path10.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
7867
8984
  const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
7868
8985
  const rewritten = sourceLines.map((line) => {
7869
8986
  try {
@@ -7897,13 +9014,13 @@ var ChatHistoryWriter = class {
7897
9014
  const sessionId = String(historySessionId || "").trim();
7898
9015
  if (!sessionId) return;
7899
9016
  try {
7900
- const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
9017
+ const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
7901
9018
  if (!fs3.existsSync(dir)) return;
7902
9019
  const prefix = `${this.sanitize(sessionId)}_`;
7903
9020
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
7904
9021
  const seen = /* @__PURE__ */ new Set();
7905
9022
  for (const file of files) {
7906
- const filePath = path7.join(dir, file);
9023
+ const filePath = path10.join(dir, file);
7907
9024
  const lines = fs3.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
7908
9025
  const next = [];
7909
9026
  for (const line of lines) {
@@ -7957,13 +9074,13 @@ var ChatHistoryWriter = class {
7957
9074
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
7958
9075
  const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
7959
9076
  for (const dir of agentDirs) {
7960
- const dirPath = path7.join(HISTORY_DIR, dir.name);
9077
+ const dirPath = path10.join(HISTORY_DIR, dir.name);
7961
9078
  const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
7962
9079
  let removedAny = false;
7963
9080
  for (const file of files) {
7964
- const filePath = path7.join(dirPath, file);
7965
- const stat = fs3.statSync(filePath);
7966
- if (stat.mtimeMs < cutoff) {
9081
+ const filePath = path10.join(dirPath, file);
9082
+ const stat2 = fs3.statSync(filePath);
9083
+ if (stat2.mtimeMs < cutoff) {
7967
9084
  fs3.unlinkSync(filePath);
7968
9085
  removedAny = true;
7969
9086
  }
@@ -7980,6 +9097,10 @@ var ChatHistoryWriter = class {
7980
9097
  return name.replace(/[^a-zA-Z0-9_-]/g, "_");
7981
9098
  }
7982
9099
  };
9100
+ function normalizePaginationNumber(value, fallback, min) {
9101
+ const numeric = Number(value);
9102
+ return Number.isFinite(numeric) ? Math.max(min, numeric) : fallback;
9103
+ }
7983
9104
  function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeRecentCount = 0, historyBehavior) {
7984
9105
  const allMessages = records.map((message) => sanitizeHistoryMessage(agentType, message)).filter(Boolean);
7985
9106
  allMessages.sort((a, b) => a.receivedAt - b.receivedAt);
@@ -7993,9 +9114,12 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
7993
9114
  if (message.role !== "system") lastTurn = message;
7994
9115
  }
7995
9116
  const collapsed = collapseReplayAssistantTurns(chronological, historyBehavior);
7996
- const boundedLimit = Math.max(1, limit);
7997
- const boundedOffset = Math.max(0, offset);
7998
- const boundedExclude = Math.max(0, Math.min(excludeRecentCount, collapsed.length));
9117
+ const boundedLimit = normalizePaginationNumber(limit, 30, 1);
9118
+ const boundedOffset = normalizePaginationNumber(offset, 0, 0);
9119
+ const boundedExclude = Math.min(
9120
+ normalizePaginationNumber(excludeRecentCount, 0, 0),
9121
+ collapsed.length
9122
+ );
7999
9123
  const endExclusive = Math.max(0, collapsed.length - boundedExclude - boundedOffset);
8000
9124
  const startInclusive = Math.max(0, endExclusive - boundedLimit);
8001
9125
  const sliced = collapsed.slice(startInclusive, endExclusive);
@@ -8004,13 +9128,13 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
8004
9128
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
8005
9129
  try {
8006
9130
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
8007
- const dir = path7.join(HISTORY_DIR, sanitized);
9131
+ const dir = path10.join(HISTORY_DIR, sanitized);
8008
9132
  if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
8009
9133
  const files = listHistoryFiles(dir, historySessionId);
8010
9134
  const allMessages = [];
8011
9135
  const seen = /* @__PURE__ */ new Set();
8012
9136
  for (const file of files) {
8013
- const filePath = path7.join(dir, file);
9137
+ const filePath = path10.join(dir, file);
8014
9138
  const content = fs3.readFileSync(filePath, "utf-8");
8015
9139
  const lines = content.trim().split("\n").filter(Boolean);
8016
9140
  for (let i = 0; i < lines.length; i++) {
@@ -8034,7 +9158,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
8034
9158
  function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
8035
9159
  try {
8036
9160
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
8037
- const dir = path7.join(HISTORY_DIR, sanitized);
9161
+ const dir = path10.join(HISTORY_DIR, sanitized);
8038
9162
  if (!fs3.existsSync(dir)) {
8039
9163
  savedHistorySessionCache.delete(sanitized);
8040
9164
  return { sessions: [], hasMore: false };
@@ -8095,11 +9219,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
8095
9219
  }
8096
9220
  function readExistingSessionStartRecord(agentType, historySessionId) {
8097
9221
  try {
8098
- const dir = path7.join(HISTORY_DIR, agentType);
9222
+ const dir = path10.join(HISTORY_DIR, agentType);
8099
9223
  if (!fs3.existsSync(dir)) return null;
8100
9224
  const files = listHistoryFiles(dir, historySessionId).sort();
8101
9225
  for (const file of files) {
8102
- const lines = fs3.readFileSync(path7.join(dir, file), "utf-8").split("\n").filter(Boolean);
9226
+ const lines = fs3.readFileSync(path10.join(dir, file), "utf-8").split("\n").filter(Boolean);
8103
9227
  for (const line of lines) {
8104
9228
  try {
8105
9229
  const parsed = JSON.parse(line);
@@ -8119,16 +9243,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
8119
9243
  function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
8120
9244
  if (records.length === 0) return false;
8121
9245
  try {
8122
- const dir = path7.join(HISTORY_DIR, agentType);
9246
+ const dir = path10.join(HISTORY_DIR, agentType);
8123
9247
  fs3.mkdirSync(dir, { recursive: true });
8124
9248
  const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
8125
9249
  for (const file of fs3.readdirSync(dir)) {
8126
9250
  if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
8127
- fs3.unlinkSync(path7.join(dir, file));
9251
+ fs3.unlinkSync(path10.join(dir, file));
8128
9252
  }
8129
9253
  }
8130
9254
  const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
8131
- const filePath = path7.join(dir, `${prefix}${targetDate}.jsonl`);
9255
+ const filePath = path10.join(dir, `${prefix}${targetDate}.jsonl`);
8132
9256
  fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
8133
9257
  `, "utf-8");
8134
9258
  invalidatePersistedSavedHistoryIndex(agentType, dir);
@@ -10000,6 +11124,10 @@ function shouldIncludeSessionMetadata(profile) {
10000
11124
  function shouldIncludeRuntimeMetadata(profile) {
10001
11125
  return true;
10002
11126
  }
11127
+ function getGitSummaryForWorkspace(workspace, options) {
11128
+ if (!workspace) return void 0;
11129
+ return options.getGitSummaryForWorkspace?.(workspace) || void 0;
11130
+ }
10003
11131
  function findCdpManager(cdpManagers, key) {
10004
11132
  const exact = cdpManagers.get(key);
10005
11133
  if (exact) return exact.isConnected ? exact : null;
@@ -10055,6 +11183,8 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
10055
11183
  const controlValues = normalizeProviderStateControlValues(state.controlValues);
10056
11184
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
10057
11185
  const includeSessionControls = shouldIncludeSessionControls(profile);
11186
+ const workspace = state.workspace || null;
11187
+ const git = getGitSummaryForWorkspace(workspace, options);
10058
11188
  const title = activeChat?.title || state.name;
10059
11189
  return {
10060
11190
  id: state.instanceId || state.type,
@@ -10067,7 +11197,8 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
10067
11197
  activeModal: activeChat?.activeModal || null
10068
11198
  }),
10069
11199
  title,
10070
- workspace: state.workspace || null,
11200
+ workspace,
11201
+ ...git && { git },
10071
11202
  activeChat,
10072
11203
  ...summaryMetadata && { summaryMetadata },
10073
11204
  ...includeSessionMetadata && { capabilities: state.sessionCapabilities || IDE_SESSION_CAPABILITIES },
@@ -10088,6 +11219,8 @@ function buildExtensionAgentSession(parent, ext, options) {
10088
11219
  const controlValues = normalizeProviderStateControlValues(ext.controlValues);
10089
11220
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
10090
11221
  const includeSessionControls = shouldIncludeSessionControls(profile);
11222
+ const workspace = parent.workspace || null;
11223
+ const git = getGitSummaryForWorkspace(workspace, options);
10091
11224
  return {
10092
11225
  id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
10093
11226
  parentId: parent.instanceId || parent.type,
@@ -10100,7 +11233,8 @@ function buildExtensionAgentSession(parent, ext, options) {
10100
11233
  activeModal: activeChat?.activeModal || null
10101
11234
  }),
10102
11235
  title: activeChat?.title || ext.name,
10103
- workspace: parent.workspace || null,
11236
+ workspace,
11237
+ ...git && { git },
10104
11238
  activeChat,
10105
11239
  ...summaryMetadata && { summaryMetadata },
10106
11240
  ...includeSessionMetadata && { capabilities: ext.sessionCapabilities || EXTENSION_SESSION_CAPABILITIES },
@@ -10136,6 +11270,8 @@ function buildCliSession(state, options) {
10136
11270
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
10137
11271
  const includeRuntimeMetadata = shouldIncludeRuntimeMetadata(profile);
10138
11272
  const includeSessionControls = shouldIncludeSessionControls(profile);
11273
+ const workspace = state.workspace || null;
11274
+ const git = getGitSummaryForWorkspace(workspace, options);
10139
11275
  return {
10140
11276
  id: state.instanceId,
10141
11277
  parentId: null,
@@ -10148,7 +11284,8 @@ function buildCliSession(state, options) {
10148
11284
  activeModal: activeChat?.activeModal || null
10149
11285
  }),
10150
11286
  title: activeChat?.title || state.name,
10151
- workspace: state.workspace || null,
11287
+ workspace,
11288
+ ...git && { git },
10152
11289
  ...includeRuntimeMetadata && {
10153
11290
  runtimeKey: state.runtime?.runtimeKey,
10154
11291
  runtimeDisplayName: state.runtime?.displayName,
@@ -10183,6 +11320,8 @@ function buildAcpSession(state, options) {
10183
11320
  const controlValues = normalizeProviderStateControlValues(state.controlValues);
10184
11321
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
10185
11322
  const includeSessionControls = shouldIncludeSessionControls(profile);
11323
+ const workspace = state.workspace || null;
11324
+ const git = getGitSummaryForWorkspace(workspace, options);
10186
11325
  return {
10187
11326
  id: state.instanceId,
10188
11327
  parentId: null,
@@ -10194,7 +11333,8 @@ function buildAcpSession(state, options) {
10194
11333
  activeModal: activeChat?.activeModal || null
10195
11334
  }),
10196
11335
  title: activeChat?.title || state.name,
10197
- workspace: state.workspace || null,
11336
+ workspace,
11337
+ ...git && { git },
10198
11338
  activeChat,
10199
11339
  ...summaryMetadata && { summaryMetadata },
10200
11340
  ...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES },
@@ -10314,7 +11454,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
10314
11454
  init_contracts();
10315
11455
  import * as fs4 from "fs";
10316
11456
  import * as os6 from "os";
10317
- import * as path8 from "path";
11457
+ import * as path11 from "path";
10318
11458
  import { randomUUID as randomUUID4 } from "crypto";
10319
11459
 
10320
11460
  // src/providers/provider-input-support.ts
@@ -11006,7 +12146,7 @@ function buildDebugBundleText(bundle) {
11006
12146
  }
11007
12147
  function getChatDebugBundleDir() {
11008
12148
  const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
11009
- return override || path8.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
12149
+ return override || path11.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
11010
12150
  }
11011
12151
  function safeBundleIdSegment(value, fallback) {
11012
12152
  const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
@@ -11039,7 +12179,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
11039
12179
  const bundleId = createChatDebugBundleId(targetSessionId);
11040
12180
  const dir = getChatDebugBundleDir();
11041
12181
  fs4.mkdirSync(dir, { recursive: true });
11042
- const savedPath = path8.join(dir, `${bundleId}.json`);
12182
+ const savedPath = path11.join(dir, `${bundleId}.json`);
11043
12183
  const json = `${JSON.stringify(bundle, null, 2)}
11044
12184
  `;
11045
12185
  fs4.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
@@ -11208,10 +12348,32 @@ function getStateLastSignature(state) {
11208
12348
  if (!last) return "";
11209
12349
  return `${last.role || ""}:${String(last.content || "").replace(/\s+/g, " ").trim()}`;
11210
12350
  }
12351
+ function toNonNegativeNumber(value) {
12352
+ const numeric = Number(value ?? 0);
12353
+ return Number.isFinite(numeric) ? Math.max(0, numeric) : 0;
12354
+ }
12355
+ function getCliVisibleTranscriptCount(adapter) {
12356
+ const adapterStatus = adapter?.getStatus?.() || {};
12357
+ const adapterMessages = Array.isArray(adapterStatus.messages) ? adapterStatus.messages : [];
12358
+ let parsedRecord = null;
12359
+ if (typeof adapter?.getScriptParsedStatus === "function") {
12360
+ try {
12361
+ const parsed = parseMaybeJson(adapter.getScriptParsedStatus());
12362
+ parsedRecord = parsed && typeof parsed === "object" ? parsed : null;
12363
+ } catch {
12364
+ parsedRecord = null;
12365
+ }
12366
+ }
12367
+ const parsedMessages = Array.isArray(parsedRecord?.messages) ? parsedRecord.messages : [];
12368
+ if (!parsedRecord) return adapterMessages.length;
12369
+ const parsedIsProviderAuthoritative = parsedRecord.transcriptAuthority === "provider" || parsedRecord.coverage === "full";
12370
+ const shouldPreferAdapterMessages = !parsedIsProviderAuthoritative && adapterMessages.length > 0 && adapterMessages.length > parsedMessages.length;
12371
+ return shouldPreferAdapterMessages ? adapterMessages.length : parsedMessages.length;
12372
+ }
11211
12373
  async function getStableExtensionBaseline(h) {
11212
12374
  const first = await readExtensionChatState(h);
11213
12375
  if (getStateMessageCount(first) > 0 || getStateLastSignature(first)) return first;
11214
- await new Promise((resolve12) => setTimeout(resolve12, 150));
12376
+ await new Promise((resolve15) => setTimeout(resolve15, 150));
11215
12377
  const second = await readExtensionChatState(h);
11216
12378
  return getStateMessageCount(second) >= getStateMessageCount(first) ? second : first;
11217
12379
  }
@@ -11219,7 +12381,7 @@ async function verifyExtensionSendObserved(h, before) {
11219
12381
  const beforeCount = getStateMessageCount(before);
11220
12382
  const beforeSignature = getStateLastSignature(before);
11221
12383
  for (let attempt = 0; attempt < 12; attempt += 1) {
11222
- await new Promise((resolve12) => setTimeout(resolve12, 250));
12384
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
11223
12385
  const state = await readExtensionChatState(h);
11224
12386
  if (state?.status === "waiting_approval") return true;
11225
12387
  const afterCount = getStateMessageCount(state);
@@ -11236,11 +12398,11 @@ async function handleChatHistory(h, args) {
11236
12398
  const provider = h.getProvider(agentType);
11237
12399
  const agentStr = provider?.type || agentType || getCurrentProviderType(h);
11238
12400
  const transport = getTargetTransport(h, provider);
11239
- let excludeRecentCount = Math.max(0, Number(args?.excludeRecentCount || 0));
11240
- if (isCliLikeTransport(transport)) {
12401
+ const hasExplicitExcludeRecentCount = args?.excludeRecentCount !== void 0 && args?.excludeRecentCount !== null;
12402
+ let excludeRecentCount = toNonNegativeNumber(args?.excludeRecentCount);
12403
+ if (!hasExplicitExcludeRecentCount && isCliLikeTransport(transport)) {
11241
12404
  const adapter = getTargetedCliAdapter(h, args, provider?.type);
11242
- const status = adapter?.getStatus?.();
11243
- const visibleCount = Array.isArray(status?.messages) ? status.messages.length : 0;
12405
+ const visibleCount = getCliVisibleTranscriptCount(adapter);
11244
12406
  if (visibleCount > excludeRecentCount) excludeRecentCount = visibleCount;
11245
12407
  }
11246
12408
  const workspace = typeof args?.workspace === "string" ? args.workspace : typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : void 0;
@@ -12155,7 +13317,7 @@ async function handleResolveAction(h, args) {
12155
13317
 
12156
13318
  // src/commands/cdp-commands.ts
12157
13319
  import * as fs5 from "fs";
12158
- import * as path9 from "path";
13320
+ import * as path12 from "path";
12159
13321
  import * as os7 from "os";
12160
13322
  var KEY_TO_VK = {
12161
13323
  Backspace: 8,
@@ -12412,25 +13574,25 @@ function resolveSafePath(requestedPath) {
12412
13574
  const inputPath = rawPath || ".";
12413
13575
  const home = os7.homedir();
12414
13576
  if (inputPath.startsWith("~")) {
12415
- return path9.resolve(path9.join(home, inputPath.slice(1)));
13577
+ return path12.resolve(path12.join(home, inputPath.slice(1)));
12416
13578
  }
12417
13579
  if (process.platform === "win32") {
12418
13580
  const normalized = normalizeWindowsRequestedPath(inputPath);
12419
- if (path9.win32.isAbsolute(normalized)) {
12420
- return path9.win32.normalize(normalized);
13581
+ if (path12.win32.isAbsolute(normalized)) {
13582
+ return path12.win32.normalize(normalized);
12421
13583
  }
12422
- return path9.win32.resolve(normalized);
13584
+ return path12.win32.resolve(normalized);
12423
13585
  }
12424
- if (path9.isAbsolute(inputPath)) {
12425
- return path9.normalize(inputPath);
13586
+ if (path12.isAbsolute(inputPath)) {
13587
+ return path12.normalize(inputPath);
12426
13588
  }
12427
- return path9.resolve(inputPath);
13589
+ return path12.resolve(inputPath);
12428
13590
  }
12429
13591
  function listDirectoryEntriesSafe(dirPath) {
12430
13592
  const entries = fs5.readdirSync(dirPath, { withFileTypes: true });
12431
13593
  const files = [];
12432
13594
  for (const entry of entries) {
12433
- const entryPath = path9.join(dirPath, entry.name);
13595
+ const entryPath = path12.join(dirPath, entry.name);
12434
13596
  try {
12435
13597
  if (entry.isDirectory()) {
12436
13598
  files.push({ name: entry.name, type: "directory" });
@@ -12446,11 +13608,11 @@ function listDirectoryEntriesSafe(dirPath) {
12446
13608
  files.push({ name: entry.name, type: "file", size });
12447
13609
  continue;
12448
13610
  }
12449
- const stat = fs5.statSync(entryPath);
13611
+ const stat2 = fs5.statSync(entryPath);
12450
13612
  files.push({
12451
13613
  name: entry.name,
12452
- type: stat.isDirectory() ? "directory" : "file",
12453
- size: stat.isFile() ? stat.size : void 0
13614
+ type: stat2.isDirectory() ? "directory" : "file",
13615
+ size: stat2.isFile() ? stat2.size : void 0
12454
13616
  });
12455
13617
  } catch {
12456
13618
  }
@@ -12484,7 +13646,7 @@ async function handleFileRead(h, args) {
12484
13646
  async function handleFileWrite(h, args) {
12485
13647
  try {
12486
13648
  const filePath = resolveSafePath(args?.path);
12487
- fs5.mkdirSync(path9.dirname(filePath), { recursive: true });
13649
+ fs5.mkdirSync(path12.dirname(filePath), { recursive: true });
12488
13650
  fs5.writeFileSync(filePath, args?.content || "", "utf-8");
12489
13651
  return { success: true, path: filePath };
12490
13652
  } catch (e) {
@@ -12833,7 +13995,7 @@ async function executeProviderScript(h, args, scriptName) {
12833
13995
  const enterCount = cliCommand.enterCount || 1;
12834
13996
  await adapter.writeRaw(cliCommand.text + "\r");
12835
13997
  for (let i = 1; i < enterCount; i += 1) {
12836
- await new Promise((resolve12) => setTimeout(resolve12, 50));
13998
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
12837
13999
  await adapter.writeRaw("\r");
12838
14000
  }
12839
14001
  }
@@ -13327,6 +14489,12 @@ var DaemonCommandHandler = class {
13327
14489
  this._currentRoute = this.resolveRoute(args);
13328
14490
  const startedAt = Date.now();
13329
14491
  this.logCommandStart(cmd, args);
14492
+ let result;
14493
+ if (isGitCommandName(cmd)) {
14494
+ result = await handleGitCommand(cmd, args, this._ctx.gitCommandServices);
14495
+ this.logCommandEnd(cmd, result, startedAt);
14496
+ return result;
14497
+ }
13330
14498
  const sessionScopedCommands = /* @__PURE__ */ new Set([
13331
14499
  "read_chat",
13332
14500
  "get_chat_debug_bundle",
@@ -13352,7 +14520,6 @@ var DaemonCommandHandler = class {
13352
14520
  this.logCommandEnd(cmd, result2, startedAt);
13353
14521
  return result2;
13354
14522
  }
13355
- let result;
13356
14523
  if (!this._currentRoute.session && !this._currentRoute.managerKey && !this._currentRoute.providerType) {
13357
14524
  const cdpCommands = ["send_chat", "read_chat", "list_chats", "new_chat", "switch_chat", "set_mode", "change_model", "set_thought_level", "resolve_action"];
13358
14525
  if (cdpCommands.includes(cmd)) {
@@ -13503,7 +14670,7 @@ var DaemonCommandHandler = class {
13503
14670
  try {
13504
14671
  const http3 = await import("http");
13505
14672
  const postData = JSON.stringify(body);
13506
- const result = await new Promise((resolve12, reject) => {
14673
+ const result = await new Promise((resolve15, reject) => {
13507
14674
  const req = http3.request({
13508
14675
  hostname: "127.0.0.1",
13509
14676
  port: 19280,
@@ -13515,9 +14682,9 @@ var DaemonCommandHandler = class {
13515
14682
  res.on("data", (chunk) => data += chunk);
13516
14683
  res.on("end", () => {
13517
14684
  try {
13518
- resolve12(JSON.parse(data));
14685
+ resolve15(JSON.parse(data));
13519
14686
  } catch {
13520
- resolve12({ raw: data });
14687
+ resolve15({ raw: data });
13521
14688
  }
13522
14689
  });
13523
14690
  });
@@ -13535,15 +14702,15 @@ var DaemonCommandHandler = class {
13535
14702
  if (!providerType) return { success: false, error: "providerType required" };
13536
14703
  try {
13537
14704
  const http3 = await import("http");
13538
- const result = await new Promise((resolve12, reject) => {
14705
+ const result = await new Promise((resolve15, reject) => {
13539
14706
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
13540
14707
  let data = "";
13541
14708
  res.on("data", (chunk) => data += chunk);
13542
14709
  res.on("end", () => {
13543
14710
  try {
13544
- resolve12(JSON.parse(data));
14711
+ resolve15(JSON.parse(data));
13545
14712
  } catch {
13546
- resolve12({ raw: data });
14713
+ resolve15({ raw: data });
13547
14714
  }
13548
14715
  });
13549
14716
  }).on("error", reject);
@@ -13557,7 +14724,7 @@ var DaemonCommandHandler = class {
13557
14724
  try {
13558
14725
  const http3 = await import("http");
13559
14726
  const postData = JSON.stringify(args || {});
13560
- const result = await new Promise((resolve12, reject) => {
14727
+ const result = await new Promise((resolve15, reject) => {
13561
14728
  const req = http3.request({
13562
14729
  hostname: "127.0.0.1",
13563
14730
  port: 19280,
@@ -13569,9 +14736,9 @@ var DaemonCommandHandler = class {
13569
14736
  res.on("data", (chunk) => data += chunk);
13570
14737
  res.on("end", () => {
13571
14738
  try {
13572
- resolve12(JSON.parse(data));
14739
+ resolve15(JSON.parse(data));
13573
14740
  } catch {
13574
- resolve12({ raw: data });
14741
+ resolve15({ raw: data });
13575
14742
  }
13576
14743
  });
13577
14744
  });
@@ -13589,7 +14756,7 @@ var DaemonCommandHandler = class {
13589
14756
  // src/commands/cli-manager.ts
13590
14757
  init_provider_cli_adapter();
13591
14758
  import * as os13 from "os";
13592
- import * as path13 from "path";
14759
+ import * as path16 from "path";
13593
14760
  import * as crypto4 from "crypto";
13594
14761
  import { existsSync as existsSync10 } from "fs";
13595
14762
  import { execFileSync } from "child_process";
@@ -13599,7 +14766,7 @@ init_config();
13599
14766
  // src/providers/cli-provider-instance.ts
13600
14767
  init_contracts();
13601
14768
  import * as os12 from "os";
13602
- import * as path12 from "path";
14769
+ import * as path15 from "path";
13603
14770
  import * as crypto3 from "crypto";
13604
14771
  import * as fs6 from "fs";
13605
14772
  import { createRequire } from "module";
@@ -13659,7 +14826,7 @@ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages
13659
14826
  var CachedDatabaseSync = null;
13660
14827
  function getDatabaseSync() {
13661
14828
  if (CachedDatabaseSync) return CachedDatabaseSync;
13662
- const requireFn = typeof __require === "function" ? __require : createRequire(path12.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
14829
+ const requireFn = typeof __require === "function" ? __require : createRequire(path15.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
13663
14830
  const sqliteModule = requireFn(`node:${"sqlite"}`);
13664
14831
  CachedDatabaseSync = sqliteModule.DatabaseSync;
13665
14832
  if (!CachedDatabaseSync) {
@@ -13697,7 +14864,7 @@ async function waitForCliAdapterReady(adapter, options) {
13697
14864
  if (status === "stopped") {
13698
14865
  throw new Error("CLI runtime stopped before it became ready");
13699
14866
  }
13700
- await new Promise((resolve12) => setTimeout(resolve12, pollMs));
14867
+ await new Promise((resolve15) => setTimeout(resolve15, pollMs));
13701
14868
  }
13702
14869
  throw new Error(`CLI runtime did not become ready within ${timeoutMs}ms`);
13703
14870
  }
@@ -14048,7 +15215,7 @@ var CliProviderInstance = class {
14048
15215
  const enterCount = cliCommand.enterCount || 1;
14049
15216
  await this.adapter.writeRaw(cliCommand.text + "\r");
14050
15217
  for (let i = 1; i < enterCount; i += 1) {
14051
- await new Promise((resolve12) => setTimeout(resolve12, 50));
15218
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
14052
15219
  await this.adapter.writeRaw("\r");
14053
15220
  }
14054
15221
  }
@@ -15167,13 +16334,13 @@ var AcpProviderInstance = class {
15167
16334
  }
15168
16335
  this.currentStatus = "waiting_approval";
15169
16336
  this.detectStatusTransition();
15170
- const approved = await new Promise((resolve12) => {
15171
- this.permissionResolvers.push(resolve12);
16337
+ const approved = await new Promise((resolve15) => {
16338
+ this.permissionResolvers.push(resolve15);
15172
16339
  setTimeout(() => {
15173
- const idx = this.permissionResolvers.indexOf(resolve12);
16340
+ const idx = this.permissionResolvers.indexOf(resolve15);
15174
16341
  if (idx >= 0) {
15175
16342
  this.permissionResolvers.splice(idx, 1);
15176
- resolve12(false);
16343
+ resolve15(false);
15177
16344
  }
15178
16345
  }, 3e5);
15179
16346
  });
@@ -15748,11 +16915,11 @@ function shouldRestoreHostedRuntime(record, managerTag) {
15748
16915
  // src/commands/cli-manager.ts
15749
16916
  function isExplicitCommand(command) {
15750
16917
  const trimmed = command.trim();
15751
- return path13.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
16918
+ return path16.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
15752
16919
  }
15753
16920
  function expandExecutable(command) {
15754
16921
  const trimmed = command.trim();
15755
- return trimmed.startsWith("~") ? path13.join(os13.homedir(), trimmed.slice(1)) : trimmed;
16922
+ return trimmed.startsWith("~") ? path16.join(os13.homedir(), trimmed.slice(1)) : trimmed;
15756
16923
  }
15757
16924
  function commandExists(command) {
15758
16925
  const trimmed = command.trim();
@@ -16033,7 +17200,7 @@ var DaemonCliManager = class {
16033
17200
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
16034
17201
  const trimmed = (workingDir || "").trim();
16035
17202
  if (!trimmed) throw new Error("working directory required");
16036
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path13.resolve(trimmed);
17203
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path16.resolve(trimmed);
16037
17204
  const normalizedType = this.providerLoader.resolveAlias(cliType);
16038
17205
  const rawProvider = this.providerLoader.getByAlias(cliType);
16039
17206
  const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
@@ -16534,11 +17701,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
16534
17701
  import { execSync as execSync4, spawn as spawn2 } from "child_process";
16535
17702
  import * as net from "net";
16536
17703
  import * as os15 from "os";
16537
- import * as path15 from "path";
17704
+ import * as path18 from "path";
16538
17705
 
16539
17706
  // src/providers/provider-loader.ts
16540
17707
  import * as fs7 from "fs";
16541
- import * as path14 from "path";
17708
+ import * as path17 from "path";
16542
17709
  import * as os14 from "os";
16543
17710
  import * as chokidar from "chokidar";
16544
17711
  init_logger();
@@ -16803,7 +17970,7 @@ var ProviderLoader = class _ProviderLoader {
16803
17970
  try {
16804
17971
  if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
16805
17972
  return ["ide", "extension", "cli", "acp"].some(
16806
- (category) => fs7.existsSync(path14.join(candidate, category))
17973
+ (category) => fs7.existsSync(path17.join(candidate, category))
16807
17974
  );
16808
17975
  } catch {
16809
17976
  return false;
@@ -16811,20 +17978,20 @@ var ProviderLoader = class _ProviderLoader {
16811
17978
  }
16812
17979
  static hasProviderRootMarker(candidate) {
16813
17980
  try {
16814
- return fs7.existsSync(path14.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
17981
+ return fs7.existsSync(path17.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
16815
17982
  } catch {
16816
17983
  return false;
16817
17984
  }
16818
17985
  }
16819
17986
  detectDefaultUserDir() {
16820
- const fallback = path14.join(os14.homedir(), ".adhdev", "providers");
17987
+ const fallback = path17.join(os14.homedir(), ".adhdev", "providers");
16821
17988
  const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
16822
17989
  const visited = /* @__PURE__ */ new Set();
16823
17990
  for (const start of this.probeStarts) {
16824
- let current = path14.resolve(start);
17991
+ let current = path17.resolve(start);
16825
17992
  while (!visited.has(current)) {
16826
17993
  visited.add(current);
16827
- const siblingCandidate = path14.join(path14.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
17994
+ const siblingCandidate = path17.join(path17.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
16828
17995
  if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
16829
17996
  const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
16830
17997
  if (envOptIn || hasMarker) {
@@ -16846,7 +18013,7 @@ var ProviderLoader = class _ProviderLoader {
16846
18013
  return { path: siblingCandidate, source };
16847
18014
  }
16848
18015
  }
16849
- const parent = path14.dirname(current);
18016
+ const parent = path17.dirname(current);
16850
18017
  if (parent === current) break;
16851
18018
  current = parent;
16852
18019
  }
@@ -16856,11 +18023,11 @@ var ProviderLoader = class _ProviderLoader {
16856
18023
  constructor(options) {
16857
18024
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
16858
18025
  this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
16859
- this.defaultProvidersDir = path14.join(os14.homedir(), ".adhdev", "providers");
18026
+ this.defaultProvidersDir = path17.join(os14.homedir(), ".adhdev", "providers");
16860
18027
  const detected = this.detectDefaultUserDir();
16861
18028
  this.userDir = detected.path;
16862
18029
  this.userDirSource = detected.source;
16863
- this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
18030
+ this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
16864
18031
  this.disableUpstream = false;
16865
18032
  this.applySourceConfig({
16866
18033
  userDir: options?.userDir,
@@ -16919,7 +18086,7 @@ var ProviderLoader = class _ProviderLoader {
16919
18086
  this.userDir = detected.path;
16920
18087
  this.userDirSource = detected.source;
16921
18088
  }
16922
- this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
18089
+ this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
16923
18090
  this.disableUpstream = this.sourceMode === "no-upstream";
16924
18091
  if (this.explicitProviderDir) {
16925
18092
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
@@ -16933,7 +18100,7 @@ var ProviderLoader = class _ProviderLoader {
16933
18100
  * Canonical provider directory shape for a given root.
16934
18101
  */
16935
18102
  getProviderDir(root, category, type) {
16936
- return path14.join(root, category, type);
18103
+ return path17.join(root, category, type);
16937
18104
  }
16938
18105
  /**
16939
18106
  * Canonical user override directory for a provider.
@@ -16960,7 +18127,7 @@ var ProviderLoader = class _ProviderLoader {
16960
18127
  resolveProviderFile(type, ...segments) {
16961
18128
  const dir = this.findProviderDirInternal(type);
16962
18129
  if (!dir) return null;
16963
- return path14.join(dir, ...segments);
18130
+ return path17.join(dir, ...segments);
16964
18131
  }
16965
18132
  /**
16966
18133
  * Load all providers (3-tier priority)
@@ -16999,7 +18166,7 @@ var ProviderLoader = class _ProviderLoader {
16999
18166
  if (!fs7.existsSync(this.upstreamDir)) return false;
17000
18167
  try {
17001
18168
  return fs7.readdirSync(this.upstreamDir).some(
17002
- (d) => fs7.statSync(path14.join(this.upstreamDir, d)).isDirectory()
18169
+ (d) => fs7.statSync(path17.join(this.upstreamDir, d)).isDirectory()
17003
18170
  );
17004
18171
  } catch {
17005
18172
  return false;
@@ -17496,8 +18663,8 @@ var ProviderLoader = class _ProviderLoader {
17496
18663
  resolved._resolvedScriptDir = entry.scriptDir;
17497
18664
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
17498
18665
  if (providerDir) {
17499
- const fullDir = path14.join(providerDir, entry.scriptDir);
17500
- resolved._resolvedScriptsPath = fs7.existsSync(path14.join(fullDir, "scripts.js")) ? path14.join(fullDir, "scripts.js") : fullDir;
18666
+ const fullDir = path17.join(providerDir, entry.scriptDir);
18667
+ resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
17501
18668
  }
17502
18669
  matched = true;
17503
18670
  }
@@ -17512,8 +18679,8 @@ var ProviderLoader = class _ProviderLoader {
17512
18679
  resolved._resolvedScriptDir = base.defaultScriptDir;
17513
18680
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
17514
18681
  if (providerDir) {
17515
- const fullDir = path14.join(providerDir, base.defaultScriptDir);
17516
- resolved._resolvedScriptsPath = fs7.existsSync(path14.join(fullDir, "scripts.js")) ? path14.join(fullDir, "scripts.js") : fullDir;
18682
+ const fullDir = path17.join(providerDir, base.defaultScriptDir);
18683
+ resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
17517
18684
  }
17518
18685
  }
17519
18686
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -17530,8 +18697,8 @@ var ProviderLoader = class _ProviderLoader {
17530
18697
  resolved._resolvedScriptDir = dirOverride;
17531
18698
  resolved._resolvedScriptsSource = `versions:${range}`;
17532
18699
  if (providerDir) {
17533
- const fullDir = path14.join(providerDir, dirOverride);
17534
- resolved._resolvedScriptsPath = fs7.existsSync(path14.join(fullDir, "scripts.js")) ? path14.join(fullDir, "scripts.js") : fullDir;
18700
+ const fullDir = path17.join(providerDir, dirOverride);
18701
+ resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
17535
18702
  }
17536
18703
  }
17537
18704
  } else if (override.scripts) {
@@ -17547,8 +18714,8 @@ var ProviderLoader = class _ProviderLoader {
17547
18714
  resolved._resolvedScriptDir = base.defaultScriptDir;
17548
18715
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
17549
18716
  if (providerDir) {
17550
- const fullDir = path14.join(providerDir, base.defaultScriptDir);
17551
- resolved._resolvedScriptsPath = fs7.existsSync(path14.join(fullDir, "scripts.js")) ? path14.join(fullDir, "scripts.js") : fullDir;
18717
+ const fullDir = path17.join(providerDir, base.defaultScriptDir);
18718
+ resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
17552
18719
  }
17553
18720
  }
17554
18721
  }
@@ -17580,14 +18747,14 @@ var ProviderLoader = class _ProviderLoader {
17580
18747
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
17581
18748
  return null;
17582
18749
  }
17583
- const dir = path14.join(providerDir, scriptDir);
18750
+ const dir = path17.join(providerDir, scriptDir);
17584
18751
  if (!fs7.existsSync(dir)) {
17585
18752
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
17586
18753
  return null;
17587
18754
  }
17588
18755
  const cached = this.scriptsCache.get(dir);
17589
18756
  if (cached) return cached;
17590
- const scriptsJs = path14.join(dir, "scripts.js");
18757
+ const scriptsJs = path17.join(dir, "scripts.js");
17591
18758
  if (fs7.existsSync(scriptsJs)) {
17592
18759
  try {
17593
18760
  delete __require.cache[__require.resolve(scriptsJs)];
@@ -17629,7 +18796,7 @@ var ProviderLoader = class _ProviderLoader {
17629
18796
  return;
17630
18797
  }
17631
18798
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
17632
- this.log(`File changed: ${path14.basename(filePath)}, reloading...`);
18799
+ this.log(`File changed: ${path17.basename(filePath)}, reloading...`);
17633
18800
  this.reload();
17634
18801
  }
17635
18802
  };
@@ -17684,7 +18851,7 @@ var ProviderLoader = class _ProviderLoader {
17684
18851
  }
17685
18852
  const https = __require("https");
17686
18853
  const { execSync: execSync7 } = __require("child_process");
17687
- const metaPath = path14.join(this.upstreamDir, _ProviderLoader.META_FILE);
18854
+ const metaPath = path17.join(this.upstreamDir, _ProviderLoader.META_FILE);
17688
18855
  let prevEtag = "";
17689
18856
  let prevTimestamp = 0;
17690
18857
  try {
@@ -17701,7 +18868,7 @@ var ProviderLoader = class _ProviderLoader {
17701
18868
  return { updated: false };
17702
18869
  }
17703
18870
  try {
17704
- const etag = await new Promise((resolve12, reject) => {
18871
+ const etag = await new Promise((resolve15, reject) => {
17705
18872
  const options = {
17706
18873
  method: "HEAD",
17707
18874
  hostname: "github.com",
@@ -17719,7 +18886,7 @@ var ProviderLoader = class _ProviderLoader {
17719
18886
  headers: { "User-Agent": "adhdev-launcher" },
17720
18887
  timeout: 1e4
17721
18888
  }, (res2) => {
17722
- resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
18889
+ resolve15(res2.headers.etag || res2.headers["last-modified"] || "");
17723
18890
  });
17724
18891
  req2.on("error", reject);
17725
18892
  req2.on("timeout", () => {
@@ -17728,7 +18895,7 @@ var ProviderLoader = class _ProviderLoader {
17728
18895
  });
17729
18896
  req2.end();
17730
18897
  } else {
17731
- resolve12(res.headers.etag || res.headers["last-modified"] || "");
18898
+ resolve15(res.headers.etag || res.headers["last-modified"] || "");
17732
18899
  }
17733
18900
  });
17734
18901
  req.on("error", reject);
@@ -17744,17 +18911,17 @@ var ProviderLoader = class _ProviderLoader {
17744
18911
  return { updated: false };
17745
18912
  }
17746
18913
  this.log("Downloading latest providers from GitHub...");
17747
- const tmpTar = path14.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
17748
- const tmpExtract = path14.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
18914
+ const tmpTar = path17.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
18915
+ const tmpExtract = path17.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
17749
18916
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
17750
18917
  fs7.mkdirSync(tmpExtract, { recursive: true });
17751
18918
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
17752
18919
  const extracted = fs7.readdirSync(tmpExtract);
17753
18920
  const rootDir = extracted.find(
17754
- (d) => fs7.statSync(path14.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
18921
+ (d) => fs7.statSync(path17.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
17755
18922
  );
17756
18923
  if (!rootDir) throw new Error("Unexpected tarball structure");
17757
- const sourceDir = path14.join(tmpExtract, rootDir);
18924
+ const sourceDir = path17.join(tmpExtract, rootDir);
17758
18925
  const backupDir = this.upstreamDir + ".bak";
17759
18926
  if (fs7.existsSync(this.upstreamDir)) {
17760
18927
  if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
@@ -17792,7 +18959,7 @@ var ProviderLoader = class _ProviderLoader {
17792
18959
  downloadFile(url, destPath) {
17793
18960
  const https = __require("https");
17794
18961
  const http3 = __require("http");
17795
- return new Promise((resolve12, reject) => {
18962
+ return new Promise((resolve15, reject) => {
17796
18963
  const doRequest = (reqUrl, redirectCount = 0) => {
17797
18964
  if (redirectCount > 5) {
17798
18965
  reject(new Error("Too many redirects"));
@@ -17812,7 +18979,7 @@ var ProviderLoader = class _ProviderLoader {
17812
18979
  res.pipe(ws);
17813
18980
  ws.on("finish", () => {
17814
18981
  ws.close();
17815
- resolve12();
18982
+ resolve15();
17816
18983
  });
17817
18984
  ws.on("error", reject);
17818
18985
  });
@@ -17829,8 +18996,8 @@ var ProviderLoader = class _ProviderLoader {
17829
18996
  copyDirRecursive(src, dest) {
17830
18997
  fs7.mkdirSync(dest, { recursive: true });
17831
18998
  for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
17832
- const srcPath = path14.join(src, entry.name);
17833
- const destPath = path14.join(dest, entry.name);
18999
+ const srcPath = path17.join(src, entry.name);
19000
+ const destPath = path17.join(dest, entry.name);
17834
19001
  if (entry.isDirectory()) {
17835
19002
  this.copyDirRecursive(srcPath, destPath);
17836
19003
  } else {
@@ -17841,7 +19008,7 @@ var ProviderLoader = class _ProviderLoader {
17841
19008
  /** .meta.json save */
17842
19009
  writeMeta(metaPath, etag, timestamp) {
17843
19010
  try {
17844
- fs7.mkdirSync(path14.dirname(metaPath), { recursive: true });
19011
+ fs7.mkdirSync(path17.dirname(metaPath), { recursive: true });
17845
19012
  fs7.writeFileSync(metaPath, JSON.stringify({
17846
19013
  etag,
17847
19014
  timestamp,
@@ -17858,7 +19025,7 @@ var ProviderLoader = class _ProviderLoader {
17858
19025
  const scan = (d) => {
17859
19026
  try {
17860
19027
  for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
17861
- if (entry.isDirectory()) scan(path14.join(d, entry.name));
19028
+ if (entry.isDirectory()) scan(path17.join(d, entry.name));
17862
19029
  else if (entry.name === "provider.json") count++;
17863
19030
  }
17864
19031
  } catch {
@@ -18086,17 +19253,17 @@ var ProviderLoader = class _ProviderLoader {
18086
19253
  for (const root of searchRoots) {
18087
19254
  if (!fs7.existsSync(root)) continue;
18088
19255
  const candidate = this.getProviderDir(root, cat, type);
18089
- if (fs7.existsSync(path14.join(candidate, "provider.json"))) return candidate;
18090
- const catDir = path14.join(root, cat);
19256
+ if (fs7.existsSync(path17.join(candidate, "provider.json"))) return candidate;
19257
+ const catDir = path17.join(root, cat);
18091
19258
  if (fs7.existsSync(catDir)) {
18092
19259
  try {
18093
19260
  for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
18094
19261
  if (!entry.isDirectory()) continue;
18095
- const jsonPath = path14.join(catDir, entry.name, "provider.json");
19262
+ const jsonPath = path17.join(catDir, entry.name, "provider.json");
18096
19263
  if (fs7.existsSync(jsonPath)) {
18097
19264
  try {
18098
19265
  const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
18099
- if (data.type === type) return path14.join(catDir, entry.name);
19266
+ if (data.type === type) return path17.join(catDir, entry.name);
18100
19267
  } catch {
18101
19268
  }
18102
19269
  }
@@ -18113,7 +19280,7 @@ var ProviderLoader = class _ProviderLoader {
18113
19280
  * (template substitution is NOT applied here — scripts.js handles that)
18114
19281
  */
18115
19282
  buildScriptWrappersFromDir(dir) {
18116
- const scriptsJs = path14.join(dir, "scripts.js");
19283
+ const scriptsJs = path17.join(dir, "scripts.js");
18117
19284
  if (fs7.existsSync(scriptsJs)) {
18118
19285
  try {
18119
19286
  delete __require.cache[__require.resolve(scriptsJs)];
@@ -18127,7 +19294,7 @@ var ProviderLoader = class _ProviderLoader {
18127
19294
  for (const file of fs7.readdirSync(dir)) {
18128
19295
  if (!file.endsWith(".js")) continue;
18129
19296
  const scriptName = toCamel(file.replace(".js", ""));
18130
- const filePath = path14.join(dir, file);
19297
+ const filePath = path17.join(dir, file);
18131
19298
  result[scriptName] = (...args) => {
18132
19299
  try {
18133
19300
  let content = fs7.readFileSync(filePath, "utf-8");
@@ -18187,7 +19354,7 @@ var ProviderLoader = class _ProviderLoader {
18187
19354
  }
18188
19355
  const hasJson = entries.some((e) => e.name === "provider.json");
18189
19356
  if (hasJson) {
18190
- const jsonPath = path14.join(d, "provider.json");
19357
+ const jsonPath = path17.join(d, "provider.json");
18191
19358
  try {
18192
19359
  const raw = fs7.readFileSync(jsonPath, "utf-8");
18193
19360
  const mod = JSON.parse(raw);
@@ -18208,7 +19375,7 @@ var ProviderLoader = class _ProviderLoader {
18208
19375
  this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
18209
19376
  } else {
18210
19377
  const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
18211
- const scriptsPath = path14.join(d, "scripts.js");
19378
+ const scriptsPath = path17.join(d, "scripts.js");
18212
19379
  if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
18213
19380
  try {
18214
19381
  delete __require.cache[__require.resolve(scriptsPath)];
@@ -18234,7 +19401,7 @@ var ProviderLoader = class _ProviderLoader {
18234
19401
  if (!entry.isDirectory()) continue;
18235
19402
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
18236
19403
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
18237
- scan(path14.join(d, entry.name));
19404
+ scan(path17.join(d, entry.name));
18238
19405
  }
18239
19406
  }
18240
19407
  };
@@ -18269,9 +19436,9 @@ var ProviderLoader = class _ProviderLoader {
18269
19436
  }
18270
19437
  }
18271
19438
  compareVersions(a, b) {
18272
- const normalize3 = (v) => v.split(/[-_+]/)[0].split(".").map((x) => parseInt(x, 10) || 0);
18273
- const pa = normalize3(a);
18274
- const pb = normalize3(b);
19439
+ const normalize4 = (v) => v.split(/[-_+]/)[0].split(".").map((x) => parseInt(x, 10) || 0);
19440
+ const pa = normalize4(a);
19441
+ const pb = normalize4(b);
18275
19442
  for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
18276
19443
  const va = pa[i] || 0;
18277
19444
  const vb = pb[i] || 0;
@@ -18391,17 +19558,17 @@ async function findFreePort(ports) {
18391
19558
  throw new Error("No free port found");
18392
19559
  }
18393
19560
  function checkPortFree(port) {
18394
- return new Promise((resolve12) => {
19561
+ return new Promise((resolve15) => {
18395
19562
  const server = net.createServer();
18396
19563
  server.unref();
18397
- server.on("error", () => resolve12(false));
19564
+ server.on("error", () => resolve15(false));
18398
19565
  server.listen(port, "127.0.0.1", () => {
18399
- server.close(() => resolve12(true));
19566
+ server.close(() => resolve15(true));
18400
19567
  });
18401
19568
  });
18402
19569
  }
18403
19570
  async function isCdpActive(port) {
18404
- return new Promise((resolve12) => {
19571
+ return new Promise((resolve15) => {
18405
19572
  const req = __require("http").get(`http://127.0.0.1:${port}/json/version`, {
18406
19573
  timeout: 2e3
18407
19574
  }, (res) => {
@@ -18410,16 +19577,16 @@ async function isCdpActive(port) {
18410
19577
  res.on("end", () => {
18411
19578
  try {
18412
19579
  const info = JSON.parse(data);
18413
- resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
19580
+ resolve15(!!info["WebKit-Version"] || !!info["Browser"]);
18414
19581
  } catch {
18415
- resolve12(false);
19582
+ resolve15(false);
18416
19583
  }
18417
19584
  });
18418
19585
  });
18419
- req.on("error", () => resolve12(false));
19586
+ req.on("error", () => resolve15(false));
18420
19587
  req.on("timeout", () => {
18421
19588
  req.destroy();
18422
- resolve12(false);
19589
+ resolve15(false);
18423
19590
  });
18424
19591
  });
18425
19592
  }
@@ -18559,8 +19726,8 @@ function detectCurrentWorkspace(ideId) {
18559
19726
  const appNameMap = getMacAppIdentifiers();
18560
19727
  const appName = appNameMap[ideId];
18561
19728
  if (appName) {
18562
- const storagePath = path15.join(
18563
- process.env.APPDATA || path15.join(os15.homedir(), "AppData", "Roaming"),
19729
+ const storagePath = path18.join(
19730
+ process.env.APPDATA || path18.join(os15.homedir(), "AppData", "Roaming"),
18564
19731
  appName,
18565
19732
  "storage.json"
18566
19733
  );
@@ -18738,9 +19905,9 @@ init_logger();
18738
19905
 
18739
19906
  // src/logging/command-log.ts
18740
19907
  import * as fs8 from "fs";
18741
- import * as path16 from "path";
19908
+ import * as path19 from "path";
18742
19909
  import * as os16 from "os";
18743
- var LOG_DIR2 = process.platform === "win32" ? path16.join(process.env.LOCALAPPDATA || process.env.APPDATA || path16.join(os16.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path16.join(os16.homedir(), "Library", "Logs", "adhdev") : path16.join(os16.homedir(), ".local", "share", "adhdev", "logs");
19910
+ var LOG_DIR2 = process.platform === "win32" ? path19.join(process.env.LOCALAPPDATA || process.env.APPDATA || path19.join(os16.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path19.join(os16.homedir(), "Library", "Logs", "adhdev") : path19.join(os16.homedir(), ".local", "share", "adhdev", "logs");
18744
19911
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
18745
19912
  var MAX_DAYS = 7;
18746
19913
  try {
@@ -18778,13 +19945,13 @@ function getDateStr2() {
18778
19945
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
18779
19946
  }
18780
19947
  var currentDate2 = getDateStr2();
18781
- var currentFile = path16.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19948
+ var currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
18782
19949
  var writeCount2 = 0;
18783
19950
  function checkRotation() {
18784
19951
  const today = getDateStr2();
18785
19952
  if (today !== currentDate2) {
18786
19953
  currentDate2 = today;
18787
- currentFile = path16.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19954
+ currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
18788
19955
  cleanOldFiles();
18789
19956
  }
18790
19957
  }
@@ -18798,7 +19965,7 @@ function cleanOldFiles() {
18798
19965
  const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
18799
19966
  if (dateMatch && dateMatch[1] < cutoffStr) {
18800
19967
  try {
18801
- fs8.unlinkSync(path16.join(LOG_DIR2, file));
19968
+ fs8.unlinkSync(path19.join(LOG_DIR2, file));
18802
19969
  } catch {
18803
19970
  }
18804
19971
  }
@@ -18808,8 +19975,8 @@ function cleanOldFiles() {
18808
19975
  }
18809
19976
  function checkSize() {
18810
19977
  try {
18811
- const stat = fs8.statSync(currentFile);
18812
- if (stat.size > MAX_FILE_SIZE) {
19978
+ const stat2 = fs8.statSync(currentFile);
19979
+ if (stat2.size > MAX_FILE_SIZE) {
18813
19980
  const backup = currentFile.replace(".jsonl", ".1.jsonl");
18814
19981
  try {
18815
19982
  fs8.unlinkSync(backup);
@@ -19095,12 +20262,18 @@ function buildStatusSnapshot(options) {
19095
20262
  const unreadSourceSessions = buildSessionEntries(
19096
20263
  options.allStates,
19097
20264
  options.cdpManagers,
19098
- { profile: "full" }
20265
+ {
20266
+ profile: "full",
20267
+ getGitSummaryForWorkspace: options.getGitSummaryForWorkspace
20268
+ }
19099
20269
  );
19100
20270
  const sessions = profile === "full" ? unreadSourceSessions : profile === "live" ? unreadSourceSessions.map(projectLiveSessionFromFull) : buildSessionEntries(
19101
20271
  options.allStates,
19102
20272
  options.cdpManagers,
19103
- { profile }
20273
+ {
20274
+ profile,
20275
+ getGitSummaryForWorkspace: options.getGitSummaryForWorkspace
20276
+ }
19104
20277
  );
19105
20278
  const sessionsById = new Map(sessions.map((session) => [session.id, session]));
19106
20279
  for (const sourceSession of unreadSourceSessions) {
@@ -19194,13 +20367,13 @@ import { execFileSync as execFileSync2 } from "child_process";
19194
20367
  import { spawn as spawn3 } from "child_process";
19195
20368
  import * as fs9 from "fs";
19196
20369
  import * as os18 from "os";
19197
- import * as path17 from "path";
20370
+ import * as path20 from "path";
19198
20371
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
19199
20372
  function getUpgradeLogPath() {
19200
20373
  const home = os18.homedir();
19201
- const dir = path17.join(home, ".adhdev");
20374
+ const dir = path20.join(home, ".adhdev");
19202
20375
  fs9.mkdirSync(dir, { recursive: true });
19203
- return path17.join(dir, "daemon-upgrade.log");
20376
+ return path20.join(dir, "daemon-upgrade.log");
19204
20377
  }
19205
20378
  function appendUpgradeLog(message) {
19206
20379
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -19211,14 +20384,14 @@ function appendUpgradeLog(message) {
19211
20384
  }
19212
20385
  }
19213
20386
  function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
19214
- const binDir = path17.dirname(nodeExecutable);
20387
+ const binDir = path20.dirname(nodeExecutable);
19215
20388
  if (platform10 === "win32") {
19216
- const npmCliPath = path17.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
20389
+ const npmCliPath = path20.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
19217
20390
  if (fs9.existsSync(npmCliPath)) {
19218
20391
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
19219
20392
  }
19220
20393
  for (const candidate of ["npm.exe", "npm"]) {
19221
- const candidatePath = path17.join(binDir, candidate);
20394
+ const candidatePath = path20.join(binDir, candidate);
19222
20395
  if (fs9.existsSync(candidatePath)) {
19223
20396
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
19224
20397
  }
@@ -19226,7 +20399,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
19226
20399
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
19227
20400
  }
19228
20401
  for (const candidate of ["npm"]) {
19229
- const candidatePath = path17.join(binDir, candidate);
20402
+ const candidatePath = path20.join(binDir, candidate);
19230
20403
  if (fs9.existsSync(candidatePath)) {
19231
20404
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
19232
20405
  }
@@ -19243,13 +20416,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
19243
20416
  let currentDir = resolvedPath;
19244
20417
  try {
19245
20418
  if (fs9.statSync(resolvedPath).isFile()) {
19246
- currentDir = path17.dirname(resolvedPath);
20419
+ currentDir = path20.dirname(resolvedPath);
19247
20420
  }
19248
20421
  } catch {
19249
- currentDir = path17.dirname(resolvedPath);
20422
+ currentDir = path20.dirname(resolvedPath);
19250
20423
  }
19251
20424
  while (true) {
19252
- const packageJsonPath = path17.join(currentDir, "package.json");
20425
+ const packageJsonPath = path20.join(currentDir, "package.json");
19253
20426
  try {
19254
20427
  if (fs9.existsSync(packageJsonPath)) {
19255
20428
  const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
@@ -19260,7 +20433,7 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
19260
20433
  }
19261
20434
  } catch {
19262
20435
  }
19263
- const parentDir = path17.dirname(currentDir);
20436
+ const parentDir = path20.dirname(currentDir);
19264
20437
  if (parentDir === currentDir) {
19265
20438
  return null;
19266
20439
  }
@@ -19268,13 +20441,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
19268
20441
  }
19269
20442
  }
19270
20443
  function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
19271
- const nodeModulesDir = packageName.startsWith("@") ? path17.dirname(path17.dirname(packageRoot)) : path17.dirname(packageRoot);
19272
- if (path17.basename(nodeModulesDir) !== "node_modules") {
20444
+ const nodeModulesDir = packageName.startsWith("@") ? path20.dirname(path20.dirname(packageRoot)) : path20.dirname(packageRoot);
20445
+ if (path20.basename(nodeModulesDir) !== "node_modules") {
19273
20446
  return null;
19274
20447
  }
19275
- const maybeLibDir = path17.dirname(nodeModulesDir);
19276
- if (path17.basename(maybeLibDir) === "lib") {
19277
- return path17.dirname(maybeLibDir);
20448
+ const maybeLibDir = path20.dirname(nodeModulesDir);
20449
+ if (path20.basename(maybeLibDir) === "lib") {
20450
+ return path20.dirname(maybeLibDir);
19278
20451
  }
19279
20452
  return maybeLibDir;
19280
20453
  }
@@ -19382,14 +20555,14 @@ async function waitForPidExit(pid, timeoutMs) {
19382
20555
  while (Date.now() - start < timeoutMs) {
19383
20556
  try {
19384
20557
  process.kill(pid, 0);
19385
- await new Promise((resolve12) => setTimeout(resolve12, 250));
20558
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
19386
20559
  } catch {
19387
20560
  return;
19388
20561
  }
19389
20562
  }
19390
20563
  }
19391
20564
  function stopSessionHostProcesses(appName) {
19392
- const pidFile = path17.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
20565
+ const pidFile = path20.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
19393
20566
  try {
19394
20567
  if (fs9.existsSync(pidFile)) {
19395
20568
  const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
@@ -19406,7 +20579,7 @@ function stopSessionHostProcesses(appName) {
19406
20579
  }
19407
20580
  }
19408
20581
  function removeDaemonPidFile() {
19409
- const pidFile = path17.join(os18.homedir(), ".adhdev", "daemon.pid");
20582
+ const pidFile = path20.join(os18.homedir(), ".adhdev", "daemon.pid");
19410
20583
  try {
19411
20584
  fs9.unlinkSync(pidFile);
19412
20585
  } catch {
@@ -19417,7 +20590,7 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
19417
20590
  const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
19418
20591
  if (!npmRoot) return;
19419
20592
  const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
19420
- const binDir = process.platform === "win32" ? npmPrefix : path17.join(npmPrefix, "bin");
20593
+ const binDir = process.platform === "win32" ? npmPrefix : path20.join(npmPrefix, "bin");
19421
20594
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
19422
20595
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
19423
20596
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -19425,25 +20598,25 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
19425
20598
  }
19426
20599
  if (pkgName.startsWith("@")) {
19427
20600
  const [scope, name] = pkgName.split("/");
19428
- const scopeDir = path17.join(npmRoot, scope);
20601
+ const scopeDir = path20.join(npmRoot, scope);
19429
20602
  if (!fs9.existsSync(scopeDir)) return;
19430
20603
  for (const entry of fs9.readdirSync(scopeDir)) {
19431
20604
  if (!entry.startsWith(`.${name}-`)) continue;
19432
- fs9.rmSync(path17.join(scopeDir, entry), { recursive: true, force: true });
19433
- appendUpgradeLog(`Removed stale scoped staging dir: ${path17.join(scopeDir, entry)}`);
20605
+ fs9.rmSync(path20.join(scopeDir, entry), { recursive: true, force: true });
20606
+ appendUpgradeLog(`Removed stale scoped staging dir: ${path20.join(scopeDir, entry)}`);
19434
20607
  }
19435
20608
  } else {
19436
20609
  for (const entry of fs9.readdirSync(npmRoot)) {
19437
20610
  if (!entry.startsWith(`.${pkgName}-`)) continue;
19438
- fs9.rmSync(path17.join(npmRoot, entry), { recursive: true, force: true });
19439
- appendUpgradeLog(`Removed stale staging dir: ${path17.join(npmRoot, entry)}`);
20611
+ fs9.rmSync(path20.join(npmRoot, entry), { recursive: true, force: true });
20612
+ appendUpgradeLog(`Removed stale staging dir: ${path20.join(npmRoot, entry)}`);
19440
20613
  }
19441
20614
  }
19442
20615
  if (fs9.existsSync(binDir)) {
19443
20616
  for (const entry of fs9.readdirSync(binDir)) {
19444
20617
  if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
19445
- fs9.rmSync(path17.join(binDir, entry), { recursive: true, force: true });
19446
- appendUpgradeLog(`Removed stale bin staging entry: ${path17.join(binDir, entry)}`);
20618
+ fs9.rmSync(path20.join(binDir, entry), { recursive: true, force: true });
20619
+ appendUpgradeLog(`Removed stale bin staging entry: ${path20.join(binDir, entry)}`);
19447
20620
  }
19448
20621
  }
19449
20622
  }
@@ -19493,7 +20666,7 @@ async function runDaemonUpgradeHelper(payload) {
19493
20666
  appendUpgradeLog(installOutput.trim());
19494
20667
  }
19495
20668
  if (process.platform === "win32") {
19496
- await new Promise((resolve12) => setTimeout(resolve12, 500));
20669
+ await new Promise((resolve15) => setTimeout(resolve15, 500));
19497
20670
  cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
19498
20671
  appendUpgradeLog("Post-install staging cleanup complete");
19499
20672
  }
@@ -20887,7 +22060,7 @@ var ProviderStreamAdapter = class {
20887
22060
  const beforeCount = this.messageCount(before);
20888
22061
  const beforeSignature = this.lastMessageSignature(before);
20889
22062
  for (let attempt = 0; attempt < 12; attempt += 1) {
20890
- await new Promise((resolve12) => setTimeout(resolve12, 250));
22063
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
20891
22064
  let state;
20892
22065
  try {
20893
22066
  state = await this.readChat(evaluate);
@@ -20909,7 +22082,7 @@ var ProviderStreamAdapter = class {
20909
22082
  if (this.messageCount(first) > 0 || this.lastMessageSignature(first)) {
20910
22083
  return first;
20911
22084
  }
20912
- await new Promise((resolve12) => setTimeout(resolve12, 150));
22085
+ await new Promise((resolve15) => setTimeout(resolve15, 150));
20913
22086
  const second = await this.readChat(evaluate);
20914
22087
  return this.messageCount(second) >= this.messageCount(first) ? second : first;
20915
22088
  }
@@ -21060,7 +22233,7 @@ var ProviderStreamAdapter = class {
21060
22233
  if (typeof data.error === "string" && data.error.trim()) return false;
21061
22234
  }
21062
22235
  for (let attempt = 0; attempt < 6; attempt += 1) {
21063
- await new Promise((resolve12) => setTimeout(resolve12, 250));
22236
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
21064
22237
  const state = await this.readChat(evaluate);
21065
22238
  const title = this.getStateTitle(state);
21066
22239
  if (this.titlesMatch(title, sessionId)) return true;
@@ -21921,11 +23094,11 @@ init_chat_message_normalization();
21921
23094
 
21922
23095
  // src/providers/version-archive.ts
21923
23096
  import * as fs11 from "fs";
21924
- import * as path18 from "path";
23097
+ import * as path21 from "path";
21925
23098
  import * as os19 from "os";
21926
23099
  import { execSync as execSync5 } from "child_process";
21927
23100
  import { platform as platform8 } from "os";
21928
- var ARCHIVE_PATH = path18.join(os19.homedir(), ".adhdev", "version-history.json");
23101
+ var ARCHIVE_PATH = path21.join(os19.homedir(), ".adhdev", "version-history.json");
21929
23102
  var MAX_ENTRIES_PER_PROVIDER = 20;
21930
23103
  var VersionArchive = class {
21931
23104
  history = {};
@@ -21972,7 +23145,7 @@ var VersionArchive = class {
21972
23145
  }
21973
23146
  save() {
21974
23147
  try {
21975
- fs11.mkdirSync(path18.dirname(ARCHIVE_PATH), { recursive: true });
23148
+ fs11.mkdirSync(path21.dirname(ARCHIVE_PATH), { recursive: true });
21976
23149
  fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
21977
23150
  } catch {
21978
23151
  }
@@ -22029,7 +23202,7 @@ function checkPathExists2(paths) {
22029
23202
  for (const p of paths) {
22030
23203
  if (p.includes("*")) {
22031
23204
  const home = os19.homedir();
22032
- const resolved = p.replace(/\*/g, home.split(path18.sep).pop() || "");
23205
+ const resolved = p.replace(/\*/g, home.split(path21.sep).pop() || "");
22033
23206
  if (fs11.existsSync(resolved)) return resolved;
22034
23207
  } else {
22035
23208
  if (fs11.existsSync(p)) return p;
@@ -22039,7 +23212,7 @@ function checkPathExists2(paths) {
22039
23212
  }
22040
23213
  function getMacAppVersion(appPath) {
22041
23214
  if (platform8() !== "darwin" || !appPath.endsWith(".app")) return null;
22042
- const plistPath = path18.join(appPath, "Contents", "Info.plist");
23215
+ const plistPath = path21.join(appPath, "Contents", "Info.plist");
22043
23216
  if (!fs11.existsSync(plistPath)) return null;
22044
23217
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
22045
23218
  return raw || null;
@@ -22065,7 +23238,7 @@ async function detectAllVersions(loader, archive) {
22065
23238
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
22066
23239
  let resolvedBin = cliBin;
22067
23240
  if (!resolvedBin && appPath && currentOs === "darwin") {
22068
- const bundled = path18.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
23241
+ const bundled = path21.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
22069
23242
  if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
22070
23243
  }
22071
23244
  info.installed = !!(appPath || resolvedBin);
@@ -22106,7 +23279,7 @@ async function detectAllVersions(loader, archive) {
22106
23279
  // src/daemon/dev-server.ts
22107
23280
  import * as http2 from "http";
22108
23281
  import * as fs15 from "fs";
22109
- import * as path22 from "path";
23282
+ import * as path25 from "path";
22110
23283
  init_config();
22111
23284
 
22112
23285
  // src/daemon/scaffold-template.ts
@@ -22458,7 +23631,7 @@ init_logger();
22458
23631
  // src/daemon/dev-cdp-handlers.ts
22459
23632
  init_logger();
22460
23633
  import * as fs12 from "fs";
22461
- import * as path19 from "path";
23634
+ import * as path22 from "path";
22462
23635
  async function handleCdpEvaluate(ctx, req, res) {
22463
23636
  const body = await ctx.readBody(req);
22464
23637
  const { expression, timeout, ideType } = body;
@@ -22636,17 +23809,17 @@ async function handleScriptHints(ctx, type, _req, res) {
22636
23809
  return;
22637
23810
  }
22638
23811
  let scriptsPath = "";
22639
- const directScripts = path19.join(dir, "scripts.js");
23812
+ const directScripts = path22.join(dir, "scripts.js");
22640
23813
  if (fs12.existsSync(directScripts)) {
22641
23814
  scriptsPath = directScripts;
22642
23815
  } else {
22643
- const scriptsDir = path19.join(dir, "scripts");
23816
+ const scriptsDir = path22.join(dir, "scripts");
22644
23817
  if (fs12.existsSync(scriptsDir)) {
22645
23818
  const versions = fs12.readdirSync(scriptsDir).filter((d) => {
22646
- return fs12.statSync(path19.join(scriptsDir, d)).isDirectory();
23819
+ return fs12.statSync(path22.join(scriptsDir, d)).isDirectory();
22647
23820
  }).sort().reverse();
22648
23821
  for (const ver of versions) {
22649
- const p = path19.join(scriptsDir, ver, "scripts.js");
23822
+ const p = path22.join(scriptsDir, ver, "scripts.js");
22650
23823
  if (fs12.existsSync(p)) {
22651
23824
  scriptsPath = p;
22652
23825
  break;
@@ -23475,7 +24648,7 @@ async function handleDomContext(ctx, type, req, res) {
23475
24648
 
23476
24649
  // src/daemon/dev-cli-debug.ts
23477
24650
  import * as fs13 from "fs";
23478
- import * as path20 from "path";
24651
+ import * as path23 from "path";
23479
24652
  function slugifyFixtureName(value) {
23480
24653
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
23481
24654
  return normalized || `fixture-${Date.now()}`;
@@ -23485,11 +24658,11 @@ function getCliFixtureDir(ctx, type) {
23485
24658
  if (!providerDir) {
23486
24659
  throw new Error(`Provider directory not found for '${type}'`);
23487
24660
  }
23488
- return path20.join(providerDir, "fixtures");
24661
+ return path23.join(providerDir, "fixtures");
23489
24662
  }
23490
24663
  function readCliFixture(ctx, type, name) {
23491
24664
  const fixtureDir = getCliFixtureDir(ctx, type);
23492
- const filePath = path20.join(fixtureDir, `${name}.json`);
24665
+ const filePath = path23.join(fixtureDir, `${name}.json`);
23493
24666
  if (!fs13.existsSync(filePath)) {
23494
24667
  throw new Error(`Fixture not found: ${filePath}`);
23495
24668
  }
@@ -23658,7 +24831,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
23658
24831
  return { target, instance, adapter };
23659
24832
  }
23660
24833
  function sleep(ms) {
23661
- return new Promise((resolve12) => setTimeout(resolve12, ms));
24834
+ return new Promise((resolve15) => setTimeout(resolve15, ms));
23662
24835
  }
23663
24836
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
23664
24837
  const startedAt = Date.now();
@@ -23956,7 +25129,7 @@ async function runCliAutoImplVerification(ctx, type, verification) {
23956
25129
  return {
23957
25130
  mode: "fixture_replay_suite",
23958
25131
  pass: results.every((item) => item.pass),
23959
- failures: results.flatMap((item) => item.failures.map((failure) => `${item.fixtureName}: ${failure}`)),
25132
+ failures: results.flatMap((item) => item.failures.map((failure2) => `${item.fixtureName}: ${failure2}`)),
23960
25133
  result: firstFailure.result,
23961
25134
  assertions: firstFailure.assertions,
23962
25135
  fixture: firstFailure.fixture,
@@ -24256,7 +25429,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
24256
25429
  },
24257
25430
  notes: typeof body?.notes === "string" ? body.notes : void 0
24258
25431
  };
24259
- const filePath = path20.join(fixtureDir, `${name}.json`);
25432
+ const filePath = path23.join(fixtureDir, `${name}.json`);
24260
25433
  fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
24261
25434
  ctx.json(res, 200, {
24262
25435
  saved: true,
@@ -24280,7 +25453,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
24280
25453
  return;
24281
25454
  }
24282
25455
  const fixtures = fs13.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
24283
- const fullPath = path20.join(fixtureDir, file);
25456
+ const fullPath = path23.join(fixtureDir, file);
24284
25457
  try {
24285
25458
  const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
24286
25459
  return {
@@ -24416,7 +25589,7 @@ async function handleCliRaw(ctx, req, res) {
24416
25589
 
24417
25590
  // src/daemon/dev-auto-implement.ts
24418
25591
  import * as fs14 from "fs";
24419
- import * as path21 from "path";
25592
+ import * as path24 from "path";
24420
25593
  import * as os20 from "os";
24421
25594
  function getAutoImplPid(ctx) {
24422
25595
  const pid = ctx.autoImplProcess?.pid;
@@ -24466,22 +25639,22 @@ function getLatestScriptVersionDir(scriptsDir) {
24466
25639
  if (!fs14.existsSync(scriptsDir)) return null;
24467
25640
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
24468
25641
  try {
24469
- return fs14.statSync(path21.join(scriptsDir, d)).isDirectory();
25642
+ return fs14.statSync(path24.join(scriptsDir, d)).isDirectory();
24470
25643
  } catch {
24471
25644
  return false;
24472
25645
  }
24473
25646
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
24474
25647
  if (versions.length === 0) return null;
24475
- return path21.join(scriptsDir, versions[0]);
25648
+ return path24.join(scriptsDir, versions[0]);
24476
25649
  }
24477
25650
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
24478
- const canonicalUserDir = path21.resolve(ctx.providerLoader.getUserProviderDir(category, type));
24479
- const desiredDir = requestedDir ? path21.resolve(requestedDir) : canonicalUserDir;
24480
- const upstreamRoot = path21.resolve(ctx.providerLoader.getUpstreamDir());
24481
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path21.sep}`)) {
25651
+ const canonicalUserDir = path24.resolve(ctx.providerLoader.getUserProviderDir(category, type));
25652
+ const desiredDir = requestedDir ? path24.resolve(requestedDir) : canonicalUserDir;
25653
+ const upstreamRoot = path24.resolve(ctx.providerLoader.getUpstreamDir());
25654
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path24.sep}`)) {
24482
25655
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
24483
25656
  }
24484
- if (path21.basename(desiredDir) !== type) {
25657
+ if (path24.basename(desiredDir) !== type) {
24485
25658
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
24486
25659
  }
24487
25660
  const sourceDir = ctx.findProviderDir(type);
@@ -24489,11 +25662,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
24489
25662
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
24490
25663
  }
24491
25664
  if (!fs14.existsSync(desiredDir)) {
24492
- fs14.mkdirSync(path21.dirname(desiredDir), { recursive: true });
25665
+ fs14.mkdirSync(path24.dirname(desiredDir), { recursive: true });
24493
25666
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
24494
25667
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
24495
25668
  }
24496
- const providerJson = path21.join(desiredDir, "provider.json");
25669
+ const providerJson = path24.join(desiredDir, "provider.json");
24497
25670
  if (!fs14.existsSync(providerJson)) {
24498
25671
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
24499
25672
  }
@@ -24504,13 +25677,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
24504
25677
  const refDir = ctx.findProviderDir(referenceType);
24505
25678
  if (!refDir || !fs14.existsSync(refDir)) return {};
24506
25679
  const referenceScripts = {};
24507
- const scriptsDir = path21.join(refDir, "scripts");
25680
+ const scriptsDir = path24.join(refDir, "scripts");
24508
25681
  const latestDir = getLatestScriptVersionDir(scriptsDir);
24509
25682
  if (!latestDir) return referenceScripts;
24510
25683
  for (const file of fs14.readdirSync(latestDir)) {
24511
25684
  if (!file.endsWith(".js")) continue;
24512
25685
  try {
24513
- referenceScripts[file] = fs14.readFileSync(path21.join(latestDir, file), "utf-8");
25686
+ referenceScripts[file] = fs14.readFileSync(path24.join(latestDir, file), "utf-8");
24514
25687
  } catch {
24515
25688
  }
24516
25689
  }
@@ -24618,9 +25791,9 @@ async function handleAutoImplement(ctx, type, req, res) {
24618
25791
  });
24619
25792
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
24620
25793
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
24621
- const tmpDir = path21.join(os20.tmpdir(), "adhdev-autoimpl");
25794
+ const tmpDir = path24.join(os20.tmpdir(), "adhdev-autoimpl");
24622
25795
  if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
24623
- const promptFile = path21.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
25796
+ const promptFile = path24.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
24624
25797
  fs14.writeFileSync(promptFile, prompt, "utf-8");
24625
25798
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
24626
25799
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -25052,7 +26225,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
25052
26225
  setMode: "set_mode.js"
25053
26226
  };
25054
26227
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
25055
- const scriptsDir = path21.join(providerDir, "scripts");
26228
+ const scriptsDir = path24.join(providerDir, "scripts");
25056
26229
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
25057
26230
  if (latestScriptsDir) {
25058
26231
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -25063,7 +26236,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
25063
26236
  for (const file of fs14.readdirSync(latestScriptsDir)) {
25064
26237
  if (file.endsWith(".js") && targetFileNames.has(file)) {
25065
26238
  try {
25066
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
26239
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
25067
26240
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
25068
26241
  lines.push("```javascript");
25069
26242
  lines.push(content);
@@ -25080,7 +26253,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
25080
26253
  lines.push("");
25081
26254
  for (const file of refFiles) {
25082
26255
  try {
25083
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
26256
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
25084
26257
  lines.push(`### \`${file}\` \u{1F512}`);
25085
26258
  lines.push("```javascript");
25086
26259
  lines.push(content);
@@ -25121,10 +26294,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
25121
26294
  lines.push("");
25122
26295
  }
25123
26296
  }
25124
- const docsDir = path21.join(providerDir, "../../docs");
26297
+ const docsDir = path24.join(providerDir, "../../docs");
25125
26298
  const loadGuide = (name) => {
25126
26299
  try {
25127
- const p = path21.join(docsDir, name);
26300
+ const p = path24.join(docsDir, name);
25128
26301
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
25129
26302
  } catch {
25130
26303
  }
@@ -25361,7 +26534,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
25361
26534
  parseApproval: "parse_approval.js"
25362
26535
  };
25363
26536
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
25364
- const scriptsDir = path21.join(providerDir, "scripts");
26537
+ const scriptsDir = path24.join(providerDir, "scripts");
25365
26538
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
25366
26539
  if (latestScriptsDir) {
25367
26540
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -25373,7 +26546,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
25373
26546
  if (!file.endsWith(".js")) continue;
25374
26547
  if (!targetFileNames.has(file)) continue;
25375
26548
  try {
25376
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
26549
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
25377
26550
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
25378
26551
  lines.push("```javascript");
25379
26552
  lines.push(content);
@@ -25389,7 +26562,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
25389
26562
  lines.push("");
25390
26563
  for (const file of refFiles) {
25391
26564
  try {
25392
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
26565
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
25393
26566
  lines.push(`### \`${file}\` \u{1F512}`);
25394
26567
  lines.push("```javascript");
25395
26568
  lines.push(content);
@@ -25422,10 +26595,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
25422
26595
  lines.push("");
25423
26596
  }
25424
26597
  }
25425
- const docsDir = path21.join(providerDir, "../../docs");
26598
+ const docsDir = path24.join(providerDir, "../../docs");
25426
26599
  const loadGuide = (name) => {
25427
26600
  try {
25428
- const p = path21.join(docsDir, name);
26601
+ const p = path24.join(docsDir, name);
25429
26602
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
25430
26603
  } catch {
25431
26604
  }
@@ -25872,8 +27045,8 @@ var DevServer = class _DevServer {
25872
27045
  }
25873
27046
  getEndpointList() {
25874
27047
  return this.routes.map((r) => {
25875
- const path23 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
25876
- return `${r.method.padEnd(5)} ${path23}`;
27048
+ const path26 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
27049
+ return `${r.method.padEnd(5)} ${path26}`;
25877
27050
  });
25878
27051
  }
25879
27052
  async start(port = DEV_SERVER_PORT) {
@@ -25904,15 +27077,15 @@ var DevServer = class _DevServer {
25904
27077
  this.json(res, 500, { error: e.message });
25905
27078
  }
25906
27079
  });
25907
- return new Promise((resolve12, reject) => {
27080
+ return new Promise((resolve15, reject) => {
25908
27081
  this.server.listen(port, "127.0.0.1", () => {
25909
27082
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
25910
- resolve12();
27083
+ resolve15();
25911
27084
  });
25912
27085
  this.server.on("error", (e) => {
25913
27086
  if (e.code === "EADDRINUSE") {
25914
27087
  this.log(`Port ${port} in use, skipping dev server`);
25915
- resolve12();
27088
+ resolve15();
25916
27089
  } else {
25917
27090
  reject(e);
25918
27091
  }
@@ -25994,20 +27167,20 @@ var DevServer = class _DevServer {
25994
27167
  child.stderr?.on("data", (d) => {
25995
27168
  stderr += d.toString().slice(0, 2e3);
25996
27169
  });
25997
- await new Promise((resolve12) => {
27170
+ await new Promise((resolve15) => {
25998
27171
  const timer = setTimeout(() => {
25999
27172
  child.kill();
26000
- resolve12();
27173
+ resolve15();
26001
27174
  }, 3e3);
26002
27175
  child.on("exit", () => {
26003
27176
  clearTimeout(timer);
26004
- resolve12();
27177
+ resolve15();
26005
27178
  });
26006
27179
  child.stdout?.once("data", () => {
26007
27180
  setTimeout(() => {
26008
27181
  child.kill();
26009
27182
  clearTimeout(timer);
26010
- resolve12();
27183
+ resolve15();
26011
27184
  }, 500);
26012
27185
  });
26013
27186
  });
@@ -26161,12 +27334,12 @@ var DevServer = class _DevServer {
26161
27334
  // ─── DevConsole SPA ───
26162
27335
  getConsoleDistDir() {
26163
27336
  const candidates = [
26164
- path22.resolve(__dirname, "../../web-devconsole/dist"),
26165
- path22.resolve(__dirname, "../../../web-devconsole/dist"),
26166
- path22.join(process.cwd(), "packages/web-devconsole/dist")
27337
+ path25.resolve(__dirname, "../../web-devconsole/dist"),
27338
+ path25.resolve(__dirname, "../../../web-devconsole/dist"),
27339
+ path25.join(process.cwd(), "packages/web-devconsole/dist")
26167
27340
  ];
26168
27341
  for (const dir of candidates) {
26169
- if (fs15.existsSync(path22.join(dir, "index.html"))) return dir;
27342
+ if (fs15.existsSync(path25.join(dir, "index.html"))) return dir;
26170
27343
  }
26171
27344
  return null;
26172
27345
  }
@@ -26176,7 +27349,7 @@ var DevServer = class _DevServer {
26176
27349
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
26177
27350
  return;
26178
27351
  }
26179
- const htmlPath = path22.join(distDir, "index.html");
27352
+ const htmlPath = path25.join(distDir, "index.html");
26180
27353
  try {
26181
27354
  const html = fs15.readFileSync(htmlPath, "utf-8");
26182
27355
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -26201,15 +27374,15 @@ var DevServer = class _DevServer {
26201
27374
  this.json(res, 404, { error: "Not found" });
26202
27375
  return;
26203
27376
  }
26204
- const safePath = path22.normalize(pathname).replace(/^\.\.\//, "");
26205
- const filePath = path22.join(distDir, safePath);
27377
+ const safePath = path25.normalize(pathname).replace(/^\.\.\//, "");
27378
+ const filePath = path25.join(distDir, safePath);
26206
27379
  if (!filePath.startsWith(distDir)) {
26207
27380
  this.json(res, 403, { error: "Forbidden" });
26208
27381
  return;
26209
27382
  }
26210
27383
  try {
26211
27384
  const content = fs15.readFileSync(filePath);
26212
- const ext = path22.extname(filePath);
27385
+ const ext = path25.extname(filePath);
26213
27386
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
26214
27387
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
26215
27388
  res.end(content);
@@ -26322,10 +27495,10 @@ var DevServer = class _DevServer {
26322
27495
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
26323
27496
  if (entry.isDirectory()) {
26324
27497
  files.push({ path: rel, size: 0, type: "dir" });
26325
- scan(path22.join(d, entry.name), rel);
27498
+ scan(path25.join(d, entry.name), rel);
26326
27499
  } else {
26327
- const stat = fs15.statSync(path22.join(d, entry.name));
26328
- files.push({ path: rel, size: stat.size, type: "file" });
27500
+ const stat2 = fs15.statSync(path25.join(d, entry.name));
27501
+ files.push({ path: rel, size: stat2.size, type: "file" });
26329
27502
  }
26330
27503
  }
26331
27504
  } catch {
@@ -26347,7 +27520,7 @@ var DevServer = class _DevServer {
26347
27520
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
26348
27521
  return;
26349
27522
  }
26350
- const fullPath = path22.resolve(dir, path22.normalize(filePath));
27523
+ const fullPath = path25.resolve(dir, path25.normalize(filePath));
26351
27524
  if (!fullPath.startsWith(dir)) {
26352
27525
  this.json(res, 403, { error: "Forbidden" });
26353
27526
  return;
@@ -26372,14 +27545,14 @@ var DevServer = class _DevServer {
26372
27545
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
26373
27546
  return;
26374
27547
  }
26375
- const fullPath = path22.resolve(dir, path22.normalize(filePath));
27548
+ const fullPath = path25.resolve(dir, path25.normalize(filePath));
26376
27549
  if (!fullPath.startsWith(dir)) {
26377
27550
  this.json(res, 403, { error: "Forbidden" });
26378
27551
  return;
26379
27552
  }
26380
27553
  try {
26381
27554
  if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
26382
- fs15.mkdirSync(path22.dirname(fullPath), { recursive: true });
27555
+ fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
26383
27556
  fs15.writeFileSync(fullPath, content, "utf-8");
26384
27557
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
26385
27558
  this.providerLoader.reload();
@@ -26396,7 +27569,7 @@ var DevServer = class _DevServer {
26396
27569
  return;
26397
27570
  }
26398
27571
  for (const name of ["scripts.js", "provider.json"]) {
26399
- const p = path22.join(dir, name);
27572
+ const p = path25.join(dir, name);
26400
27573
  if (fs15.existsSync(p)) {
26401
27574
  const source = fs15.readFileSync(p, "utf-8");
26402
27575
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -26417,8 +27590,8 @@ var DevServer = class _DevServer {
26417
27590
  this.json(res, 404, { error: `Provider not found: ${type}` });
26418
27591
  return;
26419
27592
  }
26420
- const target = fs15.existsSync(path22.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
26421
- const targetPath = path22.join(dir, target);
27593
+ const target = fs15.existsSync(path25.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
27594
+ const targetPath = path25.join(dir, target);
26422
27595
  try {
26423
27596
  if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
26424
27597
  fs15.writeFileSync(targetPath, source, "utf-8");
@@ -26510,14 +27683,14 @@ var DevServer = class _DevServer {
26510
27683
  child.stderr?.on("data", (d) => {
26511
27684
  stderr += d.toString();
26512
27685
  });
26513
- await new Promise((resolve12) => {
27686
+ await new Promise((resolve15) => {
26514
27687
  const timer = setTimeout(() => {
26515
27688
  child.kill();
26516
- resolve12();
27689
+ resolve15();
26517
27690
  }, timeout);
26518
27691
  child.on("exit", () => {
26519
27692
  clearTimeout(timer);
26520
- resolve12();
27693
+ resolve15();
26521
27694
  });
26522
27695
  });
26523
27696
  const elapsed = Date.now() - start;
@@ -26565,7 +27738,7 @@ var DevServer = class _DevServer {
26565
27738
  }
26566
27739
  let targetDir;
26567
27740
  targetDir = this.providerLoader.getUserProviderDir(category, type);
26568
- const jsonPath = path22.join(targetDir, "provider.json");
27741
+ const jsonPath = path25.join(targetDir, "provider.json");
26569
27742
  if (fs15.existsSync(jsonPath)) {
26570
27743
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
26571
27744
  return;
@@ -26577,8 +27750,8 @@ var DevServer = class _DevServer {
26577
27750
  const createdFiles = ["provider.json"];
26578
27751
  if (result.files) {
26579
27752
  for (const [relPath, content] of Object.entries(result.files)) {
26580
- const fullPath = path22.join(targetDir, relPath);
26581
- fs15.mkdirSync(path22.dirname(fullPath), { recursive: true });
27753
+ const fullPath = path25.join(targetDir, relPath);
27754
+ fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
26582
27755
  fs15.writeFileSync(fullPath, content, "utf-8");
26583
27756
  createdFiles.push(relPath);
26584
27757
  }
@@ -26631,22 +27804,22 @@ var DevServer = class _DevServer {
26631
27804
  if (!fs15.existsSync(scriptsDir)) return null;
26632
27805
  const versions = fs15.readdirSync(scriptsDir).filter((d) => {
26633
27806
  try {
26634
- return fs15.statSync(path22.join(scriptsDir, d)).isDirectory();
27807
+ return fs15.statSync(path25.join(scriptsDir, d)).isDirectory();
26635
27808
  } catch {
26636
27809
  return false;
26637
27810
  }
26638
27811
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
26639
27812
  if (versions.length === 0) return null;
26640
- return path22.join(scriptsDir, versions[0]);
27813
+ return path25.join(scriptsDir, versions[0]);
26641
27814
  }
26642
27815
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
26643
- const canonicalUserDir = path22.resolve(this.providerLoader.getUserProviderDir(category, type));
26644
- const desiredDir = requestedDir ? path22.resolve(requestedDir) : canonicalUserDir;
26645
- const upstreamRoot = path22.resolve(this.providerLoader.getUpstreamDir());
26646
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path22.sep}`)) {
27816
+ const canonicalUserDir = path25.resolve(this.providerLoader.getUserProviderDir(category, type));
27817
+ const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
27818
+ const upstreamRoot = path25.resolve(this.providerLoader.getUpstreamDir());
27819
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
26647
27820
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
26648
27821
  }
26649
- if (path22.basename(desiredDir) !== type) {
27822
+ if (path25.basename(desiredDir) !== type) {
26650
27823
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
26651
27824
  }
26652
27825
  const sourceDir = this.findProviderDir(type);
@@ -26654,11 +27827,11 @@ var DevServer = class _DevServer {
26654
27827
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
26655
27828
  }
26656
27829
  if (!fs15.existsSync(desiredDir)) {
26657
- fs15.mkdirSync(path22.dirname(desiredDir), { recursive: true });
27830
+ fs15.mkdirSync(path25.dirname(desiredDir), { recursive: true });
26658
27831
  fs15.cpSync(sourceDir, desiredDir, { recursive: true });
26659
27832
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
26660
27833
  }
26661
- const providerJson = path22.join(desiredDir, "provider.json");
27834
+ const providerJson = path25.join(desiredDir, "provider.json");
26662
27835
  if (!fs15.existsSync(providerJson)) {
26663
27836
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
26664
27837
  }
@@ -26694,7 +27867,7 @@ var DevServer = class _DevServer {
26694
27867
  setMode: "set_mode.js"
26695
27868
  };
26696
27869
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26697
- const scriptsDir = path22.join(providerDir, "scripts");
27870
+ const scriptsDir = path25.join(providerDir, "scripts");
26698
27871
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
26699
27872
  if (latestScriptsDir) {
26700
27873
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26705,7 +27878,7 @@ var DevServer = class _DevServer {
26705
27878
  for (const file of fs15.readdirSync(latestScriptsDir)) {
26706
27879
  if (file.endsWith(".js") && targetFileNames.has(file)) {
26707
27880
  try {
26708
- const content = fs15.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
27881
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26709
27882
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26710
27883
  lines.push("```javascript");
26711
27884
  lines.push(content);
@@ -26722,7 +27895,7 @@ var DevServer = class _DevServer {
26722
27895
  lines.push("");
26723
27896
  for (const file of refFiles) {
26724
27897
  try {
26725
- const content = fs15.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
27898
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26726
27899
  lines.push(`### \`${file}\` \u{1F512}`);
26727
27900
  lines.push("```javascript");
26728
27901
  lines.push(content);
@@ -26763,10 +27936,10 @@ var DevServer = class _DevServer {
26763
27936
  lines.push("");
26764
27937
  }
26765
27938
  }
26766
- const docsDir = path22.join(providerDir, "../../docs");
27939
+ const docsDir = path25.join(providerDir, "../../docs");
26767
27940
  const loadGuide = (name) => {
26768
27941
  try {
26769
- const p = path22.join(docsDir, name);
27942
+ const p = path25.join(docsDir, name);
26770
27943
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
26771
27944
  } catch {
26772
27945
  }
@@ -26940,7 +28113,7 @@ var DevServer = class _DevServer {
26940
28113
  parseApproval: "parse_approval.js"
26941
28114
  };
26942
28115
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26943
- const scriptsDir = path22.join(providerDir, "scripts");
28116
+ const scriptsDir = path25.join(providerDir, "scripts");
26944
28117
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
26945
28118
  if (latestScriptsDir) {
26946
28119
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26952,7 +28125,7 @@ var DevServer = class _DevServer {
26952
28125
  if (!file.endsWith(".js")) continue;
26953
28126
  if (!targetFileNames.has(file)) continue;
26954
28127
  try {
26955
- const content = fs15.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
28128
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26956
28129
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26957
28130
  lines.push("```javascript");
26958
28131
  lines.push(content);
@@ -26968,7 +28141,7 @@ var DevServer = class _DevServer {
26968
28141
  lines.push("");
26969
28142
  for (const file of refFiles) {
26970
28143
  try {
26971
- const content = fs15.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
28144
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26972
28145
  lines.push(`### \`${file}\` \u{1F512}`);
26973
28146
  lines.push("```javascript");
26974
28147
  lines.push(content);
@@ -27001,10 +28174,10 @@ var DevServer = class _DevServer {
27001
28174
  lines.push("");
27002
28175
  }
27003
28176
  }
27004
- const docsDir = path22.join(providerDir, "../../docs");
28177
+ const docsDir = path25.join(providerDir, "../../docs");
27005
28178
  const loadGuide = (name) => {
27006
28179
  try {
27007
- const p = path22.join(docsDir, name);
28180
+ const p = path25.join(docsDir, name);
27008
28181
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
27009
28182
  } catch {
27010
28183
  }
@@ -27187,14 +28360,14 @@ data: ${JSON.stringify(msg.data)}
27187
28360
  res.end(JSON.stringify(data, null, 2));
27188
28361
  }
27189
28362
  async readBody(req) {
27190
- return new Promise((resolve12) => {
28363
+ return new Promise((resolve15) => {
27191
28364
  let body = "";
27192
28365
  req.on("data", (chunk) => body += chunk);
27193
28366
  req.on("end", () => {
27194
28367
  try {
27195
- resolve12(JSON.parse(body));
28368
+ resolve15(JSON.parse(body));
27196
28369
  } catch {
27197
- resolve12({});
28370
+ resolve15({});
27198
28371
  }
27199
28372
  });
27200
28373
  });
@@ -27709,7 +28882,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
27709
28882
  const deadline = Date.now() + timeoutMs;
27710
28883
  while (Date.now() < deadline) {
27711
28884
  if (await canConnect(endpoint)) return;
27712
- await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
28885
+ await new Promise((resolve15) => setTimeout(resolve15, STARTUP_POLL_MS));
27713
28886
  }
27714
28887
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
27715
28888
  }
@@ -27887,10 +29060,10 @@ async function installExtension(ide, extension) {
27887
29060
  const buffer = Buffer.from(await res.arrayBuffer());
27888
29061
  const fs16 = await import("fs");
27889
29062
  fs16.writeFileSync(vsixPath, buffer);
27890
- return new Promise((resolve12) => {
29063
+ return new Promise((resolve15) => {
27891
29064
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
27892
29065
  exec2(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
27893
- resolve12({
29066
+ resolve15({
27894
29067
  extensionId: extension.id,
27895
29068
  marketplaceId: extension.marketplaceId,
27896
29069
  success: !error,
@@ -27903,11 +29076,11 @@ async function installExtension(ide, extension) {
27903
29076
  } catch (e) {
27904
29077
  }
27905
29078
  }
27906
- return new Promise((resolve12) => {
29079
+ return new Promise((resolve15) => {
27907
29080
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
27908
29081
  exec2(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
27909
29082
  if (error) {
27910
- resolve12({
29083
+ resolve15({
27911
29084
  extensionId: extension.id,
27912
29085
  marketplaceId: extension.marketplaceId,
27913
29086
  success: false,
@@ -27915,7 +29088,7 @@ async function installExtension(ide, extension) {
27915
29088
  error: stderr || error.message
27916
29089
  });
27917
29090
  } else {
27918
- resolve12({
29091
+ resolve15({
27919
29092
  extensionId: extension.id,
27920
29093
  marketplaceId: extension.marketplaceId,
27921
29094
  success: true,
@@ -28244,6 +29417,7 @@ export {
28244
29417
  DEFAULT_CDP_SCAN_INTERVAL_MS,
28245
29418
  DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS,
28246
29419
  DEFAULT_DAEMON_PORT,
29420
+ DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS,
28247
29421
  DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
28248
29422
  DEFAULT_SESSION_HOST_APP_NAME,
28249
29423
  DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
@@ -28262,8 +29436,12 @@ export {
28262
29436
  DaemonCommandRouter,
28263
29437
  DaemonStatusReporter,
28264
29438
  DevServer,
29439
+ GitCommandError,
29440
+ GitWorkspaceMonitor,
28265
29441
  IdeProviderInstance,
29442
+ InMemoryGitSnapshotStore,
28266
29443
  LOG,
29444
+ MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
28267
29445
  MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
28268
29446
  MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
28269
29447
  NodePtyTransportFactory,
@@ -28291,9 +29469,14 @@ export {
28291
29469
  buildUserChatMessage,
28292
29470
  classifyHotChatSessionsForSubscriptionFlush,
28293
29471
  clearDebugTrace,
29472
+ compareGitSnapshots,
28294
29473
  configureDebugTraceStore,
28295
29474
  connectCdpManager,
28296
29475
  createDebugTraceStore,
29476
+ createDefaultGitCommandServices,
29477
+ createGitCompactSummary,
29478
+ createGitSnapshotStore,
29479
+ createGitWorkspaceMonitor,
28297
29480
  createInteractionId,
28298
29481
  detectAllVersions,
28299
29482
  detectCLIs,
@@ -28308,6 +29491,9 @@ export {
28308
29491
  getCurrentDaemonLogPath,
28309
29492
  getDaemonLogDir,
28310
29493
  getDebugRuntimeConfig,
29494
+ getGitDiffSummary,
29495
+ getGitFileDiff,
29496
+ getGitRepoStatus,
28311
29497
  getHostMemorySnapshot,
28312
29498
  getLogLevel,
28313
29499
  getNpmExecOptions,
@@ -28319,6 +29505,7 @@ export {
28319
29505
  getSessionHostRecoveryLabel,
28320
29506
  getSessionHostSurfaceKind,
28321
29507
  getWorkspaceState,
29508
+ handleGitCommand,
28322
29509
  hasCdpManager,
28323
29510
  hashSignatureParts,
28324
29511
  initDaemonComponents,
@@ -28327,9 +29514,11 @@ export {
28327
29514
  isBuiltinChatMessageKind,
28328
29515
  isCdpConnected,
28329
29516
  isExtensionInstalled,
29517
+ isGitCommandName,
28330
29518
  isIdeRunning,
28331
29519
  isManagedStatusWaiting,
28332
29520
  isManagedStatusWorking,
29521
+ isPathInside,
28333
29522
  isSessionHostLiveRuntime,
28334
29523
  isSessionHostRecoverySnapshot,
28335
29524
  isSetupComplete,
@@ -28347,10 +29536,13 @@ export {
28347
29536
  normalizeChatMessageKind,
28348
29537
  normalizeChatMessages,
28349
29538
  normalizeChatTailActiveModal,
29539
+ normalizeGitOutput,
29540
+ normalizeGitWorkspaceSubscriptionParams,
28350
29541
  normalizeInputEnvelope,
28351
29542
  normalizeManagedStatus,
28352
29543
  normalizeMessageParts,
28353
29544
  normalizeSessionModalFields,
29545
+ parsePorcelainV2Status,
28354
29546
  parseProviderSourceConfigUpdate,
28355
29547
  partitionSessionHostDiagnosticsSessions,
28356
29548
  partitionSessionHostRecords,
@@ -28366,9 +29558,11 @@ export {
28366
29558
  resolveChatMessageKind,
28367
29559
  resolveCurrentGlobalInstallSurface,
28368
29560
  resolveDebugRuntimeConfig,
29561
+ resolveGitRepository,
28369
29562
  resolveSessionHostAppName,
28370
29563
  resolveSessionHostAppNameResolution,
28371
29564
  runAsyncBatch,
29565
+ runGit,
28372
29566
  saveConfig,
28373
29567
  saveState,
28374
29568
  setDebugRuntimeConfig,
@@ -28379,6 +29573,7 @@ export {
28379
29573
  shutdownDaemonComponents,
28380
29574
  spawnDetachedDaemonUpgradeHelper,
28381
29575
  startDaemonDevSupport,
29576
+ summarizeGitStatus,
28382
29577
  updateConfig,
28383
29578
  upsertSavedProviderSession
28384
29579
  };