@adhdev/daemon-core 0.9.53 → 0.9.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.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
  }
@@ -8166,13 +9307,13 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
8166
9307
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
8167
9308
  try {
8168
9309
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
8169
- const dir = path7.join(HISTORY_DIR, sanitized);
9310
+ const dir = path10.join(HISTORY_DIR, sanitized);
8170
9311
  if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
8171
9312
  const files = listHistoryFiles(dir, historySessionId);
8172
9313
  const allMessages = [];
8173
9314
  const seen = /* @__PURE__ */ new Set();
8174
9315
  for (const file of files) {
8175
- const filePath = path7.join(dir, file);
9316
+ const filePath = path10.join(dir, file);
8176
9317
  const content = fs3.readFileSync(filePath, "utf-8");
8177
9318
  const lines = content.trim().split("\n").filter(Boolean);
8178
9319
  for (let i = 0; i < lines.length; i++) {
@@ -8196,7 +9337,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
8196
9337
  function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
8197
9338
  try {
8198
9339
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
8199
- const dir = path7.join(HISTORY_DIR, sanitized);
9340
+ const dir = path10.join(HISTORY_DIR, sanitized);
8200
9341
  if (!fs3.existsSync(dir)) {
8201
9342
  savedHistorySessionCache.delete(sanitized);
8202
9343
  return { sessions: [], hasMore: false };
@@ -8257,11 +9398,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
8257
9398
  }
8258
9399
  function readExistingSessionStartRecord(agentType, historySessionId) {
8259
9400
  try {
8260
- const dir = path7.join(HISTORY_DIR, agentType);
9401
+ const dir = path10.join(HISTORY_DIR, agentType);
8261
9402
  if (!fs3.existsSync(dir)) return null;
8262
9403
  const files = listHistoryFiles(dir, historySessionId).sort();
8263
9404
  for (const file of files) {
8264
- 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);
8265
9406
  for (const line of lines) {
8266
9407
  try {
8267
9408
  const parsed = JSON.parse(line);
@@ -8281,16 +9422,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
8281
9422
  function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
8282
9423
  if (records.length === 0) return false;
8283
9424
  try {
8284
- const dir = path7.join(HISTORY_DIR, agentType);
9425
+ const dir = path10.join(HISTORY_DIR, agentType);
8285
9426
  fs3.mkdirSync(dir, { recursive: true });
8286
9427
  const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
8287
9428
  for (const file of fs3.readdirSync(dir)) {
8288
9429
  if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
8289
- fs3.unlinkSync(path7.join(dir, file));
9430
+ fs3.unlinkSync(path10.join(dir, file));
8290
9431
  }
8291
9432
  }
8292
9433
  const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
8293
- const filePath = path7.join(dir, `${prefix}${targetDate}.jsonl`);
9434
+ const filePath = path10.join(dir, `${prefix}${targetDate}.jsonl`);
8294
9435
  fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
8295
9436
  `, "utf-8");
8296
9437
  invalidatePersistedSavedHistoryIndex(agentType, dir);
@@ -10162,6 +11303,10 @@ function shouldIncludeSessionMetadata(profile) {
10162
11303
  function shouldIncludeRuntimeMetadata(profile) {
10163
11304
  return true;
10164
11305
  }
11306
+ function getGitSummaryForWorkspace(workspace, options) {
11307
+ if (!workspace) return void 0;
11308
+ return options.getGitSummaryForWorkspace?.(workspace) || void 0;
11309
+ }
10165
11310
  function findCdpManager(cdpManagers, key) {
10166
11311
  const exact = cdpManagers.get(key);
10167
11312
  if (exact) return exact.isConnected ? exact : null;
@@ -10217,6 +11362,8 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
10217
11362
  const controlValues = normalizeProviderStateControlValues(state.controlValues);
10218
11363
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
10219
11364
  const includeSessionControls = shouldIncludeSessionControls(profile);
11365
+ const workspace = state.workspace || null;
11366
+ const git = getGitSummaryForWorkspace(workspace, options);
10220
11367
  const title = activeChat?.title || state.name;
10221
11368
  return {
10222
11369
  id: state.instanceId || state.type,
@@ -10229,7 +11376,8 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
10229
11376
  activeModal: activeChat?.activeModal || null
10230
11377
  }),
10231
11378
  title,
10232
- workspace: state.workspace || null,
11379
+ workspace,
11380
+ ...git && { git },
10233
11381
  activeChat,
10234
11382
  ...summaryMetadata && { summaryMetadata },
10235
11383
  ...includeSessionMetadata && { capabilities: state.sessionCapabilities || IDE_SESSION_CAPABILITIES },
@@ -10250,6 +11398,8 @@ function buildExtensionAgentSession(parent, ext, options) {
10250
11398
  const controlValues = normalizeProviderStateControlValues(ext.controlValues);
10251
11399
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
10252
11400
  const includeSessionControls = shouldIncludeSessionControls(profile);
11401
+ const workspace = parent.workspace || null;
11402
+ const git = getGitSummaryForWorkspace(workspace, options);
10253
11403
  return {
10254
11404
  id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
10255
11405
  parentId: parent.instanceId || parent.type,
@@ -10262,7 +11412,8 @@ function buildExtensionAgentSession(parent, ext, options) {
10262
11412
  activeModal: activeChat?.activeModal || null
10263
11413
  }),
10264
11414
  title: activeChat?.title || ext.name,
10265
- workspace: parent.workspace || null,
11415
+ workspace,
11416
+ ...git && { git },
10266
11417
  activeChat,
10267
11418
  ...summaryMetadata && { summaryMetadata },
10268
11419
  ...includeSessionMetadata && { capabilities: ext.sessionCapabilities || EXTENSION_SESSION_CAPABILITIES },
@@ -10298,6 +11449,8 @@ function buildCliSession(state, options) {
10298
11449
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
10299
11450
  const includeRuntimeMetadata = shouldIncludeRuntimeMetadata(profile);
10300
11451
  const includeSessionControls = shouldIncludeSessionControls(profile);
11452
+ const workspace = state.workspace || null;
11453
+ const git = getGitSummaryForWorkspace(workspace, options);
10301
11454
  return {
10302
11455
  id: state.instanceId,
10303
11456
  parentId: null,
@@ -10310,7 +11463,8 @@ function buildCliSession(state, options) {
10310
11463
  activeModal: activeChat?.activeModal || null
10311
11464
  }),
10312
11465
  title: activeChat?.title || state.name,
10313
- workspace: state.workspace || null,
11466
+ workspace,
11467
+ ...git && { git },
10314
11468
  ...includeRuntimeMetadata && {
10315
11469
  runtimeKey: state.runtime?.runtimeKey,
10316
11470
  runtimeDisplayName: state.runtime?.displayName,
@@ -10345,6 +11499,8 @@ function buildAcpSession(state, options) {
10345
11499
  const controlValues = normalizeProviderStateControlValues(state.controlValues);
10346
11500
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
10347
11501
  const includeSessionControls = shouldIncludeSessionControls(profile);
11502
+ const workspace = state.workspace || null;
11503
+ const git = getGitSummaryForWorkspace(workspace, options);
10348
11504
  return {
10349
11505
  id: state.instanceId,
10350
11506
  parentId: null,
@@ -10356,7 +11512,8 @@ function buildAcpSession(state, options) {
10356
11512
  activeModal: activeChat?.activeModal || null
10357
11513
  }),
10358
11514
  title: activeChat?.title || state.name,
10359
- workspace: state.workspace || null,
11515
+ workspace,
11516
+ ...git && { git },
10360
11517
  activeChat,
10361
11518
  ...summaryMetadata && { summaryMetadata },
10362
11519
  ...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES },
@@ -10475,7 +11632,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
10475
11632
  // src/commands/chat-commands.ts
10476
11633
  var fs4 = __toESM(require("fs"));
10477
11634
  var os6 = __toESM(require("os"));
10478
- var path8 = __toESM(require("path"));
11635
+ var path11 = __toESM(require("path"));
10479
11636
  var import_node_crypto = require("crypto");
10480
11637
  init_contracts();
10481
11638
 
@@ -11168,7 +12325,7 @@ function buildDebugBundleText(bundle) {
11168
12325
  }
11169
12326
  function getChatDebugBundleDir() {
11170
12327
  const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
11171
- return override || path8.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
12328
+ return override || path11.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
11172
12329
  }
11173
12330
  function safeBundleIdSegment(value, fallback) {
11174
12331
  const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
@@ -11201,7 +12358,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
11201
12358
  const bundleId = createChatDebugBundleId(targetSessionId);
11202
12359
  const dir = getChatDebugBundleDir();
11203
12360
  fs4.mkdirSync(dir, { recursive: true });
11204
- const savedPath = path8.join(dir, `${bundleId}.json`);
12361
+ const savedPath = path11.join(dir, `${bundleId}.json`);
11205
12362
  const json = `${JSON.stringify(bundle, null, 2)}
11206
12363
  `;
11207
12364
  fs4.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
@@ -11395,7 +12552,7 @@ function getCliVisibleTranscriptCount(adapter) {
11395
12552
  async function getStableExtensionBaseline(h) {
11396
12553
  const first = await readExtensionChatState(h);
11397
12554
  if (getStateMessageCount(first) > 0 || getStateLastSignature(first)) return first;
11398
- await new Promise((resolve12) => setTimeout(resolve12, 150));
12555
+ await new Promise((resolve15) => setTimeout(resolve15, 150));
11399
12556
  const second = await readExtensionChatState(h);
11400
12557
  return getStateMessageCount(second) >= getStateMessageCount(first) ? second : first;
11401
12558
  }
@@ -11403,7 +12560,7 @@ async function verifyExtensionSendObserved(h, before) {
11403
12560
  const beforeCount = getStateMessageCount(before);
11404
12561
  const beforeSignature = getStateLastSignature(before);
11405
12562
  for (let attempt = 0; attempt < 12; attempt += 1) {
11406
- await new Promise((resolve12) => setTimeout(resolve12, 250));
12563
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
11407
12564
  const state = await readExtensionChatState(h);
11408
12565
  if (state?.status === "waiting_approval") return true;
11409
12566
  const afterCount = getStateMessageCount(state);
@@ -12339,7 +13496,7 @@ async function handleResolveAction(h, args) {
12339
13496
 
12340
13497
  // src/commands/cdp-commands.ts
12341
13498
  var fs5 = __toESM(require("fs"));
12342
- var path9 = __toESM(require("path"));
13499
+ var path12 = __toESM(require("path"));
12343
13500
  var os7 = __toESM(require("os"));
12344
13501
  var KEY_TO_VK = {
12345
13502
  Backspace: 8,
@@ -12596,25 +13753,25 @@ function resolveSafePath(requestedPath) {
12596
13753
  const inputPath = rawPath || ".";
12597
13754
  const home = os7.homedir();
12598
13755
  if (inputPath.startsWith("~")) {
12599
- return path9.resolve(path9.join(home, inputPath.slice(1)));
13756
+ return path12.resolve(path12.join(home, inputPath.slice(1)));
12600
13757
  }
12601
13758
  if (process.platform === "win32") {
12602
13759
  const normalized = normalizeWindowsRequestedPath(inputPath);
12603
- if (path9.win32.isAbsolute(normalized)) {
12604
- return path9.win32.normalize(normalized);
13760
+ if (path12.win32.isAbsolute(normalized)) {
13761
+ return path12.win32.normalize(normalized);
12605
13762
  }
12606
- return path9.win32.resolve(normalized);
13763
+ return path12.win32.resolve(normalized);
12607
13764
  }
12608
- if (path9.isAbsolute(inputPath)) {
12609
- return path9.normalize(inputPath);
13765
+ if (path12.isAbsolute(inputPath)) {
13766
+ return path12.normalize(inputPath);
12610
13767
  }
12611
- return path9.resolve(inputPath);
13768
+ return path12.resolve(inputPath);
12612
13769
  }
12613
13770
  function listDirectoryEntriesSafe(dirPath) {
12614
13771
  const entries = fs5.readdirSync(dirPath, { withFileTypes: true });
12615
13772
  const files = [];
12616
13773
  for (const entry of entries) {
12617
- const entryPath = path9.join(dirPath, entry.name);
13774
+ const entryPath = path12.join(dirPath, entry.name);
12618
13775
  try {
12619
13776
  if (entry.isDirectory()) {
12620
13777
  files.push({ name: entry.name, type: "directory" });
@@ -12630,11 +13787,11 @@ function listDirectoryEntriesSafe(dirPath) {
12630
13787
  files.push({ name: entry.name, type: "file", size });
12631
13788
  continue;
12632
13789
  }
12633
- const stat = fs5.statSync(entryPath);
13790
+ const stat2 = fs5.statSync(entryPath);
12634
13791
  files.push({
12635
13792
  name: entry.name,
12636
- type: stat.isDirectory() ? "directory" : "file",
12637
- size: stat.isFile() ? stat.size : void 0
13793
+ type: stat2.isDirectory() ? "directory" : "file",
13794
+ size: stat2.isFile() ? stat2.size : void 0
12638
13795
  });
12639
13796
  } catch {
12640
13797
  }
@@ -12668,7 +13825,7 @@ async function handleFileRead(h, args) {
12668
13825
  async function handleFileWrite(h, args) {
12669
13826
  try {
12670
13827
  const filePath = resolveSafePath(args?.path);
12671
- fs5.mkdirSync(path9.dirname(filePath), { recursive: true });
13828
+ fs5.mkdirSync(path12.dirname(filePath), { recursive: true });
12672
13829
  fs5.writeFileSync(filePath, args?.content || "", "utf-8");
12673
13830
  return { success: true, path: filePath };
12674
13831
  } catch (e) {
@@ -13017,7 +14174,7 @@ async function executeProviderScript(h, args, scriptName) {
13017
14174
  const enterCount = cliCommand.enterCount || 1;
13018
14175
  await adapter.writeRaw(cliCommand.text + "\r");
13019
14176
  for (let i = 1; i < enterCount; i += 1) {
13020
- await new Promise((resolve12) => setTimeout(resolve12, 50));
14177
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
13021
14178
  await adapter.writeRaw("\r");
13022
14179
  }
13023
14180
  }
@@ -13511,6 +14668,12 @@ var DaemonCommandHandler = class {
13511
14668
  this._currentRoute = this.resolveRoute(args);
13512
14669
  const startedAt = Date.now();
13513
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
+ }
13514
14677
  const sessionScopedCommands = /* @__PURE__ */ new Set([
13515
14678
  "read_chat",
13516
14679
  "get_chat_debug_bundle",
@@ -13536,7 +14699,6 @@ var DaemonCommandHandler = class {
13536
14699
  this.logCommandEnd(cmd, result2, startedAt);
13537
14700
  return result2;
13538
14701
  }
13539
- let result;
13540
14702
  if (!this._currentRoute.session && !this._currentRoute.managerKey && !this._currentRoute.providerType) {
13541
14703
  const cdpCommands = ["send_chat", "read_chat", "list_chats", "new_chat", "switch_chat", "set_mode", "change_model", "set_thought_level", "resolve_action"];
13542
14704
  if (cdpCommands.includes(cmd)) {
@@ -13687,7 +14849,7 @@ var DaemonCommandHandler = class {
13687
14849
  try {
13688
14850
  const http3 = await import("http");
13689
14851
  const postData = JSON.stringify(body);
13690
- const result = await new Promise((resolve12, reject) => {
14852
+ const result = await new Promise((resolve15, reject) => {
13691
14853
  const req = http3.request({
13692
14854
  hostname: "127.0.0.1",
13693
14855
  port: 19280,
@@ -13699,9 +14861,9 @@ var DaemonCommandHandler = class {
13699
14861
  res.on("data", (chunk) => data += chunk);
13700
14862
  res.on("end", () => {
13701
14863
  try {
13702
- resolve12(JSON.parse(data));
14864
+ resolve15(JSON.parse(data));
13703
14865
  } catch {
13704
- resolve12({ raw: data });
14866
+ resolve15({ raw: data });
13705
14867
  }
13706
14868
  });
13707
14869
  });
@@ -13719,15 +14881,15 @@ var DaemonCommandHandler = class {
13719
14881
  if (!providerType) return { success: false, error: "providerType required" };
13720
14882
  try {
13721
14883
  const http3 = await import("http");
13722
- const result = await new Promise((resolve12, reject) => {
14884
+ const result = await new Promise((resolve15, reject) => {
13723
14885
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
13724
14886
  let data = "";
13725
14887
  res.on("data", (chunk) => data += chunk);
13726
14888
  res.on("end", () => {
13727
14889
  try {
13728
- resolve12(JSON.parse(data));
14890
+ resolve15(JSON.parse(data));
13729
14891
  } catch {
13730
- resolve12({ raw: data });
14892
+ resolve15({ raw: data });
13731
14893
  }
13732
14894
  });
13733
14895
  }).on("error", reject);
@@ -13741,7 +14903,7 @@ var DaemonCommandHandler = class {
13741
14903
  try {
13742
14904
  const http3 = await import("http");
13743
14905
  const postData = JSON.stringify(args || {});
13744
- const result = await new Promise((resolve12, reject) => {
14906
+ const result = await new Promise((resolve15, reject) => {
13745
14907
  const req = http3.request({
13746
14908
  hostname: "127.0.0.1",
13747
14909
  port: 19280,
@@ -13753,9 +14915,9 @@ var DaemonCommandHandler = class {
13753
14915
  res.on("data", (chunk) => data += chunk);
13754
14916
  res.on("end", () => {
13755
14917
  try {
13756
- resolve12(JSON.parse(data));
14918
+ resolve15(JSON.parse(data));
13757
14919
  } catch {
13758
- resolve12({ raw: data });
14920
+ resolve15({ raw: data });
13759
14921
  }
13760
14922
  });
13761
14923
  });
@@ -13772,7 +14934,7 @@ var DaemonCommandHandler = class {
13772
14934
 
13773
14935
  // src/commands/cli-manager.ts
13774
14936
  var os13 = __toESM(require("os"));
13775
- var path13 = __toESM(require("path"));
14937
+ var path16 = __toESM(require("path"));
13776
14938
  var crypto4 = __toESM(require("crypto"));
13777
14939
  var import_fs5 = require("fs");
13778
14940
  var import_child_process6 = require("child_process");
@@ -13782,7 +14944,7 @@ init_config();
13782
14944
 
13783
14945
  // src/providers/cli-provider-instance.ts
13784
14946
  var os12 = __toESM(require("os"));
13785
- var path12 = __toESM(require("path"));
14947
+ var path15 = __toESM(require("path"));
13786
14948
  var crypto3 = __toESM(require("crypto"));
13787
14949
  var fs6 = __toESM(require("fs"));
13788
14950
  var import_node_module = require("module");
@@ -13843,7 +15005,7 @@ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages
13843
15005
  var CachedDatabaseSync = null;
13844
15006
  function getDatabaseSync() {
13845
15007
  if (CachedDatabaseSync) return CachedDatabaseSync;
13846
- 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"));
13847
15009
  const sqliteModule = requireFn(`node:${"sqlite"}`);
13848
15010
  CachedDatabaseSync = sqliteModule.DatabaseSync;
13849
15011
  if (!CachedDatabaseSync) {
@@ -13881,7 +15043,7 @@ async function waitForCliAdapterReady(adapter, options) {
13881
15043
  if (status === "stopped") {
13882
15044
  throw new Error("CLI runtime stopped before it became ready");
13883
15045
  }
13884
- await new Promise((resolve12) => setTimeout(resolve12, pollMs));
15046
+ await new Promise((resolve15) => setTimeout(resolve15, pollMs));
13885
15047
  }
13886
15048
  throw new Error(`CLI runtime did not become ready within ${timeoutMs}ms`);
13887
15049
  }
@@ -14232,7 +15394,7 @@ var CliProviderInstance = class {
14232
15394
  const enterCount = cliCommand.enterCount || 1;
14233
15395
  await this.adapter.writeRaw(cliCommand.text + "\r");
14234
15396
  for (let i = 1; i < enterCount; i += 1) {
14235
- await new Promise((resolve12) => setTimeout(resolve12, 50));
15397
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
14236
15398
  await this.adapter.writeRaw("\r");
14237
15399
  }
14238
15400
  }
@@ -15346,13 +16508,13 @@ var AcpProviderInstance = class {
15346
16508
  }
15347
16509
  this.currentStatus = "waiting_approval";
15348
16510
  this.detectStatusTransition();
15349
- const approved = await new Promise((resolve12) => {
15350
- this.permissionResolvers.push(resolve12);
16511
+ const approved = await new Promise((resolve15) => {
16512
+ this.permissionResolvers.push(resolve15);
15351
16513
  setTimeout(() => {
15352
- const idx = this.permissionResolvers.indexOf(resolve12);
16514
+ const idx = this.permissionResolvers.indexOf(resolve15);
15353
16515
  if (idx >= 0) {
15354
16516
  this.permissionResolvers.splice(idx, 1);
15355
- resolve12(false);
16517
+ resolve15(false);
15356
16518
  }
15357
16519
  }, 3e5);
15358
16520
  });
@@ -15927,11 +17089,11 @@ function shouldRestoreHostedRuntime(record, managerTag) {
15927
17089
  // src/commands/cli-manager.ts
15928
17090
  function isExplicitCommand(command) {
15929
17091
  const trimmed = command.trim();
15930
- return path13.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
17092
+ return path16.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
15931
17093
  }
15932
17094
  function expandExecutable(command) {
15933
17095
  const trimmed = command.trim();
15934
- return trimmed.startsWith("~") ? path13.join(os13.homedir(), trimmed.slice(1)) : trimmed;
17096
+ return trimmed.startsWith("~") ? path16.join(os13.homedir(), trimmed.slice(1)) : trimmed;
15935
17097
  }
15936
17098
  function commandExists(command) {
15937
17099
  const trimmed = command.trim();
@@ -16212,7 +17374,7 @@ var DaemonCliManager = class {
16212
17374
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
16213
17375
  const trimmed = (workingDir || "").trim();
16214
17376
  if (!trimmed) throw new Error("working directory required");
16215
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path13.resolve(trimmed);
17377
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path16.resolve(trimmed);
16216
17378
  const normalizedType = this.providerLoader.resolveAlias(cliType);
16217
17379
  const rawProvider = this.providerLoader.getByAlias(cliType);
16218
17380
  const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
@@ -16713,11 +17875,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
16713
17875
  var import_child_process7 = require("child_process");
16714
17876
  var net = __toESM(require("net"));
16715
17877
  var os15 = __toESM(require("os"));
16716
- var path15 = __toESM(require("path"));
17878
+ var path18 = __toESM(require("path"));
16717
17879
 
16718
17880
  // src/providers/provider-loader.ts
16719
17881
  var fs7 = __toESM(require("fs"));
16720
- var path14 = __toESM(require("path"));
17882
+ var path17 = __toESM(require("path"));
16721
17883
  var os14 = __toESM(require("os"));
16722
17884
  var chokidar = __toESM(require("chokidar"));
16723
17885
  init_logger();
@@ -16982,7 +18144,7 @@ var ProviderLoader = class _ProviderLoader {
16982
18144
  try {
16983
18145
  if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
16984
18146
  return ["ide", "extension", "cli", "acp"].some(
16985
- (category) => fs7.existsSync(path14.join(candidate, category))
18147
+ (category) => fs7.existsSync(path17.join(candidate, category))
16986
18148
  );
16987
18149
  } catch {
16988
18150
  return false;
@@ -16990,20 +18152,20 @@ var ProviderLoader = class _ProviderLoader {
16990
18152
  }
16991
18153
  static hasProviderRootMarker(candidate) {
16992
18154
  try {
16993
- return fs7.existsSync(path14.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
18155
+ return fs7.existsSync(path17.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
16994
18156
  } catch {
16995
18157
  return false;
16996
18158
  }
16997
18159
  }
16998
18160
  detectDefaultUserDir() {
16999
- const fallback = path14.join(os14.homedir(), ".adhdev", "providers");
18161
+ const fallback = path17.join(os14.homedir(), ".adhdev", "providers");
17000
18162
  const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
17001
18163
  const visited = /* @__PURE__ */ new Set();
17002
18164
  for (const start of this.probeStarts) {
17003
- let current = path14.resolve(start);
18165
+ let current = path17.resolve(start);
17004
18166
  while (!visited.has(current)) {
17005
18167
  visited.add(current);
17006
- const siblingCandidate = path14.join(path14.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
18168
+ const siblingCandidate = path17.join(path17.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
17007
18169
  if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
17008
18170
  const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
17009
18171
  if (envOptIn || hasMarker) {
@@ -17025,7 +18187,7 @@ var ProviderLoader = class _ProviderLoader {
17025
18187
  return { path: siblingCandidate, source };
17026
18188
  }
17027
18189
  }
17028
- const parent = path14.dirname(current);
18190
+ const parent = path17.dirname(current);
17029
18191
  if (parent === current) break;
17030
18192
  current = parent;
17031
18193
  }
@@ -17035,11 +18197,11 @@ var ProviderLoader = class _ProviderLoader {
17035
18197
  constructor(options) {
17036
18198
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
17037
18199
  this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
17038
- this.defaultProvidersDir = path14.join(os14.homedir(), ".adhdev", "providers");
18200
+ this.defaultProvidersDir = path17.join(os14.homedir(), ".adhdev", "providers");
17039
18201
  const detected = this.detectDefaultUserDir();
17040
18202
  this.userDir = detected.path;
17041
18203
  this.userDirSource = detected.source;
17042
- this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
18204
+ this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
17043
18205
  this.disableUpstream = false;
17044
18206
  this.applySourceConfig({
17045
18207
  userDir: options?.userDir,
@@ -17098,7 +18260,7 @@ var ProviderLoader = class _ProviderLoader {
17098
18260
  this.userDir = detected.path;
17099
18261
  this.userDirSource = detected.source;
17100
18262
  }
17101
- this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
18263
+ this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
17102
18264
  this.disableUpstream = this.sourceMode === "no-upstream";
17103
18265
  if (this.explicitProviderDir) {
17104
18266
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
@@ -17112,7 +18274,7 @@ var ProviderLoader = class _ProviderLoader {
17112
18274
  * Canonical provider directory shape for a given root.
17113
18275
  */
17114
18276
  getProviderDir(root, category, type) {
17115
- return path14.join(root, category, type);
18277
+ return path17.join(root, category, type);
17116
18278
  }
17117
18279
  /**
17118
18280
  * Canonical user override directory for a provider.
@@ -17139,7 +18301,7 @@ var ProviderLoader = class _ProviderLoader {
17139
18301
  resolveProviderFile(type, ...segments) {
17140
18302
  const dir = this.findProviderDirInternal(type);
17141
18303
  if (!dir) return null;
17142
- return path14.join(dir, ...segments);
18304
+ return path17.join(dir, ...segments);
17143
18305
  }
17144
18306
  /**
17145
18307
  * Load all providers (3-tier priority)
@@ -17178,7 +18340,7 @@ var ProviderLoader = class _ProviderLoader {
17178
18340
  if (!fs7.existsSync(this.upstreamDir)) return false;
17179
18341
  try {
17180
18342
  return fs7.readdirSync(this.upstreamDir).some(
17181
- (d) => fs7.statSync(path14.join(this.upstreamDir, d)).isDirectory()
18343
+ (d) => fs7.statSync(path17.join(this.upstreamDir, d)).isDirectory()
17182
18344
  );
17183
18345
  } catch {
17184
18346
  return false;
@@ -17675,8 +18837,8 @@ var ProviderLoader = class _ProviderLoader {
17675
18837
  resolved._resolvedScriptDir = entry.scriptDir;
17676
18838
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
17677
18839
  if (providerDir) {
17678
- const fullDir = path14.join(providerDir, entry.scriptDir);
17679
- 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;
17680
18842
  }
17681
18843
  matched = true;
17682
18844
  }
@@ -17691,8 +18853,8 @@ var ProviderLoader = class _ProviderLoader {
17691
18853
  resolved._resolvedScriptDir = base.defaultScriptDir;
17692
18854
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
17693
18855
  if (providerDir) {
17694
- const fullDir = path14.join(providerDir, base.defaultScriptDir);
17695
- 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;
17696
18858
  }
17697
18859
  }
17698
18860
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -17709,8 +18871,8 @@ var ProviderLoader = class _ProviderLoader {
17709
18871
  resolved._resolvedScriptDir = dirOverride;
17710
18872
  resolved._resolvedScriptsSource = `versions:${range}`;
17711
18873
  if (providerDir) {
17712
- const fullDir = path14.join(providerDir, dirOverride);
17713
- 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;
17714
18876
  }
17715
18877
  }
17716
18878
  } else if (override.scripts) {
@@ -17726,8 +18888,8 @@ var ProviderLoader = class _ProviderLoader {
17726
18888
  resolved._resolvedScriptDir = base.defaultScriptDir;
17727
18889
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
17728
18890
  if (providerDir) {
17729
- const fullDir = path14.join(providerDir, base.defaultScriptDir);
17730
- 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;
17731
18893
  }
17732
18894
  }
17733
18895
  }
@@ -17759,14 +18921,14 @@ var ProviderLoader = class _ProviderLoader {
17759
18921
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
17760
18922
  return null;
17761
18923
  }
17762
- const dir = path14.join(providerDir, scriptDir);
18924
+ const dir = path17.join(providerDir, scriptDir);
17763
18925
  if (!fs7.existsSync(dir)) {
17764
18926
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
17765
18927
  return null;
17766
18928
  }
17767
18929
  const cached = this.scriptsCache.get(dir);
17768
18930
  if (cached) return cached;
17769
- const scriptsJs = path14.join(dir, "scripts.js");
18931
+ const scriptsJs = path17.join(dir, "scripts.js");
17770
18932
  if (fs7.existsSync(scriptsJs)) {
17771
18933
  try {
17772
18934
  delete require.cache[require.resolve(scriptsJs)];
@@ -17808,7 +18970,7 @@ var ProviderLoader = class _ProviderLoader {
17808
18970
  return;
17809
18971
  }
17810
18972
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
17811
- this.log(`File changed: ${path14.basename(filePath)}, reloading...`);
18973
+ this.log(`File changed: ${path17.basename(filePath)}, reloading...`);
17812
18974
  this.reload();
17813
18975
  }
17814
18976
  };
@@ -17863,7 +19025,7 @@ var ProviderLoader = class _ProviderLoader {
17863
19025
  }
17864
19026
  const https = require("https");
17865
19027
  const { execSync: execSync7 } = require("child_process");
17866
- const metaPath = path14.join(this.upstreamDir, _ProviderLoader.META_FILE);
19028
+ const metaPath = path17.join(this.upstreamDir, _ProviderLoader.META_FILE);
17867
19029
  let prevEtag = "";
17868
19030
  let prevTimestamp = 0;
17869
19031
  try {
@@ -17880,7 +19042,7 @@ var ProviderLoader = class _ProviderLoader {
17880
19042
  return { updated: false };
17881
19043
  }
17882
19044
  try {
17883
- const etag = await new Promise((resolve12, reject) => {
19045
+ const etag = await new Promise((resolve15, reject) => {
17884
19046
  const options = {
17885
19047
  method: "HEAD",
17886
19048
  hostname: "github.com",
@@ -17898,7 +19060,7 @@ var ProviderLoader = class _ProviderLoader {
17898
19060
  headers: { "User-Agent": "adhdev-launcher" },
17899
19061
  timeout: 1e4
17900
19062
  }, (res2) => {
17901
- resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
19063
+ resolve15(res2.headers.etag || res2.headers["last-modified"] || "");
17902
19064
  });
17903
19065
  req2.on("error", reject);
17904
19066
  req2.on("timeout", () => {
@@ -17907,7 +19069,7 @@ var ProviderLoader = class _ProviderLoader {
17907
19069
  });
17908
19070
  req2.end();
17909
19071
  } else {
17910
- resolve12(res.headers.etag || res.headers["last-modified"] || "");
19072
+ resolve15(res.headers.etag || res.headers["last-modified"] || "");
17911
19073
  }
17912
19074
  });
17913
19075
  req.on("error", reject);
@@ -17923,17 +19085,17 @@ var ProviderLoader = class _ProviderLoader {
17923
19085
  return { updated: false };
17924
19086
  }
17925
19087
  this.log("Downloading latest providers from GitHub...");
17926
- const tmpTar = path14.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
17927
- 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()}`);
17928
19090
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
17929
19091
  fs7.mkdirSync(tmpExtract, { recursive: true });
17930
19092
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
17931
19093
  const extracted = fs7.readdirSync(tmpExtract);
17932
19094
  const rootDir = extracted.find(
17933
- (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")
17934
19096
  );
17935
19097
  if (!rootDir) throw new Error("Unexpected tarball structure");
17936
- const sourceDir = path14.join(tmpExtract, rootDir);
19098
+ const sourceDir = path17.join(tmpExtract, rootDir);
17937
19099
  const backupDir = this.upstreamDir + ".bak";
17938
19100
  if (fs7.existsSync(this.upstreamDir)) {
17939
19101
  if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
@@ -17971,7 +19133,7 @@ var ProviderLoader = class _ProviderLoader {
17971
19133
  downloadFile(url, destPath) {
17972
19134
  const https = require("https");
17973
19135
  const http3 = require("http");
17974
- return new Promise((resolve12, reject) => {
19136
+ return new Promise((resolve15, reject) => {
17975
19137
  const doRequest = (reqUrl, redirectCount = 0) => {
17976
19138
  if (redirectCount > 5) {
17977
19139
  reject(new Error("Too many redirects"));
@@ -17991,7 +19153,7 @@ var ProviderLoader = class _ProviderLoader {
17991
19153
  res.pipe(ws);
17992
19154
  ws.on("finish", () => {
17993
19155
  ws.close();
17994
- resolve12();
19156
+ resolve15();
17995
19157
  });
17996
19158
  ws.on("error", reject);
17997
19159
  });
@@ -18008,8 +19170,8 @@ var ProviderLoader = class _ProviderLoader {
18008
19170
  copyDirRecursive(src, dest) {
18009
19171
  fs7.mkdirSync(dest, { recursive: true });
18010
19172
  for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
18011
- const srcPath = path14.join(src, entry.name);
18012
- const destPath = path14.join(dest, entry.name);
19173
+ const srcPath = path17.join(src, entry.name);
19174
+ const destPath = path17.join(dest, entry.name);
18013
19175
  if (entry.isDirectory()) {
18014
19176
  this.copyDirRecursive(srcPath, destPath);
18015
19177
  } else {
@@ -18020,7 +19182,7 @@ var ProviderLoader = class _ProviderLoader {
18020
19182
  /** .meta.json save */
18021
19183
  writeMeta(metaPath, etag, timestamp) {
18022
19184
  try {
18023
- fs7.mkdirSync(path14.dirname(metaPath), { recursive: true });
19185
+ fs7.mkdirSync(path17.dirname(metaPath), { recursive: true });
18024
19186
  fs7.writeFileSync(metaPath, JSON.stringify({
18025
19187
  etag,
18026
19188
  timestamp,
@@ -18037,7 +19199,7 @@ var ProviderLoader = class _ProviderLoader {
18037
19199
  const scan = (d) => {
18038
19200
  try {
18039
19201
  for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
18040
- if (entry.isDirectory()) scan(path14.join(d, entry.name));
19202
+ if (entry.isDirectory()) scan(path17.join(d, entry.name));
18041
19203
  else if (entry.name === "provider.json") count++;
18042
19204
  }
18043
19205
  } catch {
@@ -18265,17 +19427,17 @@ var ProviderLoader = class _ProviderLoader {
18265
19427
  for (const root of searchRoots) {
18266
19428
  if (!fs7.existsSync(root)) continue;
18267
19429
  const candidate = this.getProviderDir(root, cat, type);
18268
- if (fs7.existsSync(path14.join(candidate, "provider.json"))) return candidate;
18269
- const catDir = path14.join(root, cat);
19430
+ if (fs7.existsSync(path17.join(candidate, "provider.json"))) return candidate;
19431
+ const catDir = path17.join(root, cat);
18270
19432
  if (fs7.existsSync(catDir)) {
18271
19433
  try {
18272
19434
  for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
18273
19435
  if (!entry.isDirectory()) continue;
18274
- const jsonPath = path14.join(catDir, entry.name, "provider.json");
19436
+ const jsonPath = path17.join(catDir, entry.name, "provider.json");
18275
19437
  if (fs7.existsSync(jsonPath)) {
18276
19438
  try {
18277
19439
  const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
18278
- if (data.type === type) return path14.join(catDir, entry.name);
19440
+ if (data.type === type) return path17.join(catDir, entry.name);
18279
19441
  } catch {
18280
19442
  }
18281
19443
  }
@@ -18292,7 +19454,7 @@ var ProviderLoader = class _ProviderLoader {
18292
19454
  * (template substitution is NOT applied here — scripts.js handles that)
18293
19455
  */
18294
19456
  buildScriptWrappersFromDir(dir) {
18295
- const scriptsJs = path14.join(dir, "scripts.js");
19457
+ const scriptsJs = path17.join(dir, "scripts.js");
18296
19458
  if (fs7.existsSync(scriptsJs)) {
18297
19459
  try {
18298
19460
  delete require.cache[require.resolve(scriptsJs)];
@@ -18306,7 +19468,7 @@ var ProviderLoader = class _ProviderLoader {
18306
19468
  for (const file of fs7.readdirSync(dir)) {
18307
19469
  if (!file.endsWith(".js")) continue;
18308
19470
  const scriptName = toCamel(file.replace(".js", ""));
18309
- const filePath = path14.join(dir, file);
19471
+ const filePath = path17.join(dir, file);
18310
19472
  result[scriptName] = (...args) => {
18311
19473
  try {
18312
19474
  let content = fs7.readFileSync(filePath, "utf-8");
@@ -18366,7 +19528,7 @@ var ProviderLoader = class _ProviderLoader {
18366
19528
  }
18367
19529
  const hasJson = entries.some((e) => e.name === "provider.json");
18368
19530
  if (hasJson) {
18369
- const jsonPath = path14.join(d, "provider.json");
19531
+ const jsonPath = path17.join(d, "provider.json");
18370
19532
  try {
18371
19533
  const raw = fs7.readFileSync(jsonPath, "utf-8");
18372
19534
  const mod = JSON.parse(raw);
@@ -18387,7 +19549,7 @@ var ProviderLoader = class _ProviderLoader {
18387
19549
  this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
18388
19550
  } else {
18389
19551
  const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
18390
- const scriptsPath = path14.join(d, "scripts.js");
19552
+ const scriptsPath = path17.join(d, "scripts.js");
18391
19553
  if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
18392
19554
  try {
18393
19555
  delete require.cache[require.resolve(scriptsPath)];
@@ -18413,7 +19575,7 @@ var ProviderLoader = class _ProviderLoader {
18413
19575
  if (!entry.isDirectory()) continue;
18414
19576
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
18415
19577
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
18416
- scan(path14.join(d, entry.name));
19578
+ scan(path17.join(d, entry.name));
18417
19579
  }
18418
19580
  }
18419
19581
  };
@@ -18448,9 +19610,9 @@ var ProviderLoader = class _ProviderLoader {
18448
19610
  }
18449
19611
  }
18450
19612
  compareVersions(a, b) {
18451
- const normalize3 = (v) => v.split(/[-_+]/)[0].split(".").map((x) => parseInt(x, 10) || 0);
18452
- const pa = normalize3(a);
18453
- 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);
18454
19616
  for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
18455
19617
  const va = pa[i] || 0;
18456
19618
  const vb = pb[i] || 0;
@@ -18570,17 +19732,17 @@ async function findFreePort(ports) {
18570
19732
  throw new Error("No free port found");
18571
19733
  }
18572
19734
  function checkPortFree(port) {
18573
- return new Promise((resolve12) => {
19735
+ return new Promise((resolve15) => {
18574
19736
  const server = net.createServer();
18575
19737
  server.unref();
18576
- server.on("error", () => resolve12(false));
19738
+ server.on("error", () => resolve15(false));
18577
19739
  server.listen(port, "127.0.0.1", () => {
18578
- server.close(() => resolve12(true));
19740
+ server.close(() => resolve15(true));
18579
19741
  });
18580
19742
  });
18581
19743
  }
18582
19744
  async function isCdpActive(port) {
18583
- return new Promise((resolve12) => {
19745
+ return new Promise((resolve15) => {
18584
19746
  const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
18585
19747
  timeout: 2e3
18586
19748
  }, (res) => {
@@ -18589,16 +19751,16 @@ async function isCdpActive(port) {
18589
19751
  res.on("end", () => {
18590
19752
  try {
18591
19753
  const info = JSON.parse(data);
18592
- resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
19754
+ resolve15(!!info["WebKit-Version"] || !!info["Browser"]);
18593
19755
  } catch {
18594
- resolve12(false);
19756
+ resolve15(false);
18595
19757
  }
18596
19758
  });
18597
19759
  });
18598
- req.on("error", () => resolve12(false));
19760
+ req.on("error", () => resolve15(false));
18599
19761
  req.on("timeout", () => {
18600
19762
  req.destroy();
18601
- resolve12(false);
19763
+ resolve15(false);
18602
19764
  });
18603
19765
  });
18604
19766
  }
@@ -18738,8 +19900,8 @@ function detectCurrentWorkspace(ideId) {
18738
19900
  const appNameMap = getMacAppIdentifiers();
18739
19901
  const appName = appNameMap[ideId];
18740
19902
  if (appName) {
18741
- const storagePath = path15.join(
18742
- process.env.APPDATA || path15.join(os15.homedir(), "AppData", "Roaming"),
19903
+ const storagePath = path18.join(
19904
+ process.env.APPDATA || path18.join(os15.homedir(), "AppData", "Roaming"),
18743
19905
  appName,
18744
19906
  "storage.json"
18745
19907
  );
@@ -18917,9 +20079,9 @@ init_logger();
18917
20079
 
18918
20080
  // src/logging/command-log.ts
18919
20081
  var fs8 = __toESM(require("fs"));
18920
- var path16 = __toESM(require("path"));
20082
+ var path19 = __toESM(require("path"));
18921
20083
  var os16 = __toESM(require("os"));
18922
- 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");
18923
20085
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
18924
20086
  var MAX_DAYS = 7;
18925
20087
  try {
@@ -18957,13 +20119,13 @@ function getDateStr2() {
18957
20119
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
18958
20120
  }
18959
20121
  var currentDate2 = getDateStr2();
18960
- var currentFile = path16.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
20122
+ var currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
18961
20123
  var writeCount2 = 0;
18962
20124
  function checkRotation() {
18963
20125
  const today = getDateStr2();
18964
20126
  if (today !== currentDate2) {
18965
20127
  currentDate2 = today;
18966
- currentFile = path16.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
20128
+ currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
18967
20129
  cleanOldFiles();
18968
20130
  }
18969
20131
  }
@@ -18977,7 +20139,7 @@ function cleanOldFiles() {
18977
20139
  const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
18978
20140
  if (dateMatch && dateMatch[1] < cutoffStr) {
18979
20141
  try {
18980
- fs8.unlinkSync(path16.join(LOG_DIR2, file));
20142
+ fs8.unlinkSync(path19.join(LOG_DIR2, file));
18981
20143
  } catch {
18982
20144
  }
18983
20145
  }
@@ -18987,8 +20149,8 @@ function cleanOldFiles() {
18987
20149
  }
18988
20150
  function checkSize() {
18989
20151
  try {
18990
- const stat = fs8.statSync(currentFile);
18991
- if (stat.size > MAX_FILE_SIZE) {
20152
+ const stat2 = fs8.statSync(currentFile);
20153
+ if (stat2.size > MAX_FILE_SIZE) {
18992
20154
  const backup = currentFile.replace(".jsonl", ".1.jsonl");
18993
20155
  try {
18994
20156
  fs8.unlinkSync(backup);
@@ -19274,12 +20436,18 @@ function buildStatusSnapshot(options) {
19274
20436
  const unreadSourceSessions = buildSessionEntries(
19275
20437
  options.allStates,
19276
20438
  options.cdpManagers,
19277
- { profile: "full" }
20439
+ {
20440
+ profile: "full",
20441
+ getGitSummaryForWorkspace: options.getGitSummaryForWorkspace
20442
+ }
19278
20443
  );
19279
20444
  const sessions = profile === "full" ? unreadSourceSessions : profile === "live" ? unreadSourceSessions.map(projectLiveSessionFromFull) : buildSessionEntries(
19280
20445
  options.allStates,
19281
20446
  options.cdpManagers,
19282
- { profile }
20447
+ {
20448
+ profile,
20449
+ getGitSummaryForWorkspace: options.getGitSummaryForWorkspace
20450
+ }
19283
20451
  );
19284
20452
  const sessionsById = new Map(sessions.map((session) => [session.id, session]));
19285
20453
  for (const sourceSession of unreadSourceSessions) {
@@ -19373,13 +20541,13 @@ var import_child_process8 = require("child_process");
19373
20541
  var import_child_process9 = require("child_process");
19374
20542
  var fs9 = __toESM(require("fs"));
19375
20543
  var os18 = __toESM(require("os"));
19376
- var path17 = __toESM(require("path"));
20544
+ var path20 = __toESM(require("path"));
19377
20545
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
19378
20546
  function getUpgradeLogPath() {
19379
20547
  const home = os18.homedir();
19380
- const dir = path17.join(home, ".adhdev");
20548
+ const dir = path20.join(home, ".adhdev");
19381
20549
  fs9.mkdirSync(dir, { recursive: true });
19382
- return path17.join(dir, "daemon-upgrade.log");
20550
+ return path20.join(dir, "daemon-upgrade.log");
19383
20551
  }
19384
20552
  function appendUpgradeLog(message) {
19385
20553
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -19390,14 +20558,14 @@ function appendUpgradeLog(message) {
19390
20558
  }
19391
20559
  }
19392
20560
  function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
19393
- const binDir = path17.dirname(nodeExecutable);
20561
+ const binDir = path20.dirname(nodeExecutable);
19394
20562
  if (platform10 === "win32") {
19395
- 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");
19396
20564
  if (fs9.existsSync(npmCliPath)) {
19397
20565
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
19398
20566
  }
19399
20567
  for (const candidate of ["npm.exe", "npm"]) {
19400
- const candidatePath = path17.join(binDir, candidate);
20568
+ const candidatePath = path20.join(binDir, candidate);
19401
20569
  if (fs9.existsSync(candidatePath)) {
19402
20570
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
19403
20571
  }
@@ -19405,7 +20573,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
19405
20573
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
19406
20574
  }
19407
20575
  for (const candidate of ["npm"]) {
19408
- const candidatePath = path17.join(binDir, candidate);
20576
+ const candidatePath = path20.join(binDir, candidate);
19409
20577
  if (fs9.existsSync(candidatePath)) {
19410
20578
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
19411
20579
  }
@@ -19422,13 +20590,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
19422
20590
  let currentDir = resolvedPath;
19423
20591
  try {
19424
20592
  if (fs9.statSync(resolvedPath).isFile()) {
19425
- currentDir = path17.dirname(resolvedPath);
20593
+ currentDir = path20.dirname(resolvedPath);
19426
20594
  }
19427
20595
  } catch {
19428
- currentDir = path17.dirname(resolvedPath);
20596
+ currentDir = path20.dirname(resolvedPath);
19429
20597
  }
19430
20598
  while (true) {
19431
- const packageJsonPath = path17.join(currentDir, "package.json");
20599
+ const packageJsonPath = path20.join(currentDir, "package.json");
19432
20600
  try {
19433
20601
  if (fs9.existsSync(packageJsonPath)) {
19434
20602
  const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
@@ -19439,7 +20607,7 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
19439
20607
  }
19440
20608
  } catch {
19441
20609
  }
19442
- const parentDir = path17.dirname(currentDir);
20610
+ const parentDir = path20.dirname(currentDir);
19443
20611
  if (parentDir === currentDir) {
19444
20612
  return null;
19445
20613
  }
@@ -19447,13 +20615,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
19447
20615
  }
19448
20616
  }
19449
20617
  function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
19450
- const nodeModulesDir = packageName.startsWith("@") ? path17.dirname(path17.dirname(packageRoot)) : path17.dirname(packageRoot);
19451
- 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") {
19452
20620
  return null;
19453
20621
  }
19454
- const maybeLibDir = path17.dirname(nodeModulesDir);
19455
- if (path17.basename(maybeLibDir) === "lib") {
19456
- return path17.dirname(maybeLibDir);
20622
+ const maybeLibDir = path20.dirname(nodeModulesDir);
20623
+ if (path20.basename(maybeLibDir) === "lib") {
20624
+ return path20.dirname(maybeLibDir);
19457
20625
  }
19458
20626
  return maybeLibDir;
19459
20627
  }
@@ -19561,14 +20729,14 @@ async function waitForPidExit(pid, timeoutMs) {
19561
20729
  while (Date.now() - start < timeoutMs) {
19562
20730
  try {
19563
20731
  process.kill(pid, 0);
19564
- await new Promise((resolve12) => setTimeout(resolve12, 250));
20732
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
19565
20733
  } catch {
19566
20734
  return;
19567
20735
  }
19568
20736
  }
19569
20737
  }
19570
20738
  function stopSessionHostProcesses(appName) {
19571
- const pidFile = path17.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
20739
+ const pidFile = path20.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
19572
20740
  try {
19573
20741
  if (fs9.existsSync(pidFile)) {
19574
20742
  const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
@@ -19585,7 +20753,7 @@ function stopSessionHostProcesses(appName) {
19585
20753
  }
19586
20754
  }
19587
20755
  function removeDaemonPidFile() {
19588
- const pidFile = path17.join(os18.homedir(), ".adhdev", "daemon.pid");
20756
+ const pidFile = path20.join(os18.homedir(), ".adhdev", "daemon.pid");
19589
20757
  try {
19590
20758
  fs9.unlinkSync(pidFile);
19591
20759
  } catch {
@@ -19596,7 +20764,7 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
19596
20764
  const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
19597
20765
  if (!npmRoot) return;
19598
20766
  const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
19599
- const binDir = process.platform === "win32" ? npmPrefix : path17.join(npmPrefix, "bin");
20767
+ const binDir = process.platform === "win32" ? npmPrefix : path20.join(npmPrefix, "bin");
19600
20768
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
19601
20769
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
19602
20770
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -19604,25 +20772,25 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
19604
20772
  }
19605
20773
  if (pkgName.startsWith("@")) {
19606
20774
  const [scope, name] = pkgName.split("/");
19607
- const scopeDir = path17.join(npmRoot, scope);
20775
+ const scopeDir = path20.join(npmRoot, scope);
19608
20776
  if (!fs9.existsSync(scopeDir)) return;
19609
20777
  for (const entry of fs9.readdirSync(scopeDir)) {
19610
20778
  if (!entry.startsWith(`.${name}-`)) continue;
19611
- fs9.rmSync(path17.join(scopeDir, entry), { recursive: true, force: true });
19612
- 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)}`);
19613
20781
  }
19614
20782
  } else {
19615
20783
  for (const entry of fs9.readdirSync(npmRoot)) {
19616
20784
  if (!entry.startsWith(`.${pkgName}-`)) continue;
19617
- fs9.rmSync(path17.join(npmRoot, entry), { recursive: true, force: true });
19618
- 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)}`);
19619
20787
  }
19620
20788
  }
19621
20789
  if (fs9.existsSync(binDir)) {
19622
20790
  for (const entry of fs9.readdirSync(binDir)) {
19623
20791
  if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
19624
- fs9.rmSync(path17.join(binDir, entry), { recursive: true, force: true });
19625
- 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)}`);
19626
20794
  }
19627
20795
  }
19628
20796
  }
@@ -19672,7 +20840,7 @@ async function runDaemonUpgradeHelper(payload) {
19672
20840
  appendUpgradeLog(installOutput.trim());
19673
20841
  }
19674
20842
  if (process.platform === "win32") {
19675
- await new Promise((resolve12) => setTimeout(resolve12, 500));
20843
+ await new Promise((resolve15) => setTimeout(resolve15, 500));
19676
20844
  cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
19677
20845
  appendUpgradeLog("Post-install staging cleanup complete");
19678
20846
  }
@@ -21066,7 +22234,7 @@ var ProviderStreamAdapter = class {
21066
22234
  const beforeCount = this.messageCount(before);
21067
22235
  const beforeSignature = this.lastMessageSignature(before);
21068
22236
  for (let attempt = 0; attempt < 12; attempt += 1) {
21069
- await new Promise((resolve12) => setTimeout(resolve12, 250));
22237
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
21070
22238
  let state;
21071
22239
  try {
21072
22240
  state = await this.readChat(evaluate);
@@ -21088,7 +22256,7 @@ var ProviderStreamAdapter = class {
21088
22256
  if (this.messageCount(first) > 0 || this.lastMessageSignature(first)) {
21089
22257
  return first;
21090
22258
  }
21091
- await new Promise((resolve12) => setTimeout(resolve12, 150));
22259
+ await new Promise((resolve15) => setTimeout(resolve15, 150));
21092
22260
  const second = await this.readChat(evaluate);
21093
22261
  return this.messageCount(second) >= this.messageCount(first) ? second : first;
21094
22262
  }
@@ -21239,7 +22407,7 @@ var ProviderStreamAdapter = class {
21239
22407
  if (typeof data.error === "string" && data.error.trim()) return false;
21240
22408
  }
21241
22409
  for (let attempt = 0; attempt < 6; attempt += 1) {
21242
- await new Promise((resolve12) => setTimeout(resolve12, 250));
22410
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
21243
22411
  const state = await this.readChat(evaluate);
21244
22412
  const title = this.getStateTitle(state);
21245
22413
  if (this.titlesMatch(title, sessionId)) return true;
@@ -22100,11 +23268,11 @@ init_chat_message_normalization();
22100
23268
 
22101
23269
  // src/providers/version-archive.ts
22102
23270
  var fs11 = __toESM(require("fs"));
22103
- var path18 = __toESM(require("path"));
23271
+ var path21 = __toESM(require("path"));
22104
23272
  var os19 = __toESM(require("os"));
22105
23273
  var import_child_process10 = require("child_process");
22106
23274
  var import_os3 = require("os");
22107
- var ARCHIVE_PATH = path18.join(os19.homedir(), ".adhdev", "version-history.json");
23275
+ var ARCHIVE_PATH = path21.join(os19.homedir(), ".adhdev", "version-history.json");
22108
23276
  var MAX_ENTRIES_PER_PROVIDER = 20;
22109
23277
  var VersionArchive = class {
22110
23278
  history = {};
@@ -22151,7 +23319,7 @@ var VersionArchive = class {
22151
23319
  }
22152
23320
  save() {
22153
23321
  try {
22154
- fs11.mkdirSync(path18.dirname(ARCHIVE_PATH), { recursive: true });
23322
+ fs11.mkdirSync(path21.dirname(ARCHIVE_PATH), { recursive: true });
22155
23323
  fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
22156
23324
  } catch {
22157
23325
  }
@@ -22208,7 +23376,7 @@ function checkPathExists2(paths) {
22208
23376
  for (const p of paths) {
22209
23377
  if (p.includes("*")) {
22210
23378
  const home = os19.homedir();
22211
- const resolved = p.replace(/\*/g, home.split(path18.sep).pop() || "");
23379
+ const resolved = p.replace(/\*/g, home.split(path21.sep).pop() || "");
22212
23380
  if (fs11.existsSync(resolved)) return resolved;
22213
23381
  } else {
22214
23382
  if (fs11.existsSync(p)) return p;
@@ -22218,7 +23386,7 @@ function checkPathExists2(paths) {
22218
23386
  }
22219
23387
  function getMacAppVersion(appPath) {
22220
23388
  if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
22221
- const plistPath = path18.join(appPath, "Contents", "Info.plist");
23389
+ const plistPath = path21.join(appPath, "Contents", "Info.plist");
22222
23390
  if (!fs11.existsSync(plistPath)) return null;
22223
23391
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
22224
23392
  return raw || null;
@@ -22244,7 +23412,7 @@ async function detectAllVersions(loader, archive) {
22244
23412
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
22245
23413
  let resolvedBin = cliBin;
22246
23414
  if (!resolvedBin && appPath && currentOs === "darwin") {
22247
- const bundled = path18.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
23415
+ const bundled = path21.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
22248
23416
  if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
22249
23417
  }
22250
23418
  info.installed = !!(appPath || resolvedBin);
@@ -22285,7 +23453,7 @@ async function detectAllVersions(loader, archive) {
22285
23453
  // src/daemon/dev-server.ts
22286
23454
  var http2 = __toESM(require("http"));
22287
23455
  var fs15 = __toESM(require("fs"));
22288
- var path22 = __toESM(require("path"));
23456
+ var path25 = __toESM(require("path"));
22289
23457
  init_config();
22290
23458
 
22291
23459
  // src/daemon/scaffold-template.ts
@@ -22636,7 +23804,7 @@ init_logger();
22636
23804
 
22637
23805
  // src/daemon/dev-cdp-handlers.ts
22638
23806
  var fs12 = __toESM(require("fs"));
22639
- var path19 = __toESM(require("path"));
23807
+ var path22 = __toESM(require("path"));
22640
23808
  init_logger();
22641
23809
  async function handleCdpEvaluate(ctx, req, res) {
22642
23810
  const body = await ctx.readBody(req);
@@ -22815,17 +23983,17 @@ async function handleScriptHints(ctx, type, _req, res) {
22815
23983
  return;
22816
23984
  }
22817
23985
  let scriptsPath = "";
22818
- const directScripts = path19.join(dir, "scripts.js");
23986
+ const directScripts = path22.join(dir, "scripts.js");
22819
23987
  if (fs12.existsSync(directScripts)) {
22820
23988
  scriptsPath = directScripts;
22821
23989
  } else {
22822
- const scriptsDir = path19.join(dir, "scripts");
23990
+ const scriptsDir = path22.join(dir, "scripts");
22823
23991
  if (fs12.existsSync(scriptsDir)) {
22824
23992
  const versions = fs12.readdirSync(scriptsDir).filter((d) => {
22825
- return fs12.statSync(path19.join(scriptsDir, d)).isDirectory();
23993
+ return fs12.statSync(path22.join(scriptsDir, d)).isDirectory();
22826
23994
  }).sort().reverse();
22827
23995
  for (const ver of versions) {
22828
- const p = path19.join(scriptsDir, ver, "scripts.js");
23996
+ const p = path22.join(scriptsDir, ver, "scripts.js");
22829
23997
  if (fs12.existsSync(p)) {
22830
23998
  scriptsPath = p;
22831
23999
  break;
@@ -23654,7 +24822,7 @@ async function handleDomContext(ctx, type, req, res) {
23654
24822
 
23655
24823
  // src/daemon/dev-cli-debug.ts
23656
24824
  var fs13 = __toESM(require("fs"));
23657
- var path20 = __toESM(require("path"));
24825
+ var path23 = __toESM(require("path"));
23658
24826
  function slugifyFixtureName(value) {
23659
24827
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
23660
24828
  return normalized || `fixture-${Date.now()}`;
@@ -23664,11 +24832,11 @@ function getCliFixtureDir(ctx, type) {
23664
24832
  if (!providerDir) {
23665
24833
  throw new Error(`Provider directory not found for '${type}'`);
23666
24834
  }
23667
- return path20.join(providerDir, "fixtures");
24835
+ return path23.join(providerDir, "fixtures");
23668
24836
  }
23669
24837
  function readCliFixture(ctx, type, name) {
23670
24838
  const fixtureDir = getCliFixtureDir(ctx, type);
23671
- const filePath = path20.join(fixtureDir, `${name}.json`);
24839
+ const filePath = path23.join(fixtureDir, `${name}.json`);
23672
24840
  if (!fs13.existsSync(filePath)) {
23673
24841
  throw new Error(`Fixture not found: ${filePath}`);
23674
24842
  }
@@ -23837,7 +25005,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
23837
25005
  return { target, instance, adapter };
23838
25006
  }
23839
25007
  function sleep(ms) {
23840
- return new Promise((resolve12) => setTimeout(resolve12, ms));
25008
+ return new Promise((resolve15) => setTimeout(resolve15, ms));
23841
25009
  }
23842
25010
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
23843
25011
  const startedAt = Date.now();
@@ -24135,7 +25303,7 @@ async function runCliAutoImplVerification(ctx, type, verification) {
24135
25303
  return {
24136
25304
  mode: "fixture_replay_suite",
24137
25305
  pass: results.every((item) => item.pass),
24138
- failures: results.flatMap((item) => item.failures.map((failure) => `${item.fixtureName}: ${failure}`)),
25306
+ failures: results.flatMap((item) => item.failures.map((failure2) => `${item.fixtureName}: ${failure2}`)),
24139
25307
  result: firstFailure.result,
24140
25308
  assertions: firstFailure.assertions,
24141
25309
  fixture: firstFailure.fixture,
@@ -24435,7 +25603,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
24435
25603
  },
24436
25604
  notes: typeof body?.notes === "string" ? body.notes : void 0
24437
25605
  };
24438
- const filePath = path20.join(fixtureDir, `${name}.json`);
25606
+ const filePath = path23.join(fixtureDir, `${name}.json`);
24439
25607
  fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
24440
25608
  ctx.json(res, 200, {
24441
25609
  saved: true,
@@ -24459,7 +25627,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
24459
25627
  return;
24460
25628
  }
24461
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) => {
24462
- const fullPath = path20.join(fixtureDir, file);
25630
+ const fullPath = path23.join(fixtureDir, file);
24463
25631
  try {
24464
25632
  const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
24465
25633
  return {
@@ -24595,7 +25763,7 @@ async function handleCliRaw(ctx, req, res) {
24595
25763
 
24596
25764
  // src/daemon/dev-auto-implement.ts
24597
25765
  var fs14 = __toESM(require("fs"));
24598
- var path21 = __toESM(require("path"));
25766
+ var path24 = __toESM(require("path"));
24599
25767
  var os20 = __toESM(require("os"));
24600
25768
  function getAutoImplPid(ctx) {
24601
25769
  const pid = ctx.autoImplProcess?.pid;
@@ -24645,22 +25813,22 @@ function getLatestScriptVersionDir(scriptsDir) {
24645
25813
  if (!fs14.existsSync(scriptsDir)) return null;
24646
25814
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
24647
25815
  try {
24648
- return fs14.statSync(path21.join(scriptsDir, d)).isDirectory();
25816
+ return fs14.statSync(path24.join(scriptsDir, d)).isDirectory();
24649
25817
  } catch {
24650
25818
  return false;
24651
25819
  }
24652
25820
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
24653
25821
  if (versions.length === 0) return null;
24654
- return path21.join(scriptsDir, versions[0]);
25822
+ return path24.join(scriptsDir, versions[0]);
24655
25823
  }
24656
25824
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
24657
- const canonicalUserDir = path21.resolve(ctx.providerLoader.getUserProviderDir(category, type));
24658
- const desiredDir = requestedDir ? path21.resolve(requestedDir) : canonicalUserDir;
24659
- const upstreamRoot = path21.resolve(ctx.providerLoader.getUpstreamDir());
24660
- 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}`)) {
24661
25829
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
24662
25830
  }
24663
- if (path21.basename(desiredDir) !== type) {
25831
+ if (path24.basename(desiredDir) !== type) {
24664
25832
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
24665
25833
  }
24666
25834
  const sourceDir = ctx.findProviderDir(type);
@@ -24668,11 +25836,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
24668
25836
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
24669
25837
  }
24670
25838
  if (!fs14.existsSync(desiredDir)) {
24671
- fs14.mkdirSync(path21.dirname(desiredDir), { recursive: true });
25839
+ fs14.mkdirSync(path24.dirname(desiredDir), { recursive: true });
24672
25840
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
24673
25841
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
24674
25842
  }
24675
- const providerJson = path21.join(desiredDir, "provider.json");
25843
+ const providerJson = path24.join(desiredDir, "provider.json");
24676
25844
  if (!fs14.existsSync(providerJson)) {
24677
25845
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
24678
25846
  }
@@ -24683,13 +25851,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
24683
25851
  const refDir = ctx.findProviderDir(referenceType);
24684
25852
  if (!refDir || !fs14.existsSync(refDir)) return {};
24685
25853
  const referenceScripts = {};
24686
- const scriptsDir = path21.join(refDir, "scripts");
25854
+ const scriptsDir = path24.join(refDir, "scripts");
24687
25855
  const latestDir = getLatestScriptVersionDir(scriptsDir);
24688
25856
  if (!latestDir) return referenceScripts;
24689
25857
  for (const file of fs14.readdirSync(latestDir)) {
24690
25858
  if (!file.endsWith(".js")) continue;
24691
25859
  try {
24692
- referenceScripts[file] = fs14.readFileSync(path21.join(latestDir, file), "utf-8");
25860
+ referenceScripts[file] = fs14.readFileSync(path24.join(latestDir, file), "utf-8");
24693
25861
  } catch {
24694
25862
  }
24695
25863
  }
@@ -24797,9 +25965,9 @@ async function handleAutoImplement(ctx, type, req, res) {
24797
25965
  });
24798
25966
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
24799
25967
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
24800
- const tmpDir = path21.join(os20.tmpdir(), "adhdev-autoimpl");
25968
+ const tmpDir = path24.join(os20.tmpdir(), "adhdev-autoimpl");
24801
25969
  if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
24802
- const promptFile = path21.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
25970
+ const promptFile = path24.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
24803
25971
  fs14.writeFileSync(promptFile, prompt, "utf-8");
24804
25972
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
24805
25973
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -25231,7 +26399,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
25231
26399
  setMode: "set_mode.js"
25232
26400
  };
25233
26401
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
25234
- const scriptsDir = path21.join(providerDir, "scripts");
26402
+ const scriptsDir = path24.join(providerDir, "scripts");
25235
26403
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
25236
26404
  if (latestScriptsDir) {
25237
26405
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -25242,7 +26410,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
25242
26410
  for (const file of fs14.readdirSync(latestScriptsDir)) {
25243
26411
  if (file.endsWith(".js") && targetFileNames.has(file)) {
25244
26412
  try {
25245
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
26413
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
25246
26414
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
25247
26415
  lines.push("```javascript");
25248
26416
  lines.push(content);
@@ -25259,7 +26427,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
25259
26427
  lines.push("");
25260
26428
  for (const file of refFiles) {
25261
26429
  try {
25262
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
26430
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
25263
26431
  lines.push(`### \`${file}\` \u{1F512}`);
25264
26432
  lines.push("```javascript");
25265
26433
  lines.push(content);
@@ -25300,10 +26468,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
25300
26468
  lines.push("");
25301
26469
  }
25302
26470
  }
25303
- const docsDir = path21.join(providerDir, "../../docs");
26471
+ const docsDir = path24.join(providerDir, "../../docs");
25304
26472
  const loadGuide = (name) => {
25305
26473
  try {
25306
- const p = path21.join(docsDir, name);
26474
+ const p = path24.join(docsDir, name);
25307
26475
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
25308
26476
  } catch {
25309
26477
  }
@@ -25540,7 +26708,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
25540
26708
  parseApproval: "parse_approval.js"
25541
26709
  };
25542
26710
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
25543
- const scriptsDir = path21.join(providerDir, "scripts");
26711
+ const scriptsDir = path24.join(providerDir, "scripts");
25544
26712
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
25545
26713
  if (latestScriptsDir) {
25546
26714
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -25552,7 +26720,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
25552
26720
  if (!file.endsWith(".js")) continue;
25553
26721
  if (!targetFileNames.has(file)) continue;
25554
26722
  try {
25555
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
26723
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
25556
26724
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
25557
26725
  lines.push("```javascript");
25558
26726
  lines.push(content);
@@ -25568,7 +26736,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
25568
26736
  lines.push("");
25569
26737
  for (const file of refFiles) {
25570
26738
  try {
25571
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
26739
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
25572
26740
  lines.push(`### \`${file}\` \u{1F512}`);
25573
26741
  lines.push("```javascript");
25574
26742
  lines.push(content);
@@ -25601,10 +26769,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
25601
26769
  lines.push("");
25602
26770
  }
25603
26771
  }
25604
- const docsDir = path21.join(providerDir, "../../docs");
26772
+ const docsDir = path24.join(providerDir, "../../docs");
25605
26773
  const loadGuide = (name) => {
25606
26774
  try {
25607
- const p = path21.join(docsDir, name);
26775
+ const p = path24.join(docsDir, name);
25608
26776
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
25609
26777
  } catch {
25610
26778
  }
@@ -26051,8 +27219,8 @@ var DevServer = class _DevServer {
26051
27219
  }
26052
27220
  getEndpointList() {
26053
27221
  return this.routes.map((r) => {
26054
- const path23 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
26055
- 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}`;
26056
27224
  });
26057
27225
  }
26058
27226
  async start(port = DEV_SERVER_PORT) {
@@ -26083,15 +27251,15 @@ var DevServer = class _DevServer {
26083
27251
  this.json(res, 500, { error: e.message });
26084
27252
  }
26085
27253
  });
26086
- return new Promise((resolve12, reject) => {
27254
+ return new Promise((resolve15, reject) => {
26087
27255
  this.server.listen(port, "127.0.0.1", () => {
26088
27256
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
26089
- resolve12();
27257
+ resolve15();
26090
27258
  });
26091
27259
  this.server.on("error", (e) => {
26092
27260
  if (e.code === "EADDRINUSE") {
26093
27261
  this.log(`Port ${port} in use, skipping dev server`);
26094
- resolve12();
27262
+ resolve15();
26095
27263
  } else {
26096
27264
  reject(e);
26097
27265
  }
@@ -26173,20 +27341,20 @@ var DevServer = class _DevServer {
26173
27341
  child.stderr?.on("data", (d) => {
26174
27342
  stderr += d.toString().slice(0, 2e3);
26175
27343
  });
26176
- await new Promise((resolve12) => {
27344
+ await new Promise((resolve15) => {
26177
27345
  const timer = setTimeout(() => {
26178
27346
  child.kill();
26179
- resolve12();
27347
+ resolve15();
26180
27348
  }, 3e3);
26181
27349
  child.on("exit", () => {
26182
27350
  clearTimeout(timer);
26183
- resolve12();
27351
+ resolve15();
26184
27352
  });
26185
27353
  child.stdout?.once("data", () => {
26186
27354
  setTimeout(() => {
26187
27355
  child.kill();
26188
27356
  clearTimeout(timer);
26189
- resolve12();
27357
+ resolve15();
26190
27358
  }, 500);
26191
27359
  });
26192
27360
  });
@@ -26340,12 +27508,12 @@ var DevServer = class _DevServer {
26340
27508
  // ─── DevConsole SPA ───
26341
27509
  getConsoleDistDir() {
26342
27510
  const candidates = [
26343
- path22.resolve(__dirname, "../../web-devconsole/dist"),
26344
- path22.resolve(__dirname, "../../../web-devconsole/dist"),
26345
- 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")
26346
27514
  ];
26347
27515
  for (const dir of candidates) {
26348
- if (fs15.existsSync(path22.join(dir, "index.html"))) return dir;
27516
+ if (fs15.existsSync(path25.join(dir, "index.html"))) return dir;
26349
27517
  }
26350
27518
  return null;
26351
27519
  }
@@ -26355,7 +27523,7 @@ var DevServer = class _DevServer {
26355
27523
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
26356
27524
  return;
26357
27525
  }
26358
- const htmlPath = path22.join(distDir, "index.html");
27526
+ const htmlPath = path25.join(distDir, "index.html");
26359
27527
  try {
26360
27528
  const html = fs15.readFileSync(htmlPath, "utf-8");
26361
27529
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -26380,15 +27548,15 @@ var DevServer = class _DevServer {
26380
27548
  this.json(res, 404, { error: "Not found" });
26381
27549
  return;
26382
27550
  }
26383
- const safePath = path22.normalize(pathname).replace(/^\.\.\//, "");
26384
- const filePath = path22.join(distDir, safePath);
27551
+ const safePath = path25.normalize(pathname).replace(/^\.\.\//, "");
27552
+ const filePath = path25.join(distDir, safePath);
26385
27553
  if (!filePath.startsWith(distDir)) {
26386
27554
  this.json(res, 403, { error: "Forbidden" });
26387
27555
  return;
26388
27556
  }
26389
27557
  try {
26390
27558
  const content = fs15.readFileSync(filePath);
26391
- const ext = path22.extname(filePath);
27559
+ const ext = path25.extname(filePath);
26392
27560
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
26393
27561
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
26394
27562
  res.end(content);
@@ -26501,10 +27669,10 @@ var DevServer = class _DevServer {
26501
27669
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
26502
27670
  if (entry.isDirectory()) {
26503
27671
  files.push({ path: rel, size: 0, type: "dir" });
26504
- scan(path22.join(d, entry.name), rel);
27672
+ scan(path25.join(d, entry.name), rel);
26505
27673
  } else {
26506
- const stat = fs15.statSync(path22.join(d, entry.name));
26507
- 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" });
26508
27676
  }
26509
27677
  }
26510
27678
  } catch {
@@ -26526,7 +27694,7 @@ var DevServer = class _DevServer {
26526
27694
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
26527
27695
  return;
26528
27696
  }
26529
- const fullPath = path22.resolve(dir, path22.normalize(filePath));
27697
+ const fullPath = path25.resolve(dir, path25.normalize(filePath));
26530
27698
  if (!fullPath.startsWith(dir)) {
26531
27699
  this.json(res, 403, { error: "Forbidden" });
26532
27700
  return;
@@ -26551,14 +27719,14 @@ var DevServer = class _DevServer {
26551
27719
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
26552
27720
  return;
26553
27721
  }
26554
- const fullPath = path22.resolve(dir, path22.normalize(filePath));
27722
+ const fullPath = path25.resolve(dir, path25.normalize(filePath));
26555
27723
  if (!fullPath.startsWith(dir)) {
26556
27724
  this.json(res, 403, { error: "Forbidden" });
26557
27725
  return;
26558
27726
  }
26559
27727
  try {
26560
27728
  if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
26561
- fs15.mkdirSync(path22.dirname(fullPath), { recursive: true });
27729
+ fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
26562
27730
  fs15.writeFileSync(fullPath, content, "utf-8");
26563
27731
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
26564
27732
  this.providerLoader.reload();
@@ -26575,7 +27743,7 @@ var DevServer = class _DevServer {
26575
27743
  return;
26576
27744
  }
26577
27745
  for (const name of ["scripts.js", "provider.json"]) {
26578
- const p = path22.join(dir, name);
27746
+ const p = path25.join(dir, name);
26579
27747
  if (fs15.existsSync(p)) {
26580
27748
  const source = fs15.readFileSync(p, "utf-8");
26581
27749
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -26596,8 +27764,8 @@ var DevServer = class _DevServer {
26596
27764
  this.json(res, 404, { error: `Provider not found: ${type}` });
26597
27765
  return;
26598
27766
  }
26599
- const target = fs15.existsSync(path22.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
26600
- 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);
26601
27769
  try {
26602
27770
  if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
26603
27771
  fs15.writeFileSync(targetPath, source, "utf-8");
@@ -26689,14 +27857,14 @@ var DevServer = class _DevServer {
26689
27857
  child.stderr?.on("data", (d) => {
26690
27858
  stderr += d.toString();
26691
27859
  });
26692
- await new Promise((resolve12) => {
27860
+ await new Promise((resolve15) => {
26693
27861
  const timer = setTimeout(() => {
26694
27862
  child.kill();
26695
- resolve12();
27863
+ resolve15();
26696
27864
  }, timeout);
26697
27865
  child.on("exit", () => {
26698
27866
  clearTimeout(timer);
26699
- resolve12();
27867
+ resolve15();
26700
27868
  });
26701
27869
  });
26702
27870
  const elapsed = Date.now() - start;
@@ -26744,7 +27912,7 @@ var DevServer = class _DevServer {
26744
27912
  }
26745
27913
  let targetDir;
26746
27914
  targetDir = this.providerLoader.getUserProviderDir(category, type);
26747
- const jsonPath = path22.join(targetDir, "provider.json");
27915
+ const jsonPath = path25.join(targetDir, "provider.json");
26748
27916
  if (fs15.existsSync(jsonPath)) {
26749
27917
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
26750
27918
  return;
@@ -26756,8 +27924,8 @@ var DevServer = class _DevServer {
26756
27924
  const createdFiles = ["provider.json"];
26757
27925
  if (result.files) {
26758
27926
  for (const [relPath, content] of Object.entries(result.files)) {
26759
- const fullPath = path22.join(targetDir, relPath);
26760
- fs15.mkdirSync(path22.dirname(fullPath), { recursive: true });
27927
+ const fullPath = path25.join(targetDir, relPath);
27928
+ fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
26761
27929
  fs15.writeFileSync(fullPath, content, "utf-8");
26762
27930
  createdFiles.push(relPath);
26763
27931
  }
@@ -26810,22 +27978,22 @@ var DevServer = class _DevServer {
26810
27978
  if (!fs15.existsSync(scriptsDir)) return null;
26811
27979
  const versions = fs15.readdirSync(scriptsDir).filter((d) => {
26812
27980
  try {
26813
- return fs15.statSync(path22.join(scriptsDir, d)).isDirectory();
27981
+ return fs15.statSync(path25.join(scriptsDir, d)).isDirectory();
26814
27982
  } catch {
26815
27983
  return false;
26816
27984
  }
26817
27985
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
26818
27986
  if (versions.length === 0) return null;
26819
- return path22.join(scriptsDir, versions[0]);
27987
+ return path25.join(scriptsDir, versions[0]);
26820
27988
  }
26821
27989
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
26822
- const canonicalUserDir = path22.resolve(this.providerLoader.getUserProviderDir(category, type));
26823
- const desiredDir = requestedDir ? path22.resolve(requestedDir) : canonicalUserDir;
26824
- const upstreamRoot = path22.resolve(this.providerLoader.getUpstreamDir());
26825
- 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}`)) {
26826
27994
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
26827
27995
  }
26828
- if (path22.basename(desiredDir) !== type) {
27996
+ if (path25.basename(desiredDir) !== type) {
26829
27997
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
26830
27998
  }
26831
27999
  const sourceDir = this.findProviderDir(type);
@@ -26833,11 +28001,11 @@ var DevServer = class _DevServer {
26833
28001
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
26834
28002
  }
26835
28003
  if (!fs15.existsSync(desiredDir)) {
26836
- fs15.mkdirSync(path22.dirname(desiredDir), { recursive: true });
28004
+ fs15.mkdirSync(path25.dirname(desiredDir), { recursive: true });
26837
28005
  fs15.cpSync(sourceDir, desiredDir, { recursive: true });
26838
28006
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
26839
28007
  }
26840
- const providerJson = path22.join(desiredDir, "provider.json");
28008
+ const providerJson = path25.join(desiredDir, "provider.json");
26841
28009
  if (!fs15.existsSync(providerJson)) {
26842
28010
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
26843
28011
  }
@@ -26873,7 +28041,7 @@ var DevServer = class _DevServer {
26873
28041
  setMode: "set_mode.js"
26874
28042
  };
26875
28043
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26876
- const scriptsDir = path22.join(providerDir, "scripts");
28044
+ const scriptsDir = path25.join(providerDir, "scripts");
26877
28045
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
26878
28046
  if (latestScriptsDir) {
26879
28047
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26884,7 +28052,7 @@ var DevServer = class _DevServer {
26884
28052
  for (const file of fs15.readdirSync(latestScriptsDir)) {
26885
28053
  if (file.endsWith(".js") && targetFileNames.has(file)) {
26886
28054
  try {
26887
- const content = fs15.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
28055
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26888
28056
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26889
28057
  lines.push("```javascript");
26890
28058
  lines.push(content);
@@ -26901,7 +28069,7 @@ var DevServer = class _DevServer {
26901
28069
  lines.push("");
26902
28070
  for (const file of refFiles) {
26903
28071
  try {
26904
- const content = fs15.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
28072
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26905
28073
  lines.push(`### \`${file}\` \u{1F512}`);
26906
28074
  lines.push("```javascript");
26907
28075
  lines.push(content);
@@ -26942,10 +28110,10 @@ var DevServer = class _DevServer {
26942
28110
  lines.push("");
26943
28111
  }
26944
28112
  }
26945
- const docsDir = path22.join(providerDir, "../../docs");
28113
+ const docsDir = path25.join(providerDir, "../../docs");
26946
28114
  const loadGuide = (name) => {
26947
28115
  try {
26948
- const p = path22.join(docsDir, name);
28116
+ const p = path25.join(docsDir, name);
26949
28117
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
26950
28118
  } catch {
26951
28119
  }
@@ -27119,7 +28287,7 @@ var DevServer = class _DevServer {
27119
28287
  parseApproval: "parse_approval.js"
27120
28288
  };
27121
28289
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
27122
- const scriptsDir = path22.join(providerDir, "scripts");
28290
+ const scriptsDir = path25.join(providerDir, "scripts");
27123
28291
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
27124
28292
  if (latestScriptsDir) {
27125
28293
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -27131,7 +28299,7 @@ var DevServer = class _DevServer {
27131
28299
  if (!file.endsWith(".js")) continue;
27132
28300
  if (!targetFileNames.has(file)) continue;
27133
28301
  try {
27134
- const content = fs15.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
28302
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
27135
28303
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
27136
28304
  lines.push("```javascript");
27137
28305
  lines.push(content);
@@ -27147,7 +28315,7 @@ var DevServer = class _DevServer {
27147
28315
  lines.push("");
27148
28316
  for (const file of refFiles) {
27149
28317
  try {
27150
- const content = fs15.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
28318
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
27151
28319
  lines.push(`### \`${file}\` \u{1F512}`);
27152
28320
  lines.push("```javascript");
27153
28321
  lines.push(content);
@@ -27180,10 +28348,10 @@ var DevServer = class _DevServer {
27180
28348
  lines.push("");
27181
28349
  }
27182
28350
  }
27183
- const docsDir = path22.join(providerDir, "../../docs");
28351
+ const docsDir = path25.join(providerDir, "../../docs");
27184
28352
  const loadGuide = (name) => {
27185
28353
  try {
27186
- const p = path22.join(docsDir, name);
28354
+ const p = path25.join(docsDir, name);
27187
28355
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
27188
28356
  } catch {
27189
28357
  }
@@ -27366,14 +28534,14 @@ data: ${JSON.stringify(msg.data)}
27366
28534
  res.end(JSON.stringify(data, null, 2));
27367
28535
  }
27368
28536
  async readBody(req) {
27369
- return new Promise((resolve12) => {
28537
+ return new Promise((resolve15) => {
27370
28538
  let body = "";
27371
28539
  req.on("data", (chunk) => body += chunk);
27372
28540
  req.on("end", () => {
27373
28541
  try {
27374
- resolve12(JSON.parse(body));
28542
+ resolve15(JSON.parse(body));
27375
28543
  } catch {
27376
- resolve12({});
28544
+ resolve15({});
27377
28545
  }
27378
28546
  });
27379
28547
  });
@@ -27883,7 +29051,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
27883
29051
  const deadline = Date.now() + timeoutMs;
27884
29052
  while (Date.now() < deadline) {
27885
29053
  if (await canConnect(endpoint)) return;
27886
- await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
29054
+ await new Promise((resolve15) => setTimeout(resolve15, STARTUP_POLL_MS));
27887
29055
  }
27888
29056
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
27889
29057
  }
@@ -28061,10 +29229,10 @@ async function installExtension(ide, extension) {
28061
29229
  const buffer = Buffer.from(await res.arrayBuffer());
28062
29230
  const fs16 = await import("fs");
28063
29231
  fs16.writeFileSync(vsixPath, buffer);
28064
- return new Promise((resolve12) => {
29232
+ return new Promise((resolve15) => {
28065
29233
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
28066
29234
  (0, import_child_process11.exec)(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
28067
- resolve12({
29235
+ resolve15({
28068
29236
  extensionId: extension.id,
28069
29237
  marketplaceId: extension.marketplaceId,
28070
29238
  success: !error,
@@ -28077,11 +29245,11 @@ async function installExtension(ide, extension) {
28077
29245
  } catch (e) {
28078
29246
  }
28079
29247
  }
28080
- return new Promise((resolve12) => {
29248
+ return new Promise((resolve15) => {
28081
29249
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
28082
29250
  (0, import_child_process11.exec)(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
28083
29251
  if (error) {
28084
- resolve12({
29252
+ resolve15({
28085
29253
  extensionId: extension.id,
28086
29254
  marketplaceId: extension.marketplaceId,
28087
29255
  success: false,
@@ -28089,7 +29257,7 @@ async function installExtension(ide, extension) {
28089
29257
  error: stderr || error.message
28090
29258
  });
28091
29259
  } else {
28092
- resolve12({
29260
+ resolve15({
28093
29261
  extensionId: extension.id,
28094
29262
  marketplaceId: extension.marketplaceId,
28095
29263
  success: true,
@@ -28419,6 +29587,7 @@ async function shutdownDaemonComponents(components) {
28419
29587
  DEFAULT_CDP_SCAN_INTERVAL_MS,
28420
29588
  DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS,
28421
29589
  DEFAULT_DAEMON_PORT,
29590
+ DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS,
28422
29591
  DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
28423
29592
  DEFAULT_SESSION_HOST_APP_NAME,
28424
29593
  DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
@@ -28437,8 +29606,12 @@ async function shutdownDaemonComponents(components) {
28437
29606
  DaemonCommandRouter,
28438
29607
  DaemonStatusReporter,
28439
29608
  DevServer,
29609
+ GitCommandError,
29610
+ GitWorkspaceMonitor,
28440
29611
  IdeProviderInstance,
29612
+ InMemoryGitSnapshotStore,
28441
29613
  LOG,
29614
+ MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
28442
29615
  MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
28443
29616
  MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
28444
29617
  NodePtyTransportFactory,
@@ -28466,9 +29639,14 @@ async function shutdownDaemonComponents(components) {
28466
29639
  buildUserChatMessage,
28467
29640
  classifyHotChatSessionsForSubscriptionFlush,
28468
29641
  clearDebugTrace,
29642
+ compareGitSnapshots,
28469
29643
  configureDebugTraceStore,
28470
29644
  connectCdpManager,
28471
29645
  createDebugTraceStore,
29646
+ createDefaultGitCommandServices,
29647
+ createGitCompactSummary,
29648
+ createGitSnapshotStore,
29649
+ createGitWorkspaceMonitor,
28472
29650
  createInteractionId,
28473
29651
  detectAllVersions,
28474
29652
  detectCLIs,
@@ -28483,6 +29661,9 @@ async function shutdownDaemonComponents(components) {
28483
29661
  getCurrentDaemonLogPath,
28484
29662
  getDaemonLogDir,
28485
29663
  getDebugRuntimeConfig,
29664
+ getGitDiffSummary,
29665
+ getGitFileDiff,
29666
+ getGitRepoStatus,
28486
29667
  getHostMemorySnapshot,
28487
29668
  getLogLevel,
28488
29669
  getNpmExecOptions,
@@ -28494,6 +29675,7 @@ async function shutdownDaemonComponents(components) {
28494
29675
  getSessionHostRecoveryLabel,
28495
29676
  getSessionHostSurfaceKind,
28496
29677
  getWorkspaceState,
29678
+ handleGitCommand,
28497
29679
  hasCdpManager,
28498
29680
  hashSignatureParts,
28499
29681
  initDaemonComponents,
@@ -28502,9 +29684,11 @@ async function shutdownDaemonComponents(components) {
28502
29684
  isBuiltinChatMessageKind,
28503
29685
  isCdpConnected,
28504
29686
  isExtensionInstalled,
29687
+ isGitCommandName,
28505
29688
  isIdeRunning,
28506
29689
  isManagedStatusWaiting,
28507
29690
  isManagedStatusWorking,
29691
+ isPathInside,
28508
29692
  isSessionHostLiveRuntime,
28509
29693
  isSessionHostRecoverySnapshot,
28510
29694
  isSetupComplete,
@@ -28522,10 +29706,13 @@ async function shutdownDaemonComponents(components) {
28522
29706
  normalizeChatMessageKind,
28523
29707
  normalizeChatMessages,
28524
29708
  normalizeChatTailActiveModal,
29709
+ normalizeGitOutput,
29710
+ normalizeGitWorkspaceSubscriptionParams,
28525
29711
  normalizeInputEnvelope,
28526
29712
  normalizeManagedStatus,
28527
29713
  normalizeMessageParts,
28528
29714
  normalizeSessionModalFields,
29715
+ parsePorcelainV2Status,
28529
29716
  parseProviderSourceConfigUpdate,
28530
29717
  partitionSessionHostDiagnosticsSessions,
28531
29718
  partitionSessionHostRecords,
@@ -28541,9 +29728,11 @@ async function shutdownDaemonComponents(components) {
28541
29728
  resolveChatMessageKind,
28542
29729
  resolveCurrentGlobalInstallSurface,
28543
29730
  resolveDebugRuntimeConfig,
29731
+ resolveGitRepository,
28544
29732
  resolveSessionHostAppName,
28545
29733
  resolveSessionHostAppNameResolution,
28546
29734
  runAsyncBatch,
29735
+ runGit,
28547
29736
  saveConfig,
28548
29737
  saveState,
28549
29738
  setDebugRuntimeConfig,
@@ -28554,6 +29743,7 @@ async function shutdownDaemonComponents(components) {
28554
29743
  shutdownDaemonComponents,
28555
29744
  spawnDetachedDaemonUpgradeHelper,
28556
29745
  startDaemonDevSupport,
29746
+ summarizeGitStatus,
28557
29747
  updateConfig,
28558
29748
  upsertSavedProviderSession
28559
29749
  });