@adhdev/daemon-core 0.9.52 → 0.9.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -283,13 +283,13 @@ function getDaemonLogDir() {
283
283
  return LOG_DIR;
284
284
  }
285
285
  function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
286
- return path6.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
286
+ return path9.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
287
287
  }
288
288
  function checkDateRotation() {
289
289
  const today = getDateStr();
290
290
  if (today !== currentDate) {
291
291
  currentDate = today;
292
- currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
292
+ currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
293
293
  cleanOldLogs();
294
294
  }
295
295
  }
@@ -303,7 +303,7 @@ function cleanOldLogs() {
303
303
  const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
304
304
  if (dateMatch && dateMatch[1] < cutoffStr) {
305
305
  try {
306
- fs2.unlinkSync(path6.join(LOG_DIR, file));
306
+ fs2.unlinkSync(path9.join(LOG_DIR, file));
307
307
  } catch {
308
308
  }
309
309
  }
@@ -313,8 +313,8 @@ function cleanOldLogs() {
313
313
  }
314
314
  function rotateSizeIfNeeded() {
315
315
  try {
316
- const stat = fs2.statSync(currentLogFile);
317
- if (stat.size > MAX_LOG_SIZE) {
316
+ const stat2 = fs2.statSync(currentLogFile);
317
+ if (stat2.size > MAX_LOG_SIZE) {
318
318
  const backup = currentLogFile.replace(".log", ".1.log");
319
319
  try {
320
320
  fs2.unlinkSync(backup);
@@ -419,17 +419,17 @@ function installGlobalInterceptor() {
419
419
  writeToFile(`Log file: ${currentLogFile}`);
420
420
  writeToFile(`Log level: ${currentLevel}`);
421
421
  }
422
- var fs2, path6, os4, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH;
422
+ var fs2, path9, os4, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH;
423
423
  var init_logger = __esm({
424
424
  "src/logging/logger.ts"() {
425
425
  "use strict";
426
426
  fs2 = __toESM(require("fs"));
427
- path6 = __toESM(require("path"));
427
+ path9 = __toESM(require("path"));
428
428
  os4 = __toESM(require("os"));
429
429
  LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
430
430
  LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
431
431
  currentLevel = "info";
432
- 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");
432
+ 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");
433
433
  MAX_LOG_SIZE = 5 * 1024 * 1024;
434
434
  MAX_LOG_DAYS = 7;
435
435
  try {
@@ -437,16 +437,16 @@ var init_logger = __esm({
437
437
  } catch {
438
438
  }
439
439
  currentDate = getDateStr();
440
- currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
440
+ currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
441
441
  cleanOldLogs();
442
442
  try {
443
- const oldLog = path6.join(LOG_DIR, "daemon.log");
443
+ const oldLog = path9.join(LOG_DIR, "daemon.log");
444
444
  if (fs2.existsSync(oldLog)) {
445
- const stat = fs2.statSync(oldLog);
446
- const oldDate = stat.mtime.toISOString().slice(0, 10);
447
- fs2.renameSync(oldLog, path6.join(LOG_DIR, `daemon-${oldDate}.log`));
445
+ const stat2 = fs2.statSync(oldLog);
446
+ const oldDate = stat2.mtime.toISOString().slice(0, 10);
447
+ fs2.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
448
448
  }
449
- const oldLogBackup = path6.join(LOG_DIR, "daemon.log.old");
449
+ const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
450
450
  if (fs2.existsSync(oldLogBackup)) {
451
451
  fs2.unlinkSync(oldLogBackup);
452
452
  }
@@ -478,7 +478,7 @@ var init_logger = __esm({
478
478
  }
479
479
  };
480
480
  interceptorInstalled = false;
481
- LOG_PATH = path6.join(LOG_DIR, `daemon-${getDateStr()}.log`);
481
+ LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
482
482
  }
483
483
  });
484
484
 
@@ -1382,8 +1382,8 @@ var init_pty_transport = __esm({
1382
1382
  if (cwd) {
1383
1383
  try {
1384
1384
  const fs16 = require("fs");
1385
- const stat = fs16.statSync(cwd);
1386
- if (!stat.isDirectory()) cwd = os8.homedir();
1385
+ const stat2 = fs16.statSync(cwd);
1386
+ if (!stat2.isDirectory()) cwd = os8.homedir();
1387
1387
  } catch {
1388
1388
  cwd = os8.homedir();
1389
1389
  }
@@ -1465,9 +1465,9 @@ function buildCliScreenSnapshot(text) {
1465
1465
  function findBinary(name) {
1466
1466
  const trimmed = String(name || "").trim();
1467
1467
  if (!trimmed) return trimmed;
1468
- const expanded = trimmed.startsWith("~") ? path10.join(os9.homedir(), trimmed.slice(1)) : trimmed;
1469
- if (path10.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
1470
- return path10.isAbsolute(expanded) ? expanded : path10.resolve(expanded);
1468
+ const expanded = trimmed.startsWith("~") ? path13.join(os9.homedir(), trimmed.slice(1)) : trimmed;
1469
+ if (path13.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
1470
+ return path13.isAbsolute(expanded) ? expanded : path13.resolve(expanded);
1471
1471
  }
1472
1472
  const isWin = os9.platform() === "win32";
1473
1473
  try {
@@ -1483,7 +1483,7 @@ function findBinary(name) {
1483
1483
  }
1484
1484
  }
1485
1485
  function isScriptBinary(binaryPath) {
1486
- if (!path10.isAbsolute(binaryPath)) return false;
1486
+ if (!path13.isAbsolute(binaryPath)) return false;
1487
1487
  try {
1488
1488
  const fs16 = require("fs");
1489
1489
  const resolved = fs16.realpathSync(binaryPath);
@@ -1499,7 +1499,7 @@ function isScriptBinary(binaryPath) {
1499
1499
  }
1500
1500
  }
1501
1501
  function looksLikeMachOOrElf(filePath) {
1502
- if (!path10.isAbsolute(filePath)) return false;
1502
+ if (!path13.isAbsolute(filePath)) return false;
1503
1503
  try {
1504
1504
  const fs16 = require("fs");
1505
1505
  const resolved = fs16.realpathSync(filePath);
@@ -1649,12 +1649,12 @@ function normalizeCliProviderForRuntime(raw) {
1649
1649
  }
1650
1650
  };
1651
1651
  }
1652
- var os9, path10, import_child_process4, buildCliSpawnEnv, COMMON_COMPARABLE_WRAP_WORDS;
1652
+ var os9, path13, import_child_process4, buildCliSpawnEnv, COMMON_COMPARABLE_WRAP_WORDS;
1653
1653
  var init_provider_cli_shared = __esm({
1654
1654
  "src/cli-adapters/provider-cli-shared.ts"() {
1655
1655
  "use strict";
1656
1656
  os9 = __toESM(require("os"));
1657
- path10 = __toESM(require("path"));
1657
+ path13 = __toESM(require("path"));
1658
1658
  import_child_process4 = require("child_process");
1659
1659
  init_spawn_env();
1660
1660
  buildCliSpawnEnv = import_session_host_core.sanitizeSpawnEnv;
@@ -1971,9 +1971,9 @@ function resolveCliSpawnPlan(options) {
1971
1971
  const allArgs = [...spawnConfig.args, ...extraArgs];
1972
1972
  let shellCmd;
1973
1973
  let shellArgs;
1974
- const useShellUnix = !isWin && (!!spawnConfig.shell || !path11.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1974
+ const useShellUnix = !isWin && (!!spawnConfig.shell || !path14.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1975
1975
  const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
1976
- const useShellWin = !!spawnConfig.shell || isCmdShim || !path11.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
1976
+ const useShellWin = !!spawnConfig.shell || isCmdShim || !path14.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
1977
1977
  const useShell = isWin ? useShellWin : useShellUnix;
1978
1978
  if (useShell) {
1979
1979
  shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
@@ -2049,12 +2049,12 @@ function respondToCliTerminalQueries(options) {
2049
2049
  }
2050
2050
  return "";
2051
2051
  }
2052
- var os10, path11, import_session_host_core2;
2052
+ var os10, path14, import_session_host_core2;
2053
2053
  var init_provider_cli_runtime = __esm({
2054
2054
  "src/cli-adapters/provider-cli-runtime.ts"() {
2055
2055
  "use strict";
2056
2056
  os10 = __toESM(require("os"));
2057
- path11 = __toESM(require("path"));
2057
+ path14 = __toESM(require("path"));
2058
2058
  import_session_host_core2 = require("@adhdev/session-host-core");
2059
2059
  init_provider_cli_shared();
2060
2060
  }
@@ -2854,7 +2854,7 @@ var init_provider_cli_adapter = __esm({
2854
2854
  `[${this.cliType}] Waiting for interactive prompt: status=${status} stableMs=${stableMs} recentOutputMs=${recentlyOutput} screen=${JSON.stringify(summarizeCliTraceText(screenText, 220)).slice(0, 260)}`
2855
2855
  );
2856
2856
  }
2857
- await new Promise((resolve12) => setTimeout(resolve12, 50));
2857
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
2858
2858
  }
2859
2859
  const finalScreenText = this.terminalScreen.getText() || "";
2860
2860
  LOG.warn(
@@ -4042,7 +4042,7 @@ var init_provider_cli_adapter = __esm({
4042
4042
  const deadline = Date.now() + 1e4;
4043
4043
  while (this.startupParseGate && Date.now() < deadline) {
4044
4044
  this.resolveStartupState("send_wait");
4045
- await new Promise((resolve12) => setTimeout(resolve12, 50));
4045
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
4046
4046
  }
4047
4047
  }
4048
4048
  if (!allowInterventionPrompt) {
@@ -4123,13 +4123,13 @@ var init_provider_cli_adapter = __esm({
4123
4123
  }
4124
4124
  this.responseEpoch += 1;
4125
4125
  this.responseSettleIgnoreUntil = Date.now() + submitDelayMs + this.timeouts.outputSettle + 250;
4126
- await new Promise((resolve12, reject) => {
4126
+ await new Promise((resolve15, reject) => {
4127
4127
  let resolved = false;
4128
4128
  const completion = {
4129
4129
  resolveOnce: () => {
4130
4130
  if (resolved) return;
4131
4131
  resolved = true;
4132
- resolve12();
4132
+ resolve15();
4133
4133
  },
4134
4134
  rejectOnce: (error) => {
4135
4135
  if (resolved) return;
@@ -4291,17 +4291,17 @@ var init_provider_cli_adapter = __esm({
4291
4291
  }
4292
4292
  }
4293
4293
  waitForStopped(timeoutMs) {
4294
- return new Promise((resolve12) => {
4294
+ return new Promise((resolve15) => {
4295
4295
  const startedAt = Date.now();
4296
4296
  const timer = setInterval(() => {
4297
4297
  if (!this.ptyProcess || this.currentStatus === "stopped") {
4298
4298
  clearInterval(timer);
4299
- resolve12(true);
4299
+ resolve15(true);
4300
4300
  return;
4301
4301
  }
4302
4302
  if (Date.now() - startedAt >= timeoutMs) {
4303
4303
  clearInterval(timer);
4304
- resolve12(false);
4304
+ resolve15(false);
4305
4305
  }
4306
4306
  }, 100);
4307
4307
  });
@@ -4541,6 +4541,7 @@ __export(index_exports, {
4541
4541
  DEFAULT_CDP_SCAN_INTERVAL_MS: () => DEFAULT_CDP_SCAN_INTERVAL_MS,
4542
4542
  DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS: () => DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS,
4543
4543
  DEFAULT_DAEMON_PORT: () => DEFAULT_DAEMON_PORT,
4544
+ DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS: () => DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS,
4544
4545
  DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS: () => DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
4545
4546
  DEFAULT_SESSION_HOST_APP_NAME: () => DEFAULT_SESSION_HOST_APP_NAME,
4546
4547
  DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS: () => DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
@@ -4559,8 +4560,12 @@ __export(index_exports, {
4559
4560
  DaemonCommandRouter: () => DaemonCommandRouter,
4560
4561
  DaemonStatusReporter: () => DaemonStatusReporter,
4561
4562
  DevServer: () => DevServer,
4563
+ GitCommandError: () => GitCommandError,
4564
+ GitWorkspaceMonitor: () => GitWorkspaceMonitor,
4562
4565
  IdeProviderInstance: () => IdeProviderInstance,
4566
+ InMemoryGitSnapshotStore: () => InMemoryGitSnapshotStore,
4563
4567
  LOG: () => LOG,
4568
+ MIN_GIT_WORKSPACE_POLL_INTERVAL_MS: () => MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
4564
4569
  MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS: () => MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
4565
4570
  MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS: () => MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
4566
4571
  NodePtyTransportFactory: () => NodePtyTransportFactory,
@@ -4588,9 +4593,14 @@ __export(index_exports, {
4588
4593
  buildUserChatMessage: () => buildUserChatMessage,
4589
4594
  classifyHotChatSessionsForSubscriptionFlush: () => classifyHotChatSessionsForSubscriptionFlush,
4590
4595
  clearDebugTrace: () => clearDebugTrace,
4596
+ compareGitSnapshots: () => compareGitSnapshots,
4591
4597
  configureDebugTraceStore: () => configureDebugTraceStore,
4592
4598
  connectCdpManager: () => connectCdpManager,
4593
4599
  createDebugTraceStore: () => createDebugTraceStore,
4600
+ createDefaultGitCommandServices: () => createDefaultGitCommandServices,
4601
+ createGitCompactSummary: () => createGitCompactSummary,
4602
+ createGitSnapshotStore: () => createGitSnapshotStore,
4603
+ createGitWorkspaceMonitor: () => createGitWorkspaceMonitor,
4594
4604
  createInteractionId: () => createInteractionId,
4595
4605
  detectAllVersions: () => detectAllVersions,
4596
4606
  detectCLIs: () => detectCLIs,
@@ -4605,6 +4615,9 @@ __export(index_exports, {
4605
4615
  getCurrentDaemonLogPath: () => getCurrentDaemonLogPath,
4606
4616
  getDaemonLogDir: () => getDaemonLogDir,
4607
4617
  getDebugRuntimeConfig: () => getDebugRuntimeConfig,
4618
+ getGitDiffSummary: () => getGitDiffSummary,
4619
+ getGitFileDiff: () => getGitFileDiff,
4620
+ getGitRepoStatus: () => getGitRepoStatus,
4608
4621
  getHostMemorySnapshot: () => getHostMemorySnapshot,
4609
4622
  getLogLevel: () => getLogLevel,
4610
4623
  getNpmExecOptions: () => getNpmExecOptions,
@@ -4616,6 +4629,7 @@ __export(index_exports, {
4616
4629
  getSessionHostRecoveryLabel: () => getSessionHostRecoveryLabel,
4617
4630
  getSessionHostSurfaceKind: () => getSessionHostSurfaceKind,
4618
4631
  getWorkspaceState: () => getWorkspaceState,
4632
+ handleGitCommand: () => handleGitCommand,
4619
4633
  hasCdpManager: () => hasCdpManager,
4620
4634
  hashSignatureParts: () => hashSignatureParts,
4621
4635
  initDaemonComponents: () => initDaemonComponents,
@@ -4624,9 +4638,11 @@ __export(index_exports, {
4624
4638
  isBuiltinChatMessageKind: () => isBuiltinChatMessageKind,
4625
4639
  isCdpConnected: () => isCdpConnected,
4626
4640
  isExtensionInstalled: () => isExtensionInstalled,
4641
+ isGitCommandName: () => isGitCommandName,
4627
4642
  isIdeRunning: () => isIdeRunning,
4628
4643
  isManagedStatusWaiting: () => isManagedStatusWaiting,
4629
4644
  isManagedStatusWorking: () => isManagedStatusWorking,
4645
+ isPathInside: () => isPathInside,
4630
4646
  isSessionHostLiveRuntime: () => isSessionHostLiveRuntime,
4631
4647
  isSessionHostRecoverySnapshot: () => isSessionHostRecoverySnapshot,
4632
4648
  isSetupComplete: () => isSetupComplete,
@@ -4644,10 +4660,13 @@ __export(index_exports, {
4644
4660
  normalizeChatMessageKind: () => normalizeChatMessageKind,
4645
4661
  normalizeChatMessages: () => normalizeChatMessages,
4646
4662
  normalizeChatTailActiveModal: () => normalizeChatTailActiveModal,
4663
+ normalizeGitOutput: () => normalizeGitOutput,
4664
+ normalizeGitWorkspaceSubscriptionParams: () => normalizeGitWorkspaceSubscriptionParams,
4647
4665
  normalizeInputEnvelope: () => normalizeInputEnvelope,
4648
4666
  normalizeManagedStatus: () => normalizeManagedStatus,
4649
4667
  normalizeMessageParts: () => normalizeMessageParts,
4650
4668
  normalizeSessionModalFields: () => normalizeSessionModalFields,
4669
+ parsePorcelainV2Status: () => parsePorcelainV2Status,
4651
4670
  parseProviderSourceConfigUpdate: () => parseProviderSourceConfigUpdate,
4652
4671
  partitionSessionHostDiagnosticsSessions: () => partitionSessionHostDiagnosticsSessions,
4653
4672
  partitionSessionHostRecords: () => partitionSessionHostRecords,
@@ -4663,9 +4682,11 @@ __export(index_exports, {
4663
4682
  resolveChatMessageKind: () => resolveChatMessageKind,
4664
4683
  resolveCurrentGlobalInstallSurface: () => resolveCurrentGlobalInstallSurface,
4665
4684
  resolveDebugRuntimeConfig: () => resolveDebugRuntimeConfig,
4685
+ resolveGitRepository: () => resolveGitRepository,
4666
4686
  resolveSessionHostAppName: () => resolveSessionHostAppName,
4667
4687
  resolveSessionHostAppNameResolution: () => resolveSessionHostAppNameResolution,
4668
4688
  runAsyncBatch: () => runAsyncBatch,
4689
+ runGit: () => runGit,
4669
4690
  saveConfig: () => saveConfig,
4670
4691
  saveState: () => saveState,
4671
4692
  setDebugRuntimeConfig: () => setDebugRuntimeConfig,
@@ -4676,23 +4697,1143 @@ __export(index_exports, {
4676
4697
  shutdownDaemonComponents: () => shutdownDaemonComponents,
4677
4698
  spawnDetachedDaemonUpgradeHelper: () => spawnDetachedDaemonUpgradeHelper,
4678
4699
  startDaemonDevSupport: () => startDaemonDevSupport,
4700
+ summarizeGitStatus: () => summarizeGitStatus,
4679
4701
  updateConfig: () => updateConfig,
4680
4702
  upsertSavedProviderSession: () => upsertSavedProviderSession
4681
4703
  });
4682
4704
  module.exports = __toCommonJS(index_exports);
4705
+
4706
+ // src/git/git-executor.ts
4707
+ var import_node_child_process = require("child_process");
4708
+ var import_node_fs = require("fs");
4709
+ var import_promises = require("fs/promises");
4710
+ var path = __toESM(require("path"));
4711
+ var import_node_util = require("util");
4712
+ var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
4713
+ var DEFAULT_TIMEOUT_MS = 5e3;
4714
+ var DEFAULT_MAX_BUFFER = 1024 * 1024;
4715
+ var GitCommandError = class extends Error {
4716
+ reason;
4717
+ stdout;
4718
+ stderr;
4719
+ exitCode;
4720
+ signal;
4721
+ argv;
4722
+ cwd;
4723
+ constructor(reason, message, details = {}) {
4724
+ super(message);
4725
+ if (details.cause !== void 0) {
4726
+ this.cause = details.cause;
4727
+ }
4728
+ this.name = "GitCommandError";
4729
+ this.reason = reason;
4730
+ this.stdout = normalizeGitOutput(details.stdout);
4731
+ this.stderr = normalizeGitOutput(details.stderr);
4732
+ this.exitCode = details.exitCode;
4733
+ this.signal = details.signal;
4734
+ this.argv = details.argv ? [...details.argv] : void 0;
4735
+ this.cwd = details.cwd;
4736
+ }
4737
+ };
4738
+ async function resolveGitRepository(workspace, options = {}) {
4739
+ const normalizedWorkspace = await validateWorkspace(workspace);
4740
+ const result = await execGitRaw(normalizedWorkspace, ["rev-parse", "--show-toplevel"], options, {
4741
+ mapNotGitRepo: true
4742
+ });
4743
+ const repoRoot = path.resolve(result.stdout.trim());
4744
+ if (!repoRoot) {
4745
+ throw new GitCommandError("not_git_repo", "Git did not return a repository root", {
4746
+ stdout: result.stdout,
4747
+ stderr: result.stderr,
4748
+ argv: ["rev-parse", "--show-toplevel"],
4749
+ cwd: normalizedWorkspace
4750
+ });
4751
+ }
4752
+ return {
4753
+ workspace: normalizedWorkspace,
4754
+ repoRoot,
4755
+ isGitRepo: true
4756
+ };
4757
+ }
4758
+ async function runGit(repoOrWorkspace, argv, options = {}) {
4759
+ validateGitArgv(argv);
4760
+ const repo = typeof repoOrWorkspace === "string" ? await resolveGitRepository(repoOrWorkspace, options) : repoOrWorkspace;
4761
+ if (!repo.repoRoot || !repo.isGitRepo) {
4762
+ throw new GitCommandError("not_git_repo", "Workspace is not a Git repository", {
4763
+ argv,
4764
+ cwd: repo.workspace
4765
+ });
4766
+ }
4767
+ const cwd = options.cwd ? await validateWorkspace(options.cwd) : await validateWorkspace(repo.workspace);
4768
+ const canonicalRepoRoot = await (0, import_promises.realpath)(repo.repoRoot);
4769
+ const canonicalCwd = await (0, import_promises.realpath)(cwd);
4770
+ if (!isPathInside(canonicalRepoRoot, canonicalCwd)) {
4771
+ throw new GitCommandError("path_outside_repo", "Git cwd is outside the repository root", {
4772
+ argv,
4773
+ cwd
4774
+ });
4775
+ }
4776
+ return execGitRaw(cwd, argv, options);
4777
+ }
4778
+ function normalizeGitOutput(value) {
4779
+ if (typeof value === "string") return value.replace(/\r\n/g, "\n");
4780
+ if (Buffer.isBuffer(value)) return value.toString("utf8").replace(/\r\n/g, "\n");
4781
+ if (value == null) return "";
4782
+ return String(value).replace(/\r\n/g, "\n");
4783
+ }
4784
+ function isPathInside(parent, child) {
4785
+ const relative3 = path.relative(path.resolve(parent), path.resolve(child));
4786
+ return relative3 === "" || !relative3.startsWith("..") && !path.isAbsolute(relative3);
4787
+ }
4788
+ async function validateWorkspace(workspace) {
4789
+ if (typeof workspace !== "string" || workspace.length === 0 || workspace.includes("\0")) {
4790
+ throw new GitCommandError("invalid_args", "Workspace must be a non-empty path");
4791
+ }
4792
+ if (!path.isAbsolute(workspace)) {
4793
+ throw new GitCommandError("invalid_args", "Workspace must be an absolute path", { cwd: workspace });
4794
+ }
4795
+ const normalizedWorkspace = path.resolve(workspace);
4796
+ try {
4797
+ const info = await (0, import_promises.stat)(normalizedWorkspace);
4798
+ if (!info.isDirectory()) {
4799
+ throw new GitCommandError("invalid_args", "Workspace must be an existing directory", {
4800
+ cwd: normalizedWorkspace
4801
+ });
4802
+ }
4803
+ await (0, import_promises.access)(normalizedWorkspace, import_node_fs.constants.R_OK);
4804
+ } catch (error) {
4805
+ if (error instanceof GitCommandError) throw error;
4806
+ throw new GitCommandError("invalid_args", "Workspace must be an existing directory", {
4807
+ cwd: normalizedWorkspace,
4808
+ cause: error
4809
+ });
4810
+ }
4811
+ return normalizedWorkspace;
4812
+ }
4813
+ function validateGitArgv(argv) {
4814
+ if (!Array.isArray(argv) || argv.length === 0) {
4815
+ throw new GitCommandError("invalid_args", "Git argv must be a non-empty string array", { argv });
4816
+ }
4817
+ for (const arg of argv) {
4818
+ if (typeof arg !== "string" || arg.length === 0 || arg.includes("\0")) {
4819
+ throw new GitCommandError("invalid_args", "Git argv contains an invalid argument", { argv });
4820
+ }
4821
+ }
4822
+ if (argv.includes("-C") || argv.some((arg) => arg.startsWith("--git-dir") || arg.startsWith("--work-tree"))) {
4823
+ throw new GitCommandError("invalid_args", "Git argv contains unsafe repository override arguments", {
4824
+ argv
4825
+ });
4826
+ }
4827
+ }
4828
+ async function execGitRaw(cwd, argv, options, behavior = {}) {
4829
+ validateGitArgv(argv);
4830
+ try {
4831
+ const result = await execFileAsync("git", [...argv], {
4832
+ cwd,
4833
+ encoding: "utf8",
4834
+ timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
4835
+ maxBuffer: options.maxBuffer ?? DEFAULT_MAX_BUFFER,
4836
+ windowsHide: true
4837
+ });
4838
+ return {
4839
+ stdout: normalizeGitOutput(result.stdout),
4840
+ stderr: normalizeGitOutput(result.stderr)
4841
+ };
4842
+ } catch (error) {
4843
+ throw mapExecError(error, cwd, argv, behavior);
4844
+ }
4845
+ }
4846
+ function mapExecError(error, cwd, argv, behavior) {
4847
+ const execError = error;
4848
+ const stdout = normalizeGitOutput(execError.stdout);
4849
+ const stderr = normalizeGitOutput(execError.stderr);
4850
+ const code = execError.code;
4851
+ const signal = execError.signal;
4852
+ const message = [stderr.trim(), execError.message].filter(Boolean).join("\n");
4853
+ if (code === "ENOENT") {
4854
+ return new GitCommandError("git_not_installed", "Git executable was not found", {
4855
+ stdout,
4856
+ stderr,
4857
+ exitCode: code,
4858
+ signal,
4859
+ argv,
4860
+ cwd,
4861
+ cause: error
4862
+ });
4863
+ }
4864
+ if (execError.killed || /timed out/i.test(execError.message)) {
4865
+ return new GitCommandError("timeout", "Git command timed out", {
4866
+ stdout,
4867
+ stderr,
4868
+ exitCode: code,
4869
+ signal,
4870
+ argv,
4871
+ cwd,
4872
+ cause: error
4873
+ });
4874
+ }
4875
+ if (behavior.mapNotGitRepo && /not a git repository/i.test(stderr + "\n" + execError.message)) {
4876
+ return new GitCommandError("not_git_repo", "Workspace is not a Git repository", {
4877
+ stdout,
4878
+ stderr,
4879
+ exitCode: code,
4880
+ signal,
4881
+ argv,
4882
+ cwd,
4883
+ cause: error
4884
+ });
4885
+ }
4886
+ return new GitCommandError("git_command_failed", message || "Git command failed", {
4887
+ stdout,
4888
+ stderr,
4889
+ exitCode: code,
4890
+ signal,
4891
+ argv,
4892
+ cwd,
4893
+ cause: error
4894
+ });
4895
+ }
4896
+
4897
+ // src/git/git-status.ts
4898
+ async function getGitRepoStatus(workspace, options = {}) {
4899
+ const lastCheckedAt = Date.now();
4900
+ try {
4901
+ const repo = await resolveGitRepository(workspace, options);
4902
+ const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
4903
+ const parsed = parsePorcelainV2Status(statusOutput.stdout);
4904
+ const head = await readHead(repo, options);
4905
+ const stashCount = await readStashCount(repo, options);
4906
+ return {
4907
+ workspace: repo.workspace,
4908
+ repoRoot: repo.repoRoot,
4909
+ isGitRepo: true,
4910
+ branch: parsed.branch,
4911
+ headCommit: head.commit,
4912
+ headMessage: head.message,
4913
+ upstream: parsed.upstream,
4914
+ ahead: parsed.ahead,
4915
+ behind: parsed.behind,
4916
+ staged: parsed.staged,
4917
+ modified: parsed.modified,
4918
+ untracked: parsed.untracked,
4919
+ deleted: parsed.deleted,
4920
+ renamed: parsed.renamed,
4921
+ hasConflicts: parsed.conflictFiles.length > 0,
4922
+ conflictFiles: parsed.conflictFiles,
4923
+ stashCount,
4924
+ lastCheckedAt
4925
+ };
4926
+ } catch (error) {
4927
+ if (error instanceof GitCommandError) {
4928
+ return emptyStatus(workspace, lastCheckedAt, error);
4929
+ }
4930
+ return emptyStatus(
4931
+ workspace,
4932
+ lastCheckedAt,
4933
+ new GitCommandError("git_command_failed", "Failed to read Git status", { cause: error })
4934
+ );
4935
+ }
4936
+ }
4937
+ function parsePorcelainV2Status(output) {
4938
+ const parsed = {
4939
+ branch: null,
4940
+ upstream: null,
4941
+ ahead: 0,
4942
+ behind: 0,
4943
+ staged: 0,
4944
+ modified: 0,
4945
+ untracked: 0,
4946
+ deleted: 0,
4947
+ renamed: 0,
4948
+ conflictFiles: []
4949
+ };
4950
+ for (const line of output.split("\n")) {
4951
+ if (!line) continue;
4952
+ if (line.startsWith("# branch.head ")) {
4953
+ const branch = line.slice("# branch.head ".length).trim();
4954
+ parsed.branch = branch && branch !== "(detached)" ? branch : null;
4955
+ continue;
4956
+ }
4957
+ if (line.startsWith("# branch.upstream ")) {
4958
+ parsed.upstream = line.slice("# branch.upstream ".length).trim() || null;
4959
+ continue;
4960
+ }
4961
+ if (line.startsWith("# branch.ab ")) {
4962
+ const match = line.match(/\+(-?\d+)\s+-(-?\d+)/);
4963
+ if (match) {
4964
+ parsed.ahead = Number.parseInt(match[1] ?? "0", 10) || 0;
4965
+ parsed.behind = Number.parseInt(match[2] ?? "0", 10) || 0;
4966
+ }
4967
+ continue;
4968
+ }
4969
+ if (line.startsWith("? ")) {
4970
+ parsed.untracked += 1;
4971
+ continue;
4972
+ }
4973
+ if (line.startsWith("u ")) {
4974
+ const fields = line.split(" ");
4975
+ const filePath = fields.slice(10).join(" ");
4976
+ if (filePath) parsed.conflictFiles.push(filePath);
4977
+ continue;
4978
+ }
4979
+ if (line.startsWith("1 ") || line.startsWith("2 ")) {
4980
+ const fields = line.split(" ");
4981
+ const xy = fields[1] ?? "..";
4982
+ const indexStatus = xy[0] ?? ".";
4983
+ const worktreeStatus = xy[1] ?? ".";
4984
+ if (isStagedStatus(indexStatus)) parsed.staged += 1;
4985
+ if (worktreeStatus === "M" || worktreeStatus === "T") parsed.modified += 1;
4986
+ if (indexStatus === "D" || worktreeStatus === "D") parsed.deleted += 1;
4987
+ if (indexStatus === "R" || worktreeStatus === "R") parsed.renamed += 1;
4988
+ if (xy.includes("U")) {
4989
+ const filePath = fields.slice(line.startsWith("2 ") ? 9 : 8).join(" ").split(" ")[0] ?? "";
4990
+ if (filePath) parsed.conflictFiles.push(filePath);
4991
+ }
4992
+ }
4993
+ }
4994
+ parsed.conflictFiles = Array.from(new Set(parsed.conflictFiles));
4995
+ return parsed;
4996
+ }
4997
+ async function readHead(repo, options) {
4998
+ try {
4999
+ const result = await runGit(repo, ["log", "-1", "--pretty=%h%x00%s"], options);
5000
+ const text = result.stdout.trimEnd();
5001
+ if (!text) return { commit: null, message: null };
5002
+ const [commit, ...messageParts] = text.split("\0");
5003
+ return {
5004
+ commit: commit || null,
5005
+ message: messageParts.join("\0") || null
5006
+ };
5007
+ } catch {
5008
+ return { commit: null, message: null };
5009
+ }
5010
+ }
5011
+ async function readStashCount(repo, options) {
5012
+ try {
5013
+ const result = await runGit(repo, ["stash", "list", "--format=%gd"], options);
5014
+ return result.stdout.split("\n").filter((line) => line.trim().length > 0).length;
5015
+ } catch {
5016
+ return 0;
5017
+ }
5018
+ }
5019
+ function isStagedStatus(status) {
5020
+ return status !== "." && status !== "?" && status !== "U";
5021
+ }
5022
+ function emptyStatus(workspace, lastCheckedAt, error) {
5023
+ return {
5024
+ workspace,
5025
+ repoRoot: null,
5026
+ isGitRepo: false,
5027
+ branch: null,
5028
+ headCommit: null,
5029
+ headMessage: null,
5030
+ upstream: null,
5031
+ ahead: 0,
5032
+ behind: 0,
5033
+ staged: 0,
5034
+ modified: 0,
5035
+ untracked: 0,
5036
+ deleted: 0,
5037
+ renamed: 0,
5038
+ hasConflicts: false,
5039
+ conflictFiles: [],
5040
+ stashCount: 0,
5041
+ lastCheckedAt,
5042
+ error: error.stderr || error.message,
5043
+ reason: error.reason
5044
+ };
5045
+ }
5046
+
5047
+ // src/git/git-diff.ts
5048
+ var import_promises2 = require("fs/promises");
5049
+ var path2 = __toESM(require("path"));
5050
+ var DEFAULT_MAX_FILES = 200;
5051
+ var DEFAULT_MAX_BYTES = 2e5;
5052
+ async function getGitDiffSummary(workspace, options = {}) {
5053
+ const lastCheckedAt = Date.now();
5054
+ try {
5055
+ const repo = await resolveGitRepository(workspace, options);
5056
+ const repoRoot = repo.repoRoot;
5057
+ const [unstagedNameStatus, unstagedNumstat, stagedNameStatus, stagedNumstat, untracked] = await Promise.all([
5058
+ runGit(repo, ["diff", "--no-ext-diff", "--name-status"], { ...options, cwd: repoRoot }),
5059
+ runGit(repo, ["diff", "--no-ext-diff", "--numstat"], { ...options, cwd: repoRoot }),
5060
+ runGit(repo, ["diff", "--cached", "--no-ext-diff", "--name-status"], { ...options, cwd: repoRoot }),
5061
+ runGit(repo, ["diff", "--cached", "--no-ext-diff", "--numstat"], { ...options, cwd: repoRoot }),
5062
+ runGit(repo, ["ls-files", "--others", "--exclude-standard"], { ...options, cwd: repoRoot })
5063
+ ]);
5064
+ const outputBytes = byteLength(
5065
+ unstagedNameStatus.stdout + unstagedNumstat.stdout + stagedNameStatus.stdout + stagedNumstat.stdout + untracked.stdout
5066
+ );
5067
+ const changes = [
5068
+ ...combineDiffEntries(unstagedNameStatus.stdout, unstagedNumstat.stdout, false),
5069
+ ...combineDiffEntries(stagedNameStatus.stdout, stagedNumstat.stdout, true),
5070
+ ...parseUntrackedFiles(untracked.stdout)
5071
+ ];
5072
+ const maxFiles = normalizePositiveInteger(options.maxFiles, DEFAULT_MAX_FILES);
5073
+ const maxBytes = normalizePositiveInteger(options.maxBytes, DEFAULT_MAX_BYTES);
5074
+ const files = changes.slice(0, maxFiles);
5075
+ const truncated = changes.length > files.length || outputBytes > maxBytes;
5076
+ return {
5077
+ workspace: repo.workspace,
5078
+ repoRoot,
5079
+ isGitRepo: true,
5080
+ files,
5081
+ totalInsertions: files.reduce((sum, file) => sum + file.insertions, 0),
5082
+ totalDeletions: files.reduce((sum, file) => sum + file.deletions, 0),
5083
+ truncated,
5084
+ lastCheckedAt
5085
+ };
5086
+ } catch (error) {
5087
+ const gitError = error instanceof GitCommandError ? error : new GitCommandError("git_command_failed", "Failed to read Git diff summary", { cause: error });
5088
+ return {
5089
+ workspace,
5090
+ repoRoot: null,
5091
+ isGitRepo: false,
5092
+ files: [],
5093
+ totalInsertions: 0,
5094
+ totalDeletions: 0,
5095
+ truncated: false,
5096
+ lastCheckedAt,
5097
+ error: gitError.stderr || gitError.message,
5098
+ reason: gitError.reason
5099
+ };
5100
+ }
5101
+ }
5102
+ async function getGitFileDiff(workspace, filePath, options = {}) {
5103
+ const lastCheckedAt = Date.now();
5104
+ const repo = await resolveGitRepository(workspace, options);
5105
+ const repoRoot = repo.repoRoot;
5106
+ const selected = await resolveRepoFilePath(repoRoot, filePath);
5107
+ const maxBytes = normalizePositiveInteger(options.maxBytes, DEFAULT_MAX_BYTES);
5108
+ const [unstaged, staged] = await Promise.all([
5109
+ runGit(repo, ["diff", "--no-ext-diff", "--", selected.relativePath], { ...options, cwd: repoRoot }),
5110
+ runGit(repo, ["diff", "--cached", "--no-ext-diff", "--", selected.relativePath], { ...options, cwd: repoRoot })
5111
+ ]);
5112
+ let diff = [unstaged.stdout, staged.stdout].filter((part) => part.length > 0).join("\n");
5113
+ if (!diff) {
5114
+ const untracked = await runGit(repo, ["ls-files", "--others", "--exclude-standard", "--", selected.relativePath], {
5115
+ ...options,
5116
+ cwd: repoRoot
5117
+ });
5118
+ const untrackedFiles = untracked.stdout.split("\n").filter(Boolean);
5119
+ if (untrackedFiles.includes(selected.relativePath)) {
5120
+ diff = await buildUntrackedDiff(selected.absolutePath, selected.relativePath, maxBytes + 1);
5121
+ }
5122
+ }
5123
+ const bounded = truncateText(diff, maxBytes);
5124
+ return {
5125
+ workspace: repo.workspace,
5126
+ repoRoot,
5127
+ isGitRepo: true,
5128
+ path: selected.relativePath,
5129
+ diff: bounded.text,
5130
+ truncated: bounded.truncated,
5131
+ lastCheckedAt
5132
+ };
5133
+ }
5134
+ function combineDiffEntries(nameStatusOutput, numstatOutput, staged) {
5135
+ const statusEntries = parseNameStatus(nameStatusOutput);
5136
+ const numstatEntries = parseNumstat(numstatOutput);
5137
+ return statusEntries.map((entry, index) => {
5138
+ const stats = numstatEntries[index];
5139
+ return {
5140
+ path: entry.path,
5141
+ oldPath: entry.oldPath,
5142
+ status: entry.status,
5143
+ staged,
5144
+ insertions: stats?.insertions ?? 0,
5145
+ deletions: stats?.deletions ?? 0,
5146
+ binary: stats?.binary || void 0
5147
+ };
5148
+ });
5149
+ }
5150
+ function parseNameStatus(output) {
5151
+ return output.split("\n").filter(Boolean).map((line) => {
5152
+ const fields = line.split(" ");
5153
+ const code = fields[0] ?? "";
5154
+ const statusLetter = code[0] ?? "M";
5155
+ if (statusLetter === "R") {
5156
+ return {
5157
+ oldPath: fields[1] ?? "",
5158
+ path: fields[2] ?? fields[1] ?? "",
5159
+ status: "renamed"
5160
+ };
5161
+ }
5162
+ if (statusLetter === "C") {
5163
+ return {
5164
+ oldPath: fields[1] ?? "",
5165
+ path: fields[2] ?? fields[1] ?? "",
5166
+ status: "copied"
5167
+ };
5168
+ }
5169
+ return {
5170
+ path: fields[1] ?? "",
5171
+ status: mapNameStatus(statusLetter)
5172
+ };
5173
+ }).filter((entry) => entry.path.length > 0);
5174
+ }
5175
+ function parseNumstat(output) {
5176
+ return output.split("\n").filter(Boolean).map((line) => {
5177
+ const fields = line.split(" ");
5178
+ const insertionsText = fields[0] ?? "0";
5179
+ const deletionsText = fields[1] ?? "0";
5180
+ const binary = insertionsText === "-" || deletionsText === "-";
5181
+ return {
5182
+ path: fields.slice(2).join(" "),
5183
+ insertions: binary ? 0 : Number.parseInt(insertionsText, 10) || 0,
5184
+ deletions: binary ? 0 : Number.parseInt(deletionsText, 10) || 0,
5185
+ binary
5186
+ };
5187
+ });
5188
+ }
5189
+ function parseUntrackedFiles(output) {
5190
+ return output.split("\n").filter(Boolean).map((filePath) => ({
5191
+ path: filePath,
5192
+ status: "untracked",
5193
+ staged: false,
5194
+ insertions: 0,
5195
+ deletions: 0
5196
+ }));
5197
+ }
5198
+ function mapNameStatus(status) {
5199
+ switch (status) {
5200
+ case "A":
5201
+ return "added";
5202
+ case "D":
5203
+ return "deleted";
5204
+ case "R":
5205
+ return "renamed";
5206
+ case "C":
5207
+ return "copied";
5208
+ case "U":
5209
+ return "conflict";
5210
+ case "M":
5211
+ case "T":
5212
+ default:
5213
+ return "modified";
5214
+ }
5215
+ }
5216
+ async function resolveRepoFilePath(repoRoot, filePath) {
5217
+ if (typeof filePath !== "string" || filePath.length === 0 || filePath.includes("\0")) {
5218
+ throw new GitCommandError("invalid_args", "File path must be a non-empty path");
5219
+ }
5220
+ const canonicalRepoRoot = await (0, import_promises2.realpath)(repoRoot).catch(() => path2.resolve(repoRoot));
5221
+ const absolutePath = path2.isAbsolute(filePath) ? path2.resolve(filePath) : path2.resolve(repoRoot, filePath);
5222
+ const checkPath = await (0, import_promises2.realpath)(absolutePath).catch(() => absolutePath);
5223
+ const relativeBase = isPathInside(canonicalRepoRoot, checkPath) ? canonicalRepoRoot : path2.resolve(repoRoot);
5224
+ if (!isPathInside(canonicalRepoRoot, checkPath) && !isPathInside(repoRoot, absolutePath)) {
5225
+ throw new GitCommandError("path_outside_repo", "Selected file path is outside the repository root", {
5226
+ cwd: repoRoot
5227
+ });
5228
+ }
5229
+ const relativePath = path2.relative(relativeBase, checkPath).split(path2.sep).join("/");
5230
+ if (!relativePath || relativePath.startsWith("..") || path2.isAbsolute(relativePath)) {
5231
+ throw new GitCommandError("path_outside_repo", "Selected file path is outside the repository root", {
5232
+ cwd: repoRoot
5233
+ });
5234
+ }
5235
+ return { absolutePath, relativePath };
5236
+ }
5237
+ async function buildUntrackedDiff(absolutePath, relativePath, readLimit) {
5238
+ const content = await (0, import_promises2.readFile)(absolutePath, "utf8");
5239
+ const limitedContent = content.length > readLimit ? content.slice(0, readLimit) : content;
5240
+ const lines = limitedContent.length > 0 ? limitedContent.split("\n") : [];
5241
+ const plusLines = lines.filter((line, index) => index < lines.length - 1 || line.length > 0).map((line) => `+${line}`).join("\n");
5242
+ const lineCount = plusLines ? plusLines.split("\n").length : 0;
5243
+ return [
5244
+ `diff --git a/${relativePath} b/${relativePath}`,
5245
+ "new file mode 100644",
5246
+ "index 0000000..0000000",
5247
+ "--- /dev/null",
5248
+ `+++ b/${relativePath}`,
5249
+ `@@ -0,0 +1,${lineCount} @@`,
5250
+ plusLines
5251
+ ].filter((line) => line.length > 0).join("\n");
5252
+ }
5253
+ function truncateText(text, maxBytes) {
5254
+ if (byteLength(text) <= maxBytes) return { text, truncated: false };
5255
+ return { text: Buffer.from(text, "utf8").subarray(0, maxBytes).toString("utf8"), truncated: true };
5256
+ }
5257
+ function byteLength(text) {
5258
+ return Buffer.byteLength(text, "utf8");
5259
+ }
5260
+ function normalizePositiveInteger(value, fallback) {
5261
+ if (!Number.isFinite(value) || value == null || value <= 0) return fallback;
5262
+ return Math.floor(value);
5263
+ }
5264
+
5265
+ // src/git/git-summary.ts
5266
+ function countStatusChangedFiles(status) {
5267
+ const conflictCount = status.conflictFiles.length > 0 ? status.conflictFiles.length : status.hasConflicts ? 1 : 0;
5268
+ return status.staged + status.modified + status.untracked + status.deleted + status.renamed + conflictCount;
5269
+ }
5270
+ function createGitCompactSummary(status, diffSummary) {
5271
+ const statusChangedFiles = countStatusChangedFiles(status);
5272
+ const diffChangedFiles = diffSummary?.files.length ?? 0;
5273
+ const changedFiles = Math.max(statusChangedFiles, diffChangedFiles);
5274
+ const conflictCount = status.conflictFiles.length > 0 ? status.conflictFiles.length : status.hasConflicts ? 1 : 0;
5275
+ return {
5276
+ isGitRepo: status.isGitRepo,
5277
+ repoRoot: status.repoRoot,
5278
+ branch: status.branch,
5279
+ dirty: status.staged > 0 || status.modified > 0 || status.untracked > 0 || status.deleted > 0 || status.renamed > 0 || conflictCount > 0 || changedFiles > 0,
5280
+ changedFiles,
5281
+ ahead: status.ahead,
5282
+ behind: status.behind,
5283
+ hasConflicts: status.hasConflicts || conflictCount > 0,
5284
+ lastCheckedAt: Math.max(status.lastCheckedAt, diffSummary?.lastCheckedAt ?? status.lastCheckedAt),
5285
+ error: status.error ?? diffSummary?.error,
5286
+ reason: status.reason ?? diffSummary?.reason
5287
+ };
5288
+ }
5289
+ var summarizeGitStatus = createGitCompactSummary;
5290
+
5291
+ // src/git/git-snapshot-store.ts
5292
+ function normalizeCapacity(capacity) {
5293
+ return Math.max(1, Math.floor(capacity ?? 100));
5294
+ }
5295
+ function createEmptyDiffSummary(status) {
5296
+ return {
5297
+ workspace: status.workspace,
5298
+ repoRoot: status.repoRoot,
5299
+ isGitRepo: status.isGitRepo,
5300
+ files: [],
5301
+ totalInsertions: 0,
5302
+ totalDeletions: 0,
5303
+ truncated: false,
5304
+ lastCheckedAt: status.lastCheckedAt,
5305
+ error: status.error,
5306
+ reason: status.reason
5307
+ };
5308
+ }
5309
+ function changedFileKey(file) {
5310
+ return `${file.oldPath ?? ""}\0${file.path}`;
5311
+ }
5312
+ function uniqueSorted(values) {
5313
+ return Array.from(new Set(Array.from(values).filter(Boolean))).sort((a, b) => a.localeCompare(b));
5314
+ }
5315
+ function plural(count, singular, pluralText = `${singular}s`) {
5316
+ return count === 1 ? singular : pluralText;
5317
+ }
5318
+ function compareGitSnapshots(before, after) {
5319
+ const beforeFileKeys = new Set(before.diffSummary.files.map(changedFileKey));
5320
+ const changedAfterFiles = after.diffSummary.files.filter((file) => !beforeFileKeys.has(changedFileKey(file)));
5321
+ const addedFiles = [];
5322
+ const modifiedFiles = [];
5323
+ const deletedFiles = [];
5324
+ const renamedFiles = [];
5325
+ const untrackedFiles = [];
5326
+ const conflictFilesFromDiff = [];
5327
+ let totalInsertions = 0;
5328
+ let totalDeletions = 0;
5329
+ for (const file of changedAfterFiles) {
5330
+ totalInsertions += file.insertions;
5331
+ totalDeletions += file.deletions;
5332
+ switch (file.status) {
5333
+ case "added":
5334
+ case "copied":
5335
+ addedFiles.push(file.path);
5336
+ break;
5337
+ case "modified":
5338
+ modifiedFiles.push(file.path);
5339
+ break;
5340
+ case "deleted":
5341
+ deletedFiles.push(file.path);
5342
+ break;
5343
+ case "renamed":
5344
+ renamedFiles.push({ oldPath: file.oldPath ?? file.path, path: file.path });
5345
+ break;
5346
+ case "untracked":
5347
+ untrackedFiles.push(file.path);
5348
+ break;
5349
+ case "conflict":
5350
+ conflictFilesFromDiff.push(file.path);
5351
+ break;
5352
+ }
5353
+ }
5354
+ renamedFiles.sort((a, b) => `${a.oldPath}\0${a.path}`.localeCompare(`${b.oldPath}\0${b.path}`));
5355
+ const conflictFiles = uniqueSorted([...after.status.conflictFiles, ...conflictFilesFromDiff]);
5356
+ const changedFiles = changedAfterFiles.length;
5357
+ const hasConflicts = after.status.hasConflicts || conflictFiles.length > 0;
5358
+ const summaryParts = [];
5359
+ if (changedFiles > 0) summaryParts.push(`${changedFiles} ${plural(changedFiles, "file")} changed`);
5360
+ if (addedFiles.length > 0) summaryParts.push(`${addedFiles.length} added`);
5361
+ if (modifiedFiles.length > 0) summaryParts.push(`${modifiedFiles.length} modified`);
5362
+ if (deletedFiles.length > 0) summaryParts.push(`${deletedFiles.length} deleted`);
5363
+ if (renamedFiles.length > 0) summaryParts.push(`${renamedFiles.length} renamed`);
5364
+ if (untrackedFiles.length > 0) summaryParts.push(`${untrackedFiles.length} untracked`);
5365
+ if (hasConflicts) summaryParts.push(`${conflictFiles.length || 1} ${plural(conflictFiles.length || 1, "conflict")}`);
5366
+ return {
5367
+ beforeSnapshotId: before.id,
5368
+ afterSnapshotId: after.id,
5369
+ workspace: after.workspace,
5370
+ repoRoot: after.repoRoot,
5371
+ changedFiles,
5372
+ addedFiles: uniqueSorted(addedFiles),
5373
+ modifiedFiles: uniqueSorted(modifiedFiles),
5374
+ deletedFiles: uniqueSorted(deletedFiles),
5375
+ renamedFiles,
5376
+ untrackedFiles: uniqueSorted(untrackedFiles),
5377
+ conflictFiles,
5378
+ totalInsertions,
5379
+ totalDeletions,
5380
+ hasConflicts,
5381
+ currentStatus: after.status,
5382
+ summaryText: summaryParts.length > 0 ? summaryParts.join(", ") : "No file-set changes between snapshots."
5383
+ };
5384
+ }
5385
+ var InMemoryGitSnapshotStore = class {
5386
+ snapshots = /* @__PURE__ */ new Map();
5387
+ order = [];
5388
+ capacity;
5389
+ now;
5390
+ idPrefix;
5391
+ getStatusProvider;
5392
+ getDiffSummaryProvider;
5393
+ counter = 0;
5394
+ constructor(options = {}) {
5395
+ this.capacity = normalizeCapacity(options.capacity);
5396
+ this.now = options.now ?? Date.now;
5397
+ this.idPrefix = options.idPrefix ?? "git-snapshot";
5398
+ this.getStatusProvider = options.getStatus;
5399
+ this.getDiffSummaryProvider = options.getDiffSummary;
5400
+ }
5401
+ async create(input) {
5402
+ const getStatus = input.getStatus ?? this.getStatusProvider;
5403
+ if (!getStatus) {
5404
+ throw new Error("GitSnapshotStore requires an injected getStatus provider");
5405
+ }
5406
+ const status = await getStatus(input.workspace);
5407
+ const getDiffSummary = input.getDiffSummary ?? this.getDiffSummaryProvider;
5408
+ const diffSummary = getDiffSummary ? await getDiffSummary(input.workspace, status) : createEmptyDiffSummary(status);
5409
+ const createdAt = this.now();
5410
+ const id = `${this.idPrefix}-${createdAt}-${++this.counter}`;
5411
+ const snapshot = {
5412
+ id,
5413
+ workspace: input.workspace,
5414
+ repoRoot: status.repoRoot ?? input.workspace,
5415
+ sessionId: input.sessionId,
5416
+ turnId: input.turnId,
5417
+ reason: input.reason,
5418
+ status,
5419
+ diffSummary,
5420
+ createdAt
5421
+ };
5422
+ this.snapshots.set(id, snapshot);
5423
+ this.order.push(id);
5424
+ this.enforceCapacity();
5425
+ return snapshot;
5426
+ }
5427
+ get(id) {
5428
+ return this.snapshots.get(id);
5429
+ }
5430
+ compare(beforeSnapshotId, afterSnapshotId) {
5431
+ const before = this.snapshots.get(beforeSnapshotId);
5432
+ if (!before) throw new Error(`Unknown before snapshot: ${beforeSnapshotId}`);
5433
+ const after = this.snapshots.get(afterSnapshotId);
5434
+ if (!after) throw new Error(`Unknown after snapshot: ${afterSnapshotId}`);
5435
+ return compareGitSnapshots(before, after);
5436
+ }
5437
+ list(query = {}) {
5438
+ const limit = Math.max(1, Math.floor(query.limit ?? this.capacity));
5439
+ 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);
5440
+ }
5441
+ clear() {
5442
+ this.snapshots.clear();
5443
+ this.order.splice(0, this.order.length);
5444
+ }
5445
+ enforceCapacity() {
5446
+ while (this.order.length > this.capacity) {
5447
+ const evictedId = this.order.shift();
5448
+ if (evictedId) this.snapshots.delete(evictedId);
5449
+ }
5450
+ }
5451
+ };
5452
+ function createGitSnapshotStore(options = {}) {
5453
+ return new InMemoryGitSnapshotStore(options);
5454
+ }
5455
+
5456
+ // src/git/git-monitor.ts
5457
+ var DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS = 5e3;
5458
+ var MIN_GIT_WORKSPACE_POLL_INTERVAL_MS = 1e3;
5459
+ function defaultStatusProvider(workspace) {
5460
+ return getGitRepoStatus(workspace);
5461
+ }
5462
+ function defaultDiffSummaryProvider(workspace) {
5463
+ return getGitDiffSummary(workspace);
5464
+ }
5465
+ function normalizeIntervalMs(value, defaultIntervalMs, minIntervalMs) {
5466
+ const requested = Number.isFinite(value) ? Math.floor(value) : defaultIntervalMs;
5467
+ return Math.max(minIntervalMs, requested > 0 ? requested : defaultIntervalMs);
5468
+ }
5469
+ function normalizeGitWorkspaceSubscriptionParams(params, options = {}) {
5470
+ const minIntervalMs = Math.max(1, Math.floor(options.minIntervalMs ?? MIN_GIT_WORKSPACE_POLL_INTERVAL_MS));
5471
+ const defaultIntervalMs = Math.max(minIntervalMs, Math.floor(options.defaultIntervalMs ?? DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS));
5472
+ return {
5473
+ workspace: params.workspace,
5474
+ includeDiffSummary: Boolean(params.includeDiffSummary),
5475
+ intervalMs: normalizeIntervalMs(params.intervalMs, defaultIntervalMs, minIntervalMs)
5476
+ };
5477
+ }
5478
+ var GitWorkspaceMonitor = class {
5479
+ getStatusProvider;
5480
+ getDiffSummaryProvider;
5481
+ now;
5482
+ minIntervalMs;
5483
+ defaultIntervalMs;
5484
+ keyPrefix;
5485
+ cache = /* @__PURE__ */ new Map();
5486
+ listeners = /* @__PURE__ */ new Set();
5487
+ seq = 0;
5488
+ constructor(options = {}) {
5489
+ this.getStatusProvider = options.getStatus ?? defaultStatusProvider;
5490
+ this.getDiffSummaryProvider = options.getDiffSummary ?? defaultDiffSummaryProvider;
5491
+ this.now = options.now ?? Date.now;
5492
+ this.minIntervalMs = Math.max(1, Math.floor(options.minIntervalMs ?? MIN_GIT_WORKSPACE_POLL_INTERVAL_MS));
5493
+ this.defaultIntervalMs = Math.max(
5494
+ this.minIntervalMs,
5495
+ Math.floor(options.defaultIntervalMs ?? DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS)
5496
+ );
5497
+ this.keyPrefix = options.keyPrefix ?? "git";
5498
+ }
5499
+ async refresh(params) {
5500
+ const normalized = this.normalize(typeof params === "string" ? { workspace: params } : params);
5501
+ const status = await this.getStatusProvider(normalized.workspace);
5502
+ const diffSummary = normalized.includeDiffSummary ? await this.getDiffSummaryProvider(normalized.workspace, status) : void 0;
5503
+ const compactSummary = createGitCompactSummary(status, diffSummary);
5504
+ const timestamp = this.now();
5505
+ const seq = ++this.seq;
5506
+ const key = this.keyForWorkspace(normalized.workspace);
5507
+ const update = {
5508
+ topic: "workspace.git",
5509
+ key,
5510
+ workspace: normalized.workspace,
5511
+ status,
5512
+ diffSummary,
5513
+ seq,
5514
+ timestamp
5515
+ };
5516
+ const cacheEntry = {
5517
+ key,
5518
+ workspace: normalized.workspace,
5519
+ status,
5520
+ diffSummary,
5521
+ compactSummary,
5522
+ seq,
5523
+ timestamp
5524
+ };
5525
+ this.cache.set(normalized.workspace, cacheEntry);
5526
+ this.emit(update, cacheEntry);
5527
+ return update;
5528
+ }
5529
+ poll(params) {
5530
+ return this.refresh(params);
5531
+ }
5532
+ getCached(workspace) {
5533
+ return this.cache.get(workspace);
5534
+ }
5535
+ getCompactSummary(workspace) {
5536
+ return this.cache.get(workspace)?.compactSummary;
5537
+ }
5538
+ onUpdate(listener) {
5539
+ this.listeners.add(listener);
5540
+ return () => {
5541
+ this.listeners.delete(listener);
5542
+ };
5543
+ }
5544
+ createSubscription(params, listener) {
5545
+ const normalized = this.normalize(params);
5546
+ const scopedListener = listener ? (update, cacheEntry) => {
5547
+ if (update.workspace === normalized.workspace) listener(update, cacheEntry);
5548
+ } : void 0;
5549
+ const unsubscribe = scopedListener ? this.onUpdate(scopedListener) : () => void 0;
5550
+ return {
5551
+ params: normalized,
5552
+ refresh: () => this.refresh(normalized),
5553
+ getCached: () => this.getCached(normalized.workspace),
5554
+ dispose: unsubscribe
5555
+ };
5556
+ }
5557
+ normalize(params) {
5558
+ return normalizeGitWorkspaceSubscriptionParams(params, {
5559
+ defaultIntervalMs: this.defaultIntervalMs,
5560
+ minIntervalMs: this.minIntervalMs
5561
+ });
5562
+ }
5563
+ keyForWorkspace(workspace) {
5564
+ return `${this.keyPrefix}:${workspace}`;
5565
+ }
5566
+ emit(update, cacheEntry) {
5567
+ for (const listener of this.listeners) {
5568
+ listener(update, cacheEntry);
5569
+ }
5570
+ }
5571
+ };
5572
+ function createGitWorkspaceMonitor(options = {}) {
5573
+ return new GitWorkspaceMonitor(options);
5574
+ }
5575
+
5576
+ // src/git/git-commands.ts
5577
+ var path3 = __toESM(require("path"));
5578
+ var GIT_COMMAND_NAMES = /* @__PURE__ */ new Set([
5579
+ "git_status",
5580
+ "git_diff_summary",
5581
+ "git_diff_file",
5582
+ "git_snapshot_create",
5583
+ "git_snapshot_compare",
5584
+ "git_log",
5585
+ "git_checkpoint",
5586
+ "git_stash_push",
5587
+ "git_stash_pop",
5588
+ "git_checkout_files"
5589
+ ]);
5590
+ var MUTATING_COMMAND_NAMES = /* @__PURE__ */ new Set([
5591
+ "git_checkpoint",
5592
+ "git_stash_push",
5593
+ "git_stash_pop",
5594
+ "git_checkout_files"
5595
+ ]);
5596
+ var SNAPSHOT_REASONS = /* @__PURE__ */ new Set([
5597
+ "session_baseline",
5598
+ "before_user_input_dispatch",
5599
+ "before_agent_work",
5600
+ "after_agent_work",
5601
+ "manual"
5602
+ ]);
5603
+ var FAILURE_REASONS = /* @__PURE__ */ new Set([
5604
+ "not_git_repo",
5605
+ "git_not_installed",
5606
+ "timeout",
5607
+ "path_outside_repo",
5608
+ "dirty_index_required",
5609
+ "conflict",
5610
+ "invalid_args",
5611
+ "git_command_failed"
5612
+ ]);
5613
+ function failure(reason, error) {
5614
+ return { success: false, reason, error };
5615
+ }
5616
+ function serviceNotImplemented(command) {
5617
+ return failure("invalid_args", `${command} is not implemented: daemon-core Git service is not configured`);
5618
+ }
5619
+ var defaultSnapshotStore = createGitSnapshotStore({
5620
+ getStatus: (workspace) => getGitRepoStatus(workspace),
5621
+ getDiffSummary: (workspace) => getGitDiffSummary(workspace)
5622
+ });
5623
+ function createDefaultGitCommandServices() {
5624
+ return {
5625
+ getStatus: ({ workspace }) => getGitRepoStatus(workspace),
5626
+ getDiffSummary: ({ workspace }) => getGitDiffSummary(workspace),
5627
+ getDiffFile: ({ workspace, path: filePath }) => getGitFileDiff(workspace, filePath),
5628
+ createSnapshot: ({ workspace, reason, sessionId, turnId }) => defaultSnapshotStore.create({
5629
+ workspace,
5630
+ reason,
5631
+ sessionId,
5632
+ turnId
5633
+ }),
5634
+ compareSnapshots: ({ beforeSnapshotId, afterSnapshotId }) => defaultSnapshotStore.compare(beforeSnapshotId, afterSnapshotId),
5635
+ getLog: ({ workspace, limit, path: filePath, since, until }) => getGitLog(workspace, { limit, path: filePath, since, until })
5636
+ };
5637
+ }
5638
+ var defaultGitCommandServices = createDefaultGitCommandServices();
5639
+ function validateWorkspace2(args) {
5640
+ if (typeof args?.workspace !== "string") {
5641
+ return failure("invalid_args", "workspace must be a non-empty absolute path");
5642
+ }
5643
+ const workspace = args.workspace.trim();
5644
+ if (!workspace || !path3.isAbsolute(workspace)) {
5645
+ return failure("invalid_args", "workspace must be a non-empty absolute path");
5646
+ }
5647
+ return { workspace };
5648
+ }
5649
+ function validateRepoPath(args) {
5650
+ if (typeof args?.path !== "string" || !args.path.trim()) {
5651
+ return failure("invalid_args", "path must be a non-empty repository-relative path");
5652
+ }
5653
+ return { path: args.path.trim() };
5654
+ }
5655
+ function validateSnapshotId(args, key) {
5656
+ if (typeof args?.[key] !== "string" || !args[key].trim()) {
5657
+ return failure("invalid_args", `${key} must be a non-empty string`);
5658
+ }
5659
+ return args[key].trim();
5660
+ }
5661
+ function parseSnapshotReason(args) {
5662
+ if (args?.reason === void 0 || args?.reason === null || args?.reason === "") {
5663
+ return "manual";
5664
+ }
5665
+ if (typeof args.reason !== "string" || !SNAPSHOT_REASONS.has(args.reason)) {
5666
+ return failure("invalid_args", "reason must be a valid GitSnapshotReason");
5667
+ }
5668
+ return args.reason;
5669
+ }
5670
+ function optionalString(value) {
5671
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
5672
+ }
5673
+ function optionalBoolean(value) {
5674
+ return typeof value === "boolean" ? value : void 0;
5675
+ }
5676
+ function boundedLogLimit(value) {
5677
+ if (value === void 0 || value === null || value === "") return 50;
5678
+ const numeric = typeof value === "number" ? value : Number(value);
5679
+ if (!Number.isFinite(numeric)) return 50;
5680
+ return Math.max(1, Math.min(200, Math.floor(numeric)));
5681
+ }
5682
+ function failureReasonFromError(error) {
5683
+ return typeof error?.reason === "string" && FAILURE_REASONS.has(error.reason) ? error.reason : "git_command_failed";
5684
+ }
5685
+ async function runService(fn) {
5686
+ try {
5687
+ return await fn();
5688
+ } catch (error) {
5689
+ return failure(failureReasonFromError(error), error?.message || "Git command failed");
5690
+ }
5691
+ }
5692
+ function isGitCommandName(command) {
5693
+ return GIT_COMMAND_NAMES.has(command);
5694
+ }
5695
+ async function handleGitCommand(command, args, services = defaultGitCommandServices) {
5696
+ if (!isGitCommandName(command)) {
5697
+ return failure("invalid_args", `Unknown Git command: ${command}`);
5698
+ }
5699
+ if (MUTATING_COMMAND_NAMES.has(command)) {
5700
+ return failure("invalid_args", `${command} is not implemented in daemon-core read-only Git routing`);
5701
+ }
5702
+ const workspaceResult = validateWorkspace2(args);
5703
+ if ("success" in workspaceResult) return workspaceResult;
5704
+ const { workspace } = workspaceResult;
5705
+ switch (command) {
5706
+ case "git_status": {
5707
+ if (!services.getStatus) return serviceNotImplemented(command);
5708
+ const status = await runService(() => services.getStatus({ workspace }));
5709
+ return "success" in status ? status : { success: true, status };
5710
+ }
5711
+ case "git_diff_summary": {
5712
+ if (!services.getDiffSummary) return serviceNotImplemented(command);
5713
+ const diffSummary = await runService(() => services.getDiffSummary({ workspace, staged: optionalBoolean(args?.staged) }));
5714
+ return "success" in diffSummary ? diffSummary : { success: true, diffSummary };
5715
+ }
5716
+ case "git_diff_file": {
5717
+ if (!services.getDiffFile) return serviceNotImplemented(command);
5718
+ const pathResult = validateRepoPath(args);
5719
+ if (typeof pathResult !== "object" || "success" in pathResult) return pathResult;
5720
+ const diff = await runService(() => services.getDiffFile({
5721
+ workspace,
5722
+ path: pathResult.path,
5723
+ staged: optionalBoolean(args?.staged)
5724
+ }));
5725
+ return "success" in diff ? diff : { success: true, diff };
5726
+ }
5727
+ case "git_snapshot_create": {
5728
+ if (!services.createSnapshot) return serviceNotImplemented(command);
5729
+ const reason = parseSnapshotReason(args);
5730
+ if (typeof reason !== "string") return reason;
5731
+ const snapshot = await runService(() => services.createSnapshot({
5732
+ workspace,
5733
+ reason,
5734
+ sessionId: optionalString(args?.sessionId),
5735
+ turnId: optionalString(args?.turnId)
5736
+ }));
5737
+ return "success" in snapshot ? snapshot : { success: true, snapshot };
5738
+ }
5739
+ case "git_snapshot_compare": {
5740
+ if (!services.compareSnapshots) return serviceNotImplemented(command);
5741
+ const beforeSnapshotId = validateSnapshotId(args, "beforeSnapshotId");
5742
+ if (typeof beforeSnapshotId !== "string") return beforeSnapshotId;
5743
+ const afterSnapshotId = validateSnapshotId(args, "afterSnapshotId");
5744
+ if (typeof afterSnapshotId !== "string") return afterSnapshotId;
5745
+ const compare = await runService(() => services.compareSnapshots({ workspace, beforeSnapshotId, afterSnapshotId }));
5746
+ return "success" in compare ? compare : { success: true, compare };
5747
+ }
5748
+ case "git_log": {
5749
+ if (!services.getLog) {
5750
+ return failure("invalid_args", "git_log is not implemented: bounded daemon-core Git log service is not configured");
5751
+ }
5752
+ const log = await runService(() => services.getLog({
5753
+ workspace,
5754
+ limit: boundedLogLimit(args?.limit),
5755
+ path: optionalString(args?.path),
5756
+ since: optionalString(args?.since),
5757
+ until: optionalString(args?.until)
5758
+ }));
5759
+ return "success" in log ? log : { success: true, log };
5760
+ }
5761
+ default:
5762
+ return failure("invalid_args", `Unknown Git command: ${command}`);
5763
+ }
5764
+ }
5765
+ function formatOptionalGitLogRangeArg(flag, value) {
5766
+ return value ? [`${flag}=${value}`] : [];
5767
+ }
5768
+ async function getGitLog(workspace, options) {
5769
+ const lastCheckedAt = Date.now();
5770
+ const repo = await resolveGitRepository(workspace);
5771
+ const repoRoot = repo.repoRoot;
5772
+ const boundedLimit = Math.max(1, Math.min(200, Math.floor(options.limit || 50)));
5773
+ const selectedPath = options.path ? validateGitLogPath(repoRoot, options.path) : void 0;
5774
+ const result = await runGit(
5775
+ repo,
5776
+ [
5777
+ "log",
5778
+ `--max-count=${boundedLimit}`,
5779
+ "--format=%H%x00%an%x00%ae%x00%at%x00%ct%x00%s",
5780
+ ...formatOptionalGitLogRangeArg("--since", options.since),
5781
+ ...formatOptionalGitLogRangeArg("--until", options.until),
5782
+ "--",
5783
+ ...selectedPath ? [selectedPath] : []
5784
+ ],
5785
+ { cwd: repoRoot }
5786
+ );
5787
+ const entries = result.stdout.split("\n").filter((line) => line.trim().length > 0).map((line) => {
5788
+ const [commit = "", authorName, authorEmail, authoredAt, committedAt, ...messageParts] = line.split("\0");
5789
+ return {
5790
+ commit,
5791
+ message: messageParts.join("\0"),
5792
+ authorName: authorName || void 0,
5793
+ authorEmail: authorEmail || void 0,
5794
+ authoredAt: authoredAt ? Number.parseInt(authoredAt, 10) * 1e3 : void 0,
5795
+ committedAt: committedAt ? Number.parseInt(committedAt, 10) * 1e3 : void 0
5796
+ };
5797
+ }).filter((entry) => entry.commit.length > 0);
5798
+ return {
5799
+ workspace: repo.workspace,
5800
+ repoRoot,
5801
+ isGitRepo: true,
5802
+ entries,
5803
+ limit: boundedLimit,
5804
+ truncated: entries.length >= boundedLimit,
5805
+ lastCheckedAt
5806
+ };
5807
+ }
5808
+ function validateGitLogPath(repoRoot, filePath) {
5809
+ if (!filePath.trim() || filePath.includes("\0")) {
5810
+ throw new GitCommandError("invalid_args", "path must be a non-empty repository-relative path");
5811
+ }
5812
+ if (path3.isAbsolute(filePath)) {
5813
+ throw new GitCommandError("invalid_args", "path must be repository-relative");
5814
+ }
5815
+ const normalized = path3.normalize(filePath).split(path3.sep).join("/");
5816
+ const absolutePath = path3.resolve(repoRoot, normalized);
5817
+ if (!isPathInside(repoRoot, absolutePath) || normalized.startsWith("../") || normalized === "..") {
5818
+ throw new GitCommandError("path_outside_repo", "Git log path is outside the repository root");
5819
+ }
5820
+ return normalized;
5821
+ }
5822
+
5823
+ // src/index.ts
4683
5824
  init_config();
4684
5825
 
4685
5826
  // src/config/workspaces.ts
4686
5827
  var fs = __toESM(require("fs"));
4687
5828
  var os = __toESM(require("os"));
4688
- var path = __toESM(require("path"));
5829
+ var path4 = __toESM(require("path"));
4689
5830
  var import_crypto2 = require("crypto");
4690
5831
  var MAX_WORKSPACES = 50;
4691
5832
  function expandPath(p) {
4692
5833
  const t = (p || "").trim();
4693
5834
  if (!t) return "";
4694
- if (t.startsWith("~")) return path.join(os.homedir(), t.slice(1).replace(/^\//, ""));
4695
- return path.resolve(t);
5835
+ if (t.startsWith("~")) return path4.join(os.homedir(), t.slice(1).replace(/^\//, ""));
5836
+ return path4.resolve(t);
4696
5837
  }
4697
5838
  function validateWorkspacePath(absPath) {
4698
5839
  try {
@@ -4706,7 +5847,7 @@ function validateWorkspacePath(absPath) {
4706
5847
  }
4707
5848
  }
4708
5849
  function defaultWorkspaceLabel(absPath) {
4709
- const base = path.basename(absPath) || absPath;
5850
+ const base = path4.basename(absPath) || absPath;
4710
5851
  return base;
4711
5852
  }
4712
5853
  function getDefaultWorkspacePath(config) {
@@ -4797,9 +5938,9 @@ function resolveIdeLaunchWorkspace(args, config) {
4797
5938
  return getDefaultWorkspacePath(config) || void 0;
4798
5939
  }
4799
5940
  function findWorkspaceByPath(config, rawPath) {
4800
- const abs = path.resolve(expandPath(rawPath));
5941
+ const abs = path4.resolve(expandPath(rawPath));
4801
5942
  if (!abs) return void 0;
4802
- return (config.workspaces || []).find((w) => path.resolve(expandPath(w.path)) === abs);
5943
+ return (config.workspaces || []).find((w) => path4.resolve(expandPath(w.path)) === abs);
4803
5944
  }
4804
5945
  function addWorkspaceEntry(config, rawPath, label, options) {
4805
5946
  const abs = expandPath(rawPath);
@@ -4815,7 +5956,7 @@ function addWorkspaceEntry(config, rawPath, label, options) {
4815
5956
  const v = validateWorkspacePath(abs);
4816
5957
  if (!v.ok) return { error: v.error };
4817
5958
  const list = [...config.workspaces || []];
4818
- if (list.some((w) => path.resolve(w.path) === abs)) {
5959
+ if (list.some((w) => path4.resolve(w.path) === abs)) {
4819
5960
  return { error: "Workspace already in list" };
4820
5961
  }
4821
5962
  if (list.length >= MAX_WORKSPACES) {
@@ -4849,7 +5990,7 @@ function setDefaultWorkspaceId(config, id) {
4849
5990
  }
4850
5991
 
4851
5992
  // src/config/recent-activity.ts
4852
- var path2 = __toESM(require("path"));
5993
+ var path5 = __toESM(require("path"));
4853
5994
 
4854
5995
  // src/providers/summary-metadata.ts
4855
5996
  function normalizeSummaryItem(item) {
@@ -4918,9 +6059,9 @@ var MAX_ACTIVITY = 30;
4918
6059
  function normalizeWorkspace(workspace) {
4919
6060
  if (!workspace) return "";
4920
6061
  try {
4921
- return path2.resolve(expandPath(workspace));
6062
+ return path5.resolve(expandPath(workspace));
4922
6063
  } catch {
4923
- return path2.resolve(workspace);
6064
+ return path5.resolve(workspace);
4924
6065
  }
4925
6066
  }
4926
6067
  function buildRecentActivityKey(entry) {
@@ -5088,14 +6229,14 @@ function markSessionSeen(state, sessionId, seenAt = Date.now(), completionMarker
5088
6229
  }
5089
6230
 
5090
6231
  // src/config/saved-sessions.ts
5091
- var path3 = __toESM(require("path"));
6232
+ var path6 = __toESM(require("path"));
5092
6233
  var MAX_SAVED_SESSIONS = 500;
5093
6234
  function normalizeWorkspace2(workspace) {
5094
6235
  if (!workspace) return "";
5095
6236
  try {
5096
- return path3.resolve(expandPath(workspace));
6237
+ return path6.resolve(expandPath(workspace));
5097
6238
  } catch {
5098
- return path3.resolve(workspace);
6239
+ return path6.resolve(workspace);
5099
6240
  }
5100
6241
  }
5101
6242
  function buildSavedProviderSessionKey(providerSessionId) {
@@ -5214,7 +6355,7 @@ function resetState() {
5214
6355
  var import_child_process = require("child_process");
5215
6356
  var import_fs3 = require("fs");
5216
6357
  var import_os2 = require("os");
5217
- var path4 = __toESM(require("path"));
6358
+ var path7 = __toESM(require("path"));
5218
6359
  var BUILTIN_IDE_DEFINITIONS = [];
5219
6360
  var registeredIDEs = /* @__PURE__ */ new Map();
5220
6361
  function registerIDEDefinition(def) {
@@ -5233,9 +6374,9 @@ function getMergedDefinitions() {
5233
6374
  function findCliCommand(command) {
5234
6375
  const trimmed = String(command || "").trim();
5235
6376
  if (!trimmed) return null;
5236
- if (path4.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
5237
- const candidate = trimmed.startsWith("~") ? path4.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
5238
- const resolved = path4.isAbsolute(candidate) ? candidate : path4.resolve(candidate);
6377
+ if (path7.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
6378
+ const candidate = trimmed.startsWith("~") ? path7.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
6379
+ const resolved = path7.isAbsolute(candidate) ? candidate : path7.resolve(candidate);
5239
6380
  return (0, import_fs3.existsSync)(resolved) ? resolved : null;
5240
6381
  }
5241
6382
  try {
@@ -5263,7 +6404,7 @@ function getIdeVersion(cliCommand) {
5263
6404
  function checkPathExists(paths) {
5264
6405
  const home = (0, import_os2.homedir)();
5265
6406
  for (const p of paths) {
5266
- const normalized = p.startsWith("~") ? path4.join(home, p.slice(1)) : p;
6407
+ const normalized = p.startsWith("~") ? path7.join(home, p.slice(1)) : p;
5267
6408
  if (normalized.includes("*")) {
5268
6409
  const username = home.split(/[\\/]/).pop() || "";
5269
6410
  const resolved = normalized.replace("*", username);
@@ -5321,7 +6462,7 @@ async function detectIDEs(providerLoader) {
5321
6462
  // src/detection/cli-detector.ts
5322
6463
  var import_child_process2 = require("child_process");
5323
6464
  var os2 = __toESM(require("os"));
5324
- var path5 = __toESM(require("path"));
6465
+ var path8 = __toESM(require("path"));
5325
6466
  var import_fs4 = require("fs");
5326
6467
  function parseVersion(raw) {
5327
6468
  const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
@@ -5334,36 +6475,36 @@ function shellQuote(value) {
5334
6475
  function expandHome(value) {
5335
6476
  const trimmed = value.trim();
5336
6477
  if (!trimmed.startsWith("~")) return trimmed;
5337
- return path5.join(os2.homedir(), trimmed.slice(1));
6478
+ return path8.join(os2.homedir(), trimmed.slice(1));
5338
6479
  }
5339
6480
  function isExplicitCommandPath(command) {
5340
6481
  const trimmed = command.trim();
5341
- return path5.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
6482
+ return path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
5342
6483
  }
5343
6484
  function resolveCommandPath(command) {
5344
6485
  const trimmed = command.trim();
5345
6486
  if (!trimmed) return null;
5346
6487
  if (isExplicitCommandPath(trimmed)) {
5347
6488
  const expanded = expandHome(trimmed);
5348
- const candidate = path5.isAbsolute(expanded) ? expanded : path5.resolve(expanded);
6489
+ const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
5349
6490
  return (0, import_fs4.existsSync)(candidate) ? candidate : null;
5350
6491
  }
5351
6492
  return null;
5352
6493
  }
5353
6494
  function execAsync(cmd, timeoutMs = 5e3) {
5354
- return new Promise((resolve12) => {
6495
+ return new Promise((resolve15) => {
5355
6496
  const child = (0, import_child_process2.exec)(cmd, {
5356
6497
  encoding: "utf-8",
5357
6498
  timeout: timeoutMs,
5358
6499
  ...process.platform === "win32" ? { windowsHide: true } : {}
5359
6500
  }, (err, stdout) => {
5360
6501
  if (err || !stdout?.trim()) {
5361
- resolve12(null);
6502
+ resolve15(null);
5362
6503
  } else {
5363
- resolve12(stdout.trim());
6504
+ resolve15(stdout.trim());
5364
6505
  }
5365
6506
  });
5366
- child.on("error", () => resolve12(null));
6507
+ child.on("error", () => resolve15(null));
5367
6508
  });
5368
6509
  }
5369
6510
  async function detectCLIs(providerLoader, options) {
@@ -5728,7 +6869,7 @@ var DaemonCdpManager = class {
5728
6869
  * Returns multiple entries if multiple IDE windows are open on same port
5729
6870
  */
5730
6871
  static listAllTargets(port) {
5731
- return new Promise((resolve12) => {
6872
+ return new Promise((resolve15) => {
5732
6873
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
5733
6874
  let data = "";
5734
6875
  res.on("data", (chunk) => data += chunk.toString());
@@ -5744,16 +6885,16 @@ var DaemonCdpManager = class {
5744
6885
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
5745
6886
  );
5746
6887
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
5747
- resolve12(mainPages.length > 0 ? mainPages : fallbackPages);
6888
+ resolve15(mainPages.length > 0 ? mainPages : fallbackPages);
5748
6889
  } catch {
5749
- resolve12([]);
6890
+ resolve15([]);
5750
6891
  }
5751
6892
  });
5752
6893
  });
5753
- req.on("error", () => resolve12([]));
6894
+ req.on("error", () => resolve15([]));
5754
6895
  req.setTimeout(2e3, () => {
5755
6896
  req.destroy();
5756
- resolve12([]);
6897
+ resolve15([]);
5757
6898
  });
5758
6899
  });
5759
6900
  }
@@ -5793,7 +6934,7 @@ var DaemonCdpManager = class {
5793
6934
  }
5794
6935
  }
5795
6936
  findTargetOnPort(port) {
5796
- return new Promise((resolve12) => {
6937
+ return new Promise((resolve15) => {
5797
6938
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
5798
6939
  let data = "";
5799
6940
  res.on("data", (chunk) => data += chunk.toString());
@@ -5804,7 +6945,7 @@ var DaemonCdpManager = class {
5804
6945
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
5805
6946
  );
5806
6947
  if (pages.length === 0) {
5807
- resolve12(targets.find((t) => t.webSocketDebuggerUrl) || null);
6948
+ resolve15(targets.find((t) => t.webSocketDebuggerUrl) || null);
5808
6949
  return;
5809
6950
  }
5810
6951
  const titleFilteredPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -5823,25 +6964,25 @@ var DaemonCdpManager = class {
5823
6964
  this._targetId = selected.target.id;
5824
6965
  }
5825
6966
  this._pageTitle = selected.target.title || "";
5826
- resolve12(selected.target);
6967
+ resolve15(selected.target);
5827
6968
  return;
5828
6969
  }
5829
6970
  if (previousTargetId) {
5830
6971
  this.log(`[CDP] Target ${previousTargetId} not found in page list`);
5831
- resolve12(null);
6972
+ resolve15(null);
5832
6973
  return;
5833
6974
  }
5834
6975
  this._pageTitle = list[0]?.title || "";
5835
- resolve12(list[0]);
6976
+ resolve15(list[0]);
5836
6977
  } catch {
5837
- resolve12(null);
6978
+ resolve15(null);
5838
6979
  }
5839
6980
  });
5840
6981
  });
5841
- req.on("error", () => resolve12(null));
6982
+ req.on("error", () => resolve15(null));
5842
6983
  req.setTimeout(2e3, () => {
5843
6984
  req.destroy();
5844
- resolve12(null);
6985
+ resolve15(null);
5845
6986
  });
5846
6987
  });
5847
6988
  }
@@ -5852,7 +6993,7 @@ var DaemonCdpManager = class {
5852
6993
  this.extensionProviders = providers;
5853
6994
  }
5854
6995
  connectToTarget(wsUrl) {
5855
- return new Promise((resolve12) => {
6996
+ return new Promise((resolve15) => {
5856
6997
  this.ws = new import_ws.default(wsUrl);
5857
6998
  this.ws.on("open", async () => {
5858
6999
  this._connected = true;
@@ -5862,17 +7003,17 @@ var DaemonCdpManager = class {
5862
7003
  }
5863
7004
  this.connectBrowserWs().catch(() => {
5864
7005
  });
5865
- resolve12(true);
7006
+ resolve15(true);
5866
7007
  });
5867
7008
  this.ws.on("message", (data) => {
5868
7009
  try {
5869
7010
  const msg = JSON.parse(data.toString());
5870
7011
  if (msg.id && this.pending.has(msg.id)) {
5871
- const { resolve: resolve13, reject } = this.pending.get(msg.id);
7012
+ const { resolve: resolve16, reject } = this.pending.get(msg.id);
5872
7013
  this.pending.delete(msg.id);
5873
7014
  this.failureCount = 0;
5874
7015
  if (msg.error) reject(new Error(msg.error.message));
5875
- else resolve13(msg.result);
7016
+ else resolve16(msg.result);
5876
7017
  } else if (msg.method === "Runtime.executionContextCreated") {
5877
7018
  this.contexts.add(msg.params.context.id);
5878
7019
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -5895,7 +7036,7 @@ var DaemonCdpManager = class {
5895
7036
  this.ws.on("error", (err) => {
5896
7037
  this.log(`[CDP] WebSocket error: ${err.message}`);
5897
7038
  this._connected = false;
5898
- resolve12(false);
7039
+ resolve15(false);
5899
7040
  });
5900
7041
  });
5901
7042
  }
@@ -5909,7 +7050,7 @@ var DaemonCdpManager = class {
5909
7050
  return;
5910
7051
  }
5911
7052
  this.log(`[CDP] Connecting browser WS for target discovery...`);
5912
- await new Promise((resolve12, reject) => {
7053
+ await new Promise((resolve15, reject) => {
5913
7054
  this.browserWs = new import_ws.default(browserWsUrl);
5914
7055
  this.browserWs.on("open", async () => {
5915
7056
  this._browserConnected = true;
@@ -5919,16 +7060,16 @@ var DaemonCdpManager = class {
5919
7060
  } catch (e) {
5920
7061
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
5921
7062
  }
5922
- resolve12();
7063
+ resolve15();
5923
7064
  });
5924
7065
  this.browserWs.on("message", (data) => {
5925
7066
  try {
5926
7067
  const msg = JSON.parse(data.toString());
5927
7068
  if (msg.id && this.browserPending.has(msg.id)) {
5928
- const { resolve: resolve13, reject: reject2 } = this.browserPending.get(msg.id);
7069
+ const { resolve: resolve16, reject: reject2 } = this.browserPending.get(msg.id);
5929
7070
  this.browserPending.delete(msg.id);
5930
7071
  if (msg.error) reject2(new Error(msg.error.message));
5931
- else resolve13(msg.result);
7072
+ else resolve16(msg.result);
5932
7073
  }
5933
7074
  } catch {
5934
7075
  }
@@ -5948,31 +7089,31 @@ var DaemonCdpManager = class {
5948
7089
  }
5949
7090
  }
5950
7091
  getBrowserWsUrl() {
5951
- return new Promise((resolve12) => {
7092
+ return new Promise((resolve15) => {
5952
7093
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
5953
7094
  let data = "";
5954
7095
  res.on("data", (chunk) => data += chunk.toString());
5955
7096
  res.on("end", () => {
5956
7097
  try {
5957
7098
  const info = JSON.parse(data);
5958
- resolve12(info.webSocketDebuggerUrl || null);
7099
+ resolve15(info.webSocketDebuggerUrl || null);
5959
7100
  } catch {
5960
- resolve12(null);
7101
+ resolve15(null);
5961
7102
  }
5962
7103
  });
5963
7104
  });
5964
- req.on("error", () => resolve12(null));
7105
+ req.on("error", () => resolve15(null));
5965
7106
  req.setTimeout(3e3, () => {
5966
7107
  req.destroy();
5967
- resolve12(null);
7108
+ resolve15(null);
5968
7109
  });
5969
7110
  });
5970
7111
  }
5971
7112
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
5972
- return new Promise((resolve12, reject) => {
7113
+ return new Promise((resolve15, reject) => {
5973
7114
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
5974
7115
  const id = this.browserMsgId++;
5975
- this.browserPending.set(id, { resolve: resolve12, reject });
7116
+ this.browserPending.set(id, { resolve: resolve15, reject });
5976
7117
  this.browserWs.send(JSON.stringify({ id, method, params }));
5977
7118
  setTimeout(() => {
5978
7119
  if (this.browserPending.has(id)) {
@@ -6012,11 +7153,11 @@ var DaemonCdpManager = class {
6012
7153
  }
6013
7154
  // ─── CDP Protocol ────────────────────────────────────────
6014
7155
  sendInternal(method, params = {}, timeoutMs = 15e3) {
6015
- return new Promise((resolve12, reject) => {
7156
+ return new Promise((resolve15, reject) => {
6016
7157
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
6017
7158
  if (this.ws.readyState !== import_ws.default.OPEN) return reject(new Error("WebSocket not open"));
6018
7159
  const id = this.msgId++;
6019
- this.pending.set(id, { resolve: resolve12, reject });
7160
+ this.pending.set(id, { resolve: resolve15, reject });
6020
7161
  this.ws.send(JSON.stringify({ id, method, params }));
6021
7162
  setTimeout(() => {
6022
7163
  if (this.pending.has(id)) {
@@ -6265,7 +7406,7 @@ var DaemonCdpManager = class {
6265
7406
  const browserWs = this.browserWs;
6266
7407
  let msgId = this.browserMsgId;
6267
7408
  const sendWs = (method, params = {}, sessionId) => {
6268
- return new Promise((resolve12, reject) => {
7409
+ return new Promise((resolve15, reject) => {
6269
7410
  const mid = msgId++;
6270
7411
  this.browserMsgId = msgId;
6271
7412
  const handler = (raw) => {
@@ -6274,7 +7415,7 @@ var DaemonCdpManager = class {
6274
7415
  if (msg.id === mid) {
6275
7416
  browserWs.removeListener("message", handler);
6276
7417
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
6277
- else resolve12(msg.result);
7418
+ else resolve15(msg.result);
6278
7419
  }
6279
7420
  } catch {
6280
7421
  }
@@ -6475,14 +7616,14 @@ var DaemonCdpManager = class {
6475
7616
  if (!ws || ws.readyState !== import_ws.default.OPEN) {
6476
7617
  throw new Error("CDP not connected");
6477
7618
  }
6478
- return new Promise((resolve12, reject) => {
7619
+ return new Promise((resolve15, reject) => {
6479
7620
  const id = getNextId();
6480
7621
  pendingMap.set(id, {
6481
7622
  resolve: (result) => {
6482
7623
  if (result?.result?.subtype === "error") {
6483
7624
  reject(new Error(result.result.description));
6484
7625
  } else {
6485
- resolve12(result?.result?.value);
7626
+ resolve15(result?.result?.value);
6486
7627
  }
6487
7628
  },
6488
7629
  reject
@@ -6514,10 +7655,10 @@ var DaemonCdpManager = class {
6514
7655
  throw new Error("CDP not connected");
6515
7656
  }
6516
7657
  const sendViaSession = (method, params = {}) => {
6517
- return new Promise((resolve12, reject) => {
7658
+ return new Promise((resolve15, reject) => {
6518
7659
  const pendingMap = this._browserConnected ? this.browserPending : this.pending;
6519
7660
  const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
6520
- pendingMap.set(id, { resolve: resolve12, reject });
7661
+ pendingMap.set(id, { resolve: resolve15, reject });
6521
7662
  ws.send(JSON.stringify({ id, sessionId, method, params }));
6522
7663
  setTimeout(() => {
6523
7664
  if (pendingMap.has(id)) {
@@ -7263,10 +8404,10 @@ ${cleanBody}`;
7263
8404
 
7264
8405
  // src/config/chat-history.ts
7265
8406
  var fs3 = __toESM(require("fs"));
7266
- var path7 = __toESM(require("path"));
8407
+ var path10 = __toESM(require("path"));
7267
8408
  var os5 = __toESM(require("os"));
7268
8409
  init_chat_message_normalization();
7269
- var HISTORY_DIR = path7.join(os5.homedir(), ".adhdev", "history");
8410
+ var HISTORY_DIR = path10.join(os5.homedir(), ".adhdev", "history");
7270
8411
  var RETAIN_DAYS = 30;
7271
8412
  var SAVED_HISTORY_INDEX_VERSION = 1;
7272
8413
  var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
@@ -7429,8 +8570,8 @@ function extractSavedHistorySessionIdFromFile(file) {
7429
8570
  function buildSavedHistoryFileSignatureMap(dir, files) {
7430
8571
  return new Map(files.map((file) => {
7431
8572
  try {
7432
- const stat = fs3.statSync(path7.join(dir, file));
7433
- return [file, `${file}:${stat.size}:${Math.trunc(stat.mtimeMs)}`];
8573
+ const stat2 = fs3.statSync(path10.join(dir, file));
8574
+ return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
7434
8575
  } catch {
7435
8576
  return [file, `${file}:missing`];
7436
8577
  }
@@ -7440,7 +8581,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
7440
8581
  return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
7441
8582
  }
7442
8583
  function getSavedHistoryIndexFilePath(dir) {
7443
- return path7.join(dir, SAVED_HISTORY_INDEX_FILE);
8584
+ return path10.join(dir, SAVED_HISTORY_INDEX_FILE);
7444
8585
  }
7445
8586
  function getSavedHistoryIndexLockPath(dir) {
7446
8587
  return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
@@ -7493,8 +8634,8 @@ function acquireSavedHistoryIndexLock(dir) {
7493
8634
  } catch (error) {
7494
8635
  if (error?.code !== "EEXIST") return null;
7495
8636
  try {
7496
- const stat = fs3.statSync(lockPath);
7497
- if (Date.now() - stat.mtimeMs > SAVED_HISTORY_INDEX_LOCK_STALE_MS) {
8637
+ const stat2 = fs3.statSync(lockPath);
8638
+ if (Date.now() - stat2.mtimeMs > SAVED_HISTORY_INDEX_LOCK_STALE_MS) {
7498
8639
  fs3.rmSync(lockPath, { recursive: true, force: true });
7499
8640
  continue;
7500
8641
  }
@@ -7542,7 +8683,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
7542
8683
  }
7543
8684
  for (const file of Array.from(currentEntries.keys())) {
7544
8685
  if (incomingFiles.has(file)) continue;
7545
- if (!fs3.existsSync(path7.join(dir, file))) {
8686
+ if (!fs3.existsSync(path10.join(dir, file))) {
7546
8687
  currentEntries.delete(file);
7547
8688
  }
7548
8689
  }
@@ -7557,8 +8698,8 @@ function invalidatePersistedSavedHistoryIndex(agentType, dir) {
7557
8698
  }
7558
8699
  function buildSavedHistoryIndexFileSignature(dir) {
7559
8700
  try {
7560
- const stat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
7561
- return `index:${stat.size}:${Math.trunc(stat.mtimeMs)}`;
8701
+ const stat2 = fs3.statSync(getSavedHistoryIndexFilePath(dir));
8702
+ return `index:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
7562
8703
  } catch {
7563
8704
  return "index:missing";
7564
8705
  }
@@ -7568,8 +8709,8 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
7568
8709
  const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
7569
8710
  const files = listHistoryFiles(dir);
7570
8711
  for (const file of files) {
7571
- const stat = fs3.statSync(path7.join(dir, file));
7572
- if (stat.mtimeMs > indexStat.mtimeMs) return true;
8712
+ const stat2 = fs3.statSync(path10.join(dir, file));
8713
+ if (stat2.mtimeMs > indexStat.mtimeMs) return true;
7573
8714
  }
7574
8715
  return false;
7575
8716
  } catch {
@@ -7578,14 +8719,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
7578
8719
  }
7579
8720
  function buildSavedHistoryFileSignature(dir, file) {
7580
8721
  try {
7581
- const stat = fs3.statSync(path7.join(dir, file));
7582
- return `${file}:${stat.size}:${Math.trunc(stat.mtimeMs)}`;
8722
+ const stat2 = fs3.statSync(path10.join(dir, file));
8723
+ return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
7583
8724
  } catch {
7584
8725
  return `${file}:missing`;
7585
8726
  }
7586
8727
  }
7587
8728
  function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
7588
- const filePath = path7.join(dir, file);
8729
+ const filePath = path10.join(dir, file);
7589
8730
  const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
7590
8731
  const currentEntry = entries.get(file) || null;
7591
8732
  const nextSummary = updater(currentEntry?.summary || null);
@@ -7658,7 +8799,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
7658
8799
  function computeSavedHistoryFileSummary(dir, file) {
7659
8800
  const historySessionId = extractSavedHistorySessionIdFromFile(file);
7660
8801
  if (!historySessionId) return null;
7661
- const filePath = path7.join(dir, file);
8802
+ const filePath = path10.join(dir, file);
7662
8803
  const content = fs3.readFileSync(filePath, "utf-8");
7663
8804
  const lines = content.split("\n").filter(Boolean);
7664
8805
  let messageCount = 0;
@@ -7745,7 +8886,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
7745
8886
  const summaryBySessionId = /* @__PURE__ */ new Map();
7746
8887
  const nextPersistedEntries = /* @__PURE__ */ new Map();
7747
8888
  for (const file of files.slice().sort()) {
7748
- const filePath = path7.join(dir, file);
8889
+ const filePath = path10.join(dir, file);
7749
8890
  const signature = fileSignatures.get(file) || `${file}:missing`;
7750
8891
  const cached = savedHistoryFileSummaryCache.get(filePath);
7751
8892
  const persisted = persistedEntries.get(file);
@@ -7865,12 +9006,12 @@ var ChatHistoryWriter = class {
7865
9006
  });
7866
9007
  }
7867
9008
  if (newMessages.length === 0) return;
7868
- const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
9009
+ const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
7869
9010
  fs3.mkdirSync(dir, { recursive: true });
7870
9011
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
7871
9012
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
7872
9013
  const fileName = `${filePrefix}${date}.jsonl`;
7873
- const filePath = path7.join(dir, fileName);
9014
+ const filePath = path10.join(dir, fileName);
7874
9015
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
7875
9016
  fs3.appendFileSync(filePath, lines, "utf-8");
7876
9017
  updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
@@ -7961,11 +9102,11 @@ var ChatHistoryWriter = class {
7961
9102
  const ws = String(workspace || "").trim();
7962
9103
  if (!id || !ws) return;
7963
9104
  try {
7964
- const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
9105
+ const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
7965
9106
  fs3.mkdirSync(dir, { recursive: true });
7966
9107
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
7967
9108
  const fileName = `${this.sanitize(id)}_${date}.jsonl`;
7968
- const filePath = path7.join(dir, fileName);
9109
+ const filePath = path10.join(dir, fileName);
7969
9110
  const record = {
7970
9111
  ts: (/* @__PURE__ */ new Date()).toISOString(),
7971
9112
  receivedAt: Date.now(),
@@ -8011,14 +9152,14 @@ var ChatHistoryWriter = class {
8011
9152
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
8012
9153
  this.lastSeenCounts.delete(fromDedupKey);
8013
9154
  }
8014
- const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
9155
+ const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
8015
9156
  if (!fs3.existsSync(dir)) return;
8016
9157
  const fromPrefix = `${this.sanitize(fromId)}_`;
8017
9158
  const toPrefix = `${this.sanitize(toId)}_`;
8018
9159
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
8019
9160
  for (const file of files) {
8020
- const sourcePath = path7.join(dir, file);
8021
- const targetPath = path7.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
9161
+ const sourcePath = path10.join(dir, file);
9162
+ const targetPath = path10.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
8022
9163
  const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
8023
9164
  const rewritten = sourceLines.map((line) => {
8024
9165
  try {
@@ -8052,13 +9193,13 @@ var ChatHistoryWriter = class {
8052
9193
  const sessionId = String(historySessionId || "").trim();
8053
9194
  if (!sessionId) return;
8054
9195
  try {
8055
- const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
9196
+ const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
8056
9197
  if (!fs3.existsSync(dir)) return;
8057
9198
  const prefix = `${this.sanitize(sessionId)}_`;
8058
9199
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
8059
9200
  const seen = /* @__PURE__ */ new Set();
8060
9201
  for (const file of files) {
8061
- const filePath = path7.join(dir, file);
9202
+ const filePath = path10.join(dir, file);
8062
9203
  const lines = fs3.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
8063
9204
  const next = [];
8064
9205
  for (const line of lines) {
@@ -8112,13 +9253,13 @@ var ChatHistoryWriter = class {
8112
9253
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
8113
9254
  const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
8114
9255
  for (const dir of agentDirs) {
8115
- const dirPath = path7.join(HISTORY_DIR, dir.name);
9256
+ const dirPath = path10.join(HISTORY_DIR, dir.name);
8116
9257
  const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
8117
9258
  let removedAny = false;
8118
9259
  for (const file of files) {
8119
- const filePath = path7.join(dirPath, file);
8120
- const stat = fs3.statSync(filePath);
8121
- if (stat.mtimeMs < cutoff) {
9260
+ const filePath = path10.join(dirPath, file);
9261
+ const stat2 = fs3.statSync(filePath);
9262
+ if (stat2.mtimeMs < cutoff) {
8122
9263
  fs3.unlinkSync(filePath);
8123
9264
  removedAny = true;
8124
9265
  }
@@ -8135,6 +9276,10 @@ var ChatHistoryWriter = class {
8135
9276
  return name.replace(/[^a-zA-Z0-9_-]/g, "_");
8136
9277
  }
8137
9278
  };
9279
+ function normalizePaginationNumber(value, fallback, min) {
9280
+ const numeric = Number(value);
9281
+ return Number.isFinite(numeric) ? Math.max(min, numeric) : fallback;
9282
+ }
8138
9283
  function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeRecentCount = 0, historyBehavior) {
8139
9284
  const allMessages = records.map((message) => sanitizeHistoryMessage(agentType, message)).filter(Boolean);
8140
9285
  allMessages.sort((a, b) => a.receivedAt - b.receivedAt);
@@ -8148,9 +9293,12 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
8148
9293
  if (message.role !== "system") lastTurn = message;
8149
9294
  }
8150
9295
  const collapsed = collapseReplayAssistantTurns(chronological, historyBehavior);
8151
- const boundedLimit = Math.max(1, limit);
8152
- const boundedOffset = Math.max(0, offset);
8153
- const boundedExclude = Math.max(0, Math.min(excludeRecentCount, collapsed.length));
9296
+ const boundedLimit = normalizePaginationNumber(limit, 30, 1);
9297
+ const boundedOffset = normalizePaginationNumber(offset, 0, 0);
9298
+ const boundedExclude = Math.min(
9299
+ normalizePaginationNumber(excludeRecentCount, 0, 0),
9300
+ collapsed.length
9301
+ );
8154
9302
  const endExclusive = Math.max(0, collapsed.length - boundedExclude - boundedOffset);
8155
9303
  const startInclusive = Math.max(0, endExclusive - boundedLimit);
8156
9304
  const sliced = collapsed.slice(startInclusive, endExclusive);
@@ -8159,13 +9307,13 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
8159
9307
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
8160
9308
  try {
8161
9309
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
8162
- const dir = path7.join(HISTORY_DIR, sanitized);
9310
+ const dir = path10.join(HISTORY_DIR, sanitized);
8163
9311
  if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
8164
9312
  const files = listHistoryFiles(dir, historySessionId);
8165
9313
  const allMessages = [];
8166
9314
  const seen = /* @__PURE__ */ new Set();
8167
9315
  for (const file of files) {
8168
- const filePath = path7.join(dir, file);
9316
+ const filePath = path10.join(dir, file);
8169
9317
  const content = fs3.readFileSync(filePath, "utf-8");
8170
9318
  const lines = content.trim().split("\n").filter(Boolean);
8171
9319
  for (let i = 0; i < lines.length; i++) {
@@ -8189,7 +9337,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
8189
9337
  function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
8190
9338
  try {
8191
9339
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
8192
- const dir = path7.join(HISTORY_DIR, sanitized);
9340
+ const dir = path10.join(HISTORY_DIR, sanitized);
8193
9341
  if (!fs3.existsSync(dir)) {
8194
9342
  savedHistorySessionCache.delete(sanitized);
8195
9343
  return { sessions: [], hasMore: false };
@@ -8250,11 +9398,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
8250
9398
  }
8251
9399
  function readExistingSessionStartRecord(agentType, historySessionId) {
8252
9400
  try {
8253
- const dir = path7.join(HISTORY_DIR, agentType);
9401
+ const dir = path10.join(HISTORY_DIR, agentType);
8254
9402
  if (!fs3.existsSync(dir)) return null;
8255
9403
  const files = listHistoryFiles(dir, historySessionId).sort();
8256
9404
  for (const file of files) {
8257
- const lines = fs3.readFileSync(path7.join(dir, file), "utf-8").split("\n").filter(Boolean);
9405
+ const lines = fs3.readFileSync(path10.join(dir, file), "utf-8").split("\n").filter(Boolean);
8258
9406
  for (const line of lines) {
8259
9407
  try {
8260
9408
  const parsed = JSON.parse(line);
@@ -8274,16 +9422,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
8274
9422
  function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
8275
9423
  if (records.length === 0) return false;
8276
9424
  try {
8277
- const dir = path7.join(HISTORY_DIR, agentType);
9425
+ const dir = path10.join(HISTORY_DIR, agentType);
8278
9426
  fs3.mkdirSync(dir, { recursive: true });
8279
9427
  const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
8280
9428
  for (const file of fs3.readdirSync(dir)) {
8281
9429
  if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
8282
- fs3.unlinkSync(path7.join(dir, file));
9430
+ fs3.unlinkSync(path10.join(dir, file));
8283
9431
  }
8284
9432
  }
8285
9433
  const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
8286
- const filePath = path7.join(dir, `${prefix}${targetDate}.jsonl`);
9434
+ const filePath = path10.join(dir, `${prefix}${targetDate}.jsonl`);
8287
9435
  fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
8288
9436
  `, "utf-8");
8289
9437
  invalidatePersistedSavedHistoryIndex(agentType, dir);
@@ -10155,6 +11303,10 @@ function shouldIncludeSessionMetadata(profile) {
10155
11303
  function shouldIncludeRuntimeMetadata(profile) {
10156
11304
  return true;
10157
11305
  }
11306
+ function getGitSummaryForWorkspace(workspace, options) {
11307
+ if (!workspace) return void 0;
11308
+ return options.getGitSummaryForWorkspace?.(workspace) || void 0;
11309
+ }
10158
11310
  function findCdpManager(cdpManagers, key) {
10159
11311
  const exact = cdpManagers.get(key);
10160
11312
  if (exact) return exact.isConnected ? exact : null;
@@ -10210,6 +11362,8 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
10210
11362
  const controlValues = normalizeProviderStateControlValues(state.controlValues);
10211
11363
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
10212
11364
  const includeSessionControls = shouldIncludeSessionControls(profile);
11365
+ const workspace = state.workspace || null;
11366
+ const git = getGitSummaryForWorkspace(workspace, options);
10213
11367
  const title = activeChat?.title || state.name;
10214
11368
  return {
10215
11369
  id: state.instanceId || state.type,
@@ -10222,7 +11376,8 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
10222
11376
  activeModal: activeChat?.activeModal || null
10223
11377
  }),
10224
11378
  title,
10225
- workspace: state.workspace || null,
11379
+ workspace,
11380
+ ...git && { git },
10226
11381
  activeChat,
10227
11382
  ...summaryMetadata && { summaryMetadata },
10228
11383
  ...includeSessionMetadata && { capabilities: state.sessionCapabilities || IDE_SESSION_CAPABILITIES },
@@ -10243,6 +11398,8 @@ function buildExtensionAgentSession(parent, ext, options) {
10243
11398
  const controlValues = normalizeProviderStateControlValues(ext.controlValues);
10244
11399
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
10245
11400
  const includeSessionControls = shouldIncludeSessionControls(profile);
11401
+ const workspace = parent.workspace || null;
11402
+ const git = getGitSummaryForWorkspace(workspace, options);
10246
11403
  return {
10247
11404
  id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
10248
11405
  parentId: parent.instanceId || parent.type,
@@ -10255,7 +11412,8 @@ function buildExtensionAgentSession(parent, ext, options) {
10255
11412
  activeModal: activeChat?.activeModal || null
10256
11413
  }),
10257
11414
  title: activeChat?.title || ext.name,
10258
- workspace: parent.workspace || null,
11415
+ workspace,
11416
+ ...git && { git },
10259
11417
  activeChat,
10260
11418
  ...summaryMetadata && { summaryMetadata },
10261
11419
  ...includeSessionMetadata && { capabilities: ext.sessionCapabilities || EXTENSION_SESSION_CAPABILITIES },
@@ -10291,6 +11449,8 @@ function buildCliSession(state, options) {
10291
11449
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
10292
11450
  const includeRuntimeMetadata = shouldIncludeRuntimeMetadata(profile);
10293
11451
  const includeSessionControls = shouldIncludeSessionControls(profile);
11452
+ const workspace = state.workspace || null;
11453
+ const git = getGitSummaryForWorkspace(workspace, options);
10294
11454
  return {
10295
11455
  id: state.instanceId,
10296
11456
  parentId: null,
@@ -10303,7 +11463,8 @@ function buildCliSession(state, options) {
10303
11463
  activeModal: activeChat?.activeModal || null
10304
11464
  }),
10305
11465
  title: activeChat?.title || state.name,
10306
- workspace: state.workspace || null,
11466
+ workspace,
11467
+ ...git && { git },
10307
11468
  ...includeRuntimeMetadata && {
10308
11469
  runtimeKey: state.runtime?.runtimeKey,
10309
11470
  runtimeDisplayName: state.runtime?.displayName,
@@ -10338,6 +11499,8 @@ function buildAcpSession(state, options) {
10338
11499
  const controlValues = normalizeProviderStateControlValues(state.controlValues);
10339
11500
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
10340
11501
  const includeSessionControls = shouldIncludeSessionControls(profile);
11502
+ const workspace = state.workspace || null;
11503
+ const git = getGitSummaryForWorkspace(workspace, options);
10341
11504
  return {
10342
11505
  id: state.instanceId,
10343
11506
  parentId: null,
@@ -10349,7 +11512,8 @@ function buildAcpSession(state, options) {
10349
11512
  activeModal: activeChat?.activeModal || null
10350
11513
  }),
10351
11514
  title: activeChat?.title || state.name,
10352
- workspace: state.workspace || null,
11515
+ workspace,
11516
+ ...git && { git },
10353
11517
  activeChat,
10354
11518
  ...summaryMetadata && { summaryMetadata },
10355
11519
  ...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES },
@@ -10468,7 +11632,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
10468
11632
  // src/commands/chat-commands.ts
10469
11633
  var fs4 = __toESM(require("fs"));
10470
11634
  var os6 = __toESM(require("os"));
10471
- var path8 = __toESM(require("path"));
11635
+ var path11 = __toESM(require("path"));
10472
11636
  var import_node_crypto = require("crypto");
10473
11637
  init_contracts();
10474
11638
 
@@ -11161,7 +12325,7 @@ function buildDebugBundleText(bundle) {
11161
12325
  }
11162
12326
  function getChatDebugBundleDir() {
11163
12327
  const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
11164
- return override || path8.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
12328
+ return override || path11.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
11165
12329
  }
11166
12330
  function safeBundleIdSegment(value, fallback) {
11167
12331
  const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
@@ -11194,7 +12358,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
11194
12358
  const bundleId = createChatDebugBundleId(targetSessionId);
11195
12359
  const dir = getChatDebugBundleDir();
11196
12360
  fs4.mkdirSync(dir, { recursive: true });
11197
- const savedPath = path8.join(dir, `${bundleId}.json`);
12361
+ const savedPath = path11.join(dir, `${bundleId}.json`);
11198
12362
  const json = `${JSON.stringify(bundle, null, 2)}
11199
12363
  `;
11200
12364
  fs4.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
@@ -11363,10 +12527,32 @@ function getStateLastSignature(state) {
11363
12527
  if (!last) return "";
11364
12528
  return `${last.role || ""}:${String(last.content || "").replace(/\s+/g, " ").trim()}`;
11365
12529
  }
12530
+ function toNonNegativeNumber(value) {
12531
+ const numeric = Number(value ?? 0);
12532
+ return Number.isFinite(numeric) ? Math.max(0, numeric) : 0;
12533
+ }
12534
+ function getCliVisibleTranscriptCount(adapter) {
12535
+ const adapterStatus = adapter?.getStatus?.() || {};
12536
+ const adapterMessages = Array.isArray(adapterStatus.messages) ? adapterStatus.messages : [];
12537
+ let parsedRecord = null;
12538
+ if (typeof adapter?.getScriptParsedStatus === "function") {
12539
+ try {
12540
+ const parsed = parseMaybeJson(adapter.getScriptParsedStatus());
12541
+ parsedRecord = parsed && typeof parsed === "object" ? parsed : null;
12542
+ } catch {
12543
+ parsedRecord = null;
12544
+ }
12545
+ }
12546
+ const parsedMessages = Array.isArray(parsedRecord?.messages) ? parsedRecord.messages : [];
12547
+ if (!parsedRecord) return adapterMessages.length;
12548
+ const parsedIsProviderAuthoritative = parsedRecord.transcriptAuthority === "provider" || parsedRecord.coverage === "full";
12549
+ const shouldPreferAdapterMessages = !parsedIsProviderAuthoritative && adapterMessages.length > 0 && adapterMessages.length > parsedMessages.length;
12550
+ return shouldPreferAdapterMessages ? adapterMessages.length : parsedMessages.length;
12551
+ }
11366
12552
  async function getStableExtensionBaseline(h) {
11367
12553
  const first = await readExtensionChatState(h);
11368
12554
  if (getStateMessageCount(first) > 0 || getStateLastSignature(first)) return first;
11369
- await new Promise((resolve12) => setTimeout(resolve12, 150));
12555
+ await new Promise((resolve15) => setTimeout(resolve15, 150));
11370
12556
  const second = await readExtensionChatState(h);
11371
12557
  return getStateMessageCount(second) >= getStateMessageCount(first) ? second : first;
11372
12558
  }
@@ -11374,7 +12560,7 @@ async function verifyExtensionSendObserved(h, before) {
11374
12560
  const beforeCount = getStateMessageCount(before);
11375
12561
  const beforeSignature = getStateLastSignature(before);
11376
12562
  for (let attempt = 0; attempt < 12; attempt += 1) {
11377
- await new Promise((resolve12) => setTimeout(resolve12, 250));
12563
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
11378
12564
  const state = await readExtensionChatState(h);
11379
12565
  if (state?.status === "waiting_approval") return true;
11380
12566
  const afterCount = getStateMessageCount(state);
@@ -11391,11 +12577,11 @@ async function handleChatHistory(h, args) {
11391
12577
  const provider = h.getProvider(agentType);
11392
12578
  const agentStr = provider?.type || agentType || getCurrentProviderType(h);
11393
12579
  const transport = getTargetTransport(h, provider);
11394
- let excludeRecentCount = Math.max(0, Number(args?.excludeRecentCount || 0));
11395
- if (isCliLikeTransport(transport)) {
12580
+ const hasExplicitExcludeRecentCount = args?.excludeRecentCount !== void 0 && args?.excludeRecentCount !== null;
12581
+ let excludeRecentCount = toNonNegativeNumber(args?.excludeRecentCount);
12582
+ if (!hasExplicitExcludeRecentCount && isCliLikeTransport(transport)) {
11396
12583
  const adapter = getTargetedCliAdapter(h, args, provider?.type);
11397
- const status = adapter?.getStatus?.();
11398
- const visibleCount = Array.isArray(status?.messages) ? status.messages.length : 0;
12584
+ const visibleCount = getCliVisibleTranscriptCount(adapter);
11399
12585
  if (visibleCount > excludeRecentCount) excludeRecentCount = visibleCount;
11400
12586
  }
11401
12587
  const workspace = typeof args?.workspace === "string" ? args.workspace : typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : void 0;
@@ -12310,7 +13496,7 @@ async function handleResolveAction(h, args) {
12310
13496
 
12311
13497
  // src/commands/cdp-commands.ts
12312
13498
  var fs5 = __toESM(require("fs"));
12313
- var path9 = __toESM(require("path"));
13499
+ var path12 = __toESM(require("path"));
12314
13500
  var os7 = __toESM(require("os"));
12315
13501
  var KEY_TO_VK = {
12316
13502
  Backspace: 8,
@@ -12567,25 +13753,25 @@ function resolveSafePath(requestedPath) {
12567
13753
  const inputPath = rawPath || ".";
12568
13754
  const home = os7.homedir();
12569
13755
  if (inputPath.startsWith("~")) {
12570
- return path9.resolve(path9.join(home, inputPath.slice(1)));
13756
+ return path12.resolve(path12.join(home, inputPath.slice(1)));
12571
13757
  }
12572
13758
  if (process.platform === "win32") {
12573
13759
  const normalized = normalizeWindowsRequestedPath(inputPath);
12574
- if (path9.win32.isAbsolute(normalized)) {
12575
- return path9.win32.normalize(normalized);
13760
+ if (path12.win32.isAbsolute(normalized)) {
13761
+ return path12.win32.normalize(normalized);
12576
13762
  }
12577
- return path9.win32.resolve(normalized);
13763
+ return path12.win32.resolve(normalized);
12578
13764
  }
12579
- if (path9.isAbsolute(inputPath)) {
12580
- return path9.normalize(inputPath);
13765
+ if (path12.isAbsolute(inputPath)) {
13766
+ return path12.normalize(inputPath);
12581
13767
  }
12582
- return path9.resolve(inputPath);
13768
+ return path12.resolve(inputPath);
12583
13769
  }
12584
13770
  function listDirectoryEntriesSafe(dirPath) {
12585
13771
  const entries = fs5.readdirSync(dirPath, { withFileTypes: true });
12586
13772
  const files = [];
12587
13773
  for (const entry of entries) {
12588
- const entryPath = path9.join(dirPath, entry.name);
13774
+ const entryPath = path12.join(dirPath, entry.name);
12589
13775
  try {
12590
13776
  if (entry.isDirectory()) {
12591
13777
  files.push({ name: entry.name, type: "directory" });
@@ -12601,11 +13787,11 @@ function listDirectoryEntriesSafe(dirPath) {
12601
13787
  files.push({ name: entry.name, type: "file", size });
12602
13788
  continue;
12603
13789
  }
12604
- const stat = fs5.statSync(entryPath);
13790
+ const stat2 = fs5.statSync(entryPath);
12605
13791
  files.push({
12606
13792
  name: entry.name,
12607
- type: stat.isDirectory() ? "directory" : "file",
12608
- size: stat.isFile() ? stat.size : void 0
13793
+ type: stat2.isDirectory() ? "directory" : "file",
13794
+ size: stat2.isFile() ? stat2.size : void 0
12609
13795
  });
12610
13796
  } catch {
12611
13797
  }
@@ -12639,7 +13825,7 @@ async function handleFileRead(h, args) {
12639
13825
  async function handleFileWrite(h, args) {
12640
13826
  try {
12641
13827
  const filePath = resolveSafePath(args?.path);
12642
- fs5.mkdirSync(path9.dirname(filePath), { recursive: true });
13828
+ fs5.mkdirSync(path12.dirname(filePath), { recursive: true });
12643
13829
  fs5.writeFileSync(filePath, args?.content || "", "utf-8");
12644
13830
  return { success: true, path: filePath };
12645
13831
  } catch (e) {
@@ -12988,7 +14174,7 @@ async function executeProviderScript(h, args, scriptName) {
12988
14174
  const enterCount = cliCommand.enterCount || 1;
12989
14175
  await adapter.writeRaw(cliCommand.text + "\r");
12990
14176
  for (let i = 1; i < enterCount; i += 1) {
12991
- await new Promise((resolve12) => setTimeout(resolve12, 50));
14177
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
12992
14178
  await adapter.writeRaw("\r");
12993
14179
  }
12994
14180
  }
@@ -13482,6 +14668,12 @@ var DaemonCommandHandler = class {
13482
14668
  this._currentRoute = this.resolveRoute(args);
13483
14669
  const startedAt = Date.now();
13484
14670
  this.logCommandStart(cmd, args);
14671
+ let result;
14672
+ if (isGitCommandName(cmd)) {
14673
+ result = await handleGitCommand(cmd, args, this._ctx.gitCommandServices);
14674
+ this.logCommandEnd(cmd, result, startedAt);
14675
+ return result;
14676
+ }
13485
14677
  const sessionScopedCommands = /* @__PURE__ */ new Set([
13486
14678
  "read_chat",
13487
14679
  "get_chat_debug_bundle",
@@ -13507,7 +14699,6 @@ var DaemonCommandHandler = class {
13507
14699
  this.logCommandEnd(cmd, result2, startedAt);
13508
14700
  return result2;
13509
14701
  }
13510
- let result;
13511
14702
  if (!this._currentRoute.session && !this._currentRoute.managerKey && !this._currentRoute.providerType) {
13512
14703
  const cdpCommands = ["send_chat", "read_chat", "list_chats", "new_chat", "switch_chat", "set_mode", "change_model", "set_thought_level", "resolve_action"];
13513
14704
  if (cdpCommands.includes(cmd)) {
@@ -13658,7 +14849,7 @@ var DaemonCommandHandler = class {
13658
14849
  try {
13659
14850
  const http3 = await import("http");
13660
14851
  const postData = JSON.stringify(body);
13661
- const result = await new Promise((resolve12, reject) => {
14852
+ const result = await new Promise((resolve15, reject) => {
13662
14853
  const req = http3.request({
13663
14854
  hostname: "127.0.0.1",
13664
14855
  port: 19280,
@@ -13670,9 +14861,9 @@ var DaemonCommandHandler = class {
13670
14861
  res.on("data", (chunk) => data += chunk);
13671
14862
  res.on("end", () => {
13672
14863
  try {
13673
- resolve12(JSON.parse(data));
14864
+ resolve15(JSON.parse(data));
13674
14865
  } catch {
13675
- resolve12({ raw: data });
14866
+ resolve15({ raw: data });
13676
14867
  }
13677
14868
  });
13678
14869
  });
@@ -13690,15 +14881,15 @@ var DaemonCommandHandler = class {
13690
14881
  if (!providerType) return { success: false, error: "providerType required" };
13691
14882
  try {
13692
14883
  const http3 = await import("http");
13693
- const result = await new Promise((resolve12, reject) => {
14884
+ const result = await new Promise((resolve15, reject) => {
13694
14885
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
13695
14886
  let data = "";
13696
14887
  res.on("data", (chunk) => data += chunk);
13697
14888
  res.on("end", () => {
13698
14889
  try {
13699
- resolve12(JSON.parse(data));
14890
+ resolve15(JSON.parse(data));
13700
14891
  } catch {
13701
- resolve12({ raw: data });
14892
+ resolve15({ raw: data });
13702
14893
  }
13703
14894
  });
13704
14895
  }).on("error", reject);
@@ -13712,7 +14903,7 @@ var DaemonCommandHandler = class {
13712
14903
  try {
13713
14904
  const http3 = await import("http");
13714
14905
  const postData = JSON.stringify(args || {});
13715
- const result = await new Promise((resolve12, reject) => {
14906
+ const result = await new Promise((resolve15, reject) => {
13716
14907
  const req = http3.request({
13717
14908
  hostname: "127.0.0.1",
13718
14909
  port: 19280,
@@ -13724,9 +14915,9 @@ var DaemonCommandHandler = class {
13724
14915
  res.on("data", (chunk) => data += chunk);
13725
14916
  res.on("end", () => {
13726
14917
  try {
13727
- resolve12(JSON.parse(data));
14918
+ resolve15(JSON.parse(data));
13728
14919
  } catch {
13729
- resolve12({ raw: data });
14920
+ resolve15({ raw: data });
13730
14921
  }
13731
14922
  });
13732
14923
  });
@@ -13743,7 +14934,7 @@ var DaemonCommandHandler = class {
13743
14934
 
13744
14935
  // src/commands/cli-manager.ts
13745
14936
  var os13 = __toESM(require("os"));
13746
- var path13 = __toESM(require("path"));
14937
+ var path16 = __toESM(require("path"));
13747
14938
  var crypto4 = __toESM(require("crypto"));
13748
14939
  var import_fs5 = require("fs");
13749
14940
  var import_child_process6 = require("child_process");
@@ -13753,7 +14944,7 @@ init_config();
13753
14944
 
13754
14945
  // src/providers/cli-provider-instance.ts
13755
14946
  var os12 = __toESM(require("os"));
13756
- var path12 = __toESM(require("path"));
14947
+ var path15 = __toESM(require("path"));
13757
14948
  var crypto3 = __toESM(require("crypto"));
13758
14949
  var fs6 = __toESM(require("fs"));
13759
14950
  var import_node_module = require("module");
@@ -13814,7 +15005,7 @@ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages
13814
15005
  var CachedDatabaseSync = null;
13815
15006
  function getDatabaseSync() {
13816
15007
  if (CachedDatabaseSync) return CachedDatabaseSync;
13817
- const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path12.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
15008
+ const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path15.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
13818
15009
  const sqliteModule = requireFn(`node:${"sqlite"}`);
13819
15010
  CachedDatabaseSync = sqliteModule.DatabaseSync;
13820
15011
  if (!CachedDatabaseSync) {
@@ -13852,7 +15043,7 @@ async function waitForCliAdapterReady(adapter, options) {
13852
15043
  if (status === "stopped") {
13853
15044
  throw new Error("CLI runtime stopped before it became ready");
13854
15045
  }
13855
- await new Promise((resolve12) => setTimeout(resolve12, pollMs));
15046
+ await new Promise((resolve15) => setTimeout(resolve15, pollMs));
13856
15047
  }
13857
15048
  throw new Error(`CLI runtime did not become ready within ${timeoutMs}ms`);
13858
15049
  }
@@ -14203,7 +15394,7 @@ var CliProviderInstance = class {
14203
15394
  const enterCount = cliCommand.enterCount || 1;
14204
15395
  await this.adapter.writeRaw(cliCommand.text + "\r");
14205
15396
  for (let i = 1; i < enterCount; i += 1) {
14206
- await new Promise((resolve12) => setTimeout(resolve12, 50));
15397
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
14207
15398
  await this.adapter.writeRaw("\r");
14208
15399
  }
14209
15400
  }
@@ -15317,13 +16508,13 @@ var AcpProviderInstance = class {
15317
16508
  }
15318
16509
  this.currentStatus = "waiting_approval";
15319
16510
  this.detectStatusTransition();
15320
- const approved = await new Promise((resolve12) => {
15321
- this.permissionResolvers.push(resolve12);
16511
+ const approved = await new Promise((resolve15) => {
16512
+ this.permissionResolvers.push(resolve15);
15322
16513
  setTimeout(() => {
15323
- const idx = this.permissionResolvers.indexOf(resolve12);
16514
+ const idx = this.permissionResolvers.indexOf(resolve15);
15324
16515
  if (idx >= 0) {
15325
16516
  this.permissionResolvers.splice(idx, 1);
15326
- resolve12(false);
16517
+ resolve15(false);
15327
16518
  }
15328
16519
  }, 3e5);
15329
16520
  });
@@ -15898,11 +17089,11 @@ function shouldRestoreHostedRuntime(record, managerTag) {
15898
17089
  // src/commands/cli-manager.ts
15899
17090
  function isExplicitCommand(command) {
15900
17091
  const trimmed = command.trim();
15901
- return path13.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
17092
+ return path16.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
15902
17093
  }
15903
17094
  function expandExecutable(command) {
15904
17095
  const trimmed = command.trim();
15905
- return trimmed.startsWith("~") ? path13.join(os13.homedir(), trimmed.slice(1)) : trimmed;
17096
+ return trimmed.startsWith("~") ? path16.join(os13.homedir(), trimmed.slice(1)) : trimmed;
15906
17097
  }
15907
17098
  function commandExists(command) {
15908
17099
  const trimmed = command.trim();
@@ -16183,7 +17374,7 @@ var DaemonCliManager = class {
16183
17374
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
16184
17375
  const trimmed = (workingDir || "").trim();
16185
17376
  if (!trimmed) throw new Error("working directory required");
16186
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path13.resolve(trimmed);
17377
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path16.resolve(trimmed);
16187
17378
  const normalizedType = this.providerLoader.resolveAlias(cliType);
16188
17379
  const rawProvider = this.providerLoader.getByAlias(cliType);
16189
17380
  const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
@@ -16684,11 +17875,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
16684
17875
  var import_child_process7 = require("child_process");
16685
17876
  var net = __toESM(require("net"));
16686
17877
  var os15 = __toESM(require("os"));
16687
- var path15 = __toESM(require("path"));
17878
+ var path18 = __toESM(require("path"));
16688
17879
 
16689
17880
  // src/providers/provider-loader.ts
16690
17881
  var fs7 = __toESM(require("fs"));
16691
- var path14 = __toESM(require("path"));
17882
+ var path17 = __toESM(require("path"));
16692
17883
  var os14 = __toESM(require("os"));
16693
17884
  var chokidar = __toESM(require("chokidar"));
16694
17885
  init_logger();
@@ -16953,7 +18144,7 @@ var ProviderLoader = class _ProviderLoader {
16953
18144
  try {
16954
18145
  if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
16955
18146
  return ["ide", "extension", "cli", "acp"].some(
16956
- (category) => fs7.existsSync(path14.join(candidate, category))
18147
+ (category) => fs7.existsSync(path17.join(candidate, category))
16957
18148
  );
16958
18149
  } catch {
16959
18150
  return false;
@@ -16961,20 +18152,20 @@ var ProviderLoader = class _ProviderLoader {
16961
18152
  }
16962
18153
  static hasProviderRootMarker(candidate) {
16963
18154
  try {
16964
- return fs7.existsSync(path14.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
18155
+ return fs7.existsSync(path17.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
16965
18156
  } catch {
16966
18157
  return false;
16967
18158
  }
16968
18159
  }
16969
18160
  detectDefaultUserDir() {
16970
- const fallback = path14.join(os14.homedir(), ".adhdev", "providers");
18161
+ const fallback = path17.join(os14.homedir(), ".adhdev", "providers");
16971
18162
  const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
16972
18163
  const visited = /* @__PURE__ */ new Set();
16973
18164
  for (const start of this.probeStarts) {
16974
- let current = path14.resolve(start);
18165
+ let current = path17.resolve(start);
16975
18166
  while (!visited.has(current)) {
16976
18167
  visited.add(current);
16977
- const siblingCandidate = path14.join(path14.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
18168
+ const siblingCandidate = path17.join(path17.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
16978
18169
  if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
16979
18170
  const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
16980
18171
  if (envOptIn || hasMarker) {
@@ -16996,7 +18187,7 @@ var ProviderLoader = class _ProviderLoader {
16996
18187
  return { path: siblingCandidate, source };
16997
18188
  }
16998
18189
  }
16999
- const parent = path14.dirname(current);
18190
+ const parent = path17.dirname(current);
17000
18191
  if (parent === current) break;
17001
18192
  current = parent;
17002
18193
  }
@@ -17006,11 +18197,11 @@ var ProviderLoader = class _ProviderLoader {
17006
18197
  constructor(options) {
17007
18198
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
17008
18199
  this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
17009
- this.defaultProvidersDir = path14.join(os14.homedir(), ".adhdev", "providers");
18200
+ this.defaultProvidersDir = path17.join(os14.homedir(), ".adhdev", "providers");
17010
18201
  const detected = this.detectDefaultUserDir();
17011
18202
  this.userDir = detected.path;
17012
18203
  this.userDirSource = detected.source;
17013
- this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
18204
+ this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
17014
18205
  this.disableUpstream = false;
17015
18206
  this.applySourceConfig({
17016
18207
  userDir: options?.userDir,
@@ -17069,7 +18260,7 @@ var ProviderLoader = class _ProviderLoader {
17069
18260
  this.userDir = detected.path;
17070
18261
  this.userDirSource = detected.source;
17071
18262
  }
17072
- this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
18263
+ this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
17073
18264
  this.disableUpstream = this.sourceMode === "no-upstream";
17074
18265
  if (this.explicitProviderDir) {
17075
18266
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
@@ -17083,7 +18274,7 @@ var ProviderLoader = class _ProviderLoader {
17083
18274
  * Canonical provider directory shape for a given root.
17084
18275
  */
17085
18276
  getProviderDir(root, category, type) {
17086
- return path14.join(root, category, type);
18277
+ return path17.join(root, category, type);
17087
18278
  }
17088
18279
  /**
17089
18280
  * Canonical user override directory for a provider.
@@ -17110,7 +18301,7 @@ var ProviderLoader = class _ProviderLoader {
17110
18301
  resolveProviderFile(type, ...segments) {
17111
18302
  const dir = this.findProviderDirInternal(type);
17112
18303
  if (!dir) return null;
17113
- return path14.join(dir, ...segments);
18304
+ return path17.join(dir, ...segments);
17114
18305
  }
17115
18306
  /**
17116
18307
  * Load all providers (3-tier priority)
@@ -17149,7 +18340,7 @@ var ProviderLoader = class _ProviderLoader {
17149
18340
  if (!fs7.existsSync(this.upstreamDir)) return false;
17150
18341
  try {
17151
18342
  return fs7.readdirSync(this.upstreamDir).some(
17152
- (d) => fs7.statSync(path14.join(this.upstreamDir, d)).isDirectory()
18343
+ (d) => fs7.statSync(path17.join(this.upstreamDir, d)).isDirectory()
17153
18344
  );
17154
18345
  } catch {
17155
18346
  return false;
@@ -17646,8 +18837,8 @@ var ProviderLoader = class _ProviderLoader {
17646
18837
  resolved._resolvedScriptDir = entry.scriptDir;
17647
18838
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
17648
18839
  if (providerDir) {
17649
- const fullDir = path14.join(providerDir, entry.scriptDir);
17650
- resolved._resolvedScriptsPath = fs7.existsSync(path14.join(fullDir, "scripts.js")) ? path14.join(fullDir, "scripts.js") : fullDir;
18840
+ const fullDir = path17.join(providerDir, entry.scriptDir);
18841
+ resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
17651
18842
  }
17652
18843
  matched = true;
17653
18844
  }
@@ -17662,8 +18853,8 @@ var ProviderLoader = class _ProviderLoader {
17662
18853
  resolved._resolvedScriptDir = base.defaultScriptDir;
17663
18854
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
17664
18855
  if (providerDir) {
17665
- const fullDir = path14.join(providerDir, base.defaultScriptDir);
17666
- resolved._resolvedScriptsPath = fs7.existsSync(path14.join(fullDir, "scripts.js")) ? path14.join(fullDir, "scripts.js") : fullDir;
18856
+ const fullDir = path17.join(providerDir, base.defaultScriptDir);
18857
+ resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
17667
18858
  }
17668
18859
  }
17669
18860
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -17680,8 +18871,8 @@ var ProviderLoader = class _ProviderLoader {
17680
18871
  resolved._resolvedScriptDir = dirOverride;
17681
18872
  resolved._resolvedScriptsSource = `versions:${range}`;
17682
18873
  if (providerDir) {
17683
- const fullDir = path14.join(providerDir, dirOverride);
17684
- resolved._resolvedScriptsPath = fs7.existsSync(path14.join(fullDir, "scripts.js")) ? path14.join(fullDir, "scripts.js") : fullDir;
18874
+ const fullDir = path17.join(providerDir, dirOverride);
18875
+ resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
17685
18876
  }
17686
18877
  }
17687
18878
  } else if (override.scripts) {
@@ -17697,8 +18888,8 @@ var ProviderLoader = class _ProviderLoader {
17697
18888
  resolved._resolvedScriptDir = base.defaultScriptDir;
17698
18889
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
17699
18890
  if (providerDir) {
17700
- const fullDir = path14.join(providerDir, base.defaultScriptDir);
17701
- resolved._resolvedScriptsPath = fs7.existsSync(path14.join(fullDir, "scripts.js")) ? path14.join(fullDir, "scripts.js") : fullDir;
18891
+ const fullDir = path17.join(providerDir, base.defaultScriptDir);
18892
+ resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
17702
18893
  }
17703
18894
  }
17704
18895
  }
@@ -17730,14 +18921,14 @@ var ProviderLoader = class _ProviderLoader {
17730
18921
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
17731
18922
  return null;
17732
18923
  }
17733
- const dir = path14.join(providerDir, scriptDir);
18924
+ const dir = path17.join(providerDir, scriptDir);
17734
18925
  if (!fs7.existsSync(dir)) {
17735
18926
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
17736
18927
  return null;
17737
18928
  }
17738
18929
  const cached = this.scriptsCache.get(dir);
17739
18930
  if (cached) return cached;
17740
- const scriptsJs = path14.join(dir, "scripts.js");
18931
+ const scriptsJs = path17.join(dir, "scripts.js");
17741
18932
  if (fs7.existsSync(scriptsJs)) {
17742
18933
  try {
17743
18934
  delete require.cache[require.resolve(scriptsJs)];
@@ -17779,7 +18970,7 @@ var ProviderLoader = class _ProviderLoader {
17779
18970
  return;
17780
18971
  }
17781
18972
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
17782
- this.log(`File changed: ${path14.basename(filePath)}, reloading...`);
18973
+ this.log(`File changed: ${path17.basename(filePath)}, reloading...`);
17783
18974
  this.reload();
17784
18975
  }
17785
18976
  };
@@ -17834,7 +19025,7 @@ var ProviderLoader = class _ProviderLoader {
17834
19025
  }
17835
19026
  const https = require("https");
17836
19027
  const { execSync: execSync7 } = require("child_process");
17837
- const metaPath = path14.join(this.upstreamDir, _ProviderLoader.META_FILE);
19028
+ const metaPath = path17.join(this.upstreamDir, _ProviderLoader.META_FILE);
17838
19029
  let prevEtag = "";
17839
19030
  let prevTimestamp = 0;
17840
19031
  try {
@@ -17851,7 +19042,7 @@ var ProviderLoader = class _ProviderLoader {
17851
19042
  return { updated: false };
17852
19043
  }
17853
19044
  try {
17854
- const etag = await new Promise((resolve12, reject) => {
19045
+ const etag = await new Promise((resolve15, reject) => {
17855
19046
  const options = {
17856
19047
  method: "HEAD",
17857
19048
  hostname: "github.com",
@@ -17869,7 +19060,7 @@ var ProviderLoader = class _ProviderLoader {
17869
19060
  headers: { "User-Agent": "adhdev-launcher" },
17870
19061
  timeout: 1e4
17871
19062
  }, (res2) => {
17872
- resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
19063
+ resolve15(res2.headers.etag || res2.headers["last-modified"] || "");
17873
19064
  });
17874
19065
  req2.on("error", reject);
17875
19066
  req2.on("timeout", () => {
@@ -17878,7 +19069,7 @@ var ProviderLoader = class _ProviderLoader {
17878
19069
  });
17879
19070
  req2.end();
17880
19071
  } else {
17881
- resolve12(res.headers.etag || res.headers["last-modified"] || "");
19072
+ resolve15(res.headers.etag || res.headers["last-modified"] || "");
17882
19073
  }
17883
19074
  });
17884
19075
  req.on("error", reject);
@@ -17894,17 +19085,17 @@ var ProviderLoader = class _ProviderLoader {
17894
19085
  return { updated: false };
17895
19086
  }
17896
19087
  this.log("Downloading latest providers from GitHub...");
17897
- const tmpTar = path14.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
17898
- const tmpExtract = path14.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
19088
+ const tmpTar = path17.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
19089
+ const tmpExtract = path17.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
17899
19090
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
17900
19091
  fs7.mkdirSync(tmpExtract, { recursive: true });
17901
19092
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
17902
19093
  const extracted = fs7.readdirSync(tmpExtract);
17903
19094
  const rootDir = extracted.find(
17904
- (d) => fs7.statSync(path14.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
19095
+ (d) => fs7.statSync(path17.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
17905
19096
  );
17906
19097
  if (!rootDir) throw new Error("Unexpected tarball structure");
17907
- const sourceDir = path14.join(tmpExtract, rootDir);
19098
+ const sourceDir = path17.join(tmpExtract, rootDir);
17908
19099
  const backupDir = this.upstreamDir + ".bak";
17909
19100
  if (fs7.existsSync(this.upstreamDir)) {
17910
19101
  if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
@@ -17942,7 +19133,7 @@ var ProviderLoader = class _ProviderLoader {
17942
19133
  downloadFile(url, destPath) {
17943
19134
  const https = require("https");
17944
19135
  const http3 = require("http");
17945
- return new Promise((resolve12, reject) => {
19136
+ return new Promise((resolve15, reject) => {
17946
19137
  const doRequest = (reqUrl, redirectCount = 0) => {
17947
19138
  if (redirectCount > 5) {
17948
19139
  reject(new Error("Too many redirects"));
@@ -17962,7 +19153,7 @@ var ProviderLoader = class _ProviderLoader {
17962
19153
  res.pipe(ws);
17963
19154
  ws.on("finish", () => {
17964
19155
  ws.close();
17965
- resolve12();
19156
+ resolve15();
17966
19157
  });
17967
19158
  ws.on("error", reject);
17968
19159
  });
@@ -17979,8 +19170,8 @@ var ProviderLoader = class _ProviderLoader {
17979
19170
  copyDirRecursive(src, dest) {
17980
19171
  fs7.mkdirSync(dest, { recursive: true });
17981
19172
  for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
17982
- const srcPath = path14.join(src, entry.name);
17983
- const destPath = path14.join(dest, entry.name);
19173
+ const srcPath = path17.join(src, entry.name);
19174
+ const destPath = path17.join(dest, entry.name);
17984
19175
  if (entry.isDirectory()) {
17985
19176
  this.copyDirRecursive(srcPath, destPath);
17986
19177
  } else {
@@ -17991,7 +19182,7 @@ var ProviderLoader = class _ProviderLoader {
17991
19182
  /** .meta.json save */
17992
19183
  writeMeta(metaPath, etag, timestamp) {
17993
19184
  try {
17994
- fs7.mkdirSync(path14.dirname(metaPath), { recursive: true });
19185
+ fs7.mkdirSync(path17.dirname(metaPath), { recursive: true });
17995
19186
  fs7.writeFileSync(metaPath, JSON.stringify({
17996
19187
  etag,
17997
19188
  timestamp,
@@ -18008,7 +19199,7 @@ var ProviderLoader = class _ProviderLoader {
18008
19199
  const scan = (d) => {
18009
19200
  try {
18010
19201
  for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
18011
- if (entry.isDirectory()) scan(path14.join(d, entry.name));
19202
+ if (entry.isDirectory()) scan(path17.join(d, entry.name));
18012
19203
  else if (entry.name === "provider.json") count++;
18013
19204
  }
18014
19205
  } catch {
@@ -18236,17 +19427,17 @@ var ProviderLoader = class _ProviderLoader {
18236
19427
  for (const root of searchRoots) {
18237
19428
  if (!fs7.existsSync(root)) continue;
18238
19429
  const candidate = this.getProviderDir(root, cat, type);
18239
- if (fs7.existsSync(path14.join(candidate, "provider.json"))) return candidate;
18240
- const catDir = path14.join(root, cat);
19430
+ if (fs7.existsSync(path17.join(candidate, "provider.json"))) return candidate;
19431
+ const catDir = path17.join(root, cat);
18241
19432
  if (fs7.existsSync(catDir)) {
18242
19433
  try {
18243
19434
  for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
18244
19435
  if (!entry.isDirectory()) continue;
18245
- const jsonPath = path14.join(catDir, entry.name, "provider.json");
19436
+ const jsonPath = path17.join(catDir, entry.name, "provider.json");
18246
19437
  if (fs7.existsSync(jsonPath)) {
18247
19438
  try {
18248
19439
  const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
18249
- if (data.type === type) return path14.join(catDir, entry.name);
19440
+ if (data.type === type) return path17.join(catDir, entry.name);
18250
19441
  } catch {
18251
19442
  }
18252
19443
  }
@@ -18263,7 +19454,7 @@ var ProviderLoader = class _ProviderLoader {
18263
19454
  * (template substitution is NOT applied here — scripts.js handles that)
18264
19455
  */
18265
19456
  buildScriptWrappersFromDir(dir) {
18266
- const scriptsJs = path14.join(dir, "scripts.js");
19457
+ const scriptsJs = path17.join(dir, "scripts.js");
18267
19458
  if (fs7.existsSync(scriptsJs)) {
18268
19459
  try {
18269
19460
  delete require.cache[require.resolve(scriptsJs)];
@@ -18277,7 +19468,7 @@ var ProviderLoader = class _ProviderLoader {
18277
19468
  for (const file of fs7.readdirSync(dir)) {
18278
19469
  if (!file.endsWith(".js")) continue;
18279
19470
  const scriptName = toCamel(file.replace(".js", ""));
18280
- const filePath = path14.join(dir, file);
19471
+ const filePath = path17.join(dir, file);
18281
19472
  result[scriptName] = (...args) => {
18282
19473
  try {
18283
19474
  let content = fs7.readFileSync(filePath, "utf-8");
@@ -18337,7 +19528,7 @@ var ProviderLoader = class _ProviderLoader {
18337
19528
  }
18338
19529
  const hasJson = entries.some((e) => e.name === "provider.json");
18339
19530
  if (hasJson) {
18340
- const jsonPath = path14.join(d, "provider.json");
19531
+ const jsonPath = path17.join(d, "provider.json");
18341
19532
  try {
18342
19533
  const raw = fs7.readFileSync(jsonPath, "utf-8");
18343
19534
  const mod = JSON.parse(raw);
@@ -18358,7 +19549,7 @@ var ProviderLoader = class _ProviderLoader {
18358
19549
  this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
18359
19550
  } else {
18360
19551
  const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
18361
- const scriptsPath = path14.join(d, "scripts.js");
19552
+ const scriptsPath = path17.join(d, "scripts.js");
18362
19553
  if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
18363
19554
  try {
18364
19555
  delete require.cache[require.resolve(scriptsPath)];
@@ -18384,7 +19575,7 @@ var ProviderLoader = class _ProviderLoader {
18384
19575
  if (!entry.isDirectory()) continue;
18385
19576
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
18386
19577
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
18387
- scan(path14.join(d, entry.name));
19578
+ scan(path17.join(d, entry.name));
18388
19579
  }
18389
19580
  }
18390
19581
  };
@@ -18419,9 +19610,9 @@ var ProviderLoader = class _ProviderLoader {
18419
19610
  }
18420
19611
  }
18421
19612
  compareVersions(a, b) {
18422
- const normalize3 = (v) => v.split(/[-_+]/)[0].split(".").map((x) => parseInt(x, 10) || 0);
18423
- const pa = normalize3(a);
18424
- const pb = normalize3(b);
19613
+ const normalize4 = (v) => v.split(/[-_+]/)[0].split(".").map((x) => parseInt(x, 10) || 0);
19614
+ const pa = normalize4(a);
19615
+ const pb = normalize4(b);
18425
19616
  for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
18426
19617
  const va = pa[i] || 0;
18427
19618
  const vb = pb[i] || 0;
@@ -18541,17 +19732,17 @@ async function findFreePort(ports) {
18541
19732
  throw new Error("No free port found");
18542
19733
  }
18543
19734
  function checkPortFree(port) {
18544
- return new Promise((resolve12) => {
19735
+ return new Promise((resolve15) => {
18545
19736
  const server = net.createServer();
18546
19737
  server.unref();
18547
- server.on("error", () => resolve12(false));
19738
+ server.on("error", () => resolve15(false));
18548
19739
  server.listen(port, "127.0.0.1", () => {
18549
- server.close(() => resolve12(true));
19740
+ server.close(() => resolve15(true));
18550
19741
  });
18551
19742
  });
18552
19743
  }
18553
19744
  async function isCdpActive(port) {
18554
- return new Promise((resolve12) => {
19745
+ return new Promise((resolve15) => {
18555
19746
  const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
18556
19747
  timeout: 2e3
18557
19748
  }, (res) => {
@@ -18560,16 +19751,16 @@ async function isCdpActive(port) {
18560
19751
  res.on("end", () => {
18561
19752
  try {
18562
19753
  const info = JSON.parse(data);
18563
- resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
19754
+ resolve15(!!info["WebKit-Version"] || !!info["Browser"]);
18564
19755
  } catch {
18565
- resolve12(false);
19756
+ resolve15(false);
18566
19757
  }
18567
19758
  });
18568
19759
  });
18569
- req.on("error", () => resolve12(false));
19760
+ req.on("error", () => resolve15(false));
18570
19761
  req.on("timeout", () => {
18571
19762
  req.destroy();
18572
- resolve12(false);
19763
+ resolve15(false);
18573
19764
  });
18574
19765
  });
18575
19766
  }
@@ -18709,8 +19900,8 @@ function detectCurrentWorkspace(ideId) {
18709
19900
  const appNameMap = getMacAppIdentifiers();
18710
19901
  const appName = appNameMap[ideId];
18711
19902
  if (appName) {
18712
- const storagePath = path15.join(
18713
- process.env.APPDATA || path15.join(os15.homedir(), "AppData", "Roaming"),
19903
+ const storagePath = path18.join(
19904
+ process.env.APPDATA || path18.join(os15.homedir(), "AppData", "Roaming"),
18714
19905
  appName,
18715
19906
  "storage.json"
18716
19907
  );
@@ -18888,9 +20079,9 @@ init_logger();
18888
20079
 
18889
20080
  // src/logging/command-log.ts
18890
20081
  var fs8 = __toESM(require("fs"));
18891
- var path16 = __toESM(require("path"));
20082
+ var path19 = __toESM(require("path"));
18892
20083
  var os16 = __toESM(require("os"));
18893
- 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");
20084
+ 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");
18894
20085
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
18895
20086
  var MAX_DAYS = 7;
18896
20087
  try {
@@ -18928,13 +20119,13 @@ function getDateStr2() {
18928
20119
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
18929
20120
  }
18930
20121
  var currentDate2 = getDateStr2();
18931
- var currentFile = path16.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
20122
+ var currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
18932
20123
  var writeCount2 = 0;
18933
20124
  function checkRotation() {
18934
20125
  const today = getDateStr2();
18935
20126
  if (today !== currentDate2) {
18936
20127
  currentDate2 = today;
18937
- currentFile = path16.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
20128
+ currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
18938
20129
  cleanOldFiles();
18939
20130
  }
18940
20131
  }
@@ -18948,7 +20139,7 @@ function cleanOldFiles() {
18948
20139
  const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
18949
20140
  if (dateMatch && dateMatch[1] < cutoffStr) {
18950
20141
  try {
18951
- fs8.unlinkSync(path16.join(LOG_DIR2, file));
20142
+ fs8.unlinkSync(path19.join(LOG_DIR2, file));
18952
20143
  } catch {
18953
20144
  }
18954
20145
  }
@@ -18958,8 +20149,8 @@ function cleanOldFiles() {
18958
20149
  }
18959
20150
  function checkSize() {
18960
20151
  try {
18961
- const stat = fs8.statSync(currentFile);
18962
- if (stat.size > MAX_FILE_SIZE) {
20152
+ const stat2 = fs8.statSync(currentFile);
20153
+ if (stat2.size > MAX_FILE_SIZE) {
18963
20154
  const backup = currentFile.replace(".jsonl", ".1.jsonl");
18964
20155
  try {
18965
20156
  fs8.unlinkSync(backup);
@@ -19245,12 +20436,18 @@ function buildStatusSnapshot(options) {
19245
20436
  const unreadSourceSessions = buildSessionEntries(
19246
20437
  options.allStates,
19247
20438
  options.cdpManagers,
19248
- { profile: "full" }
20439
+ {
20440
+ profile: "full",
20441
+ getGitSummaryForWorkspace: options.getGitSummaryForWorkspace
20442
+ }
19249
20443
  );
19250
20444
  const sessions = profile === "full" ? unreadSourceSessions : profile === "live" ? unreadSourceSessions.map(projectLiveSessionFromFull) : buildSessionEntries(
19251
20445
  options.allStates,
19252
20446
  options.cdpManagers,
19253
- { profile }
20447
+ {
20448
+ profile,
20449
+ getGitSummaryForWorkspace: options.getGitSummaryForWorkspace
20450
+ }
19254
20451
  );
19255
20452
  const sessionsById = new Map(sessions.map((session) => [session.id, session]));
19256
20453
  for (const sourceSession of unreadSourceSessions) {
@@ -19344,13 +20541,13 @@ var import_child_process8 = require("child_process");
19344
20541
  var import_child_process9 = require("child_process");
19345
20542
  var fs9 = __toESM(require("fs"));
19346
20543
  var os18 = __toESM(require("os"));
19347
- var path17 = __toESM(require("path"));
20544
+ var path20 = __toESM(require("path"));
19348
20545
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
19349
20546
  function getUpgradeLogPath() {
19350
20547
  const home = os18.homedir();
19351
- const dir = path17.join(home, ".adhdev");
20548
+ const dir = path20.join(home, ".adhdev");
19352
20549
  fs9.mkdirSync(dir, { recursive: true });
19353
- return path17.join(dir, "daemon-upgrade.log");
20550
+ return path20.join(dir, "daemon-upgrade.log");
19354
20551
  }
19355
20552
  function appendUpgradeLog(message) {
19356
20553
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -19361,14 +20558,14 @@ function appendUpgradeLog(message) {
19361
20558
  }
19362
20559
  }
19363
20560
  function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
19364
- const binDir = path17.dirname(nodeExecutable);
20561
+ const binDir = path20.dirname(nodeExecutable);
19365
20562
  if (platform10 === "win32") {
19366
- const npmCliPath = path17.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
20563
+ const npmCliPath = path20.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
19367
20564
  if (fs9.existsSync(npmCliPath)) {
19368
20565
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
19369
20566
  }
19370
20567
  for (const candidate of ["npm.exe", "npm"]) {
19371
- const candidatePath = path17.join(binDir, candidate);
20568
+ const candidatePath = path20.join(binDir, candidate);
19372
20569
  if (fs9.existsSync(candidatePath)) {
19373
20570
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
19374
20571
  }
@@ -19376,7 +20573,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
19376
20573
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
19377
20574
  }
19378
20575
  for (const candidate of ["npm"]) {
19379
- const candidatePath = path17.join(binDir, candidate);
20576
+ const candidatePath = path20.join(binDir, candidate);
19380
20577
  if (fs9.existsSync(candidatePath)) {
19381
20578
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
19382
20579
  }
@@ -19393,13 +20590,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
19393
20590
  let currentDir = resolvedPath;
19394
20591
  try {
19395
20592
  if (fs9.statSync(resolvedPath).isFile()) {
19396
- currentDir = path17.dirname(resolvedPath);
20593
+ currentDir = path20.dirname(resolvedPath);
19397
20594
  }
19398
20595
  } catch {
19399
- currentDir = path17.dirname(resolvedPath);
20596
+ currentDir = path20.dirname(resolvedPath);
19400
20597
  }
19401
20598
  while (true) {
19402
- const packageJsonPath = path17.join(currentDir, "package.json");
20599
+ const packageJsonPath = path20.join(currentDir, "package.json");
19403
20600
  try {
19404
20601
  if (fs9.existsSync(packageJsonPath)) {
19405
20602
  const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
@@ -19410,7 +20607,7 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
19410
20607
  }
19411
20608
  } catch {
19412
20609
  }
19413
- const parentDir = path17.dirname(currentDir);
20610
+ const parentDir = path20.dirname(currentDir);
19414
20611
  if (parentDir === currentDir) {
19415
20612
  return null;
19416
20613
  }
@@ -19418,13 +20615,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
19418
20615
  }
19419
20616
  }
19420
20617
  function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
19421
- const nodeModulesDir = packageName.startsWith("@") ? path17.dirname(path17.dirname(packageRoot)) : path17.dirname(packageRoot);
19422
- if (path17.basename(nodeModulesDir) !== "node_modules") {
20618
+ const nodeModulesDir = packageName.startsWith("@") ? path20.dirname(path20.dirname(packageRoot)) : path20.dirname(packageRoot);
20619
+ if (path20.basename(nodeModulesDir) !== "node_modules") {
19423
20620
  return null;
19424
20621
  }
19425
- const maybeLibDir = path17.dirname(nodeModulesDir);
19426
- if (path17.basename(maybeLibDir) === "lib") {
19427
- return path17.dirname(maybeLibDir);
20622
+ const maybeLibDir = path20.dirname(nodeModulesDir);
20623
+ if (path20.basename(maybeLibDir) === "lib") {
20624
+ return path20.dirname(maybeLibDir);
19428
20625
  }
19429
20626
  return maybeLibDir;
19430
20627
  }
@@ -19532,14 +20729,14 @@ async function waitForPidExit(pid, timeoutMs) {
19532
20729
  while (Date.now() - start < timeoutMs) {
19533
20730
  try {
19534
20731
  process.kill(pid, 0);
19535
- await new Promise((resolve12) => setTimeout(resolve12, 250));
20732
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
19536
20733
  } catch {
19537
20734
  return;
19538
20735
  }
19539
20736
  }
19540
20737
  }
19541
20738
  function stopSessionHostProcesses(appName) {
19542
- const pidFile = path17.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
20739
+ const pidFile = path20.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
19543
20740
  try {
19544
20741
  if (fs9.existsSync(pidFile)) {
19545
20742
  const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
@@ -19556,7 +20753,7 @@ function stopSessionHostProcesses(appName) {
19556
20753
  }
19557
20754
  }
19558
20755
  function removeDaemonPidFile() {
19559
- const pidFile = path17.join(os18.homedir(), ".adhdev", "daemon.pid");
20756
+ const pidFile = path20.join(os18.homedir(), ".adhdev", "daemon.pid");
19560
20757
  try {
19561
20758
  fs9.unlinkSync(pidFile);
19562
20759
  } catch {
@@ -19567,7 +20764,7 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
19567
20764
  const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
19568
20765
  if (!npmRoot) return;
19569
20766
  const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
19570
- const binDir = process.platform === "win32" ? npmPrefix : path17.join(npmPrefix, "bin");
20767
+ const binDir = process.platform === "win32" ? npmPrefix : path20.join(npmPrefix, "bin");
19571
20768
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
19572
20769
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
19573
20770
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -19575,25 +20772,25 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
19575
20772
  }
19576
20773
  if (pkgName.startsWith("@")) {
19577
20774
  const [scope, name] = pkgName.split("/");
19578
- const scopeDir = path17.join(npmRoot, scope);
20775
+ const scopeDir = path20.join(npmRoot, scope);
19579
20776
  if (!fs9.existsSync(scopeDir)) return;
19580
20777
  for (const entry of fs9.readdirSync(scopeDir)) {
19581
20778
  if (!entry.startsWith(`.${name}-`)) continue;
19582
- fs9.rmSync(path17.join(scopeDir, entry), { recursive: true, force: true });
19583
- appendUpgradeLog(`Removed stale scoped staging dir: ${path17.join(scopeDir, entry)}`);
20779
+ fs9.rmSync(path20.join(scopeDir, entry), { recursive: true, force: true });
20780
+ appendUpgradeLog(`Removed stale scoped staging dir: ${path20.join(scopeDir, entry)}`);
19584
20781
  }
19585
20782
  } else {
19586
20783
  for (const entry of fs9.readdirSync(npmRoot)) {
19587
20784
  if (!entry.startsWith(`.${pkgName}-`)) continue;
19588
- fs9.rmSync(path17.join(npmRoot, entry), { recursive: true, force: true });
19589
- appendUpgradeLog(`Removed stale staging dir: ${path17.join(npmRoot, entry)}`);
20785
+ fs9.rmSync(path20.join(npmRoot, entry), { recursive: true, force: true });
20786
+ appendUpgradeLog(`Removed stale staging dir: ${path20.join(npmRoot, entry)}`);
19590
20787
  }
19591
20788
  }
19592
20789
  if (fs9.existsSync(binDir)) {
19593
20790
  for (const entry of fs9.readdirSync(binDir)) {
19594
20791
  if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
19595
- fs9.rmSync(path17.join(binDir, entry), { recursive: true, force: true });
19596
- appendUpgradeLog(`Removed stale bin staging entry: ${path17.join(binDir, entry)}`);
20792
+ fs9.rmSync(path20.join(binDir, entry), { recursive: true, force: true });
20793
+ appendUpgradeLog(`Removed stale bin staging entry: ${path20.join(binDir, entry)}`);
19597
20794
  }
19598
20795
  }
19599
20796
  }
@@ -19643,7 +20840,7 @@ async function runDaemonUpgradeHelper(payload) {
19643
20840
  appendUpgradeLog(installOutput.trim());
19644
20841
  }
19645
20842
  if (process.platform === "win32") {
19646
- await new Promise((resolve12) => setTimeout(resolve12, 500));
20843
+ await new Promise((resolve15) => setTimeout(resolve15, 500));
19647
20844
  cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
19648
20845
  appendUpgradeLog("Post-install staging cleanup complete");
19649
20846
  }
@@ -21037,7 +22234,7 @@ var ProviderStreamAdapter = class {
21037
22234
  const beforeCount = this.messageCount(before);
21038
22235
  const beforeSignature = this.lastMessageSignature(before);
21039
22236
  for (let attempt = 0; attempt < 12; attempt += 1) {
21040
- await new Promise((resolve12) => setTimeout(resolve12, 250));
22237
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
21041
22238
  let state;
21042
22239
  try {
21043
22240
  state = await this.readChat(evaluate);
@@ -21059,7 +22256,7 @@ var ProviderStreamAdapter = class {
21059
22256
  if (this.messageCount(first) > 0 || this.lastMessageSignature(first)) {
21060
22257
  return first;
21061
22258
  }
21062
- await new Promise((resolve12) => setTimeout(resolve12, 150));
22259
+ await new Promise((resolve15) => setTimeout(resolve15, 150));
21063
22260
  const second = await this.readChat(evaluate);
21064
22261
  return this.messageCount(second) >= this.messageCount(first) ? second : first;
21065
22262
  }
@@ -21210,7 +22407,7 @@ var ProviderStreamAdapter = class {
21210
22407
  if (typeof data.error === "string" && data.error.trim()) return false;
21211
22408
  }
21212
22409
  for (let attempt = 0; attempt < 6; attempt += 1) {
21213
- await new Promise((resolve12) => setTimeout(resolve12, 250));
22410
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
21214
22411
  const state = await this.readChat(evaluate);
21215
22412
  const title = this.getStateTitle(state);
21216
22413
  if (this.titlesMatch(title, sessionId)) return true;
@@ -22071,11 +23268,11 @@ init_chat_message_normalization();
22071
23268
 
22072
23269
  // src/providers/version-archive.ts
22073
23270
  var fs11 = __toESM(require("fs"));
22074
- var path18 = __toESM(require("path"));
23271
+ var path21 = __toESM(require("path"));
22075
23272
  var os19 = __toESM(require("os"));
22076
23273
  var import_child_process10 = require("child_process");
22077
23274
  var import_os3 = require("os");
22078
- var ARCHIVE_PATH = path18.join(os19.homedir(), ".adhdev", "version-history.json");
23275
+ var ARCHIVE_PATH = path21.join(os19.homedir(), ".adhdev", "version-history.json");
22079
23276
  var MAX_ENTRIES_PER_PROVIDER = 20;
22080
23277
  var VersionArchive = class {
22081
23278
  history = {};
@@ -22122,7 +23319,7 @@ var VersionArchive = class {
22122
23319
  }
22123
23320
  save() {
22124
23321
  try {
22125
- fs11.mkdirSync(path18.dirname(ARCHIVE_PATH), { recursive: true });
23322
+ fs11.mkdirSync(path21.dirname(ARCHIVE_PATH), { recursive: true });
22126
23323
  fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
22127
23324
  } catch {
22128
23325
  }
@@ -22179,7 +23376,7 @@ function checkPathExists2(paths) {
22179
23376
  for (const p of paths) {
22180
23377
  if (p.includes("*")) {
22181
23378
  const home = os19.homedir();
22182
- const resolved = p.replace(/\*/g, home.split(path18.sep).pop() || "");
23379
+ const resolved = p.replace(/\*/g, home.split(path21.sep).pop() || "");
22183
23380
  if (fs11.existsSync(resolved)) return resolved;
22184
23381
  } else {
22185
23382
  if (fs11.existsSync(p)) return p;
@@ -22189,7 +23386,7 @@ function checkPathExists2(paths) {
22189
23386
  }
22190
23387
  function getMacAppVersion(appPath) {
22191
23388
  if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
22192
- const plistPath = path18.join(appPath, "Contents", "Info.plist");
23389
+ const plistPath = path21.join(appPath, "Contents", "Info.plist");
22193
23390
  if (!fs11.existsSync(plistPath)) return null;
22194
23391
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
22195
23392
  return raw || null;
@@ -22215,7 +23412,7 @@ async function detectAllVersions(loader, archive) {
22215
23412
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
22216
23413
  let resolvedBin = cliBin;
22217
23414
  if (!resolvedBin && appPath && currentOs === "darwin") {
22218
- const bundled = path18.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
23415
+ const bundled = path21.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
22219
23416
  if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
22220
23417
  }
22221
23418
  info.installed = !!(appPath || resolvedBin);
@@ -22256,7 +23453,7 @@ async function detectAllVersions(loader, archive) {
22256
23453
  // src/daemon/dev-server.ts
22257
23454
  var http2 = __toESM(require("http"));
22258
23455
  var fs15 = __toESM(require("fs"));
22259
- var path22 = __toESM(require("path"));
23456
+ var path25 = __toESM(require("path"));
22260
23457
  init_config();
22261
23458
 
22262
23459
  // src/daemon/scaffold-template.ts
@@ -22607,7 +23804,7 @@ init_logger();
22607
23804
 
22608
23805
  // src/daemon/dev-cdp-handlers.ts
22609
23806
  var fs12 = __toESM(require("fs"));
22610
- var path19 = __toESM(require("path"));
23807
+ var path22 = __toESM(require("path"));
22611
23808
  init_logger();
22612
23809
  async function handleCdpEvaluate(ctx, req, res) {
22613
23810
  const body = await ctx.readBody(req);
@@ -22786,17 +23983,17 @@ async function handleScriptHints(ctx, type, _req, res) {
22786
23983
  return;
22787
23984
  }
22788
23985
  let scriptsPath = "";
22789
- const directScripts = path19.join(dir, "scripts.js");
23986
+ const directScripts = path22.join(dir, "scripts.js");
22790
23987
  if (fs12.existsSync(directScripts)) {
22791
23988
  scriptsPath = directScripts;
22792
23989
  } else {
22793
- const scriptsDir = path19.join(dir, "scripts");
23990
+ const scriptsDir = path22.join(dir, "scripts");
22794
23991
  if (fs12.existsSync(scriptsDir)) {
22795
23992
  const versions = fs12.readdirSync(scriptsDir).filter((d) => {
22796
- return fs12.statSync(path19.join(scriptsDir, d)).isDirectory();
23993
+ return fs12.statSync(path22.join(scriptsDir, d)).isDirectory();
22797
23994
  }).sort().reverse();
22798
23995
  for (const ver of versions) {
22799
- const p = path19.join(scriptsDir, ver, "scripts.js");
23996
+ const p = path22.join(scriptsDir, ver, "scripts.js");
22800
23997
  if (fs12.existsSync(p)) {
22801
23998
  scriptsPath = p;
22802
23999
  break;
@@ -23625,7 +24822,7 @@ async function handleDomContext(ctx, type, req, res) {
23625
24822
 
23626
24823
  // src/daemon/dev-cli-debug.ts
23627
24824
  var fs13 = __toESM(require("fs"));
23628
- var path20 = __toESM(require("path"));
24825
+ var path23 = __toESM(require("path"));
23629
24826
  function slugifyFixtureName(value) {
23630
24827
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
23631
24828
  return normalized || `fixture-${Date.now()}`;
@@ -23635,11 +24832,11 @@ function getCliFixtureDir(ctx, type) {
23635
24832
  if (!providerDir) {
23636
24833
  throw new Error(`Provider directory not found for '${type}'`);
23637
24834
  }
23638
- return path20.join(providerDir, "fixtures");
24835
+ return path23.join(providerDir, "fixtures");
23639
24836
  }
23640
24837
  function readCliFixture(ctx, type, name) {
23641
24838
  const fixtureDir = getCliFixtureDir(ctx, type);
23642
- const filePath = path20.join(fixtureDir, `${name}.json`);
24839
+ const filePath = path23.join(fixtureDir, `${name}.json`);
23643
24840
  if (!fs13.existsSync(filePath)) {
23644
24841
  throw new Error(`Fixture not found: ${filePath}`);
23645
24842
  }
@@ -23808,7 +25005,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
23808
25005
  return { target, instance, adapter };
23809
25006
  }
23810
25007
  function sleep(ms) {
23811
- return new Promise((resolve12) => setTimeout(resolve12, ms));
25008
+ return new Promise((resolve15) => setTimeout(resolve15, ms));
23812
25009
  }
23813
25010
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
23814
25011
  const startedAt = Date.now();
@@ -24106,7 +25303,7 @@ async function runCliAutoImplVerification(ctx, type, verification) {
24106
25303
  return {
24107
25304
  mode: "fixture_replay_suite",
24108
25305
  pass: results.every((item) => item.pass),
24109
- failures: results.flatMap((item) => item.failures.map((failure) => `${item.fixtureName}: ${failure}`)),
25306
+ failures: results.flatMap((item) => item.failures.map((failure2) => `${item.fixtureName}: ${failure2}`)),
24110
25307
  result: firstFailure.result,
24111
25308
  assertions: firstFailure.assertions,
24112
25309
  fixture: firstFailure.fixture,
@@ -24406,7 +25603,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
24406
25603
  },
24407
25604
  notes: typeof body?.notes === "string" ? body.notes : void 0
24408
25605
  };
24409
- const filePath = path20.join(fixtureDir, `${name}.json`);
25606
+ const filePath = path23.join(fixtureDir, `${name}.json`);
24410
25607
  fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
24411
25608
  ctx.json(res, 200, {
24412
25609
  saved: true,
@@ -24430,7 +25627,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
24430
25627
  return;
24431
25628
  }
24432
25629
  const fixtures = fs13.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
24433
- const fullPath = path20.join(fixtureDir, file);
25630
+ const fullPath = path23.join(fixtureDir, file);
24434
25631
  try {
24435
25632
  const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
24436
25633
  return {
@@ -24566,7 +25763,7 @@ async function handleCliRaw(ctx, req, res) {
24566
25763
 
24567
25764
  // src/daemon/dev-auto-implement.ts
24568
25765
  var fs14 = __toESM(require("fs"));
24569
- var path21 = __toESM(require("path"));
25766
+ var path24 = __toESM(require("path"));
24570
25767
  var os20 = __toESM(require("os"));
24571
25768
  function getAutoImplPid(ctx) {
24572
25769
  const pid = ctx.autoImplProcess?.pid;
@@ -24616,22 +25813,22 @@ function getLatestScriptVersionDir(scriptsDir) {
24616
25813
  if (!fs14.existsSync(scriptsDir)) return null;
24617
25814
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
24618
25815
  try {
24619
- return fs14.statSync(path21.join(scriptsDir, d)).isDirectory();
25816
+ return fs14.statSync(path24.join(scriptsDir, d)).isDirectory();
24620
25817
  } catch {
24621
25818
  return false;
24622
25819
  }
24623
25820
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
24624
25821
  if (versions.length === 0) return null;
24625
- return path21.join(scriptsDir, versions[0]);
25822
+ return path24.join(scriptsDir, versions[0]);
24626
25823
  }
24627
25824
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
24628
- const canonicalUserDir = path21.resolve(ctx.providerLoader.getUserProviderDir(category, type));
24629
- const desiredDir = requestedDir ? path21.resolve(requestedDir) : canonicalUserDir;
24630
- const upstreamRoot = path21.resolve(ctx.providerLoader.getUpstreamDir());
24631
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path21.sep}`)) {
25825
+ const canonicalUserDir = path24.resolve(ctx.providerLoader.getUserProviderDir(category, type));
25826
+ const desiredDir = requestedDir ? path24.resolve(requestedDir) : canonicalUserDir;
25827
+ const upstreamRoot = path24.resolve(ctx.providerLoader.getUpstreamDir());
25828
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path24.sep}`)) {
24632
25829
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
24633
25830
  }
24634
- if (path21.basename(desiredDir) !== type) {
25831
+ if (path24.basename(desiredDir) !== type) {
24635
25832
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
24636
25833
  }
24637
25834
  const sourceDir = ctx.findProviderDir(type);
@@ -24639,11 +25836,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
24639
25836
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
24640
25837
  }
24641
25838
  if (!fs14.existsSync(desiredDir)) {
24642
- fs14.mkdirSync(path21.dirname(desiredDir), { recursive: true });
25839
+ fs14.mkdirSync(path24.dirname(desiredDir), { recursive: true });
24643
25840
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
24644
25841
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
24645
25842
  }
24646
- const providerJson = path21.join(desiredDir, "provider.json");
25843
+ const providerJson = path24.join(desiredDir, "provider.json");
24647
25844
  if (!fs14.existsSync(providerJson)) {
24648
25845
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
24649
25846
  }
@@ -24654,13 +25851,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
24654
25851
  const refDir = ctx.findProviderDir(referenceType);
24655
25852
  if (!refDir || !fs14.existsSync(refDir)) return {};
24656
25853
  const referenceScripts = {};
24657
- const scriptsDir = path21.join(refDir, "scripts");
25854
+ const scriptsDir = path24.join(refDir, "scripts");
24658
25855
  const latestDir = getLatestScriptVersionDir(scriptsDir);
24659
25856
  if (!latestDir) return referenceScripts;
24660
25857
  for (const file of fs14.readdirSync(latestDir)) {
24661
25858
  if (!file.endsWith(".js")) continue;
24662
25859
  try {
24663
- referenceScripts[file] = fs14.readFileSync(path21.join(latestDir, file), "utf-8");
25860
+ referenceScripts[file] = fs14.readFileSync(path24.join(latestDir, file), "utf-8");
24664
25861
  } catch {
24665
25862
  }
24666
25863
  }
@@ -24768,9 +25965,9 @@ async function handleAutoImplement(ctx, type, req, res) {
24768
25965
  });
24769
25966
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
24770
25967
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
24771
- const tmpDir = path21.join(os20.tmpdir(), "adhdev-autoimpl");
25968
+ const tmpDir = path24.join(os20.tmpdir(), "adhdev-autoimpl");
24772
25969
  if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
24773
- const promptFile = path21.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
25970
+ const promptFile = path24.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
24774
25971
  fs14.writeFileSync(promptFile, prompt, "utf-8");
24775
25972
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
24776
25973
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -25202,7 +26399,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
25202
26399
  setMode: "set_mode.js"
25203
26400
  };
25204
26401
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
25205
- const scriptsDir = path21.join(providerDir, "scripts");
26402
+ const scriptsDir = path24.join(providerDir, "scripts");
25206
26403
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
25207
26404
  if (latestScriptsDir) {
25208
26405
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -25213,7 +26410,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
25213
26410
  for (const file of fs14.readdirSync(latestScriptsDir)) {
25214
26411
  if (file.endsWith(".js") && targetFileNames.has(file)) {
25215
26412
  try {
25216
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
26413
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
25217
26414
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
25218
26415
  lines.push("```javascript");
25219
26416
  lines.push(content);
@@ -25230,7 +26427,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
25230
26427
  lines.push("");
25231
26428
  for (const file of refFiles) {
25232
26429
  try {
25233
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
26430
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
25234
26431
  lines.push(`### \`${file}\` \u{1F512}`);
25235
26432
  lines.push("```javascript");
25236
26433
  lines.push(content);
@@ -25271,10 +26468,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
25271
26468
  lines.push("");
25272
26469
  }
25273
26470
  }
25274
- const docsDir = path21.join(providerDir, "../../docs");
26471
+ const docsDir = path24.join(providerDir, "../../docs");
25275
26472
  const loadGuide = (name) => {
25276
26473
  try {
25277
- const p = path21.join(docsDir, name);
26474
+ const p = path24.join(docsDir, name);
25278
26475
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
25279
26476
  } catch {
25280
26477
  }
@@ -25511,7 +26708,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
25511
26708
  parseApproval: "parse_approval.js"
25512
26709
  };
25513
26710
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
25514
- const scriptsDir = path21.join(providerDir, "scripts");
26711
+ const scriptsDir = path24.join(providerDir, "scripts");
25515
26712
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
25516
26713
  if (latestScriptsDir) {
25517
26714
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -25523,7 +26720,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
25523
26720
  if (!file.endsWith(".js")) continue;
25524
26721
  if (!targetFileNames.has(file)) continue;
25525
26722
  try {
25526
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
26723
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
25527
26724
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
25528
26725
  lines.push("```javascript");
25529
26726
  lines.push(content);
@@ -25539,7 +26736,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
25539
26736
  lines.push("");
25540
26737
  for (const file of refFiles) {
25541
26738
  try {
25542
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
26739
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
25543
26740
  lines.push(`### \`${file}\` \u{1F512}`);
25544
26741
  lines.push("```javascript");
25545
26742
  lines.push(content);
@@ -25572,10 +26769,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
25572
26769
  lines.push("");
25573
26770
  }
25574
26771
  }
25575
- const docsDir = path21.join(providerDir, "../../docs");
26772
+ const docsDir = path24.join(providerDir, "../../docs");
25576
26773
  const loadGuide = (name) => {
25577
26774
  try {
25578
- const p = path21.join(docsDir, name);
26775
+ const p = path24.join(docsDir, name);
25579
26776
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
25580
26777
  } catch {
25581
26778
  }
@@ -26022,8 +27219,8 @@ var DevServer = class _DevServer {
26022
27219
  }
26023
27220
  getEndpointList() {
26024
27221
  return this.routes.map((r) => {
26025
- const path23 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
26026
- return `${r.method.padEnd(5)} ${path23}`;
27222
+ const path26 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
27223
+ return `${r.method.padEnd(5)} ${path26}`;
26027
27224
  });
26028
27225
  }
26029
27226
  async start(port = DEV_SERVER_PORT) {
@@ -26054,15 +27251,15 @@ var DevServer = class _DevServer {
26054
27251
  this.json(res, 500, { error: e.message });
26055
27252
  }
26056
27253
  });
26057
- return new Promise((resolve12, reject) => {
27254
+ return new Promise((resolve15, reject) => {
26058
27255
  this.server.listen(port, "127.0.0.1", () => {
26059
27256
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
26060
- resolve12();
27257
+ resolve15();
26061
27258
  });
26062
27259
  this.server.on("error", (e) => {
26063
27260
  if (e.code === "EADDRINUSE") {
26064
27261
  this.log(`Port ${port} in use, skipping dev server`);
26065
- resolve12();
27262
+ resolve15();
26066
27263
  } else {
26067
27264
  reject(e);
26068
27265
  }
@@ -26144,20 +27341,20 @@ var DevServer = class _DevServer {
26144
27341
  child.stderr?.on("data", (d) => {
26145
27342
  stderr += d.toString().slice(0, 2e3);
26146
27343
  });
26147
- await new Promise((resolve12) => {
27344
+ await new Promise((resolve15) => {
26148
27345
  const timer = setTimeout(() => {
26149
27346
  child.kill();
26150
- resolve12();
27347
+ resolve15();
26151
27348
  }, 3e3);
26152
27349
  child.on("exit", () => {
26153
27350
  clearTimeout(timer);
26154
- resolve12();
27351
+ resolve15();
26155
27352
  });
26156
27353
  child.stdout?.once("data", () => {
26157
27354
  setTimeout(() => {
26158
27355
  child.kill();
26159
27356
  clearTimeout(timer);
26160
- resolve12();
27357
+ resolve15();
26161
27358
  }, 500);
26162
27359
  });
26163
27360
  });
@@ -26311,12 +27508,12 @@ var DevServer = class _DevServer {
26311
27508
  // ─── DevConsole SPA ───
26312
27509
  getConsoleDistDir() {
26313
27510
  const candidates = [
26314
- path22.resolve(__dirname, "../../web-devconsole/dist"),
26315
- path22.resolve(__dirname, "../../../web-devconsole/dist"),
26316
- path22.join(process.cwd(), "packages/web-devconsole/dist")
27511
+ path25.resolve(__dirname, "../../web-devconsole/dist"),
27512
+ path25.resolve(__dirname, "../../../web-devconsole/dist"),
27513
+ path25.join(process.cwd(), "packages/web-devconsole/dist")
26317
27514
  ];
26318
27515
  for (const dir of candidates) {
26319
- if (fs15.existsSync(path22.join(dir, "index.html"))) return dir;
27516
+ if (fs15.existsSync(path25.join(dir, "index.html"))) return dir;
26320
27517
  }
26321
27518
  return null;
26322
27519
  }
@@ -26326,7 +27523,7 @@ var DevServer = class _DevServer {
26326
27523
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
26327
27524
  return;
26328
27525
  }
26329
- const htmlPath = path22.join(distDir, "index.html");
27526
+ const htmlPath = path25.join(distDir, "index.html");
26330
27527
  try {
26331
27528
  const html = fs15.readFileSync(htmlPath, "utf-8");
26332
27529
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -26351,15 +27548,15 @@ var DevServer = class _DevServer {
26351
27548
  this.json(res, 404, { error: "Not found" });
26352
27549
  return;
26353
27550
  }
26354
- const safePath = path22.normalize(pathname).replace(/^\.\.\//, "");
26355
- const filePath = path22.join(distDir, safePath);
27551
+ const safePath = path25.normalize(pathname).replace(/^\.\.\//, "");
27552
+ const filePath = path25.join(distDir, safePath);
26356
27553
  if (!filePath.startsWith(distDir)) {
26357
27554
  this.json(res, 403, { error: "Forbidden" });
26358
27555
  return;
26359
27556
  }
26360
27557
  try {
26361
27558
  const content = fs15.readFileSync(filePath);
26362
- const ext = path22.extname(filePath);
27559
+ const ext = path25.extname(filePath);
26363
27560
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
26364
27561
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
26365
27562
  res.end(content);
@@ -26472,10 +27669,10 @@ var DevServer = class _DevServer {
26472
27669
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
26473
27670
  if (entry.isDirectory()) {
26474
27671
  files.push({ path: rel, size: 0, type: "dir" });
26475
- scan(path22.join(d, entry.name), rel);
27672
+ scan(path25.join(d, entry.name), rel);
26476
27673
  } else {
26477
- const stat = fs15.statSync(path22.join(d, entry.name));
26478
- files.push({ path: rel, size: stat.size, type: "file" });
27674
+ const stat2 = fs15.statSync(path25.join(d, entry.name));
27675
+ files.push({ path: rel, size: stat2.size, type: "file" });
26479
27676
  }
26480
27677
  }
26481
27678
  } catch {
@@ -26497,7 +27694,7 @@ var DevServer = class _DevServer {
26497
27694
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
26498
27695
  return;
26499
27696
  }
26500
- const fullPath = path22.resolve(dir, path22.normalize(filePath));
27697
+ const fullPath = path25.resolve(dir, path25.normalize(filePath));
26501
27698
  if (!fullPath.startsWith(dir)) {
26502
27699
  this.json(res, 403, { error: "Forbidden" });
26503
27700
  return;
@@ -26522,14 +27719,14 @@ var DevServer = class _DevServer {
26522
27719
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
26523
27720
  return;
26524
27721
  }
26525
- const fullPath = path22.resolve(dir, path22.normalize(filePath));
27722
+ const fullPath = path25.resolve(dir, path25.normalize(filePath));
26526
27723
  if (!fullPath.startsWith(dir)) {
26527
27724
  this.json(res, 403, { error: "Forbidden" });
26528
27725
  return;
26529
27726
  }
26530
27727
  try {
26531
27728
  if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
26532
- fs15.mkdirSync(path22.dirname(fullPath), { recursive: true });
27729
+ fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
26533
27730
  fs15.writeFileSync(fullPath, content, "utf-8");
26534
27731
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
26535
27732
  this.providerLoader.reload();
@@ -26546,7 +27743,7 @@ var DevServer = class _DevServer {
26546
27743
  return;
26547
27744
  }
26548
27745
  for (const name of ["scripts.js", "provider.json"]) {
26549
- const p = path22.join(dir, name);
27746
+ const p = path25.join(dir, name);
26550
27747
  if (fs15.existsSync(p)) {
26551
27748
  const source = fs15.readFileSync(p, "utf-8");
26552
27749
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -26567,8 +27764,8 @@ var DevServer = class _DevServer {
26567
27764
  this.json(res, 404, { error: `Provider not found: ${type}` });
26568
27765
  return;
26569
27766
  }
26570
- const target = fs15.existsSync(path22.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
26571
- const targetPath = path22.join(dir, target);
27767
+ const target = fs15.existsSync(path25.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
27768
+ const targetPath = path25.join(dir, target);
26572
27769
  try {
26573
27770
  if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
26574
27771
  fs15.writeFileSync(targetPath, source, "utf-8");
@@ -26660,14 +27857,14 @@ var DevServer = class _DevServer {
26660
27857
  child.stderr?.on("data", (d) => {
26661
27858
  stderr += d.toString();
26662
27859
  });
26663
- await new Promise((resolve12) => {
27860
+ await new Promise((resolve15) => {
26664
27861
  const timer = setTimeout(() => {
26665
27862
  child.kill();
26666
- resolve12();
27863
+ resolve15();
26667
27864
  }, timeout);
26668
27865
  child.on("exit", () => {
26669
27866
  clearTimeout(timer);
26670
- resolve12();
27867
+ resolve15();
26671
27868
  });
26672
27869
  });
26673
27870
  const elapsed = Date.now() - start;
@@ -26715,7 +27912,7 @@ var DevServer = class _DevServer {
26715
27912
  }
26716
27913
  let targetDir;
26717
27914
  targetDir = this.providerLoader.getUserProviderDir(category, type);
26718
- const jsonPath = path22.join(targetDir, "provider.json");
27915
+ const jsonPath = path25.join(targetDir, "provider.json");
26719
27916
  if (fs15.existsSync(jsonPath)) {
26720
27917
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
26721
27918
  return;
@@ -26727,8 +27924,8 @@ var DevServer = class _DevServer {
26727
27924
  const createdFiles = ["provider.json"];
26728
27925
  if (result.files) {
26729
27926
  for (const [relPath, content] of Object.entries(result.files)) {
26730
- const fullPath = path22.join(targetDir, relPath);
26731
- fs15.mkdirSync(path22.dirname(fullPath), { recursive: true });
27927
+ const fullPath = path25.join(targetDir, relPath);
27928
+ fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
26732
27929
  fs15.writeFileSync(fullPath, content, "utf-8");
26733
27930
  createdFiles.push(relPath);
26734
27931
  }
@@ -26781,22 +27978,22 @@ var DevServer = class _DevServer {
26781
27978
  if (!fs15.existsSync(scriptsDir)) return null;
26782
27979
  const versions = fs15.readdirSync(scriptsDir).filter((d) => {
26783
27980
  try {
26784
- return fs15.statSync(path22.join(scriptsDir, d)).isDirectory();
27981
+ return fs15.statSync(path25.join(scriptsDir, d)).isDirectory();
26785
27982
  } catch {
26786
27983
  return false;
26787
27984
  }
26788
27985
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
26789
27986
  if (versions.length === 0) return null;
26790
- return path22.join(scriptsDir, versions[0]);
27987
+ return path25.join(scriptsDir, versions[0]);
26791
27988
  }
26792
27989
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
26793
- const canonicalUserDir = path22.resolve(this.providerLoader.getUserProviderDir(category, type));
26794
- const desiredDir = requestedDir ? path22.resolve(requestedDir) : canonicalUserDir;
26795
- const upstreamRoot = path22.resolve(this.providerLoader.getUpstreamDir());
26796
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path22.sep}`)) {
27990
+ const canonicalUserDir = path25.resolve(this.providerLoader.getUserProviderDir(category, type));
27991
+ const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
27992
+ const upstreamRoot = path25.resolve(this.providerLoader.getUpstreamDir());
27993
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
26797
27994
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
26798
27995
  }
26799
- if (path22.basename(desiredDir) !== type) {
27996
+ if (path25.basename(desiredDir) !== type) {
26800
27997
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
26801
27998
  }
26802
27999
  const sourceDir = this.findProviderDir(type);
@@ -26804,11 +28001,11 @@ var DevServer = class _DevServer {
26804
28001
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
26805
28002
  }
26806
28003
  if (!fs15.existsSync(desiredDir)) {
26807
- fs15.mkdirSync(path22.dirname(desiredDir), { recursive: true });
28004
+ fs15.mkdirSync(path25.dirname(desiredDir), { recursive: true });
26808
28005
  fs15.cpSync(sourceDir, desiredDir, { recursive: true });
26809
28006
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
26810
28007
  }
26811
- const providerJson = path22.join(desiredDir, "provider.json");
28008
+ const providerJson = path25.join(desiredDir, "provider.json");
26812
28009
  if (!fs15.existsSync(providerJson)) {
26813
28010
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
26814
28011
  }
@@ -26844,7 +28041,7 @@ var DevServer = class _DevServer {
26844
28041
  setMode: "set_mode.js"
26845
28042
  };
26846
28043
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26847
- const scriptsDir = path22.join(providerDir, "scripts");
28044
+ const scriptsDir = path25.join(providerDir, "scripts");
26848
28045
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
26849
28046
  if (latestScriptsDir) {
26850
28047
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26855,7 +28052,7 @@ var DevServer = class _DevServer {
26855
28052
  for (const file of fs15.readdirSync(latestScriptsDir)) {
26856
28053
  if (file.endsWith(".js") && targetFileNames.has(file)) {
26857
28054
  try {
26858
- const content = fs15.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
28055
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26859
28056
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26860
28057
  lines.push("```javascript");
26861
28058
  lines.push(content);
@@ -26872,7 +28069,7 @@ var DevServer = class _DevServer {
26872
28069
  lines.push("");
26873
28070
  for (const file of refFiles) {
26874
28071
  try {
26875
- const content = fs15.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
28072
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26876
28073
  lines.push(`### \`${file}\` \u{1F512}`);
26877
28074
  lines.push("```javascript");
26878
28075
  lines.push(content);
@@ -26913,10 +28110,10 @@ var DevServer = class _DevServer {
26913
28110
  lines.push("");
26914
28111
  }
26915
28112
  }
26916
- const docsDir = path22.join(providerDir, "../../docs");
28113
+ const docsDir = path25.join(providerDir, "../../docs");
26917
28114
  const loadGuide = (name) => {
26918
28115
  try {
26919
- const p = path22.join(docsDir, name);
28116
+ const p = path25.join(docsDir, name);
26920
28117
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
26921
28118
  } catch {
26922
28119
  }
@@ -27090,7 +28287,7 @@ var DevServer = class _DevServer {
27090
28287
  parseApproval: "parse_approval.js"
27091
28288
  };
27092
28289
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
27093
- const scriptsDir = path22.join(providerDir, "scripts");
28290
+ const scriptsDir = path25.join(providerDir, "scripts");
27094
28291
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
27095
28292
  if (latestScriptsDir) {
27096
28293
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -27102,7 +28299,7 @@ var DevServer = class _DevServer {
27102
28299
  if (!file.endsWith(".js")) continue;
27103
28300
  if (!targetFileNames.has(file)) continue;
27104
28301
  try {
27105
- const content = fs15.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
28302
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
27106
28303
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
27107
28304
  lines.push("```javascript");
27108
28305
  lines.push(content);
@@ -27118,7 +28315,7 @@ var DevServer = class _DevServer {
27118
28315
  lines.push("");
27119
28316
  for (const file of refFiles) {
27120
28317
  try {
27121
- const content = fs15.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
28318
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
27122
28319
  lines.push(`### \`${file}\` \u{1F512}`);
27123
28320
  lines.push("```javascript");
27124
28321
  lines.push(content);
@@ -27151,10 +28348,10 @@ var DevServer = class _DevServer {
27151
28348
  lines.push("");
27152
28349
  }
27153
28350
  }
27154
- const docsDir = path22.join(providerDir, "../../docs");
28351
+ const docsDir = path25.join(providerDir, "../../docs");
27155
28352
  const loadGuide = (name) => {
27156
28353
  try {
27157
- const p = path22.join(docsDir, name);
28354
+ const p = path25.join(docsDir, name);
27158
28355
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
27159
28356
  } catch {
27160
28357
  }
@@ -27337,14 +28534,14 @@ data: ${JSON.stringify(msg.data)}
27337
28534
  res.end(JSON.stringify(data, null, 2));
27338
28535
  }
27339
28536
  async readBody(req) {
27340
- return new Promise((resolve12) => {
28537
+ return new Promise((resolve15) => {
27341
28538
  let body = "";
27342
28539
  req.on("data", (chunk) => body += chunk);
27343
28540
  req.on("end", () => {
27344
28541
  try {
27345
- resolve12(JSON.parse(body));
28542
+ resolve15(JSON.parse(body));
27346
28543
  } catch {
27347
- resolve12({});
28544
+ resolve15({});
27348
28545
  }
27349
28546
  });
27350
28547
  });
@@ -27854,7 +29051,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
27854
29051
  const deadline = Date.now() + timeoutMs;
27855
29052
  while (Date.now() < deadline) {
27856
29053
  if (await canConnect(endpoint)) return;
27857
- await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
29054
+ await new Promise((resolve15) => setTimeout(resolve15, STARTUP_POLL_MS));
27858
29055
  }
27859
29056
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
27860
29057
  }
@@ -28032,10 +29229,10 @@ async function installExtension(ide, extension) {
28032
29229
  const buffer = Buffer.from(await res.arrayBuffer());
28033
29230
  const fs16 = await import("fs");
28034
29231
  fs16.writeFileSync(vsixPath, buffer);
28035
- return new Promise((resolve12) => {
29232
+ return new Promise((resolve15) => {
28036
29233
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
28037
29234
  (0, import_child_process11.exec)(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
28038
- resolve12({
29235
+ resolve15({
28039
29236
  extensionId: extension.id,
28040
29237
  marketplaceId: extension.marketplaceId,
28041
29238
  success: !error,
@@ -28048,11 +29245,11 @@ async function installExtension(ide, extension) {
28048
29245
  } catch (e) {
28049
29246
  }
28050
29247
  }
28051
- return new Promise((resolve12) => {
29248
+ return new Promise((resolve15) => {
28052
29249
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
28053
29250
  (0, import_child_process11.exec)(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
28054
29251
  if (error) {
28055
- resolve12({
29252
+ resolve15({
28056
29253
  extensionId: extension.id,
28057
29254
  marketplaceId: extension.marketplaceId,
28058
29255
  success: false,
@@ -28060,7 +29257,7 @@ async function installExtension(ide, extension) {
28060
29257
  error: stderr || error.message
28061
29258
  });
28062
29259
  } else {
28063
- resolve12({
29260
+ resolve15({
28064
29261
  extensionId: extension.id,
28065
29262
  marketplaceId: extension.marketplaceId,
28066
29263
  success: true,
@@ -28390,6 +29587,7 @@ async function shutdownDaemonComponents(components) {
28390
29587
  DEFAULT_CDP_SCAN_INTERVAL_MS,
28391
29588
  DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS,
28392
29589
  DEFAULT_DAEMON_PORT,
29590
+ DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS,
28393
29591
  DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
28394
29592
  DEFAULT_SESSION_HOST_APP_NAME,
28395
29593
  DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
@@ -28408,8 +29606,12 @@ async function shutdownDaemonComponents(components) {
28408
29606
  DaemonCommandRouter,
28409
29607
  DaemonStatusReporter,
28410
29608
  DevServer,
29609
+ GitCommandError,
29610
+ GitWorkspaceMonitor,
28411
29611
  IdeProviderInstance,
29612
+ InMemoryGitSnapshotStore,
28412
29613
  LOG,
29614
+ MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
28413
29615
  MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
28414
29616
  MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
28415
29617
  NodePtyTransportFactory,
@@ -28437,9 +29639,14 @@ async function shutdownDaemonComponents(components) {
28437
29639
  buildUserChatMessage,
28438
29640
  classifyHotChatSessionsForSubscriptionFlush,
28439
29641
  clearDebugTrace,
29642
+ compareGitSnapshots,
28440
29643
  configureDebugTraceStore,
28441
29644
  connectCdpManager,
28442
29645
  createDebugTraceStore,
29646
+ createDefaultGitCommandServices,
29647
+ createGitCompactSummary,
29648
+ createGitSnapshotStore,
29649
+ createGitWorkspaceMonitor,
28443
29650
  createInteractionId,
28444
29651
  detectAllVersions,
28445
29652
  detectCLIs,
@@ -28454,6 +29661,9 @@ async function shutdownDaemonComponents(components) {
28454
29661
  getCurrentDaemonLogPath,
28455
29662
  getDaemonLogDir,
28456
29663
  getDebugRuntimeConfig,
29664
+ getGitDiffSummary,
29665
+ getGitFileDiff,
29666
+ getGitRepoStatus,
28457
29667
  getHostMemorySnapshot,
28458
29668
  getLogLevel,
28459
29669
  getNpmExecOptions,
@@ -28465,6 +29675,7 @@ async function shutdownDaemonComponents(components) {
28465
29675
  getSessionHostRecoveryLabel,
28466
29676
  getSessionHostSurfaceKind,
28467
29677
  getWorkspaceState,
29678
+ handleGitCommand,
28468
29679
  hasCdpManager,
28469
29680
  hashSignatureParts,
28470
29681
  initDaemonComponents,
@@ -28473,9 +29684,11 @@ async function shutdownDaemonComponents(components) {
28473
29684
  isBuiltinChatMessageKind,
28474
29685
  isCdpConnected,
28475
29686
  isExtensionInstalled,
29687
+ isGitCommandName,
28476
29688
  isIdeRunning,
28477
29689
  isManagedStatusWaiting,
28478
29690
  isManagedStatusWorking,
29691
+ isPathInside,
28479
29692
  isSessionHostLiveRuntime,
28480
29693
  isSessionHostRecoverySnapshot,
28481
29694
  isSetupComplete,
@@ -28493,10 +29706,13 @@ async function shutdownDaemonComponents(components) {
28493
29706
  normalizeChatMessageKind,
28494
29707
  normalizeChatMessages,
28495
29708
  normalizeChatTailActiveModal,
29709
+ normalizeGitOutput,
29710
+ normalizeGitWorkspaceSubscriptionParams,
28496
29711
  normalizeInputEnvelope,
28497
29712
  normalizeManagedStatus,
28498
29713
  normalizeMessageParts,
28499
29714
  normalizeSessionModalFields,
29715
+ parsePorcelainV2Status,
28500
29716
  parseProviderSourceConfigUpdate,
28501
29717
  partitionSessionHostDiagnosticsSessions,
28502
29718
  partitionSessionHostRecords,
@@ -28512,9 +29728,11 @@ async function shutdownDaemonComponents(components) {
28512
29728
  resolveChatMessageKind,
28513
29729
  resolveCurrentGlobalInstallSurface,
28514
29730
  resolveDebugRuntimeConfig,
29731
+ resolveGitRepository,
28515
29732
  resolveSessionHostAppName,
28516
29733
  resolveSessionHostAppNameResolution,
28517
29734
  runAsyncBatch,
29735
+ runGit,
28518
29736
  saveConfig,
28519
29737
  saveState,
28520
29738
  setDebugRuntimeConfig,
@@ -28525,6 +29743,7 @@ async function shutdownDaemonComponents(components) {
28525
29743
  shutdownDaemonComponents,
28526
29744
  spawnDetachedDaemonUpgradeHelper,
28527
29745
  startDaemonDevSupport,
29746
+ summarizeGitStatus,
28528
29747
  updateConfig,
28529
29748
  upsertSavedProviderSession
28530
29749
  });