@adhdev/daemon-core 0.9.53 → 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
  }
@@ -8011,13 +9128,13 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
8011
9128
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
8012
9129
  try {
8013
9130
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
8014
- const dir = path7.join(HISTORY_DIR, sanitized);
9131
+ const dir = path10.join(HISTORY_DIR, sanitized);
8015
9132
  if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
8016
9133
  const files = listHistoryFiles(dir, historySessionId);
8017
9134
  const allMessages = [];
8018
9135
  const seen = /* @__PURE__ */ new Set();
8019
9136
  for (const file of files) {
8020
- const filePath = path7.join(dir, file);
9137
+ const filePath = path10.join(dir, file);
8021
9138
  const content = fs3.readFileSync(filePath, "utf-8");
8022
9139
  const lines = content.trim().split("\n").filter(Boolean);
8023
9140
  for (let i = 0; i < lines.length; i++) {
@@ -8041,7 +9158,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
8041
9158
  function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
8042
9159
  try {
8043
9160
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
8044
- const dir = path7.join(HISTORY_DIR, sanitized);
9161
+ const dir = path10.join(HISTORY_DIR, sanitized);
8045
9162
  if (!fs3.existsSync(dir)) {
8046
9163
  savedHistorySessionCache.delete(sanitized);
8047
9164
  return { sessions: [], hasMore: false };
@@ -8102,11 +9219,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
8102
9219
  }
8103
9220
  function readExistingSessionStartRecord(agentType, historySessionId) {
8104
9221
  try {
8105
- const dir = path7.join(HISTORY_DIR, agentType);
9222
+ const dir = path10.join(HISTORY_DIR, agentType);
8106
9223
  if (!fs3.existsSync(dir)) return null;
8107
9224
  const files = listHistoryFiles(dir, historySessionId).sort();
8108
9225
  for (const file of files) {
8109
- 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);
8110
9227
  for (const line of lines) {
8111
9228
  try {
8112
9229
  const parsed = JSON.parse(line);
@@ -8126,16 +9243,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
8126
9243
  function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
8127
9244
  if (records.length === 0) return false;
8128
9245
  try {
8129
- const dir = path7.join(HISTORY_DIR, agentType);
9246
+ const dir = path10.join(HISTORY_DIR, agentType);
8130
9247
  fs3.mkdirSync(dir, { recursive: true });
8131
9248
  const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
8132
9249
  for (const file of fs3.readdirSync(dir)) {
8133
9250
  if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
8134
- fs3.unlinkSync(path7.join(dir, file));
9251
+ fs3.unlinkSync(path10.join(dir, file));
8135
9252
  }
8136
9253
  }
8137
9254
  const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
8138
- const filePath = path7.join(dir, `${prefix}${targetDate}.jsonl`);
9255
+ const filePath = path10.join(dir, `${prefix}${targetDate}.jsonl`);
8139
9256
  fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
8140
9257
  `, "utf-8");
8141
9258
  invalidatePersistedSavedHistoryIndex(agentType, dir);
@@ -10007,6 +11124,10 @@ function shouldIncludeSessionMetadata(profile) {
10007
11124
  function shouldIncludeRuntimeMetadata(profile) {
10008
11125
  return true;
10009
11126
  }
11127
+ function getGitSummaryForWorkspace(workspace, options) {
11128
+ if (!workspace) return void 0;
11129
+ return options.getGitSummaryForWorkspace?.(workspace) || void 0;
11130
+ }
10010
11131
  function findCdpManager(cdpManagers, key) {
10011
11132
  const exact = cdpManagers.get(key);
10012
11133
  if (exact) return exact.isConnected ? exact : null;
@@ -10062,6 +11183,8 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
10062
11183
  const controlValues = normalizeProviderStateControlValues(state.controlValues);
10063
11184
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
10064
11185
  const includeSessionControls = shouldIncludeSessionControls(profile);
11186
+ const workspace = state.workspace || null;
11187
+ const git = getGitSummaryForWorkspace(workspace, options);
10065
11188
  const title = activeChat?.title || state.name;
10066
11189
  return {
10067
11190
  id: state.instanceId || state.type,
@@ -10074,7 +11197,8 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
10074
11197
  activeModal: activeChat?.activeModal || null
10075
11198
  }),
10076
11199
  title,
10077
- workspace: state.workspace || null,
11200
+ workspace,
11201
+ ...git && { git },
10078
11202
  activeChat,
10079
11203
  ...summaryMetadata && { summaryMetadata },
10080
11204
  ...includeSessionMetadata && { capabilities: state.sessionCapabilities || IDE_SESSION_CAPABILITIES },
@@ -10095,6 +11219,8 @@ function buildExtensionAgentSession(parent, ext, options) {
10095
11219
  const controlValues = normalizeProviderStateControlValues(ext.controlValues);
10096
11220
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
10097
11221
  const includeSessionControls = shouldIncludeSessionControls(profile);
11222
+ const workspace = parent.workspace || null;
11223
+ const git = getGitSummaryForWorkspace(workspace, options);
10098
11224
  return {
10099
11225
  id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
10100
11226
  parentId: parent.instanceId || parent.type,
@@ -10107,7 +11233,8 @@ function buildExtensionAgentSession(parent, ext, options) {
10107
11233
  activeModal: activeChat?.activeModal || null
10108
11234
  }),
10109
11235
  title: activeChat?.title || ext.name,
10110
- workspace: parent.workspace || null,
11236
+ workspace,
11237
+ ...git && { git },
10111
11238
  activeChat,
10112
11239
  ...summaryMetadata && { summaryMetadata },
10113
11240
  ...includeSessionMetadata && { capabilities: ext.sessionCapabilities || EXTENSION_SESSION_CAPABILITIES },
@@ -10143,6 +11270,8 @@ function buildCliSession(state, options) {
10143
11270
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
10144
11271
  const includeRuntimeMetadata = shouldIncludeRuntimeMetadata(profile);
10145
11272
  const includeSessionControls = shouldIncludeSessionControls(profile);
11273
+ const workspace = state.workspace || null;
11274
+ const git = getGitSummaryForWorkspace(workspace, options);
10146
11275
  return {
10147
11276
  id: state.instanceId,
10148
11277
  parentId: null,
@@ -10155,7 +11284,8 @@ function buildCliSession(state, options) {
10155
11284
  activeModal: activeChat?.activeModal || null
10156
11285
  }),
10157
11286
  title: activeChat?.title || state.name,
10158
- workspace: state.workspace || null,
11287
+ workspace,
11288
+ ...git && { git },
10159
11289
  ...includeRuntimeMetadata && {
10160
11290
  runtimeKey: state.runtime?.runtimeKey,
10161
11291
  runtimeDisplayName: state.runtime?.displayName,
@@ -10190,6 +11320,8 @@ function buildAcpSession(state, options) {
10190
11320
  const controlValues = normalizeProviderStateControlValues(state.controlValues);
10191
11321
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
10192
11322
  const includeSessionControls = shouldIncludeSessionControls(profile);
11323
+ const workspace = state.workspace || null;
11324
+ const git = getGitSummaryForWorkspace(workspace, options);
10193
11325
  return {
10194
11326
  id: state.instanceId,
10195
11327
  parentId: null,
@@ -10201,7 +11333,8 @@ function buildAcpSession(state, options) {
10201
11333
  activeModal: activeChat?.activeModal || null
10202
11334
  }),
10203
11335
  title: activeChat?.title || state.name,
10204
- workspace: state.workspace || null,
11336
+ workspace,
11337
+ ...git && { git },
10205
11338
  activeChat,
10206
11339
  ...summaryMetadata && { summaryMetadata },
10207
11340
  ...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES },
@@ -10321,7 +11454,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
10321
11454
  init_contracts();
10322
11455
  import * as fs4 from "fs";
10323
11456
  import * as os6 from "os";
10324
- import * as path8 from "path";
11457
+ import * as path11 from "path";
10325
11458
  import { randomUUID as randomUUID4 } from "crypto";
10326
11459
 
10327
11460
  // src/providers/provider-input-support.ts
@@ -11013,7 +12146,7 @@ function buildDebugBundleText(bundle) {
11013
12146
  }
11014
12147
  function getChatDebugBundleDir() {
11015
12148
  const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
11016
- return override || path8.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
12149
+ return override || path11.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
11017
12150
  }
11018
12151
  function safeBundleIdSegment(value, fallback) {
11019
12152
  const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
@@ -11046,7 +12179,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
11046
12179
  const bundleId = createChatDebugBundleId(targetSessionId);
11047
12180
  const dir = getChatDebugBundleDir();
11048
12181
  fs4.mkdirSync(dir, { recursive: true });
11049
- const savedPath = path8.join(dir, `${bundleId}.json`);
12182
+ const savedPath = path11.join(dir, `${bundleId}.json`);
11050
12183
  const json = `${JSON.stringify(bundle, null, 2)}
11051
12184
  `;
11052
12185
  fs4.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
@@ -11240,7 +12373,7 @@ function getCliVisibleTranscriptCount(adapter) {
11240
12373
  async function getStableExtensionBaseline(h) {
11241
12374
  const first = await readExtensionChatState(h);
11242
12375
  if (getStateMessageCount(first) > 0 || getStateLastSignature(first)) return first;
11243
- await new Promise((resolve12) => setTimeout(resolve12, 150));
12376
+ await new Promise((resolve15) => setTimeout(resolve15, 150));
11244
12377
  const second = await readExtensionChatState(h);
11245
12378
  return getStateMessageCount(second) >= getStateMessageCount(first) ? second : first;
11246
12379
  }
@@ -11248,7 +12381,7 @@ async function verifyExtensionSendObserved(h, before) {
11248
12381
  const beforeCount = getStateMessageCount(before);
11249
12382
  const beforeSignature = getStateLastSignature(before);
11250
12383
  for (let attempt = 0; attempt < 12; attempt += 1) {
11251
- await new Promise((resolve12) => setTimeout(resolve12, 250));
12384
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
11252
12385
  const state = await readExtensionChatState(h);
11253
12386
  if (state?.status === "waiting_approval") return true;
11254
12387
  const afterCount = getStateMessageCount(state);
@@ -12184,7 +13317,7 @@ async function handleResolveAction(h, args) {
12184
13317
 
12185
13318
  // src/commands/cdp-commands.ts
12186
13319
  import * as fs5 from "fs";
12187
- import * as path9 from "path";
13320
+ import * as path12 from "path";
12188
13321
  import * as os7 from "os";
12189
13322
  var KEY_TO_VK = {
12190
13323
  Backspace: 8,
@@ -12441,25 +13574,25 @@ function resolveSafePath(requestedPath) {
12441
13574
  const inputPath = rawPath || ".";
12442
13575
  const home = os7.homedir();
12443
13576
  if (inputPath.startsWith("~")) {
12444
- return path9.resolve(path9.join(home, inputPath.slice(1)));
13577
+ return path12.resolve(path12.join(home, inputPath.slice(1)));
12445
13578
  }
12446
13579
  if (process.platform === "win32") {
12447
13580
  const normalized = normalizeWindowsRequestedPath(inputPath);
12448
- if (path9.win32.isAbsolute(normalized)) {
12449
- return path9.win32.normalize(normalized);
13581
+ if (path12.win32.isAbsolute(normalized)) {
13582
+ return path12.win32.normalize(normalized);
12450
13583
  }
12451
- return path9.win32.resolve(normalized);
13584
+ return path12.win32.resolve(normalized);
12452
13585
  }
12453
- if (path9.isAbsolute(inputPath)) {
12454
- return path9.normalize(inputPath);
13586
+ if (path12.isAbsolute(inputPath)) {
13587
+ return path12.normalize(inputPath);
12455
13588
  }
12456
- return path9.resolve(inputPath);
13589
+ return path12.resolve(inputPath);
12457
13590
  }
12458
13591
  function listDirectoryEntriesSafe(dirPath) {
12459
13592
  const entries = fs5.readdirSync(dirPath, { withFileTypes: true });
12460
13593
  const files = [];
12461
13594
  for (const entry of entries) {
12462
- const entryPath = path9.join(dirPath, entry.name);
13595
+ const entryPath = path12.join(dirPath, entry.name);
12463
13596
  try {
12464
13597
  if (entry.isDirectory()) {
12465
13598
  files.push({ name: entry.name, type: "directory" });
@@ -12475,11 +13608,11 @@ function listDirectoryEntriesSafe(dirPath) {
12475
13608
  files.push({ name: entry.name, type: "file", size });
12476
13609
  continue;
12477
13610
  }
12478
- const stat = fs5.statSync(entryPath);
13611
+ const stat2 = fs5.statSync(entryPath);
12479
13612
  files.push({
12480
13613
  name: entry.name,
12481
- type: stat.isDirectory() ? "directory" : "file",
12482
- size: stat.isFile() ? stat.size : void 0
13614
+ type: stat2.isDirectory() ? "directory" : "file",
13615
+ size: stat2.isFile() ? stat2.size : void 0
12483
13616
  });
12484
13617
  } catch {
12485
13618
  }
@@ -12513,7 +13646,7 @@ async function handleFileRead(h, args) {
12513
13646
  async function handleFileWrite(h, args) {
12514
13647
  try {
12515
13648
  const filePath = resolveSafePath(args?.path);
12516
- fs5.mkdirSync(path9.dirname(filePath), { recursive: true });
13649
+ fs5.mkdirSync(path12.dirname(filePath), { recursive: true });
12517
13650
  fs5.writeFileSync(filePath, args?.content || "", "utf-8");
12518
13651
  return { success: true, path: filePath };
12519
13652
  } catch (e) {
@@ -12862,7 +13995,7 @@ async function executeProviderScript(h, args, scriptName) {
12862
13995
  const enterCount = cliCommand.enterCount || 1;
12863
13996
  await adapter.writeRaw(cliCommand.text + "\r");
12864
13997
  for (let i = 1; i < enterCount; i += 1) {
12865
- await new Promise((resolve12) => setTimeout(resolve12, 50));
13998
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
12866
13999
  await adapter.writeRaw("\r");
12867
14000
  }
12868
14001
  }
@@ -13356,6 +14489,12 @@ var DaemonCommandHandler = class {
13356
14489
  this._currentRoute = this.resolveRoute(args);
13357
14490
  const startedAt = Date.now();
13358
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
+ }
13359
14498
  const sessionScopedCommands = /* @__PURE__ */ new Set([
13360
14499
  "read_chat",
13361
14500
  "get_chat_debug_bundle",
@@ -13381,7 +14520,6 @@ var DaemonCommandHandler = class {
13381
14520
  this.logCommandEnd(cmd, result2, startedAt);
13382
14521
  return result2;
13383
14522
  }
13384
- let result;
13385
14523
  if (!this._currentRoute.session && !this._currentRoute.managerKey && !this._currentRoute.providerType) {
13386
14524
  const cdpCommands = ["send_chat", "read_chat", "list_chats", "new_chat", "switch_chat", "set_mode", "change_model", "set_thought_level", "resolve_action"];
13387
14525
  if (cdpCommands.includes(cmd)) {
@@ -13532,7 +14670,7 @@ var DaemonCommandHandler = class {
13532
14670
  try {
13533
14671
  const http3 = await import("http");
13534
14672
  const postData = JSON.stringify(body);
13535
- const result = await new Promise((resolve12, reject) => {
14673
+ const result = await new Promise((resolve15, reject) => {
13536
14674
  const req = http3.request({
13537
14675
  hostname: "127.0.0.1",
13538
14676
  port: 19280,
@@ -13544,9 +14682,9 @@ var DaemonCommandHandler = class {
13544
14682
  res.on("data", (chunk) => data += chunk);
13545
14683
  res.on("end", () => {
13546
14684
  try {
13547
- resolve12(JSON.parse(data));
14685
+ resolve15(JSON.parse(data));
13548
14686
  } catch {
13549
- resolve12({ raw: data });
14687
+ resolve15({ raw: data });
13550
14688
  }
13551
14689
  });
13552
14690
  });
@@ -13564,15 +14702,15 @@ var DaemonCommandHandler = class {
13564
14702
  if (!providerType) return { success: false, error: "providerType required" };
13565
14703
  try {
13566
14704
  const http3 = await import("http");
13567
- const result = await new Promise((resolve12, reject) => {
14705
+ const result = await new Promise((resolve15, reject) => {
13568
14706
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
13569
14707
  let data = "";
13570
14708
  res.on("data", (chunk) => data += chunk);
13571
14709
  res.on("end", () => {
13572
14710
  try {
13573
- resolve12(JSON.parse(data));
14711
+ resolve15(JSON.parse(data));
13574
14712
  } catch {
13575
- resolve12({ raw: data });
14713
+ resolve15({ raw: data });
13576
14714
  }
13577
14715
  });
13578
14716
  }).on("error", reject);
@@ -13586,7 +14724,7 @@ var DaemonCommandHandler = class {
13586
14724
  try {
13587
14725
  const http3 = await import("http");
13588
14726
  const postData = JSON.stringify(args || {});
13589
- const result = await new Promise((resolve12, reject) => {
14727
+ const result = await new Promise((resolve15, reject) => {
13590
14728
  const req = http3.request({
13591
14729
  hostname: "127.0.0.1",
13592
14730
  port: 19280,
@@ -13598,9 +14736,9 @@ var DaemonCommandHandler = class {
13598
14736
  res.on("data", (chunk) => data += chunk);
13599
14737
  res.on("end", () => {
13600
14738
  try {
13601
- resolve12(JSON.parse(data));
14739
+ resolve15(JSON.parse(data));
13602
14740
  } catch {
13603
- resolve12({ raw: data });
14741
+ resolve15({ raw: data });
13604
14742
  }
13605
14743
  });
13606
14744
  });
@@ -13618,7 +14756,7 @@ var DaemonCommandHandler = class {
13618
14756
  // src/commands/cli-manager.ts
13619
14757
  init_provider_cli_adapter();
13620
14758
  import * as os13 from "os";
13621
- import * as path13 from "path";
14759
+ import * as path16 from "path";
13622
14760
  import * as crypto4 from "crypto";
13623
14761
  import { existsSync as existsSync10 } from "fs";
13624
14762
  import { execFileSync } from "child_process";
@@ -13628,7 +14766,7 @@ init_config();
13628
14766
  // src/providers/cli-provider-instance.ts
13629
14767
  init_contracts();
13630
14768
  import * as os12 from "os";
13631
- import * as path12 from "path";
14769
+ import * as path15 from "path";
13632
14770
  import * as crypto3 from "crypto";
13633
14771
  import * as fs6 from "fs";
13634
14772
  import { createRequire } from "module";
@@ -13688,7 +14826,7 @@ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages
13688
14826
  var CachedDatabaseSync = null;
13689
14827
  function getDatabaseSync() {
13690
14828
  if (CachedDatabaseSync) return CachedDatabaseSync;
13691
- 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"));
13692
14830
  const sqliteModule = requireFn(`node:${"sqlite"}`);
13693
14831
  CachedDatabaseSync = sqliteModule.DatabaseSync;
13694
14832
  if (!CachedDatabaseSync) {
@@ -13726,7 +14864,7 @@ async function waitForCliAdapterReady(adapter, options) {
13726
14864
  if (status === "stopped") {
13727
14865
  throw new Error("CLI runtime stopped before it became ready");
13728
14866
  }
13729
- await new Promise((resolve12) => setTimeout(resolve12, pollMs));
14867
+ await new Promise((resolve15) => setTimeout(resolve15, pollMs));
13730
14868
  }
13731
14869
  throw new Error(`CLI runtime did not become ready within ${timeoutMs}ms`);
13732
14870
  }
@@ -14077,7 +15215,7 @@ var CliProviderInstance = class {
14077
15215
  const enterCount = cliCommand.enterCount || 1;
14078
15216
  await this.adapter.writeRaw(cliCommand.text + "\r");
14079
15217
  for (let i = 1; i < enterCount; i += 1) {
14080
- await new Promise((resolve12) => setTimeout(resolve12, 50));
15218
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
14081
15219
  await this.adapter.writeRaw("\r");
14082
15220
  }
14083
15221
  }
@@ -15196,13 +16334,13 @@ var AcpProviderInstance = class {
15196
16334
  }
15197
16335
  this.currentStatus = "waiting_approval";
15198
16336
  this.detectStatusTransition();
15199
- const approved = await new Promise((resolve12) => {
15200
- this.permissionResolvers.push(resolve12);
16337
+ const approved = await new Promise((resolve15) => {
16338
+ this.permissionResolvers.push(resolve15);
15201
16339
  setTimeout(() => {
15202
- const idx = this.permissionResolvers.indexOf(resolve12);
16340
+ const idx = this.permissionResolvers.indexOf(resolve15);
15203
16341
  if (idx >= 0) {
15204
16342
  this.permissionResolvers.splice(idx, 1);
15205
- resolve12(false);
16343
+ resolve15(false);
15206
16344
  }
15207
16345
  }, 3e5);
15208
16346
  });
@@ -15777,11 +16915,11 @@ function shouldRestoreHostedRuntime(record, managerTag) {
15777
16915
  // src/commands/cli-manager.ts
15778
16916
  function isExplicitCommand(command) {
15779
16917
  const trimmed = command.trim();
15780
- return path13.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
16918
+ return path16.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
15781
16919
  }
15782
16920
  function expandExecutable(command) {
15783
16921
  const trimmed = command.trim();
15784
- return trimmed.startsWith("~") ? path13.join(os13.homedir(), trimmed.slice(1)) : trimmed;
16922
+ return trimmed.startsWith("~") ? path16.join(os13.homedir(), trimmed.slice(1)) : trimmed;
15785
16923
  }
15786
16924
  function commandExists(command) {
15787
16925
  const trimmed = command.trim();
@@ -16062,7 +17200,7 @@ var DaemonCliManager = class {
16062
17200
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
16063
17201
  const trimmed = (workingDir || "").trim();
16064
17202
  if (!trimmed) throw new Error("working directory required");
16065
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path13.resolve(trimmed);
17203
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path16.resolve(trimmed);
16066
17204
  const normalizedType = this.providerLoader.resolveAlias(cliType);
16067
17205
  const rawProvider = this.providerLoader.getByAlias(cliType);
16068
17206
  const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
@@ -16563,11 +17701,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
16563
17701
  import { execSync as execSync4, spawn as spawn2 } from "child_process";
16564
17702
  import * as net from "net";
16565
17703
  import * as os15 from "os";
16566
- import * as path15 from "path";
17704
+ import * as path18 from "path";
16567
17705
 
16568
17706
  // src/providers/provider-loader.ts
16569
17707
  import * as fs7 from "fs";
16570
- import * as path14 from "path";
17708
+ import * as path17 from "path";
16571
17709
  import * as os14 from "os";
16572
17710
  import * as chokidar from "chokidar";
16573
17711
  init_logger();
@@ -16832,7 +17970,7 @@ var ProviderLoader = class _ProviderLoader {
16832
17970
  try {
16833
17971
  if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
16834
17972
  return ["ide", "extension", "cli", "acp"].some(
16835
- (category) => fs7.existsSync(path14.join(candidate, category))
17973
+ (category) => fs7.existsSync(path17.join(candidate, category))
16836
17974
  );
16837
17975
  } catch {
16838
17976
  return false;
@@ -16840,20 +17978,20 @@ var ProviderLoader = class _ProviderLoader {
16840
17978
  }
16841
17979
  static hasProviderRootMarker(candidate) {
16842
17980
  try {
16843
- return fs7.existsSync(path14.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
17981
+ return fs7.existsSync(path17.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
16844
17982
  } catch {
16845
17983
  return false;
16846
17984
  }
16847
17985
  }
16848
17986
  detectDefaultUserDir() {
16849
- const fallback = path14.join(os14.homedir(), ".adhdev", "providers");
17987
+ const fallback = path17.join(os14.homedir(), ".adhdev", "providers");
16850
17988
  const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
16851
17989
  const visited = /* @__PURE__ */ new Set();
16852
17990
  for (const start of this.probeStarts) {
16853
- let current = path14.resolve(start);
17991
+ let current = path17.resolve(start);
16854
17992
  while (!visited.has(current)) {
16855
17993
  visited.add(current);
16856
- const siblingCandidate = path14.join(path14.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
17994
+ const siblingCandidate = path17.join(path17.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
16857
17995
  if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
16858
17996
  const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
16859
17997
  if (envOptIn || hasMarker) {
@@ -16875,7 +18013,7 @@ var ProviderLoader = class _ProviderLoader {
16875
18013
  return { path: siblingCandidate, source };
16876
18014
  }
16877
18015
  }
16878
- const parent = path14.dirname(current);
18016
+ const parent = path17.dirname(current);
16879
18017
  if (parent === current) break;
16880
18018
  current = parent;
16881
18019
  }
@@ -16885,11 +18023,11 @@ var ProviderLoader = class _ProviderLoader {
16885
18023
  constructor(options) {
16886
18024
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
16887
18025
  this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
16888
- this.defaultProvidersDir = path14.join(os14.homedir(), ".adhdev", "providers");
18026
+ this.defaultProvidersDir = path17.join(os14.homedir(), ".adhdev", "providers");
16889
18027
  const detected = this.detectDefaultUserDir();
16890
18028
  this.userDir = detected.path;
16891
18029
  this.userDirSource = detected.source;
16892
- this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
18030
+ this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
16893
18031
  this.disableUpstream = false;
16894
18032
  this.applySourceConfig({
16895
18033
  userDir: options?.userDir,
@@ -16948,7 +18086,7 @@ var ProviderLoader = class _ProviderLoader {
16948
18086
  this.userDir = detected.path;
16949
18087
  this.userDirSource = detected.source;
16950
18088
  }
16951
- this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
18089
+ this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
16952
18090
  this.disableUpstream = this.sourceMode === "no-upstream";
16953
18091
  if (this.explicitProviderDir) {
16954
18092
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
@@ -16962,7 +18100,7 @@ var ProviderLoader = class _ProviderLoader {
16962
18100
  * Canonical provider directory shape for a given root.
16963
18101
  */
16964
18102
  getProviderDir(root, category, type) {
16965
- return path14.join(root, category, type);
18103
+ return path17.join(root, category, type);
16966
18104
  }
16967
18105
  /**
16968
18106
  * Canonical user override directory for a provider.
@@ -16989,7 +18127,7 @@ var ProviderLoader = class _ProviderLoader {
16989
18127
  resolveProviderFile(type, ...segments) {
16990
18128
  const dir = this.findProviderDirInternal(type);
16991
18129
  if (!dir) return null;
16992
- return path14.join(dir, ...segments);
18130
+ return path17.join(dir, ...segments);
16993
18131
  }
16994
18132
  /**
16995
18133
  * Load all providers (3-tier priority)
@@ -17028,7 +18166,7 @@ var ProviderLoader = class _ProviderLoader {
17028
18166
  if (!fs7.existsSync(this.upstreamDir)) return false;
17029
18167
  try {
17030
18168
  return fs7.readdirSync(this.upstreamDir).some(
17031
- (d) => fs7.statSync(path14.join(this.upstreamDir, d)).isDirectory()
18169
+ (d) => fs7.statSync(path17.join(this.upstreamDir, d)).isDirectory()
17032
18170
  );
17033
18171
  } catch {
17034
18172
  return false;
@@ -17525,8 +18663,8 @@ var ProviderLoader = class _ProviderLoader {
17525
18663
  resolved._resolvedScriptDir = entry.scriptDir;
17526
18664
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
17527
18665
  if (providerDir) {
17528
- const fullDir = path14.join(providerDir, entry.scriptDir);
17529
- 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;
17530
18668
  }
17531
18669
  matched = true;
17532
18670
  }
@@ -17541,8 +18679,8 @@ var ProviderLoader = class _ProviderLoader {
17541
18679
  resolved._resolvedScriptDir = base.defaultScriptDir;
17542
18680
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
17543
18681
  if (providerDir) {
17544
- const fullDir = path14.join(providerDir, base.defaultScriptDir);
17545
- 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;
17546
18684
  }
17547
18685
  }
17548
18686
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -17559,8 +18697,8 @@ var ProviderLoader = class _ProviderLoader {
17559
18697
  resolved._resolvedScriptDir = dirOverride;
17560
18698
  resolved._resolvedScriptsSource = `versions:${range}`;
17561
18699
  if (providerDir) {
17562
- const fullDir = path14.join(providerDir, dirOverride);
17563
- 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;
17564
18702
  }
17565
18703
  }
17566
18704
  } else if (override.scripts) {
@@ -17576,8 +18714,8 @@ var ProviderLoader = class _ProviderLoader {
17576
18714
  resolved._resolvedScriptDir = base.defaultScriptDir;
17577
18715
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
17578
18716
  if (providerDir) {
17579
- const fullDir = path14.join(providerDir, base.defaultScriptDir);
17580
- 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;
17581
18719
  }
17582
18720
  }
17583
18721
  }
@@ -17609,14 +18747,14 @@ var ProviderLoader = class _ProviderLoader {
17609
18747
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
17610
18748
  return null;
17611
18749
  }
17612
- const dir = path14.join(providerDir, scriptDir);
18750
+ const dir = path17.join(providerDir, scriptDir);
17613
18751
  if (!fs7.existsSync(dir)) {
17614
18752
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
17615
18753
  return null;
17616
18754
  }
17617
18755
  const cached = this.scriptsCache.get(dir);
17618
18756
  if (cached) return cached;
17619
- const scriptsJs = path14.join(dir, "scripts.js");
18757
+ const scriptsJs = path17.join(dir, "scripts.js");
17620
18758
  if (fs7.existsSync(scriptsJs)) {
17621
18759
  try {
17622
18760
  delete __require.cache[__require.resolve(scriptsJs)];
@@ -17658,7 +18796,7 @@ var ProviderLoader = class _ProviderLoader {
17658
18796
  return;
17659
18797
  }
17660
18798
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
17661
- this.log(`File changed: ${path14.basename(filePath)}, reloading...`);
18799
+ this.log(`File changed: ${path17.basename(filePath)}, reloading...`);
17662
18800
  this.reload();
17663
18801
  }
17664
18802
  };
@@ -17713,7 +18851,7 @@ var ProviderLoader = class _ProviderLoader {
17713
18851
  }
17714
18852
  const https = __require("https");
17715
18853
  const { execSync: execSync7 } = __require("child_process");
17716
- const metaPath = path14.join(this.upstreamDir, _ProviderLoader.META_FILE);
18854
+ const metaPath = path17.join(this.upstreamDir, _ProviderLoader.META_FILE);
17717
18855
  let prevEtag = "";
17718
18856
  let prevTimestamp = 0;
17719
18857
  try {
@@ -17730,7 +18868,7 @@ var ProviderLoader = class _ProviderLoader {
17730
18868
  return { updated: false };
17731
18869
  }
17732
18870
  try {
17733
- const etag = await new Promise((resolve12, reject) => {
18871
+ const etag = await new Promise((resolve15, reject) => {
17734
18872
  const options = {
17735
18873
  method: "HEAD",
17736
18874
  hostname: "github.com",
@@ -17748,7 +18886,7 @@ var ProviderLoader = class _ProviderLoader {
17748
18886
  headers: { "User-Agent": "adhdev-launcher" },
17749
18887
  timeout: 1e4
17750
18888
  }, (res2) => {
17751
- resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
18889
+ resolve15(res2.headers.etag || res2.headers["last-modified"] || "");
17752
18890
  });
17753
18891
  req2.on("error", reject);
17754
18892
  req2.on("timeout", () => {
@@ -17757,7 +18895,7 @@ var ProviderLoader = class _ProviderLoader {
17757
18895
  });
17758
18896
  req2.end();
17759
18897
  } else {
17760
- resolve12(res.headers.etag || res.headers["last-modified"] || "");
18898
+ resolve15(res.headers.etag || res.headers["last-modified"] || "");
17761
18899
  }
17762
18900
  });
17763
18901
  req.on("error", reject);
@@ -17773,17 +18911,17 @@ var ProviderLoader = class _ProviderLoader {
17773
18911
  return { updated: false };
17774
18912
  }
17775
18913
  this.log("Downloading latest providers from GitHub...");
17776
- const tmpTar = path14.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
17777
- 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()}`);
17778
18916
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
17779
18917
  fs7.mkdirSync(tmpExtract, { recursive: true });
17780
18918
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
17781
18919
  const extracted = fs7.readdirSync(tmpExtract);
17782
18920
  const rootDir = extracted.find(
17783
- (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")
17784
18922
  );
17785
18923
  if (!rootDir) throw new Error("Unexpected tarball structure");
17786
- const sourceDir = path14.join(tmpExtract, rootDir);
18924
+ const sourceDir = path17.join(tmpExtract, rootDir);
17787
18925
  const backupDir = this.upstreamDir + ".bak";
17788
18926
  if (fs7.existsSync(this.upstreamDir)) {
17789
18927
  if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
@@ -17821,7 +18959,7 @@ var ProviderLoader = class _ProviderLoader {
17821
18959
  downloadFile(url, destPath) {
17822
18960
  const https = __require("https");
17823
18961
  const http3 = __require("http");
17824
- return new Promise((resolve12, reject) => {
18962
+ return new Promise((resolve15, reject) => {
17825
18963
  const doRequest = (reqUrl, redirectCount = 0) => {
17826
18964
  if (redirectCount > 5) {
17827
18965
  reject(new Error("Too many redirects"));
@@ -17841,7 +18979,7 @@ var ProviderLoader = class _ProviderLoader {
17841
18979
  res.pipe(ws);
17842
18980
  ws.on("finish", () => {
17843
18981
  ws.close();
17844
- resolve12();
18982
+ resolve15();
17845
18983
  });
17846
18984
  ws.on("error", reject);
17847
18985
  });
@@ -17858,8 +18996,8 @@ var ProviderLoader = class _ProviderLoader {
17858
18996
  copyDirRecursive(src, dest) {
17859
18997
  fs7.mkdirSync(dest, { recursive: true });
17860
18998
  for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
17861
- const srcPath = path14.join(src, entry.name);
17862
- const destPath = path14.join(dest, entry.name);
18999
+ const srcPath = path17.join(src, entry.name);
19000
+ const destPath = path17.join(dest, entry.name);
17863
19001
  if (entry.isDirectory()) {
17864
19002
  this.copyDirRecursive(srcPath, destPath);
17865
19003
  } else {
@@ -17870,7 +19008,7 @@ var ProviderLoader = class _ProviderLoader {
17870
19008
  /** .meta.json save */
17871
19009
  writeMeta(metaPath, etag, timestamp) {
17872
19010
  try {
17873
- fs7.mkdirSync(path14.dirname(metaPath), { recursive: true });
19011
+ fs7.mkdirSync(path17.dirname(metaPath), { recursive: true });
17874
19012
  fs7.writeFileSync(metaPath, JSON.stringify({
17875
19013
  etag,
17876
19014
  timestamp,
@@ -17887,7 +19025,7 @@ var ProviderLoader = class _ProviderLoader {
17887
19025
  const scan = (d) => {
17888
19026
  try {
17889
19027
  for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
17890
- if (entry.isDirectory()) scan(path14.join(d, entry.name));
19028
+ if (entry.isDirectory()) scan(path17.join(d, entry.name));
17891
19029
  else if (entry.name === "provider.json") count++;
17892
19030
  }
17893
19031
  } catch {
@@ -18115,17 +19253,17 @@ var ProviderLoader = class _ProviderLoader {
18115
19253
  for (const root of searchRoots) {
18116
19254
  if (!fs7.existsSync(root)) continue;
18117
19255
  const candidate = this.getProviderDir(root, cat, type);
18118
- if (fs7.existsSync(path14.join(candidate, "provider.json"))) return candidate;
18119
- const catDir = path14.join(root, cat);
19256
+ if (fs7.existsSync(path17.join(candidate, "provider.json"))) return candidate;
19257
+ const catDir = path17.join(root, cat);
18120
19258
  if (fs7.existsSync(catDir)) {
18121
19259
  try {
18122
19260
  for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
18123
19261
  if (!entry.isDirectory()) continue;
18124
- const jsonPath = path14.join(catDir, entry.name, "provider.json");
19262
+ const jsonPath = path17.join(catDir, entry.name, "provider.json");
18125
19263
  if (fs7.existsSync(jsonPath)) {
18126
19264
  try {
18127
19265
  const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
18128
- if (data.type === type) return path14.join(catDir, entry.name);
19266
+ if (data.type === type) return path17.join(catDir, entry.name);
18129
19267
  } catch {
18130
19268
  }
18131
19269
  }
@@ -18142,7 +19280,7 @@ var ProviderLoader = class _ProviderLoader {
18142
19280
  * (template substitution is NOT applied here — scripts.js handles that)
18143
19281
  */
18144
19282
  buildScriptWrappersFromDir(dir) {
18145
- const scriptsJs = path14.join(dir, "scripts.js");
19283
+ const scriptsJs = path17.join(dir, "scripts.js");
18146
19284
  if (fs7.existsSync(scriptsJs)) {
18147
19285
  try {
18148
19286
  delete __require.cache[__require.resolve(scriptsJs)];
@@ -18156,7 +19294,7 @@ var ProviderLoader = class _ProviderLoader {
18156
19294
  for (const file of fs7.readdirSync(dir)) {
18157
19295
  if (!file.endsWith(".js")) continue;
18158
19296
  const scriptName = toCamel(file.replace(".js", ""));
18159
- const filePath = path14.join(dir, file);
19297
+ const filePath = path17.join(dir, file);
18160
19298
  result[scriptName] = (...args) => {
18161
19299
  try {
18162
19300
  let content = fs7.readFileSync(filePath, "utf-8");
@@ -18216,7 +19354,7 @@ var ProviderLoader = class _ProviderLoader {
18216
19354
  }
18217
19355
  const hasJson = entries.some((e) => e.name === "provider.json");
18218
19356
  if (hasJson) {
18219
- const jsonPath = path14.join(d, "provider.json");
19357
+ const jsonPath = path17.join(d, "provider.json");
18220
19358
  try {
18221
19359
  const raw = fs7.readFileSync(jsonPath, "utf-8");
18222
19360
  const mod = JSON.parse(raw);
@@ -18237,7 +19375,7 @@ var ProviderLoader = class _ProviderLoader {
18237
19375
  this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
18238
19376
  } else {
18239
19377
  const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
18240
- const scriptsPath = path14.join(d, "scripts.js");
19378
+ const scriptsPath = path17.join(d, "scripts.js");
18241
19379
  if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
18242
19380
  try {
18243
19381
  delete __require.cache[__require.resolve(scriptsPath)];
@@ -18263,7 +19401,7 @@ var ProviderLoader = class _ProviderLoader {
18263
19401
  if (!entry.isDirectory()) continue;
18264
19402
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
18265
19403
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
18266
- scan(path14.join(d, entry.name));
19404
+ scan(path17.join(d, entry.name));
18267
19405
  }
18268
19406
  }
18269
19407
  };
@@ -18298,9 +19436,9 @@ var ProviderLoader = class _ProviderLoader {
18298
19436
  }
18299
19437
  }
18300
19438
  compareVersions(a, b) {
18301
- const normalize3 = (v) => v.split(/[-_+]/)[0].split(".").map((x) => parseInt(x, 10) || 0);
18302
- const pa = normalize3(a);
18303
- 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);
18304
19442
  for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
18305
19443
  const va = pa[i] || 0;
18306
19444
  const vb = pb[i] || 0;
@@ -18420,17 +19558,17 @@ async function findFreePort(ports) {
18420
19558
  throw new Error("No free port found");
18421
19559
  }
18422
19560
  function checkPortFree(port) {
18423
- return new Promise((resolve12) => {
19561
+ return new Promise((resolve15) => {
18424
19562
  const server = net.createServer();
18425
19563
  server.unref();
18426
- server.on("error", () => resolve12(false));
19564
+ server.on("error", () => resolve15(false));
18427
19565
  server.listen(port, "127.0.0.1", () => {
18428
- server.close(() => resolve12(true));
19566
+ server.close(() => resolve15(true));
18429
19567
  });
18430
19568
  });
18431
19569
  }
18432
19570
  async function isCdpActive(port) {
18433
- return new Promise((resolve12) => {
19571
+ return new Promise((resolve15) => {
18434
19572
  const req = __require("http").get(`http://127.0.0.1:${port}/json/version`, {
18435
19573
  timeout: 2e3
18436
19574
  }, (res) => {
@@ -18439,16 +19577,16 @@ async function isCdpActive(port) {
18439
19577
  res.on("end", () => {
18440
19578
  try {
18441
19579
  const info = JSON.parse(data);
18442
- resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
19580
+ resolve15(!!info["WebKit-Version"] || !!info["Browser"]);
18443
19581
  } catch {
18444
- resolve12(false);
19582
+ resolve15(false);
18445
19583
  }
18446
19584
  });
18447
19585
  });
18448
- req.on("error", () => resolve12(false));
19586
+ req.on("error", () => resolve15(false));
18449
19587
  req.on("timeout", () => {
18450
19588
  req.destroy();
18451
- resolve12(false);
19589
+ resolve15(false);
18452
19590
  });
18453
19591
  });
18454
19592
  }
@@ -18588,8 +19726,8 @@ function detectCurrentWorkspace(ideId) {
18588
19726
  const appNameMap = getMacAppIdentifiers();
18589
19727
  const appName = appNameMap[ideId];
18590
19728
  if (appName) {
18591
- const storagePath = path15.join(
18592
- process.env.APPDATA || path15.join(os15.homedir(), "AppData", "Roaming"),
19729
+ const storagePath = path18.join(
19730
+ process.env.APPDATA || path18.join(os15.homedir(), "AppData", "Roaming"),
18593
19731
  appName,
18594
19732
  "storage.json"
18595
19733
  );
@@ -18767,9 +19905,9 @@ init_logger();
18767
19905
 
18768
19906
  // src/logging/command-log.ts
18769
19907
  import * as fs8 from "fs";
18770
- import * as path16 from "path";
19908
+ import * as path19 from "path";
18771
19909
  import * as os16 from "os";
18772
- 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");
18773
19911
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
18774
19912
  var MAX_DAYS = 7;
18775
19913
  try {
@@ -18807,13 +19945,13 @@ function getDateStr2() {
18807
19945
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
18808
19946
  }
18809
19947
  var currentDate2 = getDateStr2();
18810
- var currentFile = path16.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19948
+ var currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
18811
19949
  var writeCount2 = 0;
18812
19950
  function checkRotation() {
18813
19951
  const today = getDateStr2();
18814
19952
  if (today !== currentDate2) {
18815
19953
  currentDate2 = today;
18816
- currentFile = path16.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19954
+ currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
18817
19955
  cleanOldFiles();
18818
19956
  }
18819
19957
  }
@@ -18827,7 +19965,7 @@ function cleanOldFiles() {
18827
19965
  const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
18828
19966
  if (dateMatch && dateMatch[1] < cutoffStr) {
18829
19967
  try {
18830
- fs8.unlinkSync(path16.join(LOG_DIR2, file));
19968
+ fs8.unlinkSync(path19.join(LOG_DIR2, file));
18831
19969
  } catch {
18832
19970
  }
18833
19971
  }
@@ -18837,8 +19975,8 @@ function cleanOldFiles() {
18837
19975
  }
18838
19976
  function checkSize() {
18839
19977
  try {
18840
- const stat = fs8.statSync(currentFile);
18841
- if (stat.size > MAX_FILE_SIZE) {
19978
+ const stat2 = fs8.statSync(currentFile);
19979
+ if (stat2.size > MAX_FILE_SIZE) {
18842
19980
  const backup = currentFile.replace(".jsonl", ".1.jsonl");
18843
19981
  try {
18844
19982
  fs8.unlinkSync(backup);
@@ -19124,12 +20262,18 @@ function buildStatusSnapshot(options) {
19124
20262
  const unreadSourceSessions = buildSessionEntries(
19125
20263
  options.allStates,
19126
20264
  options.cdpManagers,
19127
- { profile: "full" }
20265
+ {
20266
+ profile: "full",
20267
+ getGitSummaryForWorkspace: options.getGitSummaryForWorkspace
20268
+ }
19128
20269
  );
19129
20270
  const sessions = profile === "full" ? unreadSourceSessions : profile === "live" ? unreadSourceSessions.map(projectLiveSessionFromFull) : buildSessionEntries(
19130
20271
  options.allStates,
19131
20272
  options.cdpManagers,
19132
- { profile }
20273
+ {
20274
+ profile,
20275
+ getGitSummaryForWorkspace: options.getGitSummaryForWorkspace
20276
+ }
19133
20277
  );
19134
20278
  const sessionsById = new Map(sessions.map((session) => [session.id, session]));
19135
20279
  for (const sourceSession of unreadSourceSessions) {
@@ -19223,13 +20367,13 @@ import { execFileSync as execFileSync2 } from "child_process";
19223
20367
  import { spawn as spawn3 } from "child_process";
19224
20368
  import * as fs9 from "fs";
19225
20369
  import * as os18 from "os";
19226
- import * as path17 from "path";
20370
+ import * as path20 from "path";
19227
20371
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
19228
20372
  function getUpgradeLogPath() {
19229
20373
  const home = os18.homedir();
19230
- const dir = path17.join(home, ".adhdev");
20374
+ const dir = path20.join(home, ".adhdev");
19231
20375
  fs9.mkdirSync(dir, { recursive: true });
19232
- return path17.join(dir, "daemon-upgrade.log");
20376
+ return path20.join(dir, "daemon-upgrade.log");
19233
20377
  }
19234
20378
  function appendUpgradeLog(message) {
19235
20379
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -19240,14 +20384,14 @@ function appendUpgradeLog(message) {
19240
20384
  }
19241
20385
  }
19242
20386
  function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
19243
- const binDir = path17.dirname(nodeExecutable);
20387
+ const binDir = path20.dirname(nodeExecutable);
19244
20388
  if (platform10 === "win32") {
19245
- 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");
19246
20390
  if (fs9.existsSync(npmCliPath)) {
19247
20391
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
19248
20392
  }
19249
20393
  for (const candidate of ["npm.exe", "npm"]) {
19250
- const candidatePath = path17.join(binDir, candidate);
20394
+ const candidatePath = path20.join(binDir, candidate);
19251
20395
  if (fs9.existsSync(candidatePath)) {
19252
20396
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
19253
20397
  }
@@ -19255,7 +20399,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
19255
20399
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
19256
20400
  }
19257
20401
  for (const candidate of ["npm"]) {
19258
- const candidatePath = path17.join(binDir, candidate);
20402
+ const candidatePath = path20.join(binDir, candidate);
19259
20403
  if (fs9.existsSync(candidatePath)) {
19260
20404
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
19261
20405
  }
@@ -19272,13 +20416,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
19272
20416
  let currentDir = resolvedPath;
19273
20417
  try {
19274
20418
  if (fs9.statSync(resolvedPath).isFile()) {
19275
- currentDir = path17.dirname(resolvedPath);
20419
+ currentDir = path20.dirname(resolvedPath);
19276
20420
  }
19277
20421
  } catch {
19278
- currentDir = path17.dirname(resolvedPath);
20422
+ currentDir = path20.dirname(resolvedPath);
19279
20423
  }
19280
20424
  while (true) {
19281
- const packageJsonPath = path17.join(currentDir, "package.json");
20425
+ const packageJsonPath = path20.join(currentDir, "package.json");
19282
20426
  try {
19283
20427
  if (fs9.existsSync(packageJsonPath)) {
19284
20428
  const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
@@ -19289,7 +20433,7 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
19289
20433
  }
19290
20434
  } catch {
19291
20435
  }
19292
- const parentDir = path17.dirname(currentDir);
20436
+ const parentDir = path20.dirname(currentDir);
19293
20437
  if (parentDir === currentDir) {
19294
20438
  return null;
19295
20439
  }
@@ -19297,13 +20441,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
19297
20441
  }
19298
20442
  }
19299
20443
  function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
19300
- const nodeModulesDir = packageName.startsWith("@") ? path17.dirname(path17.dirname(packageRoot)) : path17.dirname(packageRoot);
19301
- 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") {
19302
20446
  return null;
19303
20447
  }
19304
- const maybeLibDir = path17.dirname(nodeModulesDir);
19305
- if (path17.basename(maybeLibDir) === "lib") {
19306
- return path17.dirname(maybeLibDir);
20448
+ const maybeLibDir = path20.dirname(nodeModulesDir);
20449
+ if (path20.basename(maybeLibDir) === "lib") {
20450
+ return path20.dirname(maybeLibDir);
19307
20451
  }
19308
20452
  return maybeLibDir;
19309
20453
  }
@@ -19411,14 +20555,14 @@ async function waitForPidExit(pid, timeoutMs) {
19411
20555
  while (Date.now() - start < timeoutMs) {
19412
20556
  try {
19413
20557
  process.kill(pid, 0);
19414
- await new Promise((resolve12) => setTimeout(resolve12, 250));
20558
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
19415
20559
  } catch {
19416
20560
  return;
19417
20561
  }
19418
20562
  }
19419
20563
  }
19420
20564
  function stopSessionHostProcesses(appName) {
19421
- const pidFile = path17.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
20565
+ const pidFile = path20.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
19422
20566
  try {
19423
20567
  if (fs9.existsSync(pidFile)) {
19424
20568
  const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
@@ -19435,7 +20579,7 @@ function stopSessionHostProcesses(appName) {
19435
20579
  }
19436
20580
  }
19437
20581
  function removeDaemonPidFile() {
19438
- const pidFile = path17.join(os18.homedir(), ".adhdev", "daemon.pid");
20582
+ const pidFile = path20.join(os18.homedir(), ".adhdev", "daemon.pid");
19439
20583
  try {
19440
20584
  fs9.unlinkSync(pidFile);
19441
20585
  } catch {
@@ -19446,7 +20590,7 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
19446
20590
  const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
19447
20591
  if (!npmRoot) return;
19448
20592
  const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
19449
- const binDir = process.platform === "win32" ? npmPrefix : path17.join(npmPrefix, "bin");
20593
+ const binDir = process.platform === "win32" ? npmPrefix : path20.join(npmPrefix, "bin");
19450
20594
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
19451
20595
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
19452
20596
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -19454,25 +20598,25 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
19454
20598
  }
19455
20599
  if (pkgName.startsWith("@")) {
19456
20600
  const [scope, name] = pkgName.split("/");
19457
- const scopeDir = path17.join(npmRoot, scope);
20601
+ const scopeDir = path20.join(npmRoot, scope);
19458
20602
  if (!fs9.existsSync(scopeDir)) return;
19459
20603
  for (const entry of fs9.readdirSync(scopeDir)) {
19460
20604
  if (!entry.startsWith(`.${name}-`)) continue;
19461
- fs9.rmSync(path17.join(scopeDir, entry), { recursive: true, force: true });
19462
- 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)}`);
19463
20607
  }
19464
20608
  } else {
19465
20609
  for (const entry of fs9.readdirSync(npmRoot)) {
19466
20610
  if (!entry.startsWith(`.${pkgName}-`)) continue;
19467
- fs9.rmSync(path17.join(npmRoot, entry), { recursive: true, force: true });
19468
- 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)}`);
19469
20613
  }
19470
20614
  }
19471
20615
  if (fs9.existsSync(binDir)) {
19472
20616
  for (const entry of fs9.readdirSync(binDir)) {
19473
20617
  if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
19474
- fs9.rmSync(path17.join(binDir, entry), { recursive: true, force: true });
19475
- 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)}`);
19476
20620
  }
19477
20621
  }
19478
20622
  }
@@ -19522,7 +20666,7 @@ async function runDaemonUpgradeHelper(payload) {
19522
20666
  appendUpgradeLog(installOutput.trim());
19523
20667
  }
19524
20668
  if (process.platform === "win32") {
19525
- await new Promise((resolve12) => setTimeout(resolve12, 500));
20669
+ await new Promise((resolve15) => setTimeout(resolve15, 500));
19526
20670
  cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
19527
20671
  appendUpgradeLog("Post-install staging cleanup complete");
19528
20672
  }
@@ -20916,7 +22060,7 @@ var ProviderStreamAdapter = class {
20916
22060
  const beforeCount = this.messageCount(before);
20917
22061
  const beforeSignature = this.lastMessageSignature(before);
20918
22062
  for (let attempt = 0; attempt < 12; attempt += 1) {
20919
- await new Promise((resolve12) => setTimeout(resolve12, 250));
22063
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
20920
22064
  let state;
20921
22065
  try {
20922
22066
  state = await this.readChat(evaluate);
@@ -20938,7 +22082,7 @@ var ProviderStreamAdapter = class {
20938
22082
  if (this.messageCount(first) > 0 || this.lastMessageSignature(first)) {
20939
22083
  return first;
20940
22084
  }
20941
- await new Promise((resolve12) => setTimeout(resolve12, 150));
22085
+ await new Promise((resolve15) => setTimeout(resolve15, 150));
20942
22086
  const second = await this.readChat(evaluate);
20943
22087
  return this.messageCount(second) >= this.messageCount(first) ? second : first;
20944
22088
  }
@@ -21089,7 +22233,7 @@ var ProviderStreamAdapter = class {
21089
22233
  if (typeof data.error === "string" && data.error.trim()) return false;
21090
22234
  }
21091
22235
  for (let attempt = 0; attempt < 6; attempt += 1) {
21092
- await new Promise((resolve12) => setTimeout(resolve12, 250));
22236
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
21093
22237
  const state = await this.readChat(evaluate);
21094
22238
  const title = this.getStateTitle(state);
21095
22239
  if (this.titlesMatch(title, sessionId)) return true;
@@ -21950,11 +23094,11 @@ init_chat_message_normalization();
21950
23094
 
21951
23095
  // src/providers/version-archive.ts
21952
23096
  import * as fs11 from "fs";
21953
- import * as path18 from "path";
23097
+ import * as path21 from "path";
21954
23098
  import * as os19 from "os";
21955
23099
  import { execSync as execSync5 } from "child_process";
21956
23100
  import { platform as platform8 } from "os";
21957
- var ARCHIVE_PATH = path18.join(os19.homedir(), ".adhdev", "version-history.json");
23101
+ var ARCHIVE_PATH = path21.join(os19.homedir(), ".adhdev", "version-history.json");
21958
23102
  var MAX_ENTRIES_PER_PROVIDER = 20;
21959
23103
  var VersionArchive = class {
21960
23104
  history = {};
@@ -22001,7 +23145,7 @@ var VersionArchive = class {
22001
23145
  }
22002
23146
  save() {
22003
23147
  try {
22004
- fs11.mkdirSync(path18.dirname(ARCHIVE_PATH), { recursive: true });
23148
+ fs11.mkdirSync(path21.dirname(ARCHIVE_PATH), { recursive: true });
22005
23149
  fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
22006
23150
  } catch {
22007
23151
  }
@@ -22058,7 +23202,7 @@ function checkPathExists2(paths) {
22058
23202
  for (const p of paths) {
22059
23203
  if (p.includes("*")) {
22060
23204
  const home = os19.homedir();
22061
- const resolved = p.replace(/\*/g, home.split(path18.sep).pop() || "");
23205
+ const resolved = p.replace(/\*/g, home.split(path21.sep).pop() || "");
22062
23206
  if (fs11.existsSync(resolved)) return resolved;
22063
23207
  } else {
22064
23208
  if (fs11.existsSync(p)) return p;
@@ -22068,7 +23212,7 @@ function checkPathExists2(paths) {
22068
23212
  }
22069
23213
  function getMacAppVersion(appPath) {
22070
23214
  if (platform8() !== "darwin" || !appPath.endsWith(".app")) return null;
22071
- const plistPath = path18.join(appPath, "Contents", "Info.plist");
23215
+ const plistPath = path21.join(appPath, "Contents", "Info.plist");
22072
23216
  if (!fs11.existsSync(plistPath)) return null;
22073
23217
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
22074
23218
  return raw || null;
@@ -22094,7 +23238,7 @@ async function detectAllVersions(loader, archive) {
22094
23238
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
22095
23239
  let resolvedBin = cliBin;
22096
23240
  if (!resolvedBin && appPath && currentOs === "darwin") {
22097
- const bundled = path18.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
23241
+ const bundled = path21.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
22098
23242
  if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
22099
23243
  }
22100
23244
  info.installed = !!(appPath || resolvedBin);
@@ -22135,7 +23279,7 @@ async function detectAllVersions(loader, archive) {
22135
23279
  // src/daemon/dev-server.ts
22136
23280
  import * as http2 from "http";
22137
23281
  import * as fs15 from "fs";
22138
- import * as path22 from "path";
23282
+ import * as path25 from "path";
22139
23283
  init_config();
22140
23284
 
22141
23285
  // src/daemon/scaffold-template.ts
@@ -22487,7 +23631,7 @@ init_logger();
22487
23631
  // src/daemon/dev-cdp-handlers.ts
22488
23632
  init_logger();
22489
23633
  import * as fs12 from "fs";
22490
- import * as path19 from "path";
23634
+ import * as path22 from "path";
22491
23635
  async function handleCdpEvaluate(ctx, req, res) {
22492
23636
  const body = await ctx.readBody(req);
22493
23637
  const { expression, timeout, ideType } = body;
@@ -22665,17 +23809,17 @@ async function handleScriptHints(ctx, type, _req, res) {
22665
23809
  return;
22666
23810
  }
22667
23811
  let scriptsPath = "";
22668
- const directScripts = path19.join(dir, "scripts.js");
23812
+ const directScripts = path22.join(dir, "scripts.js");
22669
23813
  if (fs12.existsSync(directScripts)) {
22670
23814
  scriptsPath = directScripts;
22671
23815
  } else {
22672
- const scriptsDir = path19.join(dir, "scripts");
23816
+ const scriptsDir = path22.join(dir, "scripts");
22673
23817
  if (fs12.existsSync(scriptsDir)) {
22674
23818
  const versions = fs12.readdirSync(scriptsDir).filter((d) => {
22675
- return fs12.statSync(path19.join(scriptsDir, d)).isDirectory();
23819
+ return fs12.statSync(path22.join(scriptsDir, d)).isDirectory();
22676
23820
  }).sort().reverse();
22677
23821
  for (const ver of versions) {
22678
- const p = path19.join(scriptsDir, ver, "scripts.js");
23822
+ const p = path22.join(scriptsDir, ver, "scripts.js");
22679
23823
  if (fs12.existsSync(p)) {
22680
23824
  scriptsPath = p;
22681
23825
  break;
@@ -23504,7 +24648,7 @@ async function handleDomContext(ctx, type, req, res) {
23504
24648
 
23505
24649
  // src/daemon/dev-cli-debug.ts
23506
24650
  import * as fs13 from "fs";
23507
- import * as path20 from "path";
24651
+ import * as path23 from "path";
23508
24652
  function slugifyFixtureName(value) {
23509
24653
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
23510
24654
  return normalized || `fixture-${Date.now()}`;
@@ -23514,11 +24658,11 @@ function getCliFixtureDir(ctx, type) {
23514
24658
  if (!providerDir) {
23515
24659
  throw new Error(`Provider directory not found for '${type}'`);
23516
24660
  }
23517
- return path20.join(providerDir, "fixtures");
24661
+ return path23.join(providerDir, "fixtures");
23518
24662
  }
23519
24663
  function readCliFixture(ctx, type, name) {
23520
24664
  const fixtureDir = getCliFixtureDir(ctx, type);
23521
- const filePath = path20.join(fixtureDir, `${name}.json`);
24665
+ const filePath = path23.join(fixtureDir, `${name}.json`);
23522
24666
  if (!fs13.existsSync(filePath)) {
23523
24667
  throw new Error(`Fixture not found: ${filePath}`);
23524
24668
  }
@@ -23687,7 +24831,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
23687
24831
  return { target, instance, adapter };
23688
24832
  }
23689
24833
  function sleep(ms) {
23690
- return new Promise((resolve12) => setTimeout(resolve12, ms));
24834
+ return new Promise((resolve15) => setTimeout(resolve15, ms));
23691
24835
  }
23692
24836
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
23693
24837
  const startedAt = Date.now();
@@ -23985,7 +25129,7 @@ async function runCliAutoImplVerification(ctx, type, verification) {
23985
25129
  return {
23986
25130
  mode: "fixture_replay_suite",
23987
25131
  pass: results.every((item) => item.pass),
23988
- failures: results.flatMap((item) => item.failures.map((failure) => `${item.fixtureName}: ${failure}`)),
25132
+ failures: results.flatMap((item) => item.failures.map((failure2) => `${item.fixtureName}: ${failure2}`)),
23989
25133
  result: firstFailure.result,
23990
25134
  assertions: firstFailure.assertions,
23991
25135
  fixture: firstFailure.fixture,
@@ -24285,7 +25429,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
24285
25429
  },
24286
25430
  notes: typeof body?.notes === "string" ? body.notes : void 0
24287
25431
  };
24288
- const filePath = path20.join(fixtureDir, `${name}.json`);
25432
+ const filePath = path23.join(fixtureDir, `${name}.json`);
24289
25433
  fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
24290
25434
  ctx.json(res, 200, {
24291
25435
  saved: true,
@@ -24309,7 +25453,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
24309
25453
  return;
24310
25454
  }
24311
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) => {
24312
- const fullPath = path20.join(fixtureDir, file);
25456
+ const fullPath = path23.join(fixtureDir, file);
24313
25457
  try {
24314
25458
  const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
24315
25459
  return {
@@ -24445,7 +25589,7 @@ async function handleCliRaw(ctx, req, res) {
24445
25589
 
24446
25590
  // src/daemon/dev-auto-implement.ts
24447
25591
  import * as fs14 from "fs";
24448
- import * as path21 from "path";
25592
+ import * as path24 from "path";
24449
25593
  import * as os20 from "os";
24450
25594
  function getAutoImplPid(ctx) {
24451
25595
  const pid = ctx.autoImplProcess?.pid;
@@ -24495,22 +25639,22 @@ function getLatestScriptVersionDir(scriptsDir) {
24495
25639
  if (!fs14.existsSync(scriptsDir)) return null;
24496
25640
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
24497
25641
  try {
24498
- return fs14.statSync(path21.join(scriptsDir, d)).isDirectory();
25642
+ return fs14.statSync(path24.join(scriptsDir, d)).isDirectory();
24499
25643
  } catch {
24500
25644
  return false;
24501
25645
  }
24502
25646
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
24503
25647
  if (versions.length === 0) return null;
24504
- return path21.join(scriptsDir, versions[0]);
25648
+ return path24.join(scriptsDir, versions[0]);
24505
25649
  }
24506
25650
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
24507
- const canonicalUserDir = path21.resolve(ctx.providerLoader.getUserProviderDir(category, type));
24508
- const desiredDir = requestedDir ? path21.resolve(requestedDir) : canonicalUserDir;
24509
- const upstreamRoot = path21.resolve(ctx.providerLoader.getUpstreamDir());
24510
- 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}`)) {
24511
25655
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
24512
25656
  }
24513
- if (path21.basename(desiredDir) !== type) {
25657
+ if (path24.basename(desiredDir) !== type) {
24514
25658
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
24515
25659
  }
24516
25660
  const sourceDir = ctx.findProviderDir(type);
@@ -24518,11 +25662,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
24518
25662
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
24519
25663
  }
24520
25664
  if (!fs14.existsSync(desiredDir)) {
24521
- fs14.mkdirSync(path21.dirname(desiredDir), { recursive: true });
25665
+ fs14.mkdirSync(path24.dirname(desiredDir), { recursive: true });
24522
25666
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
24523
25667
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
24524
25668
  }
24525
- const providerJson = path21.join(desiredDir, "provider.json");
25669
+ const providerJson = path24.join(desiredDir, "provider.json");
24526
25670
  if (!fs14.existsSync(providerJson)) {
24527
25671
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
24528
25672
  }
@@ -24533,13 +25677,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
24533
25677
  const refDir = ctx.findProviderDir(referenceType);
24534
25678
  if (!refDir || !fs14.existsSync(refDir)) return {};
24535
25679
  const referenceScripts = {};
24536
- const scriptsDir = path21.join(refDir, "scripts");
25680
+ const scriptsDir = path24.join(refDir, "scripts");
24537
25681
  const latestDir = getLatestScriptVersionDir(scriptsDir);
24538
25682
  if (!latestDir) return referenceScripts;
24539
25683
  for (const file of fs14.readdirSync(latestDir)) {
24540
25684
  if (!file.endsWith(".js")) continue;
24541
25685
  try {
24542
- referenceScripts[file] = fs14.readFileSync(path21.join(latestDir, file), "utf-8");
25686
+ referenceScripts[file] = fs14.readFileSync(path24.join(latestDir, file), "utf-8");
24543
25687
  } catch {
24544
25688
  }
24545
25689
  }
@@ -24647,9 +25791,9 @@ async function handleAutoImplement(ctx, type, req, res) {
24647
25791
  });
24648
25792
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
24649
25793
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
24650
- const tmpDir = path21.join(os20.tmpdir(), "adhdev-autoimpl");
25794
+ const tmpDir = path24.join(os20.tmpdir(), "adhdev-autoimpl");
24651
25795
  if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
24652
- const promptFile = path21.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
25796
+ const promptFile = path24.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
24653
25797
  fs14.writeFileSync(promptFile, prompt, "utf-8");
24654
25798
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
24655
25799
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -25081,7 +26225,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
25081
26225
  setMode: "set_mode.js"
25082
26226
  };
25083
26227
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
25084
- const scriptsDir = path21.join(providerDir, "scripts");
26228
+ const scriptsDir = path24.join(providerDir, "scripts");
25085
26229
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
25086
26230
  if (latestScriptsDir) {
25087
26231
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -25092,7 +26236,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
25092
26236
  for (const file of fs14.readdirSync(latestScriptsDir)) {
25093
26237
  if (file.endsWith(".js") && targetFileNames.has(file)) {
25094
26238
  try {
25095
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
26239
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
25096
26240
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
25097
26241
  lines.push("```javascript");
25098
26242
  lines.push(content);
@@ -25109,7 +26253,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
25109
26253
  lines.push("");
25110
26254
  for (const file of refFiles) {
25111
26255
  try {
25112
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
26256
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
25113
26257
  lines.push(`### \`${file}\` \u{1F512}`);
25114
26258
  lines.push("```javascript");
25115
26259
  lines.push(content);
@@ -25150,10 +26294,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
25150
26294
  lines.push("");
25151
26295
  }
25152
26296
  }
25153
- const docsDir = path21.join(providerDir, "../../docs");
26297
+ const docsDir = path24.join(providerDir, "../../docs");
25154
26298
  const loadGuide = (name) => {
25155
26299
  try {
25156
- const p = path21.join(docsDir, name);
26300
+ const p = path24.join(docsDir, name);
25157
26301
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
25158
26302
  } catch {
25159
26303
  }
@@ -25390,7 +26534,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
25390
26534
  parseApproval: "parse_approval.js"
25391
26535
  };
25392
26536
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
25393
- const scriptsDir = path21.join(providerDir, "scripts");
26537
+ const scriptsDir = path24.join(providerDir, "scripts");
25394
26538
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
25395
26539
  if (latestScriptsDir) {
25396
26540
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -25402,7 +26546,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
25402
26546
  if (!file.endsWith(".js")) continue;
25403
26547
  if (!targetFileNames.has(file)) continue;
25404
26548
  try {
25405
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
26549
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
25406
26550
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
25407
26551
  lines.push("```javascript");
25408
26552
  lines.push(content);
@@ -25418,7 +26562,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
25418
26562
  lines.push("");
25419
26563
  for (const file of refFiles) {
25420
26564
  try {
25421
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
26565
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
25422
26566
  lines.push(`### \`${file}\` \u{1F512}`);
25423
26567
  lines.push("```javascript");
25424
26568
  lines.push(content);
@@ -25451,10 +26595,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
25451
26595
  lines.push("");
25452
26596
  }
25453
26597
  }
25454
- const docsDir = path21.join(providerDir, "../../docs");
26598
+ const docsDir = path24.join(providerDir, "../../docs");
25455
26599
  const loadGuide = (name) => {
25456
26600
  try {
25457
- const p = path21.join(docsDir, name);
26601
+ const p = path24.join(docsDir, name);
25458
26602
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
25459
26603
  } catch {
25460
26604
  }
@@ -25901,8 +27045,8 @@ var DevServer = class _DevServer {
25901
27045
  }
25902
27046
  getEndpointList() {
25903
27047
  return this.routes.map((r) => {
25904
- const path23 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
25905
- 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}`;
25906
27050
  });
25907
27051
  }
25908
27052
  async start(port = DEV_SERVER_PORT) {
@@ -25933,15 +27077,15 @@ var DevServer = class _DevServer {
25933
27077
  this.json(res, 500, { error: e.message });
25934
27078
  }
25935
27079
  });
25936
- return new Promise((resolve12, reject) => {
27080
+ return new Promise((resolve15, reject) => {
25937
27081
  this.server.listen(port, "127.0.0.1", () => {
25938
27082
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
25939
- resolve12();
27083
+ resolve15();
25940
27084
  });
25941
27085
  this.server.on("error", (e) => {
25942
27086
  if (e.code === "EADDRINUSE") {
25943
27087
  this.log(`Port ${port} in use, skipping dev server`);
25944
- resolve12();
27088
+ resolve15();
25945
27089
  } else {
25946
27090
  reject(e);
25947
27091
  }
@@ -26023,20 +27167,20 @@ var DevServer = class _DevServer {
26023
27167
  child.stderr?.on("data", (d) => {
26024
27168
  stderr += d.toString().slice(0, 2e3);
26025
27169
  });
26026
- await new Promise((resolve12) => {
27170
+ await new Promise((resolve15) => {
26027
27171
  const timer = setTimeout(() => {
26028
27172
  child.kill();
26029
- resolve12();
27173
+ resolve15();
26030
27174
  }, 3e3);
26031
27175
  child.on("exit", () => {
26032
27176
  clearTimeout(timer);
26033
- resolve12();
27177
+ resolve15();
26034
27178
  });
26035
27179
  child.stdout?.once("data", () => {
26036
27180
  setTimeout(() => {
26037
27181
  child.kill();
26038
27182
  clearTimeout(timer);
26039
- resolve12();
27183
+ resolve15();
26040
27184
  }, 500);
26041
27185
  });
26042
27186
  });
@@ -26190,12 +27334,12 @@ var DevServer = class _DevServer {
26190
27334
  // ─── DevConsole SPA ───
26191
27335
  getConsoleDistDir() {
26192
27336
  const candidates = [
26193
- path22.resolve(__dirname, "../../web-devconsole/dist"),
26194
- path22.resolve(__dirname, "../../../web-devconsole/dist"),
26195
- 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")
26196
27340
  ];
26197
27341
  for (const dir of candidates) {
26198
- if (fs15.existsSync(path22.join(dir, "index.html"))) return dir;
27342
+ if (fs15.existsSync(path25.join(dir, "index.html"))) return dir;
26199
27343
  }
26200
27344
  return null;
26201
27345
  }
@@ -26205,7 +27349,7 @@ var DevServer = class _DevServer {
26205
27349
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
26206
27350
  return;
26207
27351
  }
26208
- const htmlPath = path22.join(distDir, "index.html");
27352
+ const htmlPath = path25.join(distDir, "index.html");
26209
27353
  try {
26210
27354
  const html = fs15.readFileSync(htmlPath, "utf-8");
26211
27355
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -26230,15 +27374,15 @@ var DevServer = class _DevServer {
26230
27374
  this.json(res, 404, { error: "Not found" });
26231
27375
  return;
26232
27376
  }
26233
- const safePath = path22.normalize(pathname).replace(/^\.\.\//, "");
26234
- const filePath = path22.join(distDir, safePath);
27377
+ const safePath = path25.normalize(pathname).replace(/^\.\.\//, "");
27378
+ const filePath = path25.join(distDir, safePath);
26235
27379
  if (!filePath.startsWith(distDir)) {
26236
27380
  this.json(res, 403, { error: "Forbidden" });
26237
27381
  return;
26238
27382
  }
26239
27383
  try {
26240
27384
  const content = fs15.readFileSync(filePath);
26241
- const ext = path22.extname(filePath);
27385
+ const ext = path25.extname(filePath);
26242
27386
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
26243
27387
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
26244
27388
  res.end(content);
@@ -26351,10 +27495,10 @@ var DevServer = class _DevServer {
26351
27495
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
26352
27496
  if (entry.isDirectory()) {
26353
27497
  files.push({ path: rel, size: 0, type: "dir" });
26354
- scan(path22.join(d, entry.name), rel);
27498
+ scan(path25.join(d, entry.name), rel);
26355
27499
  } else {
26356
- const stat = fs15.statSync(path22.join(d, entry.name));
26357
- 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" });
26358
27502
  }
26359
27503
  }
26360
27504
  } catch {
@@ -26376,7 +27520,7 @@ var DevServer = class _DevServer {
26376
27520
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
26377
27521
  return;
26378
27522
  }
26379
- const fullPath = path22.resolve(dir, path22.normalize(filePath));
27523
+ const fullPath = path25.resolve(dir, path25.normalize(filePath));
26380
27524
  if (!fullPath.startsWith(dir)) {
26381
27525
  this.json(res, 403, { error: "Forbidden" });
26382
27526
  return;
@@ -26401,14 +27545,14 @@ var DevServer = class _DevServer {
26401
27545
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
26402
27546
  return;
26403
27547
  }
26404
- const fullPath = path22.resolve(dir, path22.normalize(filePath));
27548
+ const fullPath = path25.resolve(dir, path25.normalize(filePath));
26405
27549
  if (!fullPath.startsWith(dir)) {
26406
27550
  this.json(res, 403, { error: "Forbidden" });
26407
27551
  return;
26408
27552
  }
26409
27553
  try {
26410
27554
  if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
26411
- fs15.mkdirSync(path22.dirname(fullPath), { recursive: true });
27555
+ fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
26412
27556
  fs15.writeFileSync(fullPath, content, "utf-8");
26413
27557
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
26414
27558
  this.providerLoader.reload();
@@ -26425,7 +27569,7 @@ var DevServer = class _DevServer {
26425
27569
  return;
26426
27570
  }
26427
27571
  for (const name of ["scripts.js", "provider.json"]) {
26428
- const p = path22.join(dir, name);
27572
+ const p = path25.join(dir, name);
26429
27573
  if (fs15.existsSync(p)) {
26430
27574
  const source = fs15.readFileSync(p, "utf-8");
26431
27575
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -26446,8 +27590,8 @@ var DevServer = class _DevServer {
26446
27590
  this.json(res, 404, { error: `Provider not found: ${type}` });
26447
27591
  return;
26448
27592
  }
26449
- const target = fs15.existsSync(path22.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
26450
- 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);
26451
27595
  try {
26452
27596
  if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
26453
27597
  fs15.writeFileSync(targetPath, source, "utf-8");
@@ -26539,14 +27683,14 @@ var DevServer = class _DevServer {
26539
27683
  child.stderr?.on("data", (d) => {
26540
27684
  stderr += d.toString();
26541
27685
  });
26542
- await new Promise((resolve12) => {
27686
+ await new Promise((resolve15) => {
26543
27687
  const timer = setTimeout(() => {
26544
27688
  child.kill();
26545
- resolve12();
27689
+ resolve15();
26546
27690
  }, timeout);
26547
27691
  child.on("exit", () => {
26548
27692
  clearTimeout(timer);
26549
- resolve12();
27693
+ resolve15();
26550
27694
  });
26551
27695
  });
26552
27696
  const elapsed = Date.now() - start;
@@ -26594,7 +27738,7 @@ var DevServer = class _DevServer {
26594
27738
  }
26595
27739
  let targetDir;
26596
27740
  targetDir = this.providerLoader.getUserProviderDir(category, type);
26597
- const jsonPath = path22.join(targetDir, "provider.json");
27741
+ const jsonPath = path25.join(targetDir, "provider.json");
26598
27742
  if (fs15.existsSync(jsonPath)) {
26599
27743
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
26600
27744
  return;
@@ -26606,8 +27750,8 @@ var DevServer = class _DevServer {
26606
27750
  const createdFiles = ["provider.json"];
26607
27751
  if (result.files) {
26608
27752
  for (const [relPath, content] of Object.entries(result.files)) {
26609
- const fullPath = path22.join(targetDir, relPath);
26610
- fs15.mkdirSync(path22.dirname(fullPath), { recursive: true });
27753
+ const fullPath = path25.join(targetDir, relPath);
27754
+ fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
26611
27755
  fs15.writeFileSync(fullPath, content, "utf-8");
26612
27756
  createdFiles.push(relPath);
26613
27757
  }
@@ -26660,22 +27804,22 @@ var DevServer = class _DevServer {
26660
27804
  if (!fs15.existsSync(scriptsDir)) return null;
26661
27805
  const versions = fs15.readdirSync(scriptsDir).filter((d) => {
26662
27806
  try {
26663
- return fs15.statSync(path22.join(scriptsDir, d)).isDirectory();
27807
+ return fs15.statSync(path25.join(scriptsDir, d)).isDirectory();
26664
27808
  } catch {
26665
27809
  return false;
26666
27810
  }
26667
27811
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
26668
27812
  if (versions.length === 0) return null;
26669
- return path22.join(scriptsDir, versions[0]);
27813
+ return path25.join(scriptsDir, versions[0]);
26670
27814
  }
26671
27815
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
26672
- const canonicalUserDir = path22.resolve(this.providerLoader.getUserProviderDir(category, type));
26673
- const desiredDir = requestedDir ? path22.resolve(requestedDir) : canonicalUserDir;
26674
- const upstreamRoot = path22.resolve(this.providerLoader.getUpstreamDir());
26675
- 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}`)) {
26676
27820
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
26677
27821
  }
26678
- if (path22.basename(desiredDir) !== type) {
27822
+ if (path25.basename(desiredDir) !== type) {
26679
27823
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
26680
27824
  }
26681
27825
  const sourceDir = this.findProviderDir(type);
@@ -26683,11 +27827,11 @@ var DevServer = class _DevServer {
26683
27827
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
26684
27828
  }
26685
27829
  if (!fs15.existsSync(desiredDir)) {
26686
- fs15.mkdirSync(path22.dirname(desiredDir), { recursive: true });
27830
+ fs15.mkdirSync(path25.dirname(desiredDir), { recursive: true });
26687
27831
  fs15.cpSync(sourceDir, desiredDir, { recursive: true });
26688
27832
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
26689
27833
  }
26690
- const providerJson = path22.join(desiredDir, "provider.json");
27834
+ const providerJson = path25.join(desiredDir, "provider.json");
26691
27835
  if (!fs15.existsSync(providerJson)) {
26692
27836
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
26693
27837
  }
@@ -26723,7 +27867,7 @@ var DevServer = class _DevServer {
26723
27867
  setMode: "set_mode.js"
26724
27868
  };
26725
27869
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26726
- const scriptsDir = path22.join(providerDir, "scripts");
27870
+ const scriptsDir = path25.join(providerDir, "scripts");
26727
27871
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
26728
27872
  if (latestScriptsDir) {
26729
27873
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26734,7 +27878,7 @@ var DevServer = class _DevServer {
26734
27878
  for (const file of fs15.readdirSync(latestScriptsDir)) {
26735
27879
  if (file.endsWith(".js") && targetFileNames.has(file)) {
26736
27880
  try {
26737
- const content = fs15.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
27881
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26738
27882
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26739
27883
  lines.push("```javascript");
26740
27884
  lines.push(content);
@@ -26751,7 +27895,7 @@ var DevServer = class _DevServer {
26751
27895
  lines.push("");
26752
27896
  for (const file of refFiles) {
26753
27897
  try {
26754
- const content = fs15.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
27898
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26755
27899
  lines.push(`### \`${file}\` \u{1F512}`);
26756
27900
  lines.push("```javascript");
26757
27901
  lines.push(content);
@@ -26792,10 +27936,10 @@ var DevServer = class _DevServer {
26792
27936
  lines.push("");
26793
27937
  }
26794
27938
  }
26795
- const docsDir = path22.join(providerDir, "../../docs");
27939
+ const docsDir = path25.join(providerDir, "../../docs");
26796
27940
  const loadGuide = (name) => {
26797
27941
  try {
26798
- const p = path22.join(docsDir, name);
27942
+ const p = path25.join(docsDir, name);
26799
27943
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
26800
27944
  } catch {
26801
27945
  }
@@ -26969,7 +28113,7 @@ var DevServer = class _DevServer {
26969
28113
  parseApproval: "parse_approval.js"
26970
28114
  };
26971
28115
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26972
- const scriptsDir = path22.join(providerDir, "scripts");
28116
+ const scriptsDir = path25.join(providerDir, "scripts");
26973
28117
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
26974
28118
  if (latestScriptsDir) {
26975
28119
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26981,7 +28125,7 @@ var DevServer = class _DevServer {
26981
28125
  if (!file.endsWith(".js")) continue;
26982
28126
  if (!targetFileNames.has(file)) continue;
26983
28127
  try {
26984
- const content = fs15.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
28128
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26985
28129
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26986
28130
  lines.push("```javascript");
26987
28131
  lines.push(content);
@@ -26997,7 +28141,7 @@ var DevServer = class _DevServer {
26997
28141
  lines.push("");
26998
28142
  for (const file of refFiles) {
26999
28143
  try {
27000
- const content = fs15.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
28144
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
27001
28145
  lines.push(`### \`${file}\` \u{1F512}`);
27002
28146
  lines.push("```javascript");
27003
28147
  lines.push(content);
@@ -27030,10 +28174,10 @@ var DevServer = class _DevServer {
27030
28174
  lines.push("");
27031
28175
  }
27032
28176
  }
27033
- const docsDir = path22.join(providerDir, "../../docs");
28177
+ const docsDir = path25.join(providerDir, "../../docs");
27034
28178
  const loadGuide = (name) => {
27035
28179
  try {
27036
- const p = path22.join(docsDir, name);
28180
+ const p = path25.join(docsDir, name);
27037
28181
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
27038
28182
  } catch {
27039
28183
  }
@@ -27216,14 +28360,14 @@ data: ${JSON.stringify(msg.data)}
27216
28360
  res.end(JSON.stringify(data, null, 2));
27217
28361
  }
27218
28362
  async readBody(req) {
27219
- return new Promise((resolve12) => {
28363
+ return new Promise((resolve15) => {
27220
28364
  let body = "";
27221
28365
  req.on("data", (chunk) => body += chunk);
27222
28366
  req.on("end", () => {
27223
28367
  try {
27224
- resolve12(JSON.parse(body));
28368
+ resolve15(JSON.parse(body));
27225
28369
  } catch {
27226
- resolve12({});
28370
+ resolve15({});
27227
28371
  }
27228
28372
  });
27229
28373
  });
@@ -27738,7 +28882,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
27738
28882
  const deadline = Date.now() + timeoutMs;
27739
28883
  while (Date.now() < deadline) {
27740
28884
  if (await canConnect(endpoint)) return;
27741
- await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
28885
+ await new Promise((resolve15) => setTimeout(resolve15, STARTUP_POLL_MS));
27742
28886
  }
27743
28887
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
27744
28888
  }
@@ -27916,10 +29060,10 @@ async function installExtension(ide, extension) {
27916
29060
  const buffer = Buffer.from(await res.arrayBuffer());
27917
29061
  const fs16 = await import("fs");
27918
29062
  fs16.writeFileSync(vsixPath, buffer);
27919
- return new Promise((resolve12) => {
29063
+ return new Promise((resolve15) => {
27920
29064
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
27921
29065
  exec2(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
27922
- resolve12({
29066
+ resolve15({
27923
29067
  extensionId: extension.id,
27924
29068
  marketplaceId: extension.marketplaceId,
27925
29069
  success: !error,
@@ -27932,11 +29076,11 @@ async function installExtension(ide, extension) {
27932
29076
  } catch (e) {
27933
29077
  }
27934
29078
  }
27935
- return new Promise((resolve12) => {
29079
+ return new Promise((resolve15) => {
27936
29080
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
27937
29081
  exec2(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
27938
29082
  if (error) {
27939
- resolve12({
29083
+ resolve15({
27940
29084
  extensionId: extension.id,
27941
29085
  marketplaceId: extension.marketplaceId,
27942
29086
  success: false,
@@ -27944,7 +29088,7 @@ async function installExtension(ide, extension) {
27944
29088
  error: stderr || error.message
27945
29089
  });
27946
29090
  } else {
27947
- resolve12({
29091
+ resolve15({
27948
29092
  extensionId: extension.id,
27949
29093
  marketplaceId: extension.marketplaceId,
27950
29094
  success: true,
@@ -28273,6 +29417,7 @@ export {
28273
29417
  DEFAULT_CDP_SCAN_INTERVAL_MS,
28274
29418
  DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS,
28275
29419
  DEFAULT_DAEMON_PORT,
29420
+ DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS,
28276
29421
  DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
28277
29422
  DEFAULT_SESSION_HOST_APP_NAME,
28278
29423
  DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
@@ -28291,8 +29436,12 @@ export {
28291
29436
  DaemonCommandRouter,
28292
29437
  DaemonStatusReporter,
28293
29438
  DevServer,
29439
+ GitCommandError,
29440
+ GitWorkspaceMonitor,
28294
29441
  IdeProviderInstance,
29442
+ InMemoryGitSnapshotStore,
28295
29443
  LOG,
29444
+ MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
28296
29445
  MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
28297
29446
  MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
28298
29447
  NodePtyTransportFactory,
@@ -28320,9 +29469,14 @@ export {
28320
29469
  buildUserChatMessage,
28321
29470
  classifyHotChatSessionsForSubscriptionFlush,
28322
29471
  clearDebugTrace,
29472
+ compareGitSnapshots,
28323
29473
  configureDebugTraceStore,
28324
29474
  connectCdpManager,
28325
29475
  createDebugTraceStore,
29476
+ createDefaultGitCommandServices,
29477
+ createGitCompactSummary,
29478
+ createGitSnapshotStore,
29479
+ createGitWorkspaceMonitor,
28326
29480
  createInteractionId,
28327
29481
  detectAllVersions,
28328
29482
  detectCLIs,
@@ -28337,6 +29491,9 @@ export {
28337
29491
  getCurrentDaemonLogPath,
28338
29492
  getDaemonLogDir,
28339
29493
  getDebugRuntimeConfig,
29494
+ getGitDiffSummary,
29495
+ getGitFileDiff,
29496
+ getGitRepoStatus,
28340
29497
  getHostMemorySnapshot,
28341
29498
  getLogLevel,
28342
29499
  getNpmExecOptions,
@@ -28348,6 +29505,7 @@ export {
28348
29505
  getSessionHostRecoveryLabel,
28349
29506
  getSessionHostSurfaceKind,
28350
29507
  getWorkspaceState,
29508
+ handleGitCommand,
28351
29509
  hasCdpManager,
28352
29510
  hashSignatureParts,
28353
29511
  initDaemonComponents,
@@ -28356,9 +29514,11 @@ export {
28356
29514
  isBuiltinChatMessageKind,
28357
29515
  isCdpConnected,
28358
29516
  isExtensionInstalled,
29517
+ isGitCommandName,
28359
29518
  isIdeRunning,
28360
29519
  isManagedStatusWaiting,
28361
29520
  isManagedStatusWorking,
29521
+ isPathInside,
28362
29522
  isSessionHostLiveRuntime,
28363
29523
  isSessionHostRecoverySnapshot,
28364
29524
  isSetupComplete,
@@ -28376,10 +29536,13 @@ export {
28376
29536
  normalizeChatMessageKind,
28377
29537
  normalizeChatMessages,
28378
29538
  normalizeChatTailActiveModal,
29539
+ normalizeGitOutput,
29540
+ normalizeGitWorkspaceSubscriptionParams,
28379
29541
  normalizeInputEnvelope,
28380
29542
  normalizeManagedStatus,
28381
29543
  normalizeMessageParts,
28382
29544
  normalizeSessionModalFields,
29545
+ parsePorcelainV2Status,
28383
29546
  parseProviderSourceConfigUpdate,
28384
29547
  partitionSessionHostDiagnosticsSessions,
28385
29548
  partitionSessionHostRecords,
@@ -28395,9 +29558,11 @@ export {
28395
29558
  resolveChatMessageKind,
28396
29559
  resolveCurrentGlobalInstallSurface,
28397
29560
  resolveDebugRuntimeConfig,
29561
+ resolveGitRepository,
28398
29562
  resolveSessionHostAppName,
28399
29563
  resolveSessionHostAppNameResolution,
28400
29564
  runAsyncBatch,
29565
+ runGit,
28401
29566
  saveConfig,
28402
29567
  saveState,
28403
29568
  setDebugRuntimeConfig,
@@ -28408,6 +29573,7 @@ export {
28408
29573
  shutdownDaemonComponents,
28409
29574
  spawnDetachedDaemonUpgradeHelper,
28410
29575
  startDaemonDevSupport,
29576
+ summarizeGitStatus,
28411
29577
  updateConfig,
28412
29578
  upsertSavedProviderSession
28413
29579
  };