@adhdev/daemon-standalone 0.9.52 → 0.9.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -28139,13 +28139,13 @@ var require_dist2 = __commonJS({
28139
28139
  return LOG_DIR;
28140
28140
  }
28141
28141
  function getCurrentDaemonLogPath(date5 = /* @__PURE__ */ new Date()) {
28142
- return path6.join(LOG_DIR, `daemon-${date5.toISOString().slice(0, 10)}.log`);
28142
+ return path9.join(LOG_DIR, `daemon-${date5.toISOString().slice(0, 10)}.log`);
28143
28143
  }
28144
28144
  function checkDateRotation() {
28145
28145
  const today = getDateStr();
28146
28146
  if (today !== currentDate) {
28147
28147
  currentDate = today;
28148
- currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
28148
+ currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
28149
28149
  cleanOldLogs();
28150
28150
  }
28151
28151
  }
@@ -28159,7 +28159,7 @@ var require_dist2 = __commonJS({
28159
28159
  const dateMatch = file2.match(/daemon-(\d{4}-\d{2}-\d{2})/);
28160
28160
  if (dateMatch && dateMatch[1] < cutoffStr) {
28161
28161
  try {
28162
- fs22.unlinkSync(path6.join(LOG_DIR, file2));
28162
+ fs22.unlinkSync(path9.join(LOG_DIR, file2));
28163
28163
  } catch {
28164
28164
  }
28165
28165
  }
@@ -28169,8 +28169,8 @@ var require_dist2 = __commonJS({
28169
28169
  }
28170
28170
  function rotateSizeIfNeeded() {
28171
28171
  try {
28172
- const stat4 = fs22.statSync(currentLogFile);
28173
- if (stat4.size > MAX_LOG_SIZE) {
28172
+ const stat22 = fs22.statSync(currentLogFile);
28173
+ if (stat22.size > MAX_LOG_SIZE) {
28174
28174
  const backup = currentLogFile.replace(".log", ".1.log");
28175
28175
  try {
28176
28176
  fs22.unlinkSync(backup);
@@ -28276,7 +28276,7 @@ var require_dist2 = __commonJS({
28276
28276
  writeToFile(`Log level: ${currentLevel}`);
28277
28277
  }
28278
28278
  var fs22;
28279
- var path6;
28279
+ var path9;
28280
28280
  var os42;
28281
28281
  var LEVEL_NUM;
28282
28282
  var LEVEL_LABEL;
@@ -28299,12 +28299,12 @@ var require_dist2 = __commonJS({
28299
28299
  "src/logging/logger.ts"() {
28300
28300
  "use strict";
28301
28301
  fs22 = __toESM2(require("fs"));
28302
- path6 = __toESM2(require("path"));
28302
+ path9 = __toESM2(require("path"));
28303
28303
  os42 = __toESM2(require("os"));
28304
28304
  LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
28305
28305
  LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
28306
28306
  currentLevel = "info";
28307
- LOG_DIR = process.platform === "win32" ? path6.join(process.env.LOCALAPPDATA || process.env.APPDATA || path6.join(os42.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path6.join(os42.homedir(), "Library", "Logs", "adhdev") : path6.join(os42.homedir(), ".local", "share", "adhdev", "logs");
28307
+ LOG_DIR = process.platform === "win32" ? path9.join(process.env.LOCALAPPDATA || process.env.APPDATA || path9.join(os42.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path9.join(os42.homedir(), "Library", "Logs", "adhdev") : path9.join(os42.homedir(), ".local", "share", "adhdev", "logs");
28308
28308
  MAX_LOG_SIZE = 5 * 1024 * 1024;
28309
28309
  MAX_LOG_DAYS = 7;
28310
28310
  try {
@@ -28312,16 +28312,16 @@ var require_dist2 = __commonJS({
28312
28312
  } catch {
28313
28313
  }
28314
28314
  currentDate = getDateStr();
28315
- currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
28315
+ currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
28316
28316
  cleanOldLogs();
28317
28317
  try {
28318
- const oldLog = path6.join(LOG_DIR, "daemon.log");
28318
+ const oldLog = path9.join(LOG_DIR, "daemon.log");
28319
28319
  if (fs22.existsSync(oldLog)) {
28320
- const stat4 = fs22.statSync(oldLog);
28321
- const oldDate = stat4.mtime.toISOString().slice(0, 10);
28322
- fs22.renameSync(oldLog, path6.join(LOG_DIR, `daemon-${oldDate}.log`));
28320
+ const stat22 = fs22.statSync(oldLog);
28321
+ const oldDate = stat22.mtime.toISOString().slice(0, 10);
28322
+ fs22.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
28323
28323
  }
28324
- const oldLogBackup = path6.join(LOG_DIR, "daemon.log.old");
28324
+ const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
28325
28325
  if (fs22.existsSync(oldLogBackup)) {
28326
28326
  fs22.unlinkSync(oldLogBackup);
28327
28327
  }
@@ -28353,7 +28353,7 @@ var require_dist2 = __commonJS({
28353
28353
  }
28354
28354
  };
28355
28355
  interceptorInstalled = false;
28356
- LOG_PATH = path6.join(LOG_DIR, `daemon-${getDateStr()}.log`);
28356
+ LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
28357
28357
  }
28358
28358
  });
28359
28359
  function normalizeInputEnvelope(input) {
@@ -29254,8 +29254,8 @@ var require_dist2 = __commonJS({
29254
29254
  if (cwd) {
29255
29255
  try {
29256
29256
  const fs16 = require("fs");
29257
- const stat4 = fs16.statSync(cwd);
29258
- if (!stat4.isDirectory()) cwd = os8.homedir();
29257
+ const stat22 = fs16.statSync(cwd);
29258
+ if (!stat22.isDirectory()) cwd = os8.homedir();
29259
29259
  } catch {
29260
29260
  cwd = os8.homedir();
29261
29261
  }
@@ -29335,9 +29335,9 @@ var require_dist2 = __commonJS({
29335
29335
  function findBinary(name) {
29336
29336
  const trimmed = String(name || "").trim();
29337
29337
  if (!trimmed) return trimmed;
29338
- const expanded = trimmed.startsWith("~") ? path10.join(os9.homedir(), trimmed.slice(1)) : trimmed;
29339
- if (path10.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
29340
- return path10.isAbsolute(expanded) ? expanded : path10.resolve(expanded);
29338
+ const expanded = trimmed.startsWith("~") ? path13.join(os9.homedir(), trimmed.slice(1)) : trimmed;
29339
+ if (path13.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
29340
+ return path13.isAbsolute(expanded) ? expanded : path13.resolve(expanded);
29341
29341
  }
29342
29342
  const isWin = os9.platform() === "win32";
29343
29343
  try {
@@ -29353,7 +29353,7 @@ var require_dist2 = __commonJS({
29353
29353
  }
29354
29354
  }
29355
29355
  function isScriptBinary(binaryPath) {
29356
- if (!path10.isAbsolute(binaryPath)) return false;
29356
+ if (!path13.isAbsolute(binaryPath)) return false;
29357
29357
  try {
29358
29358
  const fs16 = require("fs");
29359
29359
  const resolved = fs16.realpathSync(binaryPath);
@@ -29369,7 +29369,7 @@ var require_dist2 = __commonJS({
29369
29369
  }
29370
29370
  }
29371
29371
  function looksLikeMachOOrElf(filePath) {
29372
- if (!path10.isAbsolute(filePath)) return false;
29372
+ if (!path13.isAbsolute(filePath)) return false;
29373
29373
  try {
29374
29374
  const fs16 = require("fs");
29375
29375
  const resolved = fs16.realpathSync(filePath);
@@ -29520,7 +29520,7 @@ var require_dist2 = __commonJS({
29520
29520
  };
29521
29521
  }
29522
29522
  var os9;
29523
- var path10;
29523
+ var path13;
29524
29524
  var import_child_process4;
29525
29525
  var buildCliSpawnEnv;
29526
29526
  var COMMON_COMPARABLE_WRAP_WORDS;
@@ -29528,7 +29528,7 @@ var require_dist2 = __commonJS({
29528
29528
  "src/cli-adapters/provider-cli-shared.ts"() {
29529
29529
  "use strict";
29530
29530
  os9 = __toESM2(require("os"));
29531
- path10 = __toESM2(require("path"));
29531
+ path13 = __toESM2(require("path"));
29532
29532
  import_child_process4 = require("child_process");
29533
29533
  init_spawn_env();
29534
29534
  buildCliSpawnEnv = import_session_host_core3.sanitizeSpawnEnv;
@@ -29839,9 +29839,9 @@ var require_dist2 = __commonJS({
29839
29839
  const allArgs = [...spawnConfig.args, ...extraArgs];
29840
29840
  let shellCmd;
29841
29841
  let shellArgs;
29842
- const useShellUnix = !isWin && (!!spawnConfig.shell || !path11.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
29842
+ const useShellUnix = !isWin && (!!spawnConfig.shell || !path14.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
29843
29843
  const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
29844
- const useShellWin = !!spawnConfig.shell || isCmdShim || !path11.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
29844
+ const useShellWin = !!spawnConfig.shell || isCmdShim || !path14.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
29845
29845
  const useShell = isWin ? useShellWin : useShellUnix;
29846
29846
  if (useShell) {
29847
29847
  shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
@@ -29918,13 +29918,13 @@ var require_dist2 = __commonJS({
29918
29918
  return "";
29919
29919
  }
29920
29920
  var os10;
29921
- var path11;
29921
+ var path14;
29922
29922
  var import_session_host_core22;
29923
29923
  var init_provider_cli_runtime = __esm2({
29924
29924
  "src/cli-adapters/provider-cli-runtime.ts"() {
29925
29925
  "use strict";
29926
29926
  os10 = __toESM2(require("os"));
29927
- path11 = __toESM2(require("path"));
29927
+ path14 = __toESM2(require("path"));
29928
29928
  import_session_host_core22 = require_dist();
29929
29929
  init_provider_cli_shared();
29930
29930
  }
@@ -30724,7 +30724,7 @@ var require_dist2 = __commonJS({
30724
30724
  `[${this.cliType}] Waiting for interactive prompt: status=${status} stableMs=${stableMs} recentOutputMs=${recentlyOutput} screen=${JSON.stringify(summarizeCliTraceText(screenText, 220)).slice(0, 260)}`
30725
30725
  );
30726
30726
  }
30727
- await new Promise((resolve12) => setTimeout(resolve12, 50));
30727
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
30728
30728
  }
30729
30729
  const finalScreenText = this.terminalScreen.getText() || "";
30730
30730
  LOG2.warn(
@@ -31912,7 +31912,7 @@ var require_dist2 = __commonJS({
31912
31912
  const deadline = Date.now() + 1e4;
31913
31913
  while (this.startupParseGate && Date.now() < deadline) {
31914
31914
  this.resolveStartupState("send_wait");
31915
- await new Promise((resolve12) => setTimeout(resolve12, 50));
31915
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
31916
31916
  }
31917
31917
  }
31918
31918
  if (!allowInterventionPrompt) {
@@ -31993,13 +31993,13 @@ var require_dist2 = __commonJS({
31993
31993
  }
31994
31994
  this.responseEpoch += 1;
31995
31995
  this.responseSettleIgnoreUntil = Date.now() + submitDelayMs + this.timeouts.outputSettle + 250;
31996
- await new Promise((resolve12, reject) => {
31996
+ await new Promise((resolve15, reject) => {
31997
31997
  let resolved = false;
31998
31998
  const completion = {
31999
31999
  resolveOnce: () => {
32000
32000
  if (resolved) return;
32001
32001
  resolved = true;
32002
- resolve12();
32002
+ resolve15();
32003
32003
  },
32004
32004
  rejectOnce: (error48) => {
32005
32005
  if (resolved) return;
@@ -32161,17 +32161,17 @@ var require_dist2 = __commonJS({
32161
32161
  }
32162
32162
  }
32163
32163
  waitForStopped(timeoutMs) {
32164
- return new Promise((resolve12) => {
32164
+ return new Promise((resolve15) => {
32165
32165
  const startedAt = Date.now();
32166
32166
  const timer = setInterval(() => {
32167
32167
  if (!this.ptyProcess || this.currentStatus === "stopped") {
32168
32168
  clearInterval(timer);
32169
- resolve12(true);
32169
+ resolve15(true);
32170
32170
  return;
32171
32171
  }
32172
32172
  if (Date.now() - startedAt >= timeoutMs) {
32173
32173
  clearInterval(timer);
32174
- resolve12(false);
32174
+ resolve15(false);
32175
32175
  }
32176
32176
  }, 100);
32177
32177
  });
@@ -32409,6 +32409,7 @@ var require_dist2 = __commonJS({
32409
32409
  DEFAULT_CDP_SCAN_INTERVAL_MS: () => DEFAULT_CDP_SCAN_INTERVAL_MS,
32410
32410
  DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS: () => DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS2,
32411
32411
  DEFAULT_DAEMON_PORT: () => DEFAULT_DAEMON_PORT,
32412
+ DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS: () => DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS,
32412
32413
  DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS: () => DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS2,
32413
32414
  DEFAULT_SESSION_HOST_APP_NAME: () => DEFAULT_SESSION_HOST_APP_NAME,
32414
32415
  DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS: () => DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS2,
@@ -32427,8 +32428,12 @@ var require_dist2 = __commonJS({
32427
32428
  DaemonCommandRouter: () => DaemonCommandRouter,
32428
32429
  DaemonStatusReporter: () => DaemonStatusReporter,
32429
32430
  DevServer: () => DevServer,
32431
+ GitCommandError: () => GitCommandError,
32432
+ GitWorkspaceMonitor: () => GitWorkspaceMonitor,
32430
32433
  IdeProviderInstance: () => IdeProviderInstance,
32434
+ InMemoryGitSnapshotStore: () => InMemoryGitSnapshotStore,
32431
32435
  LOG: () => LOG2,
32436
+ MIN_GIT_WORKSPACE_POLL_INTERVAL_MS: () => MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
32432
32437
  MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS: () => MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS2,
32433
32438
  MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS: () => MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS2,
32434
32439
  NodePtyTransportFactory: () => NodePtyTransportFactory,
@@ -32456,9 +32461,14 @@ var require_dist2 = __commonJS({
32456
32461
  buildUserChatMessage: () => buildUserChatMessage,
32457
32462
  classifyHotChatSessionsForSubscriptionFlush: () => classifyHotChatSessionsForSubscriptionFlush2,
32458
32463
  clearDebugTrace: () => clearDebugTrace,
32464
+ compareGitSnapshots: () => compareGitSnapshots,
32459
32465
  configureDebugTraceStore: () => configureDebugTraceStore,
32460
32466
  connectCdpManager: () => connectCdpManager,
32461
32467
  createDebugTraceStore: () => createDebugTraceStore,
32468
+ createDefaultGitCommandServices: () => createDefaultGitCommandServices,
32469
+ createGitCompactSummary: () => createGitCompactSummary,
32470
+ createGitSnapshotStore: () => createGitSnapshotStore,
32471
+ createGitWorkspaceMonitor: () => createGitWorkspaceMonitor2,
32462
32472
  createInteractionId: () => createInteractionId,
32463
32473
  detectAllVersions: () => detectAllVersions,
32464
32474
  detectCLIs: () => detectCLIs,
@@ -32473,6 +32483,9 @@ var require_dist2 = __commonJS({
32473
32483
  getCurrentDaemonLogPath: () => getCurrentDaemonLogPath,
32474
32484
  getDaemonLogDir: () => getDaemonLogDir,
32475
32485
  getDebugRuntimeConfig: () => getDebugRuntimeConfig,
32486
+ getGitDiffSummary: () => getGitDiffSummary,
32487
+ getGitFileDiff: () => getGitFileDiff,
32488
+ getGitRepoStatus: () => getGitRepoStatus,
32476
32489
  getHostMemorySnapshot: () => getHostMemorySnapshot,
32477
32490
  getLogLevel: () => getLogLevel,
32478
32491
  getNpmExecOptions: () => getNpmExecOptions,
@@ -32484,6 +32497,7 @@ var require_dist2 = __commonJS({
32484
32497
  getSessionHostRecoveryLabel: () => getSessionHostRecoveryLabel,
32485
32498
  getSessionHostSurfaceKind: () => getSessionHostSurfaceKind,
32486
32499
  getWorkspaceState: () => getWorkspaceState2,
32500
+ handleGitCommand: () => handleGitCommand,
32487
32501
  hasCdpManager: () => hasCdpManager,
32488
32502
  hashSignatureParts: () => hashSignatureParts,
32489
32503
  initDaemonComponents: () => initDaemonComponents2,
@@ -32492,9 +32506,11 @@ var require_dist2 = __commonJS({
32492
32506
  isBuiltinChatMessageKind: () => isBuiltinChatMessageKind,
32493
32507
  isCdpConnected: () => isCdpConnected,
32494
32508
  isExtensionInstalled: () => isExtensionInstalled,
32509
+ isGitCommandName: () => isGitCommandName,
32495
32510
  isIdeRunning: () => isIdeRunning,
32496
32511
  isManagedStatusWaiting: () => isManagedStatusWaiting,
32497
32512
  isManagedStatusWorking: () => isManagedStatusWorking,
32513
+ isPathInside: () => isPathInside,
32498
32514
  isSessionHostLiveRuntime: () => isSessionHostLiveRuntime,
32499
32515
  isSessionHostRecoverySnapshot: () => isSessionHostRecoverySnapshot,
32500
32516
  isSetupComplete: () => isSetupComplete,
@@ -32512,10 +32528,13 @@ var require_dist2 = __commonJS({
32512
32528
  normalizeChatMessageKind: () => normalizeChatMessageKind,
32513
32529
  normalizeChatMessages: () => normalizeChatMessages,
32514
32530
  normalizeChatTailActiveModal: () => normalizeChatTailActiveModal,
32531
+ normalizeGitOutput: () => normalizeGitOutput,
32532
+ normalizeGitWorkspaceSubscriptionParams: () => normalizeGitWorkspaceSubscriptionParams2,
32515
32533
  normalizeInputEnvelope: () => normalizeInputEnvelope,
32516
32534
  normalizeManagedStatus: () => normalizeManagedStatus,
32517
32535
  normalizeMessageParts: () => normalizeMessageParts,
32518
32536
  normalizeSessionModalFields: () => normalizeSessionModalFields,
32537
+ parsePorcelainV2Status: () => parsePorcelainV2Status,
32519
32538
  parseProviderSourceConfigUpdate: () => parseProviderSourceConfigUpdate,
32520
32539
  partitionSessionHostDiagnosticsSessions: () => partitionSessionHostDiagnosticsSessions,
32521
32540
  partitionSessionHostRecords: () => partitionSessionHostRecords,
@@ -32531,9 +32550,11 @@ var require_dist2 = __commonJS({
32531
32550
  resolveChatMessageKind: () => resolveChatMessageKind,
32532
32551
  resolveCurrentGlobalInstallSurface: () => resolveCurrentGlobalInstallSurface,
32533
32552
  resolveDebugRuntimeConfig: () => resolveDebugRuntimeConfig,
32553
+ resolveGitRepository: () => resolveGitRepository,
32534
32554
  resolveSessionHostAppName: () => resolveSessionHostAppName,
32535
32555
  resolveSessionHostAppNameResolution: () => resolveSessionHostAppNameResolution2,
32536
32556
  runAsyncBatch: () => runAsyncBatch2,
32557
+ runGit: () => runGit,
32537
32558
  saveConfig: () => saveConfig,
32538
32559
  saveState: () => saveState,
32539
32560
  setDebugRuntimeConfig: () => setDebugRuntimeConfig,
@@ -32544,21 +32565,1125 @@ var require_dist2 = __commonJS({
32544
32565
  shutdownDaemonComponents: () => shutdownDaemonComponents2,
32545
32566
  spawnDetachedDaemonUpgradeHelper: () => spawnDetachedDaemonUpgradeHelper,
32546
32567
  startDaemonDevSupport: () => startDaemonDevSupport2,
32568
+ summarizeGitStatus: () => summarizeGitStatus,
32547
32569
  updateConfig: () => updateConfig,
32548
32570
  upsertSavedProviderSession: () => upsertSavedProviderSession
32549
32571
  });
32550
32572
  module2.exports = __toCommonJS2(index_exports);
32573
+ var import_node_child_process = require("child_process");
32574
+ var import_node_fs3 = require("fs");
32575
+ var import_promises4 = require("fs/promises");
32576
+ var path5 = __toESM2(require("path"));
32577
+ var import_node_util = require("util");
32578
+ var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
32579
+ var DEFAULT_TIMEOUT_MS = 5e3;
32580
+ var DEFAULT_MAX_BUFFER = 1024 * 1024;
32581
+ var GitCommandError = class extends Error {
32582
+ reason;
32583
+ stdout;
32584
+ stderr;
32585
+ exitCode;
32586
+ signal;
32587
+ argv;
32588
+ cwd;
32589
+ constructor(reason, message, details = {}) {
32590
+ super(message);
32591
+ if (details.cause !== void 0) {
32592
+ this.cause = details.cause;
32593
+ }
32594
+ this.name = "GitCommandError";
32595
+ this.reason = reason;
32596
+ this.stdout = normalizeGitOutput(details.stdout);
32597
+ this.stderr = normalizeGitOutput(details.stderr);
32598
+ this.exitCode = details.exitCode;
32599
+ this.signal = details.signal;
32600
+ this.argv = details.argv ? [...details.argv] : void 0;
32601
+ this.cwd = details.cwd;
32602
+ }
32603
+ };
32604
+ async function resolveGitRepository(workspace, options = {}) {
32605
+ const normalizedWorkspace = await validateWorkspace(workspace);
32606
+ const result = await execGitRaw(normalizedWorkspace, ["rev-parse", "--show-toplevel"], options, {
32607
+ mapNotGitRepo: true
32608
+ });
32609
+ const repoRoot = path5.resolve(result.stdout.trim());
32610
+ if (!repoRoot) {
32611
+ throw new GitCommandError("not_git_repo", "Git did not return a repository root", {
32612
+ stdout: result.stdout,
32613
+ stderr: result.stderr,
32614
+ argv: ["rev-parse", "--show-toplevel"],
32615
+ cwd: normalizedWorkspace
32616
+ });
32617
+ }
32618
+ return {
32619
+ workspace: normalizedWorkspace,
32620
+ repoRoot,
32621
+ isGitRepo: true
32622
+ };
32623
+ }
32624
+ async function runGit(repoOrWorkspace, argv, options = {}) {
32625
+ validateGitArgv(argv);
32626
+ const repo = typeof repoOrWorkspace === "string" ? await resolveGitRepository(repoOrWorkspace, options) : repoOrWorkspace;
32627
+ if (!repo.repoRoot || !repo.isGitRepo) {
32628
+ throw new GitCommandError("not_git_repo", "Workspace is not a Git repository", {
32629
+ argv,
32630
+ cwd: repo.workspace
32631
+ });
32632
+ }
32633
+ const cwd = options.cwd ? await validateWorkspace(options.cwd) : await validateWorkspace(repo.workspace);
32634
+ const canonicalRepoRoot = await (0, import_promises4.realpath)(repo.repoRoot);
32635
+ const canonicalCwd = await (0, import_promises4.realpath)(cwd);
32636
+ if (!isPathInside(canonicalRepoRoot, canonicalCwd)) {
32637
+ throw new GitCommandError("path_outside_repo", "Git cwd is outside the repository root", {
32638
+ argv,
32639
+ cwd
32640
+ });
32641
+ }
32642
+ return execGitRaw(cwd, argv, options);
32643
+ }
32644
+ function normalizeGitOutput(value) {
32645
+ if (typeof value === "string") return value.replace(/\r\n/g, "\n");
32646
+ if (Buffer.isBuffer(value)) return value.toString("utf8").replace(/\r\n/g, "\n");
32647
+ if (value == null) return "";
32648
+ return String(value).replace(/\r\n/g, "\n");
32649
+ }
32650
+ function isPathInside(parent, child) {
32651
+ const relative3 = path5.relative(path5.resolve(parent), path5.resolve(child));
32652
+ return relative3 === "" || !relative3.startsWith("..") && !path5.isAbsolute(relative3);
32653
+ }
32654
+ async function validateWorkspace(workspace) {
32655
+ if (typeof workspace !== "string" || workspace.length === 0 || workspace.includes("\0")) {
32656
+ throw new GitCommandError("invalid_args", "Workspace must be a non-empty path");
32657
+ }
32658
+ if (!path5.isAbsolute(workspace)) {
32659
+ throw new GitCommandError("invalid_args", "Workspace must be an absolute path", { cwd: workspace });
32660
+ }
32661
+ const normalizedWorkspace = path5.resolve(workspace);
32662
+ try {
32663
+ const info = await (0, import_promises4.stat)(normalizedWorkspace);
32664
+ if (!info.isDirectory()) {
32665
+ throw new GitCommandError("invalid_args", "Workspace must be an existing directory", {
32666
+ cwd: normalizedWorkspace
32667
+ });
32668
+ }
32669
+ await (0, import_promises4.access)(normalizedWorkspace, import_node_fs3.constants.R_OK);
32670
+ } catch (error48) {
32671
+ if (error48 instanceof GitCommandError) throw error48;
32672
+ throw new GitCommandError("invalid_args", "Workspace must be an existing directory", {
32673
+ cwd: normalizedWorkspace,
32674
+ cause: error48
32675
+ });
32676
+ }
32677
+ return normalizedWorkspace;
32678
+ }
32679
+ function validateGitArgv(argv) {
32680
+ if (!Array.isArray(argv) || argv.length === 0) {
32681
+ throw new GitCommandError("invalid_args", "Git argv must be a non-empty string array", { argv });
32682
+ }
32683
+ for (const arg of argv) {
32684
+ if (typeof arg !== "string" || arg.length === 0 || arg.includes("\0")) {
32685
+ throw new GitCommandError("invalid_args", "Git argv contains an invalid argument", { argv });
32686
+ }
32687
+ }
32688
+ if (argv.includes("-C") || argv.some((arg) => arg.startsWith("--git-dir") || arg.startsWith("--work-tree"))) {
32689
+ throw new GitCommandError("invalid_args", "Git argv contains unsafe repository override arguments", {
32690
+ argv
32691
+ });
32692
+ }
32693
+ }
32694
+ async function execGitRaw(cwd, argv, options, behavior = {}) {
32695
+ validateGitArgv(argv);
32696
+ try {
32697
+ const result = await execFileAsync("git", [...argv], {
32698
+ cwd,
32699
+ encoding: "utf8",
32700
+ timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
32701
+ maxBuffer: options.maxBuffer ?? DEFAULT_MAX_BUFFER,
32702
+ windowsHide: true
32703
+ });
32704
+ return {
32705
+ stdout: normalizeGitOutput(result.stdout),
32706
+ stderr: normalizeGitOutput(result.stderr)
32707
+ };
32708
+ } catch (error48) {
32709
+ throw mapExecError(error48, cwd, argv, behavior);
32710
+ }
32711
+ }
32712
+ function mapExecError(error48, cwd, argv, behavior) {
32713
+ const execError = error48;
32714
+ const stdout = normalizeGitOutput(execError.stdout);
32715
+ const stderr = normalizeGitOutput(execError.stderr);
32716
+ const code = execError.code;
32717
+ const signal = execError.signal;
32718
+ const message = [stderr.trim(), execError.message].filter(Boolean).join("\n");
32719
+ if (code === "ENOENT") {
32720
+ return new GitCommandError("git_not_installed", "Git executable was not found", {
32721
+ stdout,
32722
+ stderr,
32723
+ exitCode: code,
32724
+ signal,
32725
+ argv,
32726
+ cwd,
32727
+ cause: error48
32728
+ });
32729
+ }
32730
+ if (execError.killed || /timed out/i.test(execError.message)) {
32731
+ return new GitCommandError("timeout", "Git command timed out", {
32732
+ stdout,
32733
+ stderr,
32734
+ exitCode: code,
32735
+ signal,
32736
+ argv,
32737
+ cwd,
32738
+ cause: error48
32739
+ });
32740
+ }
32741
+ if (behavior.mapNotGitRepo && /not a git repository/i.test(stderr + "\n" + execError.message)) {
32742
+ return new GitCommandError("not_git_repo", "Workspace is not a Git repository", {
32743
+ stdout,
32744
+ stderr,
32745
+ exitCode: code,
32746
+ signal,
32747
+ argv,
32748
+ cwd,
32749
+ cause: error48
32750
+ });
32751
+ }
32752
+ return new GitCommandError("git_command_failed", message || "Git command failed", {
32753
+ stdout,
32754
+ stderr,
32755
+ exitCode: code,
32756
+ signal,
32757
+ argv,
32758
+ cwd,
32759
+ cause: error48
32760
+ });
32761
+ }
32762
+ async function getGitRepoStatus(workspace, options = {}) {
32763
+ const lastCheckedAt = Date.now();
32764
+ try {
32765
+ const repo = await resolveGitRepository(workspace, options);
32766
+ const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
32767
+ const parsed = parsePorcelainV2Status(statusOutput.stdout);
32768
+ const head = await readHead(repo, options);
32769
+ const stashCount = await readStashCount(repo, options);
32770
+ return {
32771
+ workspace: repo.workspace,
32772
+ repoRoot: repo.repoRoot,
32773
+ isGitRepo: true,
32774
+ branch: parsed.branch,
32775
+ headCommit: head.commit,
32776
+ headMessage: head.message,
32777
+ upstream: parsed.upstream,
32778
+ ahead: parsed.ahead,
32779
+ behind: parsed.behind,
32780
+ staged: parsed.staged,
32781
+ modified: parsed.modified,
32782
+ untracked: parsed.untracked,
32783
+ deleted: parsed.deleted,
32784
+ renamed: parsed.renamed,
32785
+ hasConflicts: parsed.conflictFiles.length > 0,
32786
+ conflictFiles: parsed.conflictFiles,
32787
+ stashCount,
32788
+ lastCheckedAt
32789
+ };
32790
+ } catch (error48) {
32791
+ if (error48 instanceof GitCommandError) {
32792
+ return emptyStatus(workspace, lastCheckedAt, error48);
32793
+ }
32794
+ return emptyStatus(
32795
+ workspace,
32796
+ lastCheckedAt,
32797
+ new GitCommandError("git_command_failed", "Failed to read Git status", { cause: error48 })
32798
+ );
32799
+ }
32800
+ }
32801
+ function parsePorcelainV2Status(output) {
32802
+ const parsed = {
32803
+ branch: null,
32804
+ upstream: null,
32805
+ ahead: 0,
32806
+ behind: 0,
32807
+ staged: 0,
32808
+ modified: 0,
32809
+ untracked: 0,
32810
+ deleted: 0,
32811
+ renamed: 0,
32812
+ conflictFiles: []
32813
+ };
32814
+ for (const line of output.split("\n")) {
32815
+ if (!line) continue;
32816
+ if (line.startsWith("# branch.head ")) {
32817
+ const branch = line.slice("# branch.head ".length).trim();
32818
+ parsed.branch = branch && branch !== "(detached)" ? branch : null;
32819
+ continue;
32820
+ }
32821
+ if (line.startsWith("# branch.upstream ")) {
32822
+ parsed.upstream = line.slice("# branch.upstream ".length).trim() || null;
32823
+ continue;
32824
+ }
32825
+ if (line.startsWith("# branch.ab ")) {
32826
+ const match = line.match(/\+(-?\d+)\s+-(-?\d+)/);
32827
+ if (match) {
32828
+ parsed.ahead = Number.parseInt(match[1] ?? "0", 10) || 0;
32829
+ parsed.behind = Number.parseInt(match[2] ?? "0", 10) || 0;
32830
+ }
32831
+ continue;
32832
+ }
32833
+ if (line.startsWith("? ")) {
32834
+ parsed.untracked += 1;
32835
+ continue;
32836
+ }
32837
+ if (line.startsWith("u ")) {
32838
+ const fields = line.split(" ");
32839
+ const filePath = fields.slice(10).join(" ");
32840
+ if (filePath) parsed.conflictFiles.push(filePath);
32841
+ continue;
32842
+ }
32843
+ if (line.startsWith("1 ") || line.startsWith("2 ")) {
32844
+ const fields = line.split(" ");
32845
+ const xy = fields[1] ?? "..";
32846
+ const indexStatus = xy[0] ?? ".";
32847
+ const worktreeStatus = xy[1] ?? ".";
32848
+ if (isStagedStatus(indexStatus)) parsed.staged += 1;
32849
+ if (worktreeStatus === "M" || worktreeStatus === "T") parsed.modified += 1;
32850
+ if (indexStatus === "D" || worktreeStatus === "D") parsed.deleted += 1;
32851
+ if (indexStatus === "R" || worktreeStatus === "R") parsed.renamed += 1;
32852
+ if (xy.includes("U")) {
32853
+ const filePath = fields.slice(line.startsWith("2 ") ? 9 : 8).join(" ").split(" ")[0] ?? "";
32854
+ if (filePath) parsed.conflictFiles.push(filePath);
32855
+ }
32856
+ }
32857
+ }
32858
+ parsed.conflictFiles = Array.from(new Set(parsed.conflictFiles));
32859
+ return parsed;
32860
+ }
32861
+ async function readHead(repo, options) {
32862
+ try {
32863
+ const result = await runGit(repo, ["log", "-1", "--pretty=%h%x00%s"], options);
32864
+ const text = result.stdout.trimEnd();
32865
+ if (!text) return { commit: null, message: null };
32866
+ const [commit, ...messageParts] = text.split("\0");
32867
+ return {
32868
+ commit: commit || null,
32869
+ message: messageParts.join("\0") || null
32870
+ };
32871
+ } catch {
32872
+ return { commit: null, message: null };
32873
+ }
32874
+ }
32875
+ async function readStashCount(repo, options) {
32876
+ try {
32877
+ const result = await runGit(repo, ["stash", "list", "--format=%gd"], options);
32878
+ return result.stdout.split("\n").filter((line) => line.trim().length > 0).length;
32879
+ } catch {
32880
+ return 0;
32881
+ }
32882
+ }
32883
+ function isStagedStatus(status) {
32884
+ return status !== "." && status !== "?" && status !== "U";
32885
+ }
32886
+ function emptyStatus(workspace, lastCheckedAt, error48) {
32887
+ return {
32888
+ workspace,
32889
+ repoRoot: null,
32890
+ isGitRepo: false,
32891
+ branch: null,
32892
+ headCommit: null,
32893
+ headMessage: null,
32894
+ upstream: null,
32895
+ ahead: 0,
32896
+ behind: 0,
32897
+ staged: 0,
32898
+ modified: 0,
32899
+ untracked: 0,
32900
+ deleted: 0,
32901
+ renamed: 0,
32902
+ hasConflicts: false,
32903
+ conflictFiles: [],
32904
+ stashCount: 0,
32905
+ lastCheckedAt,
32906
+ error: error48.stderr || error48.message,
32907
+ reason: error48.reason
32908
+ };
32909
+ }
32910
+ var import_promises22 = require("fs/promises");
32911
+ var path23 = __toESM2(require("path"));
32912
+ var DEFAULT_MAX_FILES = 200;
32913
+ var DEFAULT_MAX_BYTES = 2e5;
32914
+ async function getGitDiffSummary(workspace, options = {}) {
32915
+ const lastCheckedAt = Date.now();
32916
+ try {
32917
+ const repo = await resolveGitRepository(workspace, options);
32918
+ const repoRoot = repo.repoRoot;
32919
+ const [unstagedNameStatus, unstagedNumstat, stagedNameStatus, stagedNumstat, untracked] = await Promise.all([
32920
+ runGit(repo, ["diff", "--no-ext-diff", "--name-status"], { ...options, cwd: repoRoot }),
32921
+ runGit(repo, ["diff", "--no-ext-diff", "--numstat"], { ...options, cwd: repoRoot }),
32922
+ runGit(repo, ["diff", "--cached", "--no-ext-diff", "--name-status"], { ...options, cwd: repoRoot }),
32923
+ runGit(repo, ["diff", "--cached", "--no-ext-diff", "--numstat"], { ...options, cwd: repoRoot }),
32924
+ runGit(repo, ["ls-files", "--others", "--exclude-standard"], { ...options, cwd: repoRoot })
32925
+ ]);
32926
+ const outputBytes = byteLength(
32927
+ unstagedNameStatus.stdout + unstagedNumstat.stdout + stagedNameStatus.stdout + stagedNumstat.stdout + untracked.stdout
32928
+ );
32929
+ const changes = [
32930
+ ...combineDiffEntries(unstagedNameStatus.stdout, unstagedNumstat.stdout, false),
32931
+ ...combineDiffEntries(stagedNameStatus.stdout, stagedNumstat.stdout, true),
32932
+ ...parseUntrackedFiles(untracked.stdout)
32933
+ ];
32934
+ const maxFiles = normalizePositiveInteger(options.maxFiles, DEFAULT_MAX_FILES);
32935
+ const maxBytes = normalizePositiveInteger(options.maxBytes, DEFAULT_MAX_BYTES);
32936
+ const files = changes.slice(0, maxFiles);
32937
+ const truncated = changes.length > files.length || outputBytes > maxBytes;
32938
+ return {
32939
+ workspace: repo.workspace,
32940
+ repoRoot,
32941
+ isGitRepo: true,
32942
+ files,
32943
+ totalInsertions: files.reduce((sum, file2) => sum + file2.insertions, 0),
32944
+ totalDeletions: files.reduce((sum, file2) => sum + file2.deletions, 0),
32945
+ truncated,
32946
+ lastCheckedAt
32947
+ };
32948
+ } catch (error48) {
32949
+ const gitError = error48 instanceof GitCommandError ? error48 : new GitCommandError("git_command_failed", "Failed to read Git diff summary", { cause: error48 });
32950
+ return {
32951
+ workspace,
32952
+ repoRoot: null,
32953
+ isGitRepo: false,
32954
+ files: [],
32955
+ totalInsertions: 0,
32956
+ totalDeletions: 0,
32957
+ truncated: false,
32958
+ lastCheckedAt,
32959
+ error: gitError.stderr || gitError.message,
32960
+ reason: gitError.reason
32961
+ };
32962
+ }
32963
+ }
32964
+ async function getGitFileDiff(workspace, filePath, options = {}) {
32965
+ const lastCheckedAt = Date.now();
32966
+ const repo = await resolveGitRepository(workspace, options);
32967
+ const repoRoot = repo.repoRoot;
32968
+ const selected = await resolveRepoFilePath(repoRoot, filePath);
32969
+ const maxBytes = normalizePositiveInteger(options.maxBytes, DEFAULT_MAX_BYTES);
32970
+ const [unstaged, staged] = await Promise.all([
32971
+ runGit(repo, ["diff", "--no-ext-diff", "--", selected.relativePath], { ...options, cwd: repoRoot }),
32972
+ runGit(repo, ["diff", "--cached", "--no-ext-diff", "--", selected.relativePath], { ...options, cwd: repoRoot })
32973
+ ]);
32974
+ let diff = [unstaged.stdout, staged.stdout].filter((part) => part.length > 0).join("\n");
32975
+ if (!diff) {
32976
+ const untracked = await runGit(repo, ["ls-files", "--others", "--exclude-standard", "--", selected.relativePath], {
32977
+ ...options,
32978
+ cwd: repoRoot
32979
+ });
32980
+ const untrackedFiles = untracked.stdout.split("\n").filter(Boolean);
32981
+ if (untrackedFiles.includes(selected.relativePath)) {
32982
+ diff = await buildUntrackedDiff(selected.absolutePath, selected.relativePath, maxBytes + 1);
32983
+ }
32984
+ }
32985
+ const bounded = truncateText(diff, maxBytes);
32986
+ return {
32987
+ workspace: repo.workspace,
32988
+ repoRoot,
32989
+ isGitRepo: true,
32990
+ path: selected.relativePath,
32991
+ diff: bounded.text,
32992
+ truncated: bounded.truncated,
32993
+ lastCheckedAt
32994
+ };
32995
+ }
32996
+ function combineDiffEntries(nameStatusOutput, numstatOutput, staged) {
32997
+ const statusEntries = parseNameStatus(nameStatusOutput);
32998
+ const numstatEntries = parseNumstat(numstatOutput);
32999
+ return statusEntries.map((entry, index) => {
33000
+ const stats = numstatEntries[index];
33001
+ return {
33002
+ path: entry.path,
33003
+ oldPath: entry.oldPath,
33004
+ status: entry.status,
33005
+ staged,
33006
+ insertions: stats?.insertions ?? 0,
33007
+ deletions: stats?.deletions ?? 0,
33008
+ binary: stats?.binary || void 0
33009
+ };
33010
+ });
33011
+ }
33012
+ function parseNameStatus(output) {
33013
+ return output.split("\n").filter(Boolean).map((line) => {
33014
+ const fields = line.split(" ");
33015
+ const code = fields[0] ?? "";
33016
+ const statusLetter = code[0] ?? "M";
33017
+ if (statusLetter === "R") {
33018
+ return {
33019
+ oldPath: fields[1] ?? "",
33020
+ path: fields[2] ?? fields[1] ?? "",
33021
+ status: "renamed"
33022
+ };
33023
+ }
33024
+ if (statusLetter === "C") {
33025
+ return {
33026
+ oldPath: fields[1] ?? "",
33027
+ path: fields[2] ?? fields[1] ?? "",
33028
+ status: "copied"
33029
+ };
33030
+ }
33031
+ return {
33032
+ path: fields[1] ?? "",
33033
+ status: mapNameStatus(statusLetter)
33034
+ };
33035
+ }).filter((entry) => entry.path.length > 0);
33036
+ }
33037
+ function parseNumstat(output) {
33038
+ return output.split("\n").filter(Boolean).map((line) => {
33039
+ const fields = line.split(" ");
33040
+ const insertionsText = fields[0] ?? "0";
33041
+ const deletionsText = fields[1] ?? "0";
33042
+ const binary = insertionsText === "-" || deletionsText === "-";
33043
+ return {
33044
+ path: fields.slice(2).join(" "),
33045
+ insertions: binary ? 0 : Number.parseInt(insertionsText, 10) || 0,
33046
+ deletions: binary ? 0 : Number.parseInt(deletionsText, 10) || 0,
33047
+ binary
33048
+ };
33049
+ });
33050
+ }
33051
+ function parseUntrackedFiles(output) {
33052
+ return output.split("\n").filter(Boolean).map((filePath) => ({
33053
+ path: filePath,
33054
+ status: "untracked",
33055
+ staged: false,
33056
+ insertions: 0,
33057
+ deletions: 0
33058
+ }));
33059
+ }
33060
+ function mapNameStatus(status) {
33061
+ switch (status) {
33062
+ case "A":
33063
+ return "added";
33064
+ case "D":
33065
+ return "deleted";
33066
+ case "R":
33067
+ return "renamed";
33068
+ case "C":
33069
+ return "copied";
33070
+ case "U":
33071
+ return "conflict";
33072
+ case "M":
33073
+ case "T":
33074
+ default:
33075
+ return "modified";
33076
+ }
33077
+ }
33078
+ async function resolveRepoFilePath(repoRoot, filePath) {
33079
+ if (typeof filePath !== "string" || filePath.length === 0 || filePath.includes("\0")) {
33080
+ throw new GitCommandError("invalid_args", "File path must be a non-empty path");
33081
+ }
33082
+ const canonicalRepoRoot = await (0, import_promises22.realpath)(repoRoot).catch(() => path23.resolve(repoRoot));
33083
+ const absolutePath = path23.isAbsolute(filePath) ? path23.resolve(filePath) : path23.resolve(repoRoot, filePath);
33084
+ const checkPath = await (0, import_promises22.realpath)(absolutePath).catch(() => absolutePath);
33085
+ const relativeBase = isPathInside(canonicalRepoRoot, checkPath) ? canonicalRepoRoot : path23.resolve(repoRoot);
33086
+ if (!isPathInside(canonicalRepoRoot, checkPath) && !isPathInside(repoRoot, absolutePath)) {
33087
+ throw new GitCommandError("path_outside_repo", "Selected file path is outside the repository root", {
33088
+ cwd: repoRoot
33089
+ });
33090
+ }
33091
+ const relativePath = path23.relative(relativeBase, checkPath).split(path23.sep).join("/");
33092
+ if (!relativePath || relativePath.startsWith("..") || path23.isAbsolute(relativePath)) {
33093
+ throw new GitCommandError("path_outside_repo", "Selected file path is outside the repository root", {
33094
+ cwd: repoRoot
33095
+ });
33096
+ }
33097
+ return { absolutePath, relativePath };
33098
+ }
33099
+ async function buildUntrackedDiff(absolutePath, relativePath, readLimit) {
33100
+ const content = await (0, import_promises22.readFile)(absolutePath, "utf8");
33101
+ const limitedContent = content.length > readLimit ? content.slice(0, readLimit) : content;
33102
+ const lines = limitedContent.length > 0 ? limitedContent.split("\n") : [];
33103
+ const plusLines = lines.filter((line, index) => index < lines.length - 1 || line.length > 0).map((line) => `+${line}`).join("\n");
33104
+ const lineCount = plusLines ? plusLines.split("\n").length : 0;
33105
+ return [
33106
+ `diff --git a/${relativePath} b/${relativePath}`,
33107
+ "new file mode 100644",
33108
+ "index 0000000..0000000",
33109
+ "--- /dev/null",
33110
+ `+++ b/${relativePath}`,
33111
+ `@@ -0,0 +1,${lineCount} @@`,
33112
+ plusLines
33113
+ ].filter((line) => line.length > 0).join("\n");
33114
+ }
33115
+ function truncateText(text, maxBytes) {
33116
+ if (byteLength(text) <= maxBytes) return { text, truncated: false };
33117
+ return { text: Buffer.from(text, "utf8").subarray(0, maxBytes).toString("utf8"), truncated: true };
33118
+ }
33119
+ function byteLength(text) {
33120
+ return Buffer.byteLength(text, "utf8");
33121
+ }
33122
+ function normalizePositiveInteger(value, fallback) {
33123
+ if (!Number.isFinite(value) || value == null || value <= 0) return fallback;
33124
+ return Math.floor(value);
33125
+ }
33126
+ function countStatusChangedFiles(status) {
33127
+ const conflictCount = status.conflictFiles.length > 0 ? status.conflictFiles.length : status.hasConflicts ? 1 : 0;
33128
+ return status.staged + status.modified + status.untracked + status.deleted + status.renamed + conflictCount;
33129
+ }
33130
+ function createGitCompactSummary(status, diffSummary) {
33131
+ const statusChangedFiles = countStatusChangedFiles(status);
33132
+ const diffChangedFiles = diffSummary?.files.length ?? 0;
33133
+ const changedFiles = Math.max(statusChangedFiles, diffChangedFiles);
33134
+ const conflictCount = status.conflictFiles.length > 0 ? status.conflictFiles.length : status.hasConflicts ? 1 : 0;
33135
+ return {
33136
+ isGitRepo: status.isGitRepo,
33137
+ repoRoot: status.repoRoot,
33138
+ branch: status.branch,
33139
+ dirty: status.staged > 0 || status.modified > 0 || status.untracked > 0 || status.deleted > 0 || status.renamed > 0 || conflictCount > 0 || changedFiles > 0,
33140
+ changedFiles,
33141
+ ahead: status.ahead,
33142
+ behind: status.behind,
33143
+ hasConflicts: status.hasConflicts || conflictCount > 0,
33144
+ lastCheckedAt: Math.max(status.lastCheckedAt, diffSummary?.lastCheckedAt ?? status.lastCheckedAt),
33145
+ error: status.error ?? diffSummary?.error,
33146
+ reason: status.reason ?? diffSummary?.reason
33147
+ };
33148
+ }
33149
+ var summarizeGitStatus = createGitCompactSummary;
33150
+ function normalizeCapacity(capacity) {
33151
+ return Math.max(1, Math.floor(capacity ?? 100));
33152
+ }
33153
+ function createEmptyDiffSummary(status) {
33154
+ return {
33155
+ workspace: status.workspace,
33156
+ repoRoot: status.repoRoot,
33157
+ isGitRepo: status.isGitRepo,
33158
+ files: [],
33159
+ totalInsertions: 0,
33160
+ totalDeletions: 0,
33161
+ truncated: false,
33162
+ lastCheckedAt: status.lastCheckedAt,
33163
+ error: status.error,
33164
+ reason: status.reason
33165
+ };
33166
+ }
33167
+ function changedFileKey(file2) {
33168
+ return `${file2.oldPath ?? ""}\0${file2.path}`;
33169
+ }
33170
+ function uniqueSorted(values) {
33171
+ return Array.from(new Set(Array.from(values).filter(Boolean))).sort((a, b2) => a.localeCompare(b2));
33172
+ }
33173
+ function plural(count, singular, pluralText = `${singular}s`) {
33174
+ return count === 1 ? singular : pluralText;
33175
+ }
33176
+ function compareGitSnapshots(before, after) {
33177
+ const beforeFileKeys = new Set(before.diffSummary.files.map(changedFileKey));
33178
+ const changedAfterFiles = after.diffSummary.files.filter((file2) => !beforeFileKeys.has(changedFileKey(file2)));
33179
+ const addedFiles = [];
33180
+ const modifiedFiles = [];
33181
+ const deletedFiles = [];
33182
+ const renamedFiles = [];
33183
+ const untrackedFiles = [];
33184
+ const conflictFilesFromDiff = [];
33185
+ let totalInsertions = 0;
33186
+ let totalDeletions = 0;
33187
+ for (const file2 of changedAfterFiles) {
33188
+ totalInsertions += file2.insertions;
33189
+ totalDeletions += file2.deletions;
33190
+ switch (file2.status) {
33191
+ case "added":
33192
+ case "copied":
33193
+ addedFiles.push(file2.path);
33194
+ break;
33195
+ case "modified":
33196
+ modifiedFiles.push(file2.path);
33197
+ break;
33198
+ case "deleted":
33199
+ deletedFiles.push(file2.path);
33200
+ break;
33201
+ case "renamed":
33202
+ renamedFiles.push({ oldPath: file2.oldPath ?? file2.path, path: file2.path });
33203
+ break;
33204
+ case "untracked":
33205
+ untrackedFiles.push(file2.path);
33206
+ break;
33207
+ case "conflict":
33208
+ conflictFilesFromDiff.push(file2.path);
33209
+ break;
33210
+ }
33211
+ }
33212
+ renamedFiles.sort((a, b2) => `${a.oldPath}\0${a.path}`.localeCompare(`${b2.oldPath}\0${b2.path}`));
33213
+ const conflictFiles = uniqueSorted([...after.status.conflictFiles, ...conflictFilesFromDiff]);
33214
+ const changedFiles = changedAfterFiles.length;
33215
+ const hasConflicts = after.status.hasConflicts || conflictFiles.length > 0;
33216
+ const summaryParts = [];
33217
+ if (changedFiles > 0) summaryParts.push(`${changedFiles} ${plural(changedFiles, "file")} changed`);
33218
+ if (addedFiles.length > 0) summaryParts.push(`${addedFiles.length} added`);
33219
+ if (modifiedFiles.length > 0) summaryParts.push(`${modifiedFiles.length} modified`);
33220
+ if (deletedFiles.length > 0) summaryParts.push(`${deletedFiles.length} deleted`);
33221
+ if (renamedFiles.length > 0) summaryParts.push(`${renamedFiles.length} renamed`);
33222
+ if (untrackedFiles.length > 0) summaryParts.push(`${untrackedFiles.length} untracked`);
33223
+ if (hasConflicts) summaryParts.push(`${conflictFiles.length || 1} ${plural(conflictFiles.length || 1, "conflict")}`);
33224
+ return {
33225
+ beforeSnapshotId: before.id,
33226
+ afterSnapshotId: after.id,
33227
+ workspace: after.workspace,
33228
+ repoRoot: after.repoRoot,
33229
+ changedFiles,
33230
+ addedFiles: uniqueSorted(addedFiles),
33231
+ modifiedFiles: uniqueSorted(modifiedFiles),
33232
+ deletedFiles: uniqueSorted(deletedFiles),
33233
+ renamedFiles,
33234
+ untrackedFiles: uniqueSorted(untrackedFiles),
33235
+ conflictFiles,
33236
+ totalInsertions,
33237
+ totalDeletions,
33238
+ hasConflicts,
33239
+ currentStatus: after.status,
33240
+ summaryText: summaryParts.length > 0 ? summaryParts.join(", ") : "No file-set changes between snapshots."
33241
+ };
33242
+ }
33243
+ var InMemoryGitSnapshotStore = class {
33244
+ snapshots = /* @__PURE__ */ new Map();
33245
+ order = [];
33246
+ capacity;
33247
+ now;
33248
+ idPrefix;
33249
+ getStatusProvider;
33250
+ getDiffSummaryProvider;
33251
+ counter = 0;
33252
+ constructor(options = {}) {
33253
+ this.capacity = normalizeCapacity(options.capacity);
33254
+ this.now = options.now ?? Date.now;
33255
+ this.idPrefix = options.idPrefix ?? "git-snapshot";
33256
+ this.getStatusProvider = options.getStatus;
33257
+ this.getDiffSummaryProvider = options.getDiffSummary;
33258
+ }
33259
+ async create(input) {
33260
+ const getStatus = input.getStatus ?? this.getStatusProvider;
33261
+ if (!getStatus) {
33262
+ throw new Error("GitSnapshotStore requires an injected getStatus provider");
33263
+ }
33264
+ const status = await getStatus(input.workspace);
33265
+ const getDiffSummary = input.getDiffSummary ?? this.getDiffSummaryProvider;
33266
+ const diffSummary = getDiffSummary ? await getDiffSummary(input.workspace, status) : createEmptyDiffSummary(status);
33267
+ const createdAt = this.now();
33268
+ const id = `${this.idPrefix}-${createdAt}-${++this.counter}`;
33269
+ const snapshot = {
33270
+ id,
33271
+ workspace: input.workspace,
33272
+ repoRoot: status.repoRoot ?? input.workspace,
33273
+ sessionId: input.sessionId,
33274
+ turnId: input.turnId,
33275
+ reason: input.reason,
33276
+ status,
33277
+ diffSummary,
33278
+ createdAt
33279
+ };
33280
+ this.snapshots.set(id, snapshot);
33281
+ this.order.push(id);
33282
+ this.enforceCapacity();
33283
+ return snapshot;
33284
+ }
33285
+ get(id) {
33286
+ return this.snapshots.get(id);
33287
+ }
33288
+ compare(beforeSnapshotId, afterSnapshotId) {
33289
+ const before = this.snapshots.get(beforeSnapshotId);
33290
+ if (!before) throw new Error(`Unknown before snapshot: ${beforeSnapshotId}`);
33291
+ const after = this.snapshots.get(afterSnapshotId);
33292
+ if (!after) throw new Error(`Unknown after snapshot: ${afterSnapshotId}`);
33293
+ return compareGitSnapshots(before, after);
33294
+ }
33295
+ list(query = {}) {
33296
+ const limit = Math.max(1, Math.floor(query.limit ?? this.capacity));
33297
+ 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);
33298
+ }
33299
+ clear() {
33300
+ this.snapshots.clear();
33301
+ this.order.splice(0, this.order.length);
33302
+ }
33303
+ enforceCapacity() {
33304
+ while (this.order.length > this.capacity) {
33305
+ const evictedId = this.order.shift();
33306
+ if (evictedId) this.snapshots.delete(evictedId);
33307
+ }
33308
+ }
33309
+ };
33310
+ function createGitSnapshotStore(options = {}) {
33311
+ return new InMemoryGitSnapshotStore(options);
33312
+ }
33313
+ var DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS = 5e3;
33314
+ var MIN_GIT_WORKSPACE_POLL_INTERVAL_MS = 1e3;
33315
+ function defaultStatusProvider(workspace) {
33316
+ return getGitRepoStatus(workspace);
33317
+ }
33318
+ function defaultDiffSummaryProvider(workspace) {
33319
+ return getGitDiffSummary(workspace);
33320
+ }
33321
+ function normalizeIntervalMs(value, defaultIntervalMs, minIntervalMs) {
33322
+ const requested = Number.isFinite(value) ? Math.floor(value) : defaultIntervalMs;
33323
+ return Math.max(minIntervalMs, requested > 0 ? requested : defaultIntervalMs);
33324
+ }
33325
+ function normalizeGitWorkspaceSubscriptionParams2(params, options = {}) {
33326
+ const minIntervalMs = Math.max(1, Math.floor(options.minIntervalMs ?? MIN_GIT_WORKSPACE_POLL_INTERVAL_MS));
33327
+ const defaultIntervalMs = Math.max(minIntervalMs, Math.floor(options.defaultIntervalMs ?? DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS));
33328
+ return {
33329
+ workspace: params.workspace,
33330
+ includeDiffSummary: Boolean(params.includeDiffSummary),
33331
+ intervalMs: normalizeIntervalMs(params.intervalMs, defaultIntervalMs, minIntervalMs)
33332
+ };
33333
+ }
33334
+ var GitWorkspaceMonitor = class {
33335
+ getStatusProvider;
33336
+ getDiffSummaryProvider;
33337
+ now;
33338
+ minIntervalMs;
33339
+ defaultIntervalMs;
33340
+ keyPrefix;
33341
+ cache = /* @__PURE__ */ new Map();
33342
+ listeners = /* @__PURE__ */ new Set();
33343
+ seq = 0;
33344
+ constructor(options = {}) {
33345
+ this.getStatusProvider = options.getStatus ?? defaultStatusProvider;
33346
+ this.getDiffSummaryProvider = options.getDiffSummary ?? defaultDiffSummaryProvider;
33347
+ this.now = options.now ?? Date.now;
33348
+ this.minIntervalMs = Math.max(1, Math.floor(options.minIntervalMs ?? MIN_GIT_WORKSPACE_POLL_INTERVAL_MS));
33349
+ this.defaultIntervalMs = Math.max(
33350
+ this.minIntervalMs,
33351
+ Math.floor(options.defaultIntervalMs ?? DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS)
33352
+ );
33353
+ this.keyPrefix = options.keyPrefix ?? "git";
33354
+ }
33355
+ async refresh(params) {
33356
+ const normalized = this.normalize(typeof params === "string" ? { workspace: params } : params);
33357
+ const status = await this.getStatusProvider(normalized.workspace);
33358
+ const diffSummary = normalized.includeDiffSummary ? await this.getDiffSummaryProvider(normalized.workspace, status) : void 0;
33359
+ const compactSummary = createGitCompactSummary(status, diffSummary);
33360
+ const timestamp = this.now();
33361
+ const seq = ++this.seq;
33362
+ const key = this.keyForWorkspace(normalized.workspace);
33363
+ const update = {
33364
+ topic: "workspace.git",
33365
+ key,
33366
+ workspace: normalized.workspace,
33367
+ status,
33368
+ diffSummary,
33369
+ seq,
33370
+ timestamp
33371
+ };
33372
+ const cacheEntry = {
33373
+ key,
33374
+ workspace: normalized.workspace,
33375
+ status,
33376
+ diffSummary,
33377
+ compactSummary,
33378
+ seq,
33379
+ timestamp
33380
+ };
33381
+ this.cache.set(normalized.workspace, cacheEntry);
33382
+ this.emit(update, cacheEntry);
33383
+ return update;
33384
+ }
33385
+ poll(params) {
33386
+ return this.refresh(params);
33387
+ }
33388
+ getCached(workspace) {
33389
+ return this.cache.get(workspace);
33390
+ }
33391
+ getCompactSummary(workspace) {
33392
+ return this.cache.get(workspace)?.compactSummary;
33393
+ }
33394
+ onUpdate(listener) {
33395
+ this.listeners.add(listener);
33396
+ return () => {
33397
+ this.listeners.delete(listener);
33398
+ };
33399
+ }
33400
+ createSubscription(params, listener) {
33401
+ const normalized = this.normalize(params);
33402
+ const scopedListener = listener ? (update, cacheEntry) => {
33403
+ if (update.workspace === normalized.workspace) listener(update, cacheEntry);
33404
+ } : void 0;
33405
+ const unsubscribe = scopedListener ? this.onUpdate(scopedListener) : () => void 0;
33406
+ return {
33407
+ params: normalized,
33408
+ refresh: () => this.refresh(normalized),
33409
+ getCached: () => this.getCached(normalized.workspace),
33410
+ dispose: unsubscribe
33411
+ };
33412
+ }
33413
+ normalize(params) {
33414
+ return normalizeGitWorkspaceSubscriptionParams2(params, {
33415
+ defaultIntervalMs: this.defaultIntervalMs,
33416
+ minIntervalMs: this.minIntervalMs
33417
+ });
33418
+ }
33419
+ keyForWorkspace(workspace) {
33420
+ return `${this.keyPrefix}:${workspace}`;
33421
+ }
33422
+ emit(update, cacheEntry) {
33423
+ for (const listener of this.listeners) {
33424
+ listener(update, cacheEntry);
33425
+ }
33426
+ }
33427
+ };
33428
+ function createGitWorkspaceMonitor2(options = {}) {
33429
+ return new GitWorkspaceMonitor(options);
33430
+ }
33431
+ var path32 = __toESM2(require("path"));
33432
+ var GIT_COMMAND_NAMES = /* @__PURE__ */ new Set([
33433
+ "git_status",
33434
+ "git_diff_summary",
33435
+ "git_diff_file",
33436
+ "git_snapshot_create",
33437
+ "git_snapshot_compare",
33438
+ "git_log",
33439
+ "git_checkpoint",
33440
+ "git_stash_push",
33441
+ "git_stash_pop",
33442
+ "git_checkout_files"
33443
+ ]);
33444
+ var MUTATING_COMMAND_NAMES = /* @__PURE__ */ new Set([
33445
+ "git_checkpoint",
33446
+ "git_stash_push",
33447
+ "git_stash_pop",
33448
+ "git_checkout_files"
33449
+ ]);
33450
+ var SNAPSHOT_REASONS = /* @__PURE__ */ new Set([
33451
+ "session_baseline",
33452
+ "before_user_input_dispatch",
33453
+ "before_agent_work",
33454
+ "after_agent_work",
33455
+ "manual"
33456
+ ]);
33457
+ var FAILURE_REASONS = /* @__PURE__ */ new Set([
33458
+ "not_git_repo",
33459
+ "git_not_installed",
33460
+ "timeout",
33461
+ "path_outside_repo",
33462
+ "dirty_index_required",
33463
+ "conflict",
33464
+ "invalid_args",
33465
+ "git_command_failed"
33466
+ ]);
33467
+ function failure(reason, error48) {
33468
+ return { success: false, reason, error: error48 };
33469
+ }
33470
+ function serviceNotImplemented(command) {
33471
+ return failure("invalid_args", `${command} is not implemented: daemon-core Git service is not configured`);
33472
+ }
33473
+ var defaultSnapshotStore = createGitSnapshotStore({
33474
+ getStatus: (workspace) => getGitRepoStatus(workspace),
33475
+ getDiffSummary: (workspace) => getGitDiffSummary(workspace)
33476
+ });
33477
+ function createDefaultGitCommandServices() {
33478
+ return {
33479
+ getStatus: ({ workspace }) => getGitRepoStatus(workspace),
33480
+ getDiffSummary: ({ workspace }) => getGitDiffSummary(workspace),
33481
+ getDiffFile: ({ workspace, path: filePath }) => getGitFileDiff(workspace, filePath),
33482
+ createSnapshot: ({ workspace, reason, sessionId, turnId }) => defaultSnapshotStore.create({
33483
+ workspace,
33484
+ reason,
33485
+ sessionId,
33486
+ turnId
33487
+ }),
33488
+ compareSnapshots: ({ beforeSnapshotId, afterSnapshotId }) => defaultSnapshotStore.compare(beforeSnapshotId, afterSnapshotId),
33489
+ getLog: ({ workspace, limit, path: filePath, since, until }) => getGitLog(workspace, { limit, path: filePath, since, until })
33490
+ };
33491
+ }
33492
+ var defaultGitCommandServices = createDefaultGitCommandServices();
33493
+ function validateWorkspace2(args) {
33494
+ if (typeof args?.workspace !== "string") {
33495
+ return failure("invalid_args", "workspace must be a non-empty absolute path");
33496
+ }
33497
+ const workspace = args.workspace.trim();
33498
+ if (!workspace || !path32.isAbsolute(workspace)) {
33499
+ return failure("invalid_args", "workspace must be a non-empty absolute path");
33500
+ }
33501
+ return { workspace };
33502
+ }
33503
+ function validateRepoPath(args) {
33504
+ if (typeof args?.path !== "string" || !args.path.trim()) {
33505
+ return failure("invalid_args", "path must be a non-empty repository-relative path");
33506
+ }
33507
+ return { path: args.path.trim() };
33508
+ }
33509
+ function validateSnapshotId(args, key) {
33510
+ if (typeof args?.[key] !== "string" || !args[key].trim()) {
33511
+ return failure("invalid_args", `${key} must be a non-empty string`);
33512
+ }
33513
+ return args[key].trim();
33514
+ }
33515
+ function parseSnapshotReason(args) {
33516
+ if (args?.reason === void 0 || args?.reason === null || args?.reason === "") {
33517
+ return "manual";
33518
+ }
33519
+ if (typeof args.reason !== "string" || !SNAPSHOT_REASONS.has(args.reason)) {
33520
+ return failure("invalid_args", "reason must be a valid GitSnapshotReason");
33521
+ }
33522
+ return args.reason;
33523
+ }
33524
+ function optionalString(value) {
33525
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
33526
+ }
33527
+ function optionalBoolean(value) {
33528
+ return typeof value === "boolean" ? value : void 0;
33529
+ }
33530
+ function boundedLogLimit(value) {
33531
+ if (value === void 0 || value === null || value === "") return 50;
33532
+ const numeric = typeof value === "number" ? value : Number(value);
33533
+ if (!Number.isFinite(numeric)) return 50;
33534
+ return Math.max(1, Math.min(200, Math.floor(numeric)));
33535
+ }
33536
+ function failureReasonFromError(error48) {
33537
+ return typeof error48?.reason === "string" && FAILURE_REASONS.has(error48.reason) ? error48.reason : "git_command_failed";
33538
+ }
33539
+ async function runService(fn2) {
33540
+ try {
33541
+ return await fn2();
33542
+ } catch (error48) {
33543
+ return failure(failureReasonFromError(error48), error48?.message || "Git command failed");
33544
+ }
33545
+ }
33546
+ function isGitCommandName(command) {
33547
+ return GIT_COMMAND_NAMES.has(command);
33548
+ }
33549
+ async function handleGitCommand(command, args, services = defaultGitCommandServices) {
33550
+ if (!isGitCommandName(command)) {
33551
+ return failure("invalid_args", `Unknown Git command: ${command}`);
33552
+ }
33553
+ if (MUTATING_COMMAND_NAMES.has(command)) {
33554
+ return failure("invalid_args", `${command} is not implemented in daemon-core read-only Git routing`);
33555
+ }
33556
+ const workspaceResult = validateWorkspace2(args);
33557
+ if ("success" in workspaceResult) return workspaceResult;
33558
+ const { workspace } = workspaceResult;
33559
+ switch (command) {
33560
+ case "git_status": {
33561
+ if (!services.getStatus) return serviceNotImplemented(command);
33562
+ const status = await runService(() => services.getStatus({ workspace }));
33563
+ return "success" in status ? status : { success: true, status };
33564
+ }
33565
+ case "git_diff_summary": {
33566
+ if (!services.getDiffSummary) return serviceNotImplemented(command);
33567
+ const diffSummary = await runService(() => services.getDiffSummary({ workspace, staged: optionalBoolean(args?.staged) }));
33568
+ return "success" in diffSummary ? diffSummary : { success: true, diffSummary };
33569
+ }
33570
+ case "git_diff_file": {
33571
+ if (!services.getDiffFile) return serviceNotImplemented(command);
33572
+ const pathResult = validateRepoPath(args);
33573
+ if (typeof pathResult !== "object" || "success" in pathResult) return pathResult;
33574
+ const diff = await runService(() => services.getDiffFile({
33575
+ workspace,
33576
+ path: pathResult.path,
33577
+ staged: optionalBoolean(args?.staged)
33578
+ }));
33579
+ return "success" in diff ? diff : { success: true, diff };
33580
+ }
33581
+ case "git_snapshot_create": {
33582
+ if (!services.createSnapshot) return serviceNotImplemented(command);
33583
+ const reason = parseSnapshotReason(args);
33584
+ if (typeof reason !== "string") return reason;
33585
+ const snapshot = await runService(() => services.createSnapshot({
33586
+ workspace,
33587
+ reason,
33588
+ sessionId: optionalString(args?.sessionId),
33589
+ turnId: optionalString(args?.turnId)
33590
+ }));
33591
+ return "success" in snapshot ? snapshot : { success: true, snapshot };
33592
+ }
33593
+ case "git_snapshot_compare": {
33594
+ if (!services.compareSnapshots) return serviceNotImplemented(command);
33595
+ const beforeSnapshotId = validateSnapshotId(args, "beforeSnapshotId");
33596
+ if (typeof beforeSnapshotId !== "string") return beforeSnapshotId;
33597
+ const afterSnapshotId = validateSnapshotId(args, "afterSnapshotId");
33598
+ if (typeof afterSnapshotId !== "string") return afterSnapshotId;
33599
+ const compare = await runService(() => services.compareSnapshots({ workspace, beforeSnapshotId, afterSnapshotId }));
33600
+ return "success" in compare ? compare : { success: true, compare };
33601
+ }
33602
+ case "git_log": {
33603
+ if (!services.getLog) {
33604
+ return failure("invalid_args", "git_log is not implemented: bounded daemon-core Git log service is not configured");
33605
+ }
33606
+ const log = await runService(() => services.getLog({
33607
+ workspace,
33608
+ limit: boundedLogLimit(args?.limit),
33609
+ path: optionalString(args?.path),
33610
+ since: optionalString(args?.since),
33611
+ until: optionalString(args?.until)
33612
+ }));
33613
+ return "success" in log ? log : { success: true, log };
33614
+ }
33615
+ default:
33616
+ return failure("invalid_args", `Unknown Git command: ${command}`);
33617
+ }
33618
+ }
33619
+ function formatOptionalGitLogRangeArg(flag, value) {
33620
+ return value ? [`${flag}=${value}`] : [];
33621
+ }
33622
+ async function getGitLog(workspace, options) {
33623
+ const lastCheckedAt = Date.now();
33624
+ const repo = await resolveGitRepository(workspace);
33625
+ const repoRoot = repo.repoRoot;
33626
+ const boundedLimit = Math.max(1, Math.min(200, Math.floor(options.limit || 50)));
33627
+ const selectedPath = options.path ? validateGitLogPath(repoRoot, options.path) : void 0;
33628
+ const result = await runGit(
33629
+ repo,
33630
+ [
33631
+ "log",
33632
+ `--max-count=${boundedLimit}`,
33633
+ "--format=%H%x00%an%x00%ae%x00%at%x00%ct%x00%s",
33634
+ ...formatOptionalGitLogRangeArg("--since", options.since),
33635
+ ...formatOptionalGitLogRangeArg("--until", options.until),
33636
+ "--",
33637
+ ...selectedPath ? [selectedPath] : []
33638
+ ],
33639
+ { cwd: repoRoot }
33640
+ );
33641
+ const entries = result.stdout.split("\n").filter((line) => line.trim().length > 0).map((line) => {
33642
+ const [commit = "", authorName, authorEmail, authoredAt, committedAt, ...messageParts] = line.split("\0");
33643
+ return {
33644
+ commit,
33645
+ message: messageParts.join("\0"),
33646
+ authorName: authorName || void 0,
33647
+ authorEmail: authorEmail || void 0,
33648
+ authoredAt: authoredAt ? Number.parseInt(authoredAt, 10) * 1e3 : void 0,
33649
+ committedAt: committedAt ? Number.parseInt(committedAt, 10) * 1e3 : void 0
33650
+ };
33651
+ }).filter((entry) => entry.commit.length > 0);
33652
+ return {
33653
+ workspace: repo.workspace,
33654
+ repoRoot,
33655
+ isGitRepo: true,
33656
+ entries,
33657
+ limit: boundedLimit,
33658
+ truncated: entries.length >= boundedLimit,
33659
+ lastCheckedAt
33660
+ };
33661
+ }
33662
+ function validateGitLogPath(repoRoot, filePath) {
33663
+ if (!filePath.trim() || filePath.includes("\0")) {
33664
+ throw new GitCommandError("invalid_args", "path must be a non-empty repository-relative path");
33665
+ }
33666
+ if (path32.isAbsolute(filePath)) {
33667
+ throw new GitCommandError("invalid_args", "path must be repository-relative");
33668
+ }
33669
+ const normalized = path32.normalize(filePath).split(path32.sep).join("/");
33670
+ const absolutePath = path32.resolve(repoRoot, normalized);
33671
+ if (!isPathInside(repoRoot, absolutePath) || normalized.startsWith("../") || normalized === "..") {
33672
+ throw new GitCommandError("path_outside_repo", "Git log path is outside the repository root");
33673
+ }
33674
+ return normalized;
33675
+ }
32551
33676
  init_config();
32552
33677
  var fs5 = __toESM2(require("fs"));
32553
33678
  var os6 = __toESM2(require("os"));
32554
- var path5 = __toESM2(require("path"));
33679
+ var path42 = __toESM2(require("path"));
32555
33680
  var import_crypto22 = require("crypto");
32556
33681
  var MAX_WORKSPACES = 50;
32557
33682
  function expandPath(p) {
32558
33683
  const t = (p || "").trim();
32559
33684
  if (!t) return "";
32560
- if (t.startsWith("~")) return path5.join(os6.homedir(), t.slice(1).replace(/^\//, ""));
32561
- return path5.resolve(t);
33685
+ if (t.startsWith("~")) return path42.join(os6.homedir(), t.slice(1).replace(/^\//, ""));
33686
+ return path42.resolve(t);
32562
33687
  }
32563
33688
  function validateWorkspacePath(absPath) {
32564
33689
  try {
@@ -32572,7 +33697,7 @@ var require_dist2 = __commonJS({
32572
33697
  }
32573
33698
  }
32574
33699
  function defaultWorkspaceLabel(absPath) {
32575
- const base = path5.basename(absPath) || absPath;
33700
+ const base = path42.basename(absPath) || absPath;
32576
33701
  return base;
32577
33702
  }
32578
33703
  function getDefaultWorkspacePath(config2) {
@@ -32663,9 +33788,9 @@ var require_dist2 = __commonJS({
32663
33788
  return getDefaultWorkspacePath(config2) || void 0;
32664
33789
  }
32665
33790
  function findWorkspaceByPath(config2, rawPath) {
32666
- const abs = path5.resolve(expandPath(rawPath));
33791
+ const abs = path42.resolve(expandPath(rawPath));
32667
33792
  if (!abs) return void 0;
32668
- return (config2.workspaces || []).find((w) => path5.resolve(expandPath(w.path)) === abs);
33793
+ return (config2.workspaces || []).find((w) => path42.resolve(expandPath(w.path)) === abs);
32669
33794
  }
32670
33795
  function addWorkspaceEntry(config2, rawPath, label, options) {
32671
33796
  const abs = expandPath(rawPath);
@@ -32681,7 +33806,7 @@ var require_dist2 = __commonJS({
32681
33806
  const v2 = validateWorkspacePath(abs);
32682
33807
  if (!v2.ok) return { error: v2.error };
32683
33808
  const list = [...config2.workspaces || []];
32684
- if (list.some((w) => path5.resolve(w.path) === abs)) {
33809
+ if (list.some((w) => path42.resolve(w.path) === abs)) {
32685
33810
  return { error: "Workspace already in list" };
32686
33811
  }
32687
33812
  if (list.length >= MAX_WORKSPACES) {
@@ -32713,7 +33838,7 @@ var require_dist2 = __commonJS({
32713
33838
  if (validateWorkspacePath(abs).ok !== true) return { error: "Workspace path is no longer valid" };
32714
33839
  return { config: { ...config2, defaultWorkspaceId: id } };
32715
33840
  }
32716
- var path23 = __toESM2(require("path"));
33841
+ var path52 = __toESM2(require("path"));
32717
33842
  function normalizeSummaryItem(item) {
32718
33843
  if (!item || typeof item !== "object") return null;
32719
33844
  const id = String(item.id || "").trim();
@@ -32778,9 +33903,9 @@ var require_dist2 = __commonJS({
32778
33903
  function normalizeWorkspace(workspace) {
32779
33904
  if (!workspace) return "";
32780
33905
  try {
32781
- return path23.resolve(expandPath(workspace));
33906
+ return path52.resolve(expandPath(workspace));
32782
33907
  } catch {
32783
- return path23.resolve(workspace);
33908
+ return path52.resolve(workspace);
32784
33909
  }
32785
33910
  }
32786
33911
  function buildRecentActivityKey(entry) {
@@ -32946,14 +34071,14 @@ var require_dist2 = __commonJS({
32946
34071
  sessionNotificationUnreadOverrides: nextSessionNotificationUnreadOverrides
32947
34072
  };
32948
34073
  }
32949
- var path32 = __toESM2(require("path"));
34074
+ var path6 = __toESM2(require("path"));
32950
34075
  var MAX_SAVED_SESSIONS = 500;
32951
34076
  function normalizeWorkspace2(workspace) {
32952
34077
  if (!workspace) return "";
32953
34078
  try {
32954
- return path32.resolve(expandPath(workspace));
34079
+ return path6.resolve(expandPath(workspace));
32955
34080
  } catch {
32956
- return path32.resolve(workspace);
34081
+ return path6.resolve(workspace);
32957
34082
  }
32958
34083
  }
32959
34084
  function buildSavedProviderSessionKey(providerSessionId) {
@@ -33068,7 +34193,7 @@ var require_dist2 = __commonJS({
33068
34193
  var import_child_process = require("child_process");
33069
34194
  var import_fs3 = require("fs");
33070
34195
  var import_os22 = require("os");
33071
- var path42 = __toESM2(require("path"));
34196
+ var path7 = __toESM2(require("path"));
33072
34197
  var BUILTIN_IDE_DEFINITIONS = [];
33073
34198
  var registeredIDEs = /* @__PURE__ */ new Map();
33074
34199
  function registerIDEDefinition(def) {
@@ -33087,9 +34212,9 @@ var require_dist2 = __commonJS({
33087
34212
  function findCliCommand(command) {
33088
34213
  const trimmed = String(command || "").trim();
33089
34214
  if (!trimmed) return null;
33090
- if (path42.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
33091
- const candidate = trimmed.startsWith("~") ? path42.join((0, import_os22.homedir)(), trimmed.slice(1)) : trimmed;
33092
- const resolved = path42.isAbsolute(candidate) ? candidate : path42.resolve(candidate);
34215
+ if (path7.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
34216
+ const candidate = trimmed.startsWith("~") ? path7.join((0, import_os22.homedir)(), trimmed.slice(1)) : trimmed;
34217
+ const resolved = path7.isAbsolute(candidate) ? candidate : path7.resolve(candidate);
33093
34218
  return (0, import_fs3.existsSync)(resolved) ? resolved : null;
33094
34219
  }
33095
34220
  try {
@@ -33117,7 +34242,7 @@ var require_dist2 = __commonJS({
33117
34242
  function checkPathExists(paths) {
33118
34243
  const home = (0, import_os22.homedir)();
33119
34244
  for (const p of paths) {
33120
- const normalized = p.startsWith("~") ? path42.join(home, p.slice(1)) : p;
34245
+ const normalized = p.startsWith("~") ? path7.join(home, p.slice(1)) : p;
33121
34246
  if (normalized.includes("*")) {
33122
34247
  const username = home.split(/[\\/]/).pop() || "";
33123
34248
  const resolved = normalized.replace("*", username);
@@ -33173,7 +34298,7 @@ var require_dist2 = __commonJS({
33173
34298
  }
33174
34299
  var import_child_process2 = require("child_process");
33175
34300
  var os22 = __toESM2(require("os"));
33176
- var path52 = __toESM2(require("path"));
34301
+ var path8 = __toESM2(require("path"));
33177
34302
  var import_fs4 = require("fs");
33178
34303
  function parseVersion(raw) {
33179
34304
  const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
@@ -33186,36 +34311,36 @@ var require_dist2 = __commonJS({
33186
34311
  function expandHome(value) {
33187
34312
  const trimmed = value.trim();
33188
34313
  if (!trimmed.startsWith("~")) return trimmed;
33189
- return path52.join(os22.homedir(), trimmed.slice(1));
34314
+ return path8.join(os22.homedir(), trimmed.slice(1));
33190
34315
  }
33191
34316
  function isExplicitCommandPath(command) {
33192
34317
  const trimmed = command.trim();
33193
- return path52.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
34318
+ return path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
33194
34319
  }
33195
34320
  function resolveCommandPath(command) {
33196
34321
  const trimmed = command.trim();
33197
34322
  if (!trimmed) return null;
33198
34323
  if (isExplicitCommandPath(trimmed)) {
33199
34324
  const expanded = expandHome(trimmed);
33200
- const candidate = path52.isAbsolute(expanded) ? expanded : path52.resolve(expanded);
34325
+ const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
33201
34326
  return (0, import_fs4.existsSync)(candidate) ? candidate : null;
33202
34327
  }
33203
34328
  return null;
33204
34329
  }
33205
34330
  function execAsync(cmd, timeoutMs = 5e3) {
33206
- return new Promise((resolve12) => {
34331
+ return new Promise((resolve15) => {
33207
34332
  const child = (0, import_child_process2.exec)(cmd, {
33208
34333
  encoding: "utf-8",
33209
34334
  timeout: timeoutMs,
33210
34335
  ...process.platform === "win32" ? { windowsHide: true } : {}
33211
34336
  }, (err, stdout) => {
33212
34337
  if (err || !stdout?.trim()) {
33213
- resolve12(null);
34338
+ resolve15(null);
33214
34339
  } else {
33215
- resolve12(stdout.trim());
34340
+ resolve15(stdout.trim());
33216
34341
  }
33217
34342
  });
33218
- child.on("error", () => resolve12(null));
34343
+ child.on("error", () => resolve15(null));
33219
34344
  });
33220
34345
  }
33221
34346
  async function detectCLIs(providerLoader, options) {
@@ -33572,7 +34697,7 @@ var require_dist2 = __commonJS({
33572
34697
  * Returns multiple entries if multiple IDE windows are open on same port
33573
34698
  */
33574
34699
  static listAllTargets(port) {
33575
- return new Promise((resolve12) => {
34700
+ return new Promise((resolve15) => {
33576
34701
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
33577
34702
  let data = "";
33578
34703
  res.on("data", (chunk) => data += chunk.toString());
@@ -33588,16 +34713,16 @@ var require_dist2 = __commonJS({
33588
34713
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
33589
34714
  );
33590
34715
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
33591
- resolve12(mainPages.length > 0 ? mainPages : fallbackPages);
34716
+ resolve15(mainPages.length > 0 ? mainPages : fallbackPages);
33592
34717
  } catch {
33593
- resolve12([]);
34718
+ resolve15([]);
33594
34719
  }
33595
34720
  });
33596
34721
  });
33597
- req.on("error", () => resolve12([]));
34722
+ req.on("error", () => resolve15([]));
33598
34723
  req.setTimeout(2e3, () => {
33599
34724
  req.destroy();
33600
- resolve12([]);
34725
+ resolve15([]);
33601
34726
  });
33602
34727
  });
33603
34728
  }
@@ -33637,7 +34762,7 @@ var require_dist2 = __commonJS({
33637
34762
  }
33638
34763
  }
33639
34764
  findTargetOnPort(port) {
33640
- return new Promise((resolve12) => {
34765
+ return new Promise((resolve15) => {
33641
34766
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
33642
34767
  let data = "";
33643
34768
  res.on("data", (chunk) => data += chunk.toString());
@@ -33648,7 +34773,7 @@ var require_dist2 = __commonJS({
33648
34773
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
33649
34774
  );
33650
34775
  if (pages.length === 0) {
33651
- resolve12(targets.find((t) => t.webSocketDebuggerUrl) || null);
34776
+ resolve15(targets.find((t) => t.webSocketDebuggerUrl) || null);
33652
34777
  return;
33653
34778
  }
33654
34779
  const titleFilteredPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -33667,25 +34792,25 @@ var require_dist2 = __commonJS({
33667
34792
  this._targetId = selected.target.id;
33668
34793
  }
33669
34794
  this._pageTitle = selected.target.title || "";
33670
- resolve12(selected.target);
34795
+ resolve15(selected.target);
33671
34796
  return;
33672
34797
  }
33673
34798
  if (previousTargetId) {
33674
34799
  this.log(`[CDP] Target ${previousTargetId} not found in page list`);
33675
- resolve12(null);
34800
+ resolve15(null);
33676
34801
  return;
33677
34802
  }
33678
34803
  this._pageTitle = list[0]?.title || "";
33679
- resolve12(list[0]);
34804
+ resolve15(list[0]);
33680
34805
  } catch {
33681
- resolve12(null);
34806
+ resolve15(null);
33682
34807
  }
33683
34808
  });
33684
34809
  });
33685
- req.on("error", () => resolve12(null));
34810
+ req.on("error", () => resolve15(null));
33686
34811
  req.setTimeout(2e3, () => {
33687
34812
  req.destroy();
33688
- resolve12(null);
34813
+ resolve15(null);
33689
34814
  });
33690
34815
  });
33691
34816
  }
@@ -33696,7 +34821,7 @@ var require_dist2 = __commonJS({
33696
34821
  this.extensionProviders = providers;
33697
34822
  }
33698
34823
  connectToTarget(wsUrl) {
33699
- return new Promise((resolve12) => {
34824
+ return new Promise((resolve15) => {
33700
34825
  this.ws = new import_ws2.default(wsUrl);
33701
34826
  this.ws.on("open", async () => {
33702
34827
  this._connected = true;
@@ -33706,17 +34831,17 @@ var require_dist2 = __commonJS({
33706
34831
  }
33707
34832
  this.connectBrowserWs().catch(() => {
33708
34833
  });
33709
- resolve12(true);
34834
+ resolve15(true);
33710
34835
  });
33711
34836
  this.ws.on("message", (data) => {
33712
34837
  try {
33713
34838
  const msg = JSON.parse(data.toString());
33714
34839
  if (msg.id && this.pending.has(msg.id)) {
33715
- const { resolve: resolve13, reject } = this.pending.get(msg.id);
34840
+ const { resolve: resolve16, reject } = this.pending.get(msg.id);
33716
34841
  this.pending.delete(msg.id);
33717
34842
  this.failureCount = 0;
33718
34843
  if (msg.error) reject(new Error(msg.error.message));
33719
- else resolve13(msg.result);
34844
+ else resolve16(msg.result);
33720
34845
  } else if (msg.method === "Runtime.executionContextCreated") {
33721
34846
  this.contexts.add(msg.params.context.id);
33722
34847
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -33739,7 +34864,7 @@ var require_dist2 = __commonJS({
33739
34864
  this.ws.on("error", (err) => {
33740
34865
  this.log(`[CDP] WebSocket error: ${err.message}`);
33741
34866
  this._connected = false;
33742
- resolve12(false);
34867
+ resolve15(false);
33743
34868
  });
33744
34869
  });
33745
34870
  }
@@ -33753,7 +34878,7 @@ var require_dist2 = __commonJS({
33753
34878
  return;
33754
34879
  }
33755
34880
  this.log(`[CDP] Connecting browser WS for target discovery...`);
33756
- await new Promise((resolve12, reject) => {
34881
+ await new Promise((resolve15, reject) => {
33757
34882
  this.browserWs = new import_ws2.default(browserWsUrl);
33758
34883
  this.browserWs.on("open", async () => {
33759
34884
  this._browserConnected = true;
@@ -33763,16 +34888,16 @@ var require_dist2 = __commonJS({
33763
34888
  } catch (e) {
33764
34889
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
33765
34890
  }
33766
- resolve12();
34891
+ resolve15();
33767
34892
  });
33768
34893
  this.browserWs.on("message", (data) => {
33769
34894
  try {
33770
34895
  const msg = JSON.parse(data.toString());
33771
34896
  if (msg.id && this.browserPending.has(msg.id)) {
33772
- const { resolve: resolve13, reject: reject2 } = this.browserPending.get(msg.id);
34897
+ const { resolve: resolve16, reject: reject2 } = this.browserPending.get(msg.id);
33773
34898
  this.browserPending.delete(msg.id);
33774
34899
  if (msg.error) reject2(new Error(msg.error.message));
33775
- else resolve13(msg.result);
34900
+ else resolve16(msg.result);
33776
34901
  }
33777
34902
  } catch {
33778
34903
  }
@@ -33792,31 +34917,31 @@ var require_dist2 = __commonJS({
33792
34917
  }
33793
34918
  }
33794
34919
  getBrowserWsUrl() {
33795
- return new Promise((resolve12) => {
34920
+ return new Promise((resolve15) => {
33796
34921
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
33797
34922
  let data = "";
33798
34923
  res.on("data", (chunk) => data += chunk.toString());
33799
34924
  res.on("end", () => {
33800
34925
  try {
33801
34926
  const info = JSON.parse(data);
33802
- resolve12(info.webSocketDebuggerUrl || null);
34927
+ resolve15(info.webSocketDebuggerUrl || null);
33803
34928
  } catch {
33804
- resolve12(null);
34929
+ resolve15(null);
33805
34930
  }
33806
34931
  });
33807
34932
  });
33808
- req.on("error", () => resolve12(null));
34933
+ req.on("error", () => resolve15(null));
33809
34934
  req.setTimeout(3e3, () => {
33810
34935
  req.destroy();
33811
- resolve12(null);
34936
+ resolve15(null);
33812
34937
  });
33813
34938
  });
33814
34939
  }
33815
34940
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
33816
- return new Promise((resolve12, reject) => {
34941
+ return new Promise((resolve15, reject) => {
33817
34942
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
33818
34943
  const id = this.browserMsgId++;
33819
- this.browserPending.set(id, { resolve: resolve12, reject });
34944
+ this.browserPending.set(id, { resolve: resolve15, reject });
33820
34945
  this.browserWs.send(JSON.stringify({ id, method, params }));
33821
34946
  setTimeout(() => {
33822
34947
  if (this.browserPending.has(id)) {
@@ -33856,11 +34981,11 @@ var require_dist2 = __commonJS({
33856
34981
  }
33857
34982
  // ─── CDP Protocol ────────────────────────────────────────
33858
34983
  sendInternal(method, params = {}, timeoutMs = 15e3) {
33859
- return new Promise((resolve12, reject) => {
34984
+ return new Promise((resolve15, reject) => {
33860
34985
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
33861
34986
  if (this.ws.readyState !== import_ws2.default.OPEN) return reject(new Error("WebSocket not open"));
33862
34987
  const id = this.msgId++;
33863
- this.pending.set(id, { resolve: resolve12, reject });
34988
+ this.pending.set(id, { resolve: resolve15, reject });
33864
34989
  this.ws.send(JSON.stringify({ id, method, params }));
33865
34990
  setTimeout(() => {
33866
34991
  if (this.pending.has(id)) {
@@ -34109,7 +35234,7 @@ var require_dist2 = __commonJS({
34109
35234
  const browserWs = this.browserWs;
34110
35235
  let msgId = this.browserMsgId;
34111
35236
  const sendWs = (method, params = {}, sessionId) => {
34112
- return new Promise((resolve12, reject) => {
35237
+ return new Promise((resolve15, reject) => {
34113
35238
  const mid = msgId++;
34114
35239
  this.browserMsgId = msgId;
34115
35240
  const handler = (raw) => {
@@ -34118,7 +35243,7 @@ var require_dist2 = __commonJS({
34118
35243
  if (msg.id === mid) {
34119
35244
  browserWs.removeListener("message", handler);
34120
35245
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
34121
- else resolve12(msg.result);
35246
+ else resolve15(msg.result);
34122
35247
  }
34123
35248
  } catch {
34124
35249
  }
@@ -34319,14 +35444,14 @@ var require_dist2 = __commonJS({
34319
35444
  if (!ws2 || ws2.readyState !== import_ws2.default.OPEN) {
34320
35445
  throw new Error("CDP not connected");
34321
35446
  }
34322
- return new Promise((resolve12, reject) => {
35447
+ return new Promise((resolve15, reject) => {
34323
35448
  const id = getNextId();
34324
35449
  pendingMap.set(id, {
34325
35450
  resolve: (result) => {
34326
35451
  if (result?.result?.subtype === "error") {
34327
35452
  reject(new Error(result.result.description));
34328
35453
  } else {
34329
- resolve12(result?.result?.value);
35454
+ resolve15(result?.result?.value);
34330
35455
  }
34331
35456
  },
34332
35457
  reject
@@ -34358,10 +35483,10 @@ var require_dist2 = __commonJS({
34358
35483
  throw new Error("CDP not connected");
34359
35484
  }
34360
35485
  const sendViaSession = (method, params = {}) => {
34361
- return new Promise((resolve12, reject) => {
35486
+ return new Promise((resolve15, reject) => {
34362
35487
  const pendingMap = this._browserConnected ? this.browserPending : this.pending;
34363
35488
  const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
34364
- pendingMap.set(id, { resolve: resolve12, reject });
35489
+ pendingMap.set(id, { resolve: resolve15, reject });
34365
35490
  ws2.send(JSON.stringify({ id, sessionId, method, params }));
34366
35491
  setTimeout(() => {
34367
35492
  if (pendingMap.has(id)) {
@@ -35095,10 +36220,10 @@ ${cleanBody}`;
35095
36220
  return cleanTitle || cleanBody;
35096
36221
  }
35097
36222
  var fs32 = __toESM2(require("fs"));
35098
- var path7 = __toESM2(require("path"));
36223
+ var path10 = __toESM2(require("path"));
35099
36224
  var os52 = __toESM2(require("os"));
35100
36225
  init_chat_message_normalization();
35101
- var HISTORY_DIR = path7.join(os52.homedir(), ".adhdev", "history");
36226
+ var HISTORY_DIR = path10.join(os52.homedir(), ".adhdev", "history");
35102
36227
  var RETAIN_DAYS = 30;
35103
36228
  var SAVED_HISTORY_INDEX_VERSION = 1;
35104
36229
  var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
@@ -35261,8 +36386,8 @@ ${cleanBody}`;
35261
36386
  function buildSavedHistoryFileSignatureMap(dir, files) {
35262
36387
  return new Map(files.map((file2) => {
35263
36388
  try {
35264
- const stat4 = fs32.statSync(path7.join(dir, file2));
35265
- return [file2, `${file2}:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`];
36389
+ const stat22 = fs32.statSync(path10.join(dir, file2));
36390
+ return [file2, `${file2}:${stat22.size}:${Math.trunc(stat22.mtimeMs)}`];
35266
36391
  } catch {
35267
36392
  return [file2, `${file2}:missing`];
35268
36393
  }
@@ -35272,7 +36397,7 @@ ${cleanBody}`;
35272
36397
  return files.map((file2) => fileSignatures.get(file2) || `${file2}:missing`).join("|");
35273
36398
  }
35274
36399
  function getSavedHistoryIndexFilePath(dir) {
35275
- return path7.join(dir, SAVED_HISTORY_INDEX_FILE);
36400
+ return path10.join(dir, SAVED_HISTORY_INDEX_FILE);
35276
36401
  }
35277
36402
  function getSavedHistoryIndexLockPath(dir) {
35278
36403
  return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
@@ -35325,8 +36450,8 @@ ${cleanBody}`;
35325
36450
  } catch (error48) {
35326
36451
  if (error48?.code !== "EEXIST") return null;
35327
36452
  try {
35328
- const stat4 = fs32.statSync(lockPath);
35329
- if (Date.now() - stat4.mtimeMs > SAVED_HISTORY_INDEX_LOCK_STALE_MS) {
36453
+ const stat22 = fs32.statSync(lockPath);
36454
+ if (Date.now() - stat22.mtimeMs > SAVED_HISTORY_INDEX_LOCK_STALE_MS) {
35330
36455
  fs32.rmSync(lockPath, { recursive: true, force: true });
35331
36456
  continue;
35332
36457
  }
@@ -35374,7 +36499,7 @@ ${cleanBody}`;
35374
36499
  }
35375
36500
  for (const file2 of Array.from(currentEntries.keys())) {
35376
36501
  if (incomingFiles.has(file2)) continue;
35377
- if (!fs32.existsSync(path7.join(dir, file2))) {
36502
+ if (!fs32.existsSync(path10.join(dir, file2))) {
35378
36503
  currentEntries.delete(file2);
35379
36504
  }
35380
36505
  }
@@ -35389,8 +36514,8 @@ ${cleanBody}`;
35389
36514
  }
35390
36515
  function buildSavedHistoryIndexFileSignature(dir) {
35391
36516
  try {
35392
- const stat4 = fs32.statSync(getSavedHistoryIndexFilePath(dir));
35393
- return `index:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`;
36517
+ const stat22 = fs32.statSync(getSavedHistoryIndexFilePath(dir));
36518
+ return `index:${stat22.size}:${Math.trunc(stat22.mtimeMs)}`;
35394
36519
  } catch {
35395
36520
  return "index:missing";
35396
36521
  }
@@ -35400,8 +36525,8 @@ ${cleanBody}`;
35400
36525
  const indexStat = fs32.statSync(getSavedHistoryIndexFilePath(dir));
35401
36526
  const files = listHistoryFiles(dir);
35402
36527
  for (const file2 of files) {
35403
- const stat4 = fs32.statSync(path7.join(dir, file2));
35404
- if (stat4.mtimeMs > indexStat.mtimeMs) return true;
36528
+ const stat22 = fs32.statSync(path10.join(dir, file2));
36529
+ if (stat22.mtimeMs > indexStat.mtimeMs) return true;
35405
36530
  }
35406
36531
  return false;
35407
36532
  } catch {
@@ -35410,14 +36535,14 @@ ${cleanBody}`;
35410
36535
  }
35411
36536
  function buildSavedHistoryFileSignature(dir, file2) {
35412
36537
  try {
35413
- const stat4 = fs32.statSync(path7.join(dir, file2));
35414
- return `${file2}:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`;
36538
+ const stat22 = fs32.statSync(path10.join(dir, file2));
36539
+ return `${file2}:${stat22.size}:${Math.trunc(stat22.mtimeMs)}`;
35415
36540
  } catch {
35416
36541
  return `${file2}:missing`;
35417
36542
  }
35418
36543
  }
35419
36544
  function persistSavedHistoryFileSummaryEntry(agentType, dir, file2, updater) {
35420
- const filePath = path7.join(dir, file2);
36545
+ const filePath = path10.join(dir, file2);
35421
36546
  const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
35422
36547
  const currentEntry = entries.get(file2) || null;
35423
36548
  const nextSummary = updater(currentEntry?.summary || null);
@@ -35490,7 +36615,7 @@ ${cleanBody}`;
35490
36615
  function computeSavedHistoryFileSummary(dir, file2) {
35491
36616
  const historySessionId = extractSavedHistorySessionIdFromFile(file2);
35492
36617
  if (!historySessionId) return null;
35493
- const filePath = path7.join(dir, file2);
36618
+ const filePath = path10.join(dir, file2);
35494
36619
  const content = fs32.readFileSync(filePath, "utf-8");
35495
36620
  const lines = content.split("\n").filter(Boolean);
35496
36621
  let messageCount = 0;
@@ -35577,7 +36702,7 @@ ${cleanBody}`;
35577
36702
  const summaryBySessionId = /* @__PURE__ */ new Map();
35578
36703
  const nextPersistedEntries = /* @__PURE__ */ new Map();
35579
36704
  for (const file2 of files.slice().sort()) {
35580
- const filePath = path7.join(dir, file2);
36705
+ const filePath = path10.join(dir, file2);
35581
36706
  const signature = fileSignatures.get(file2) || `${file2}:missing`;
35582
36707
  const cached2 = savedHistoryFileSummaryCache.get(filePath);
35583
36708
  const persisted = persistedEntries.get(file2);
@@ -35697,12 +36822,12 @@ ${cleanBody}`;
35697
36822
  });
35698
36823
  }
35699
36824
  if (newMessages.length === 0) return;
35700
- const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
36825
+ const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
35701
36826
  fs32.mkdirSync(dir, { recursive: true });
35702
36827
  const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
35703
36828
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
35704
36829
  const fileName = `${filePrefix}${date5}.jsonl`;
35705
- const filePath = path7.join(dir, fileName);
36830
+ const filePath = path10.join(dir, fileName);
35706
36831
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
35707
36832
  fs32.appendFileSync(filePath, lines, "utf-8");
35708
36833
  updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
@@ -35793,11 +36918,11 @@ ${cleanBody}`;
35793
36918
  const ws2 = String(workspace || "").trim();
35794
36919
  if (!id || !ws2) return;
35795
36920
  try {
35796
- const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
36921
+ const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
35797
36922
  fs32.mkdirSync(dir, { recursive: true });
35798
36923
  const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
35799
36924
  const fileName = `${this.sanitize(id)}_${date5}.jsonl`;
35800
- const filePath = path7.join(dir, fileName);
36925
+ const filePath = path10.join(dir, fileName);
35801
36926
  const record2 = {
35802
36927
  ts: (/* @__PURE__ */ new Date()).toISOString(),
35803
36928
  receivedAt: Date.now(),
@@ -35843,14 +36968,14 @@ ${cleanBody}`;
35843
36968
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
35844
36969
  this.lastSeenCounts.delete(fromDedupKey);
35845
36970
  }
35846
- const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
36971
+ const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
35847
36972
  if (!fs32.existsSync(dir)) return;
35848
36973
  const fromPrefix = `${this.sanitize(fromId)}_`;
35849
36974
  const toPrefix = `${this.sanitize(toId)}_`;
35850
36975
  const files = fs32.readdirSync(dir).filter((file2) => file2.startsWith(fromPrefix) && file2.endsWith(".jsonl"));
35851
36976
  for (const file2 of files) {
35852
- const sourcePath = path7.join(dir, file2);
35853
- const targetPath = path7.join(dir, `${toPrefix}${file2.slice(fromPrefix.length)}`);
36977
+ const sourcePath = path10.join(dir, file2);
36978
+ const targetPath = path10.join(dir, `${toPrefix}${file2.slice(fromPrefix.length)}`);
35854
36979
  const sourceLines = fs32.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
35855
36980
  const rewritten = sourceLines.map((line) => {
35856
36981
  try {
@@ -35884,13 +37009,13 @@ ${cleanBody}`;
35884
37009
  const sessionId = String(historySessionId || "").trim();
35885
37010
  if (!sessionId) return;
35886
37011
  try {
35887
- const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
37012
+ const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
35888
37013
  if (!fs32.existsSync(dir)) return;
35889
37014
  const prefix = `${this.sanitize(sessionId)}_`;
35890
37015
  const files = fs32.readdirSync(dir).filter((file2) => file2.startsWith(prefix) && file2.endsWith(".jsonl")).sort();
35891
37016
  const seen = /* @__PURE__ */ new Set();
35892
37017
  for (const file2 of files) {
35893
- const filePath = path7.join(dir, file2);
37018
+ const filePath = path10.join(dir, file2);
35894
37019
  const lines = fs32.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
35895
37020
  const next = [];
35896
37021
  for (const line of lines) {
@@ -35944,13 +37069,13 @@ ${cleanBody}`;
35944
37069
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
35945
37070
  const agentDirs = fs32.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
35946
37071
  for (const dir of agentDirs) {
35947
- const dirPath = path7.join(HISTORY_DIR, dir.name);
37072
+ const dirPath = path10.join(HISTORY_DIR, dir.name);
35948
37073
  const files = fs32.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
35949
37074
  let removedAny = false;
35950
37075
  for (const file2 of files) {
35951
- const filePath = path7.join(dirPath, file2);
35952
- const stat4 = fs32.statSync(filePath);
35953
- if (stat4.mtimeMs < cutoff) {
37076
+ const filePath = path10.join(dirPath, file2);
37077
+ const stat22 = fs32.statSync(filePath);
37078
+ if (stat22.mtimeMs < cutoff) {
35954
37079
  fs32.unlinkSync(filePath);
35955
37080
  removedAny = true;
35956
37081
  }
@@ -35967,6 +37092,10 @@ ${cleanBody}`;
35967
37092
  return name.replace(/[^a-zA-Z0-9_-]/g, "_");
35968
37093
  }
35969
37094
  };
37095
+ function normalizePaginationNumber(value, fallback, min) {
37096
+ const numeric = Number(value);
37097
+ return Number.isFinite(numeric) ? Math.max(min, numeric) : fallback;
37098
+ }
35970
37099
  function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeRecentCount = 0, historyBehavior) {
35971
37100
  const allMessages = records.map((message) => sanitizeHistoryMessage(agentType, message)).filter(Boolean);
35972
37101
  allMessages.sort((a, b2) => a.receivedAt - b2.receivedAt);
@@ -35980,9 +37109,12 @@ ${cleanBody}`;
35980
37109
  if (message.role !== "system") lastTurn = message;
35981
37110
  }
35982
37111
  const collapsed = collapseReplayAssistantTurns(chronological, historyBehavior);
35983
- const boundedLimit = Math.max(1, limit);
35984
- const boundedOffset = Math.max(0, offset);
35985
- const boundedExclude = Math.max(0, Math.min(excludeRecentCount, collapsed.length));
37112
+ const boundedLimit = normalizePaginationNumber(limit, 30, 1);
37113
+ const boundedOffset = normalizePaginationNumber(offset, 0, 0);
37114
+ const boundedExclude = Math.min(
37115
+ normalizePaginationNumber(excludeRecentCount, 0, 0),
37116
+ collapsed.length
37117
+ );
35986
37118
  const endExclusive = Math.max(0, collapsed.length - boundedExclude - boundedOffset);
35987
37119
  const startInclusive = Math.max(0, endExclusive - boundedLimit);
35988
37120
  const sliced = collapsed.slice(startInclusive, endExclusive);
@@ -35991,13 +37123,13 @@ ${cleanBody}`;
35991
37123
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
35992
37124
  try {
35993
37125
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
35994
- const dir = path7.join(HISTORY_DIR, sanitized);
37126
+ const dir = path10.join(HISTORY_DIR, sanitized);
35995
37127
  if (!fs32.existsSync(dir)) return { messages: [], hasMore: false };
35996
37128
  const files = listHistoryFiles(dir, historySessionId);
35997
37129
  const allMessages = [];
35998
37130
  const seen = /* @__PURE__ */ new Set();
35999
37131
  for (const file2 of files) {
36000
- const filePath = path7.join(dir, file2);
37132
+ const filePath = path10.join(dir, file2);
36001
37133
  const content = fs32.readFileSync(filePath, "utf-8");
36002
37134
  const lines = content.trim().split("\n").filter(Boolean);
36003
37135
  for (let i = 0; i < lines.length; i++) {
@@ -36021,7 +37153,7 @@ ${cleanBody}`;
36021
37153
  function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
36022
37154
  try {
36023
37155
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
36024
- const dir = path7.join(HISTORY_DIR, sanitized);
37156
+ const dir = path10.join(HISTORY_DIR, sanitized);
36025
37157
  if (!fs32.existsSync(dir)) {
36026
37158
  savedHistorySessionCache.delete(sanitized);
36027
37159
  return { sessions: [], hasMore: false };
@@ -36082,11 +37214,11 @@ ${cleanBody}`;
36082
37214
  }
36083
37215
  function readExistingSessionStartRecord(agentType, historySessionId) {
36084
37216
  try {
36085
- const dir = path7.join(HISTORY_DIR, agentType);
37217
+ const dir = path10.join(HISTORY_DIR, agentType);
36086
37218
  if (!fs32.existsSync(dir)) return null;
36087
37219
  const files = listHistoryFiles(dir, historySessionId).sort();
36088
37220
  for (const file2 of files) {
36089
- const lines = fs32.readFileSync(path7.join(dir, file2), "utf-8").split("\n").filter(Boolean);
37221
+ const lines = fs32.readFileSync(path10.join(dir, file2), "utf-8").split("\n").filter(Boolean);
36090
37222
  for (const line of lines) {
36091
37223
  try {
36092
37224
  const parsed = JSON.parse(line);
@@ -36106,16 +37238,16 @@ ${cleanBody}`;
36106
37238
  function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
36107
37239
  if (records.length === 0) return false;
36108
37240
  try {
36109
- const dir = path7.join(HISTORY_DIR, agentType);
37241
+ const dir = path10.join(HISTORY_DIR, agentType);
36110
37242
  fs32.mkdirSync(dir, { recursive: true });
36111
37243
  const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
36112
37244
  for (const file2 of fs32.readdirSync(dir)) {
36113
37245
  if (file2.startsWith(prefix) && file2.endsWith(".jsonl")) {
36114
- fs32.unlinkSync(path7.join(dir, file2));
37246
+ fs32.unlinkSync(path10.join(dir, file2));
36115
37247
  }
36116
37248
  }
36117
37249
  const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
36118
- const filePath = path7.join(dir, `${prefix}${targetDate}.jsonl`);
37250
+ const filePath = path10.join(dir, `${prefix}${targetDate}.jsonl`);
36119
37251
  fs32.writeFileSync(filePath, `${records.map((record2) => JSON.stringify(record2)).join("\n")}
36120
37252
  `, "utf-8");
36121
37253
  invalidatePersistedSavedHistoryIndex(agentType, dir);
@@ -37959,6 +39091,10 @@ ${effect.notification.body || ""}`.trim();
37959
39091
  function shouldIncludeRuntimeMetadata(profile) {
37960
39092
  return true;
37961
39093
  }
39094
+ function getGitSummaryForWorkspace(workspace, options) {
39095
+ if (!workspace) return void 0;
39096
+ return options.getGitSummaryForWorkspace?.(workspace) || void 0;
39097
+ }
37962
39098
  function findCdpManager(cdpManagers, key) {
37963
39099
  const exact = cdpManagers.get(key);
37964
39100
  if (exact) return exact.isConnected ? exact : null;
@@ -38014,6 +39150,8 @@ ${effect.notification.body || ""}`.trim();
38014
39150
  const controlValues = normalizeProviderStateControlValues(state.controlValues);
38015
39151
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
38016
39152
  const includeSessionControls = shouldIncludeSessionControls(profile);
39153
+ const workspace = state.workspace || null;
39154
+ const git = getGitSummaryForWorkspace(workspace, options);
38017
39155
  const title = activeChat?.title || state.name;
38018
39156
  return {
38019
39157
  id: state.instanceId || state.type,
@@ -38026,7 +39164,8 @@ ${effect.notification.body || ""}`.trim();
38026
39164
  activeModal: activeChat?.activeModal || null
38027
39165
  }),
38028
39166
  title,
38029
- workspace: state.workspace || null,
39167
+ workspace,
39168
+ ...git && { git },
38030
39169
  activeChat,
38031
39170
  ...summaryMetadata && { summaryMetadata },
38032
39171
  ...includeSessionMetadata && { capabilities: state.sessionCapabilities || IDE_SESSION_CAPABILITIES },
@@ -38047,6 +39186,8 @@ ${effect.notification.body || ""}`.trim();
38047
39186
  const controlValues = normalizeProviderStateControlValues(ext.controlValues);
38048
39187
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
38049
39188
  const includeSessionControls = shouldIncludeSessionControls(profile);
39189
+ const workspace = parent.workspace || null;
39190
+ const git = getGitSummaryForWorkspace(workspace, options);
38050
39191
  return {
38051
39192
  id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
38052
39193
  parentId: parent.instanceId || parent.type,
@@ -38059,7 +39200,8 @@ ${effect.notification.body || ""}`.trim();
38059
39200
  activeModal: activeChat?.activeModal || null
38060
39201
  }),
38061
39202
  title: activeChat?.title || ext.name,
38062
- workspace: parent.workspace || null,
39203
+ workspace,
39204
+ ...git && { git },
38063
39205
  activeChat,
38064
39206
  ...summaryMetadata && { summaryMetadata },
38065
39207
  ...includeSessionMetadata && { capabilities: ext.sessionCapabilities || EXTENSION_SESSION_CAPABILITIES },
@@ -38095,6 +39237,8 @@ ${effect.notification.body || ""}`.trim();
38095
39237
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
38096
39238
  const includeRuntimeMetadata = shouldIncludeRuntimeMetadata(profile);
38097
39239
  const includeSessionControls = shouldIncludeSessionControls(profile);
39240
+ const workspace = state.workspace || null;
39241
+ const git = getGitSummaryForWorkspace(workspace, options);
38098
39242
  return {
38099
39243
  id: state.instanceId,
38100
39244
  parentId: null,
@@ -38107,7 +39251,8 @@ ${effect.notification.body || ""}`.trim();
38107
39251
  activeModal: activeChat?.activeModal || null
38108
39252
  }),
38109
39253
  title: activeChat?.title || state.name,
38110
- workspace: state.workspace || null,
39254
+ workspace,
39255
+ ...git && { git },
38111
39256
  ...includeRuntimeMetadata && {
38112
39257
  runtimeKey: state.runtime?.runtimeKey,
38113
39258
  runtimeDisplayName: state.runtime?.displayName,
@@ -38142,6 +39287,8 @@ ${effect.notification.body || ""}`.trim();
38142
39287
  const controlValues = normalizeProviderStateControlValues(state.controlValues);
38143
39288
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
38144
39289
  const includeSessionControls = shouldIncludeSessionControls(profile);
39290
+ const workspace = state.workspace || null;
39291
+ const git = getGitSummaryForWorkspace(workspace, options);
38145
39292
  return {
38146
39293
  id: state.instanceId,
38147
39294
  parentId: null,
@@ -38153,7 +39300,8 @@ ${effect.notification.body || ""}`.trim();
38153
39300
  activeModal: activeChat?.activeModal || null
38154
39301
  }),
38155
39302
  title: activeChat?.title || state.name,
38156
- workspace: state.workspace || null,
39303
+ workspace,
39304
+ ...git && { git },
38157
39305
  activeChat,
38158
39306
  ...summaryMetadata && { summaryMetadata },
38159
39307
  ...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES },
@@ -38264,7 +39412,7 @@ ${effect.notification.body || ""}`.trim();
38264
39412
  }
38265
39413
  var fs42 = __toESM2(require("fs"));
38266
39414
  var os62 = __toESM2(require("os"));
38267
- var path8 = __toESM2(require("path"));
39415
+ var path11 = __toESM2(require("path"));
38268
39416
  var import_node_crypto = require("crypto");
38269
39417
  init_contracts();
38270
39418
  var VALID_INPUT_MEDIA_TYPES = /* @__PURE__ */ new Set(["text", "image", "audio", "video", "resource"]);
@@ -38947,7 +40095,7 @@ ${effect.notification.body || ""}`.trim();
38947
40095
  }
38948
40096
  function getChatDebugBundleDir() {
38949
40097
  const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
38950
- return override || path8.join(os62.homedir(), ".adhdev", "debug-bundles", "chat");
40098
+ return override || path11.join(os62.homedir(), ".adhdev", "debug-bundles", "chat");
38951
40099
  }
38952
40100
  function safeBundleIdSegment(value, fallback) {
38953
40101
  const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
@@ -38980,7 +40128,7 @@ ${effect.notification.body || ""}`.trim();
38980
40128
  const bundleId = createChatDebugBundleId(targetSessionId);
38981
40129
  const dir = getChatDebugBundleDir();
38982
40130
  fs42.mkdirSync(dir, { recursive: true });
38983
- const savedPath = path8.join(dir, `${bundleId}.json`);
40131
+ const savedPath = path11.join(dir, `${bundleId}.json`);
38984
40132
  const json2 = `${JSON.stringify(bundle, null, 2)}
38985
40133
  `;
38986
40134
  fs42.writeFileSync(savedPath, json2, { encoding: "utf8", mode: 384 });
@@ -39149,10 +40297,32 @@ ${effect.notification.body || ""}`.trim();
39149
40297
  if (!last) return "";
39150
40298
  return `${last.role || ""}:${String(last.content || "").replace(/\s+/g, " ").trim()}`;
39151
40299
  }
40300
+ function toNonNegativeNumber(value) {
40301
+ const numeric = Number(value ?? 0);
40302
+ return Number.isFinite(numeric) ? Math.max(0, numeric) : 0;
40303
+ }
40304
+ function getCliVisibleTranscriptCount(adapter) {
40305
+ const adapterStatus = adapter?.getStatus?.() || {};
40306
+ const adapterMessages = Array.isArray(adapterStatus.messages) ? adapterStatus.messages : [];
40307
+ let parsedRecord = null;
40308
+ if (typeof adapter?.getScriptParsedStatus === "function") {
40309
+ try {
40310
+ const parsed = parseMaybeJson(adapter.getScriptParsedStatus());
40311
+ parsedRecord = parsed && typeof parsed === "object" ? parsed : null;
40312
+ } catch {
40313
+ parsedRecord = null;
40314
+ }
40315
+ }
40316
+ const parsedMessages = Array.isArray(parsedRecord?.messages) ? parsedRecord.messages : [];
40317
+ if (!parsedRecord) return adapterMessages.length;
40318
+ const parsedIsProviderAuthoritative = parsedRecord.transcriptAuthority === "provider" || parsedRecord.coverage === "full";
40319
+ const shouldPreferAdapterMessages = !parsedIsProviderAuthoritative && adapterMessages.length > 0 && adapterMessages.length > parsedMessages.length;
40320
+ return shouldPreferAdapterMessages ? adapterMessages.length : parsedMessages.length;
40321
+ }
39152
40322
  async function getStableExtensionBaseline(h) {
39153
40323
  const first = await readExtensionChatState(h);
39154
40324
  if (getStateMessageCount(first) > 0 || getStateLastSignature(first)) return first;
39155
- await new Promise((resolve12) => setTimeout(resolve12, 150));
40325
+ await new Promise((resolve15) => setTimeout(resolve15, 150));
39156
40326
  const second = await readExtensionChatState(h);
39157
40327
  return getStateMessageCount(second) >= getStateMessageCount(first) ? second : first;
39158
40328
  }
@@ -39160,7 +40330,7 @@ ${effect.notification.body || ""}`.trim();
39160
40330
  const beforeCount = getStateMessageCount(before);
39161
40331
  const beforeSignature = getStateLastSignature(before);
39162
40332
  for (let attempt = 0; attempt < 12; attempt += 1) {
39163
- await new Promise((resolve12) => setTimeout(resolve12, 250));
40333
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
39164
40334
  const state = await readExtensionChatState(h);
39165
40335
  if (state?.status === "waiting_approval") return true;
39166
40336
  const afterCount = getStateMessageCount(state);
@@ -39177,11 +40347,11 @@ ${effect.notification.body || ""}`.trim();
39177
40347
  const provider = h.getProvider(agentType);
39178
40348
  const agentStr = provider?.type || agentType || getCurrentProviderType(h);
39179
40349
  const transport = getTargetTransport(h, provider);
39180
- let excludeRecentCount = Math.max(0, Number(args?.excludeRecentCount || 0));
39181
- if (isCliLikeTransport(transport)) {
40350
+ const hasExplicitExcludeRecentCount = args?.excludeRecentCount !== void 0 && args?.excludeRecentCount !== null;
40351
+ let excludeRecentCount = toNonNegativeNumber(args?.excludeRecentCount);
40352
+ if (!hasExplicitExcludeRecentCount && isCliLikeTransport(transport)) {
39182
40353
  const adapter = getTargetedCliAdapter(h, args, provider?.type);
39183
- const status = adapter?.getStatus?.();
39184
- const visibleCount = Array.isArray(status?.messages) ? status.messages.length : 0;
40354
+ const visibleCount = getCliVisibleTranscriptCount(adapter);
39185
40355
  if (visibleCount > excludeRecentCount) excludeRecentCount = visibleCount;
39186
40356
  }
39187
40357
  const workspace = typeof args?.workspace === "string" ? args.workspace : typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : void 0;
@@ -40094,7 +41264,7 @@ ${effect.notification.body || ""}`.trim();
40094
41264
  return { success: false, error: "resolveAction script not available for this provider" };
40095
41265
  }
40096
41266
  var fs52 = __toESM2(require("fs"));
40097
- var path9 = __toESM2(require("path"));
41267
+ var path12 = __toESM2(require("path"));
40098
41268
  var os7 = __toESM2(require("os"));
40099
41269
  var KEY_TO_VK = {
40100
41270
  Backspace: 8,
@@ -40351,25 +41521,25 @@ ${effect.notification.body || ""}`.trim();
40351
41521
  const inputPath = rawPath || ".";
40352
41522
  const home = os7.homedir();
40353
41523
  if (inputPath.startsWith("~")) {
40354
- return path9.resolve(path9.join(home, inputPath.slice(1)));
41524
+ return path12.resolve(path12.join(home, inputPath.slice(1)));
40355
41525
  }
40356
41526
  if (process.platform === "win32") {
40357
41527
  const normalized = normalizeWindowsRequestedPath(inputPath);
40358
- if (path9.win32.isAbsolute(normalized)) {
40359
- return path9.win32.normalize(normalized);
41528
+ if (path12.win32.isAbsolute(normalized)) {
41529
+ return path12.win32.normalize(normalized);
40360
41530
  }
40361
- return path9.win32.resolve(normalized);
41531
+ return path12.win32.resolve(normalized);
40362
41532
  }
40363
- if (path9.isAbsolute(inputPath)) {
40364
- return path9.normalize(inputPath);
41533
+ if (path12.isAbsolute(inputPath)) {
41534
+ return path12.normalize(inputPath);
40365
41535
  }
40366
- return path9.resolve(inputPath);
41536
+ return path12.resolve(inputPath);
40367
41537
  }
40368
41538
  function listDirectoryEntriesSafe(dirPath) {
40369
41539
  const entries = fs52.readdirSync(dirPath, { withFileTypes: true });
40370
41540
  const files = [];
40371
41541
  for (const entry of entries) {
40372
- const entryPath = path9.join(dirPath, entry.name);
41542
+ const entryPath = path12.join(dirPath, entry.name);
40373
41543
  try {
40374
41544
  if (entry.isDirectory()) {
40375
41545
  files.push({ name: entry.name, type: "directory" });
@@ -40385,11 +41555,11 @@ ${effect.notification.body || ""}`.trim();
40385
41555
  files.push({ name: entry.name, type: "file", size });
40386
41556
  continue;
40387
41557
  }
40388
- const stat4 = fs52.statSync(entryPath);
41558
+ const stat22 = fs52.statSync(entryPath);
40389
41559
  files.push({
40390
41560
  name: entry.name,
40391
- type: stat4.isDirectory() ? "directory" : "file",
40392
- size: stat4.isFile() ? stat4.size : void 0
41561
+ type: stat22.isDirectory() ? "directory" : "file",
41562
+ size: stat22.isFile() ? stat22.size : void 0
40393
41563
  });
40394
41564
  } catch {
40395
41565
  }
@@ -40423,7 +41593,7 @@ ${effect.notification.body || ""}`.trim();
40423
41593
  async function handleFileWrite(h, args) {
40424
41594
  try {
40425
41595
  const filePath = resolveSafePath(args?.path);
40426
- fs52.mkdirSync(path9.dirname(filePath), { recursive: true });
41596
+ fs52.mkdirSync(path12.dirname(filePath), { recursive: true });
40427
41597
  fs52.writeFileSync(filePath, args?.content || "", "utf-8");
40428
41598
  return { success: true, path: filePath };
40429
41599
  } catch (e) {
@@ -40764,7 +41934,7 @@ ${effect.notification.body || ""}`.trim();
40764
41934
  const enterCount = cliCommand.enterCount || 1;
40765
41935
  await adapter.writeRaw(cliCommand.text + "\r");
40766
41936
  for (let i = 1; i < enterCount; i += 1) {
40767
- await new Promise((resolve12) => setTimeout(resolve12, 50));
41937
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
40768
41938
  await adapter.writeRaw("\r");
40769
41939
  }
40770
41940
  }
@@ -41254,6 +42424,12 @@ ${effect.notification.body || ""}`.trim();
41254
42424
  this._currentRoute = this.resolveRoute(args);
41255
42425
  const startedAt = Date.now();
41256
42426
  this.logCommandStart(cmd, args);
42427
+ let result;
42428
+ if (isGitCommandName(cmd)) {
42429
+ result = await handleGitCommand(cmd, args, this._ctx.gitCommandServices);
42430
+ this.logCommandEnd(cmd, result, startedAt);
42431
+ return result;
42432
+ }
41257
42433
  const sessionScopedCommands = /* @__PURE__ */ new Set([
41258
42434
  "read_chat",
41259
42435
  "get_chat_debug_bundle",
@@ -41279,7 +42455,6 @@ ${effect.notification.body || ""}`.trim();
41279
42455
  this.logCommandEnd(cmd, result2, startedAt);
41280
42456
  return result2;
41281
42457
  }
41282
- let result;
41283
42458
  if (!this._currentRoute.session && !this._currentRoute.managerKey && !this._currentRoute.providerType) {
41284
42459
  const cdpCommands = ["send_chat", "read_chat", "list_chats", "new_chat", "switch_chat", "set_mode", "change_model", "set_thought_level", "resolve_action"];
41285
42460
  if (cdpCommands.includes(cmd)) {
@@ -41430,7 +42605,7 @@ ${effect.notification.body || ""}`.trim();
41430
42605
  try {
41431
42606
  const http3 = await import("http");
41432
42607
  const postData = JSON.stringify(body);
41433
- const result = await new Promise((resolve12, reject) => {
42608
+ const result = await new Promise((resolve15, reject) => {
41434
42609
  const req = http3.request({
41435
42610
  hostname: "127.0.0.1",
41436
42611
  port: 19280,
@@ -41442,9 +42617,9 @@ ${effect.notification.body || ""}`.trim();
41442
42617
  res.on("data", (chunk) => data += chunk);
41443
42618
  res.on("end", () => {
41444
42619
  try {
41445
- resolve12(JSON.parse(data));
42620
+ resolve15(JSON.parse(data));
41446
42621
  } catch {
41447
- resolve12({ raw: data });
42622
+ resolve15({ raw: data });
41448
42623
  }
41449
42624
  });
41450
42625
  });
@@ -41462,15 +42637,15 @@ ${effect.notification.body || ""}`.trim();
41462
42637
  if (!providerType) return { success: false, error: "providerType required" };
41463
42638
  try {
41464
42639
  const http3 = await import("http");
41465
- const result = await new Promise((resolve12, reject) => {
42640
+ const result = await new Promise((resolve15, reject) => {
41466
42641
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
41467
42642
  let data = "";
41468
42643
  res.on("data", (chunk) => data += chunk);
41469
42644
  res.on("end", () => {
41470
42645
  try {
41471
- resolve12(JSON.parse(data));
42646
+ resolve15(JSON.parse(data));
41472
42647
  } catch {
41473
- resolve12({ raw: data });
42648
+ resolve15({ raw: data });
41474
42649
  }
41475
42650
  });
41476
42651
  }).on("error", reject);
@@ -41484,7 +42659,7 @@ ${effect.notification.body || ""}`.trim();
41484
42659
  try {
41485
42660
  const http3 = await import("http");
41486
42661
  const postData = JSON.stringify(args || {});
41487
- const result = await new Promise((resolve12, reject) => {
42662
+ const result = await new Promise((resolve15, reject) => {
41488
42663
  const req = http3.request({
41489
42664
  hostname: "127.0.0.1",
41490
42665
  port: 19280,
@@ -41496,9 +42671,9 @@ ${effect.notification.body || ""}`.trim();
41496
42671
  res.on("data", (chunk) => data += chunk);
41497
42672
  res.on("end", () => {
41498
42673
  try {
41499
- resolve12(JSON.parse(data));
42674
+ resolve15(JSON.parse(data));
41500
42675
  } catch {
41501
- resolve12({ raw: data });
42676
+ resolve15({ raw: data });
41502
42677
  }
41503
42678
  });
41504
42679
  });
@@ -41513,7 +42688,7 @@ ${effect.notification.body || ""}`.trim();
41513
42688
  }
41514
42689
  };
41515
42690
  var os13 = __toESM2(require("os"));
41516
- var path13 = __toESM2(require("path"));
42691
+ var path16 = __toESM2(require("path"));
41517
42692
  var crypto4 = __toESM2(require("crypto"));
41518
42693
  var import_fs5 = require("fs");
41519
42694
  var import_child_process6 = require("child_process");
@@ -41521,7 +42696,7 @@ ${effect.notification.body || ""}`.trim();
41521
42696
  init_provider_cli_adapter();
41522
42697
  init_config();
41523
42698
  var os12 = __toESM2(require("os"));
41524
- var path12 = __toESM2(require("path"));
42699
+ var path15 = __toESM2(require("path"));
41525
42700
  var crypto3 = __toESM2(require("crypto"));
41526
42701
  var fs6 = __toESM2(require("fs"));
41527
42702
  var import_node_module = require("module");
@@ -41578,7 +42753,7 @@ ${effect.notification.body || ""}`.trim();
41578
42753
  var CachedDatabaseSync = null;
41579
42754
  function getDatabaseSync() {
41580
42755
  if (CachedDatabaseSync) return CachedDatabaseSync;
41581
- const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path12.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
42756
+ const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path15.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
41582
42757
  const sqliteModule = requireFn(`node:${"sqlite"}`);
41583
42758
  CachedDatabaseSync = sqliteModule.DatabaseSync;
41584
42759
  if (!CachedDatabaseSync) {
@@ -41616,7 +42791,7 @@ ${effect.notification.body || ""}`.trim();
41616
42791
  if (status === "stopped") {
41617
42792
  throw new Error("CLI runtime stopped before it became ready");
41618
42793
  }
41619
- await new Promise((resolve12) => setTimeout(resolve12, pollMs));
42794
+ await new Promise((resolve15) => setTimeout(resolve15, pollMs));
41620
42795
  }
41621
42796
  throw new Error(`CLI runtime did not become ready within ${timeoutMs}ms`);
41622
42797
  }
@@ -41967,7 +43142,7 @@ ${effect.notification.body || ""}`.trim();
41967
43142
  const enterCount = cliCommand.enterCount || 1;
41968
43143
  await this.adapter.writeRaw(cliCommand.text + "\r");
41969
43144
  for (let i = 1; i < enterCount; i += 1) {
41970
- await new Promise((resolve12) => setTimeout(resolve12, 50));
43145
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
41971
43146
  await this.adapter.writeRaw("\r");
41972
43147
  }
41973
43148
  }
@@ -43079,13 +44254,13 @@ ${effect.notification.body || ""}`.trim();
43079
44254
  }
43080
44255
  this.currentStatus = "waiting_approval";
43081
44256
  this.detectStatusTransition();
43082
- const approved = await new Promise((resolve12) => {
43083
- this.permissionResolvers.push(resolve12);
44257
+ const approved = await new Promise((resolve15) => {
44258
+ this.permissionResolvers.push(resolve15);
43084
44259
  setTimeout(() => {
43085
- const idx = this.permissionResolvers.indexOf(resolve12);
44260
+ const idx = this.permissionResolvers.indexOf(resolve15);
43086
44261
  if (idx >= 0) {
43087
44262
  this.permissionResolvers.splice(idx, 1);
43088
- resolve12(false);
44263
+ resolve15(false);
43089
44264
  }
43090
44265
  }, 3e5);
43091
44266
  });
@@ -43654,11 +44829,11 @@ ${rawInput}` : rawInput;
43654
44829
  }
43655
44830
  function isExplicitCommand(command) {
43656
44831
  const trimmed = command.trim();
43657
- return path13.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
44832
+ return path16.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
43658
44833
  }
43659
44834
  function expandExecutable(command) {
43660
44835
  const trimmed = command.trim();
43661
- return trimmed.startsWith("~") ? path13.join(os13.homedir(), trimmed.slice(1)) : trimmed;
44836
+ return trimmed.startsWith("~") ? path16.join(os13.homedir(), trimmed.slice(1)) : trimmed;
43662
44837
  }
43663
44838
  function commandExists(command) {
43664
44839
  const trimmed = command.trim();
@@ -43939,7 +45114,7 @@ ${rawInput}` : rawInput;
43939
45114
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
43940
45115
  const trimmed = (workingDir || "").trim();
43941
45116
  if (!trimmed) throw new Error("working directory required");
43942
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path13.resolve(trimmed);
45117
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path16.resolve(trimmed);
43943
45118
  const normalizedType = this.providerLoader.resolveAlias(cliType);
43944
45119
  const rawProvider = this.providerLoader.getByAlias(cliType);
43945
45120
  const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
@@ -44438,9 +45613,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
44438
45613
  var import_child_process7 = require("child_process");
44439
45614
  var net3 = __toESM2(require("net"));
44440
45615
  var os15 = __toESM2(require("os"));
44441
- var path15 = __toESM2(require("path"));
45616
+ var path18 = __toESM2(require("path"));
44442
45617
  var fs7 = __toESM2(require("fs"));
44443
- var path14 = __toESM2(require("path"));
45618
+ var path17 = __toESM2(require("path"));
44444
45619
  var os14 = __toESM2(require("os"));
44445
45620
  var chokidar = __toESM2((init_chokidar(), __toCommonJS(chokidar_exports)));
44446
45621
  init_logger();
@@ -44701,7 +45876,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44701
45876
  try {
44702
45877
  if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
44703
45878
  return ["ide", "extension", "cli", "acp"].some(
44704
- (category) => fs7.existsSync(path14.join(candidate, category))
45879
+ (category) => fs7.existsSync(path17.join(candidate, category))
44705
45880
  );
44706
45881
  } catch {
44707
45882
  return false;
@@ -44709,20 +45884,20 @@ Run 'adhdev doctor' for detailed diagnostics.`
44709
45884
  }
44710
45885
  static hasProviderRootMarker(candidate) {
44711
45886
  try {
44712
- return fs7.existsSync(path14.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
45887
+ return fs7.existsSync(path17.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
44713
45888
  } catch {
44714
45889
  return false;
44715
45890
  }
44716
45891
  }
44717
45892
  detectDefaultUserDir() {
44718
- const fallback = path14.join(os14.homedir(), ".adhdev", "providers");
45893
+ const fallback = path17.join(os14.homedir(), ".adhdev", "providers");
44719
45894
  const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
44720
45895
  const visited = /* @__PURE__ */ new Set();
44721
45896
  for (const start of this.probeStarts) {
44722
- let current = path14.resolve(start);
45897
+ let current = path17.resolve(start);
44723
45898
  while (!visited.has(current)) {
44724
45899
  visited.add(current);
44725
- const siblingCandidate = path14.join(path14.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
45900
+ const siblingCandidate = path17.join(path17.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
44726
45901
  if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
44727
45902
  const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
44728
45903
  if (envOptIn || hasMarker) {
@@ -44744,7 +45919,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44744
45919
  return { path: siblingCandidate, source };
44745
45920
  }
44746
45921
  }
44747
- const parent = path14.dirname(current);
45922
+ const parent = path17.dirname(current);
44748
45923
  if (parent === current) break;
44749
45924
  current = parent;
44750
45925
  }
@@ -44754,11 +45929,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
44754
45929
  constructor(options) {
44755
45930
  this.logFn = options?.logFn || LOG2.forComponent("Provider").asLogFn();
44756
45931
  this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
44757
- this.defaultProvidersDir = path14.join(os14.homedir(), ".adhdev", "providers");
45932
+ this.defaultProvidersDir = path17.join(os14.homedir(), ".adhdev", "providers");
44758
45933
  const detected = this.detectDefaultUserDir();
44759
45934
  this.userDir = detected.path;
44760
45935
  this.userDirSource = detected.source;
44761
- this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
45936
+ this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
44762
45937
  this.disableUpstream = false;
44763
45938
  this.applySourceConfig({
44764
45939
  userDir: options?.userDir,
@@ -44817,7 +45992,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44817
45992
  this.userDir = detected.path;
44818
45993
  this.userDirSource = detected.source;
44819
45994
  }
44820
- this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
45995
+ this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
44821
45996
  this.disableUpstream = this.sourceMode === "no-upstream";
44822
45997
  if (this.explicitProviderDir) {
44823
45998
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
@@ -44831,7 +46006,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44831
46006
  * Canonical provider directory shape for a given root.
44832
46007
  */
44833
46008
  getProviderDir(root, category, type) {
44834
- return path14.join(root, category, type);
46009
+ return path17.join(root, category, type);
44835
46010
  }
44836
46011
  /**
44837
46012
  * Canonical user override directory for a provider.
@@ -44858,7 +46033,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44858
46033
  resolveProviderFile(type, ...segments) {
44859
46034
  const dir = this.findProviderDirInternal(type);
44860
46035
  if (!dir) return null;
44861
- return path14.join(dir, ...segments);
46036
+ return path17.join(dir, ...segments);
44862
46037
  }
44863
46038
  /**
44864
46039
  * Load all providers (3-tier priority)
@@ -44897,7 +46072,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44897
46072
  if (!fs7.existsSync(this.upstreamDir)) return false;
44898
46073
  try {
44899
46074
  return fs7.readdirSync(this.upstreamDir).some(
44900
- (d) => fs7.statSync(path14.join(this.upstreamDir, d)).isDirectory()
46075
+ (d) => fs7.statSync(path17.join(this.upstreamDir, d)).isDirectory()
44901
46076
  );
44902
46077
  } catch {
44903
46078
  return false;
@@ -45394,8 +46569,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
45394
46569
  resolved._resolvedScriptDir = entry.scriptDir;
45395
46570
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
45396
46571
  if (providerDir) {
45397
- const fullDir = path14.join(providerDir, entry.scriptDir);
45398
- resolved._resolvedScriptsPath = fs7.existsSync(path14.join(fullDir, "scripts.js")) ? path14.join(fullDir, "scripts.js") : fullDir;
46572
+ const fullDir = path17.join(providerDir, entry.scriptDir);
46573
+ resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
45399
46574
  }
45400
46575
  matched = true;
45401
46576
  }
@@ -45410,8 +46585,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
45410
46585
  resolved._resolvedScriptDir = base.defaultScriptDir;
45411
46586
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
45412
46587
  if (providerDir) {
45413
- const fullDir = path14.join(providerDir, base.defaultScriptDir);
45414
- resolved._resolvedScriptsPath = fs7.existsSync(path14.join(fullDir, "scripts.js")) ? path14.join(fullDir, "scripts.js") : fullDir;
46588
+ const fullDir = path17.join(providerDir, base.defaultScriptDir);
46589
+ resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
45415
46590
  }
45416
46591
  }
45417
46592
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -45428,8 +46603,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
45428
46603
  resolved._resolvedScriptDir = dirOverride;
45429
46604
  resolved._resolvedScriptsSource = `versions:${range}`;
45430
46605
  if (providerDir) {
45431
- const fullDir = path14.join(providerDir, dirOverride);
45432
- resolved._resolvedScriptsPath = fs7.existsSync(path14.join(fullDir, "scripts.js")) ? path14.join(fullDir, "scripts.js") : fullDir;
46606
+ const fullDir = path17.join(providerDir, dirOverride);
46607
+ resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
45433
46608
  }
45434
46609
  }
45435
46610
  } else if (override.scripts) {
@@ -45445,8 +46620,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
45445
46620
  resolved._resolvedScriptDir = base.defaultScriptDir;
45446
46621
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
45447
46622
  if (providerDir) {
45448
- const fullDir = path14.join(providerDir, base.defaultScriptDir);
45449
- resolved._resolvedScriptsPath = fs7.existsSync(path14.join(fullDir, "scripts.js")) ? path14.join(fullDir, "scripts.js") : fullDir;
46623
+ const fullDir = path17.join(providerDir, base.defaultScriptDir);
46624
+ resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
45450
46625
  }
45451
46626
  }
45452
46627
  }
@@ -45478,14 +46653,14 @@ Run 'adhdev doctor' for detailed diagnostics.`
45478
46653
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
45479
46654
  return null;
45480
46655
  }
45481
- const dir = path14.join(providerDir, scriptDir);
46656
+ const dir = path17.join(providerDir, scriptDir);
45482
46657
  if (!fs7.existsSync(dir)) {
45483
46658
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
45484
46659
  return null;
45485
46660
  }
45486
46661
  const cached2 = this.scriptsCache.get(dir);
45487
46662
  if (cached2) return cached2;
45488
- const scriptsJs = path14.join(dir, "scripts.js");
46663
+ const scriptsJs = path17.join(dir, "scripts.js");
45489
46664
  if (fs7.existsSync(scriptsJs)) {
45490
46665
  try {
45491
46666
  delete require.cache[require.resolve(scriptsJs)];
@@ -45527,7 +46702,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45527
46702
  return;
45528
46703
  }
45529
46704
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
45530
- this.log(`File changed: ${path14.basename(filePath)}, reloading...`);
46705
+ this.log(`File changed: ${path17.basename(filePath)}, reloading...`);
45531
46706
  this.reload();
45532
46707
  }
45533
46708
  };
@@ -45582,7 +46757,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45582
46757
  }
45583
46758
  const https = require("https");
45584
46759
  const { execSync: execSync7 } = require("child_process");
45585
- const metaPath = path14.join(this.upstreamDir, _ProviderLoader.META_FILE);
46760
+ const metaPath = path17.join(this.upstreamDir, _ProviderLoader.META_FILE);
45586
46761
  let prevEtag = "";
45587
46762
  let prevTimestamp = 0;
45588
46763
  try {
@@ -45599,7 +46774,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45599
46774
  return { updated: false };
45600
46775
  }
45601
46776
  try {
45602
- const etag = await new Promise((resolve12, reject) => {
46777
+ const etag = await new Promise((resolve15, reject) => {
45603
46778
  const options = {
45604
46779
  method: "HEAD",
45605
46780
  hostname: "github.com",
@@ -45617,7 +46792,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45617
46792
  headers: { "User-Agent": "adhdev-launcher" },
45618
46793
  timeout: 1e4
45619
46794
  }, (res2) => {
45620
- resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
46795
+ resolve15(res2.headers.etag || res2.headers["last-modified"] || "");
45621
46796
  });
45622
46797
  req2.on("error", reject);
45623
46798
  req2.on("timeout", () => {
@@ -45626,7 +46801,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45626
46801
  });
45627
46802
  req2.end();
45628
46803
  } else {
45629
- resolve12(res.headers.etag || res.headers["last-modified"] || "");
46804
+ resolve15(res.headers.etag || res.headers["last-modified"] || "");
45630
46805
  }
45631
46806
  });
45632
46807
  req.on("error", reject);
@@ -45642,17 +46817,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
45642
46817
  return { updated: false };
45643
46818
  }
45644
46819
  this.log("Downloading latest providers from GitHub...");
45645
- const tmpTar = path14.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
45646
- const tmpExtract = path14.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
46820
+ const tmpTar = path17.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
46821
+ const tmpExtract = path17.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
45647
46822
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
45648
46823
  fs7.mkdirSync(tmpExtract, { recursive: true });
45649
46824
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
45650
46825
  const extracted = fs7.readdirSync(tmpExtract);
45651
46826
  const rootDir = extracted.find(
45652
- (d) => fs7.statSync(path14.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
46827
+ (d) => fs7.statSync(path17.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
45653
46828
  );
45654
46829
  if (!rootDir) throw new Error("Unexpected tarball structure");
45655
- const sourceDir = path14.join(tmpExtract, rootDir);
46830
+ const sourceDir = path17.join(tmpExtract, rootDir);
45656
46831
  const backupDir = this.upstreamDir + ".bak";
45657
46832
  if (fs7.existsSync(this.upstreamDir)) {
45658
46833
  if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
@@ -45690,7 +46865,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45690
46865
  downloadFile(url2, destPath) {
45691
46866
  const https = require("https");
45692
46867
  const http3 = require("http");
45693
- return new Promise((resolve12, reject) => {
46868
+ return new Promise((resolve15, reject) => {
45694
46869
  const doRequest = (reqUrl, redirectCount = 0) => {
45695
46870
  if (redirectCount > 5) {
45696
46871
  reject(new Error("Too many redirects"));
@@ -45710,7 +46885,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45710
46885
  res.pipe(ws2);
45711
46886
  ws2.on("finish", () => {
45712
46887
  ws2.close();
45713
- resolve12();
46888
+ resolve15();
45714
46889
  });
45715
46890
  ws2.on("error", reject);
45716
46891
  });
@@ -45727,8 +46902,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
45727
46902
  copyDirRecursive(src, dest) {
45728
46903
  fs7.mkdirSync(dest, { recursive: true });
45729
46904
  for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
45730
- const srcPath = path14.join(src, entry.name);
45731
- const destPath = path14.join(dest, entry.name);
46905
+ const srcPath = path17.join(src, entry.name);
46906
+ const destPath = path17.join(dest, entry.name);
45732
46907
  if (entry.isDirectory()) {
45733
46908
  this.copyDirRecursive(srcPath, destPath);
45734
46909
  } else {
@@ -45739,7 +46914,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45739
46914
  /** .meta.json save */
45740
46915
  writeMeta(metaPath, etag, timestamp) {
45741
46916
  try {
45742
- fs7.mkdirSync(path14.dirname(metaPath), { recursive: true });
46917
+ fs7.mkdirSync(path17.dirname(metaPath), { recursive: true });
45743
46918
  fs7.writeFileSync(metaPath, JSON.stringify({
45744
46919
  etag,
45745
46920
  timestamp,
@@ -45756,7 +46931,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45756
46931
  const scan = (d) => {
45757
46932
  try {
45758
46933
  for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
45759
- if (entry.isDirectory()) scan(path14.join(d, entry.name));
46934
+ if (entry.isDirectory()) scan(path17.join(d, entry.name));
45760
46935
  else if (entry.name === "provider.json") count++;
45761
46936
  }
45762
46937
  } catch {
@@ -45984,17 +47159,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
45984
47159
  for (const root of searchRoots) {
45985
47160
  if (!fs7.existsSync(root)) continue;
45986
47161
  const candidate = this.getProviderDir(root, cat, type);
45987
- if (fs7.existsSync(path14.join(candidate, "provider.json"))) return candidate;
45988
- const catDir = path14.join(root, cat);
47162
+ if (fs7.existsSync(path17.join(candidate, "provider.json"))) return candidate;
47163
+ const catDir = path17.join(root, cat);
45989
47164
  if (fs7.existsSync(catDir)) {
45990
47165
  try {
45991
47166
  for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
45992
47167
  if (!entry.isDirectory()) continue;
45993
- const jsonPath = path14.join(catDir, entry.name, "provider.json");
47168
+ const jsonPath = path17.join(catDir, entry.name, "provider.json");
45994
47169
  if (fs7.existsSync(jsonPath)) {
45995
47170
  try {
45996
47171
  const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
45997
- if (data.type === type) return path14.join(catDir, entry.name);
47172
+ if (data.type === type) return path17.join(catDir, entry.name);
45998
47173
  } catch {
45999
47174
  }
46000
47175
  }
@@ -46011,7 +47186,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
46011
47186
  * (template substitution is NOT applied here — scripts.js handles that)
46012
47187
  */
46013
47188
  buildScriptWrappersFromDir(dir) {
46014
- const scriptsJs = path14.join(dir, "scripts.js");
47189
+ const scriptsJs = path17.join(dir, "scripts.js");
46015
47190
  if (fs7.existsSync(scriptsJs)) {
46016
47191
  try {
46017
47192
  delete require.cache[require.resolve(scriptsJs)];
@@ -46025,7 +47200,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
46025
47200
  for (const file2 of fs7.readdirSync(dir)) {
46026
47201
  if (!file2.endsWith(".js")) continue;
46027
47202
  const scriptName = toCamel(file2.replace(".js", ""));
46028
- const filePath = path14.join(dir, file2);
47203
+ const filePath = path17.join(dir, file2);
46029
47204
  result[scriptName] = (...args) => {
46030
47205
  try {
46031
47206
  let content = fs7.readFileSync(filePath, "utf-8");
@@ -46085,7 +47260,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
46085
47260
  }
46086
47261
  const hasJson = entries.some((e) => e.name === "provider.json");
46087
47262
  if (hasJson) {
46088
- const jsonPath = path14.join(d, "provider.json");
47263
+ const jsonPath = path17.join(d, "provider.json");
46089
47264
  try {
46090
47265
  const raw = fs7.readFileSync(jsonPath, "utf-8");
46091
47266
  const mod = JSON.parse(raw);
@@ -46106,7 +47281,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
46106
47281
  this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
46107
47282
  } else {
46108
47283
  const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
46109
- const scriptsPath = path14.join(d, "scripts.js");
47284
+ const scriptsPath = path17.join(d, "scripts.js");
46110
47285
  if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
46111
47286
  try {
46112
47287
  delete require.cache[require.resolve(scriptsPath)];
@@ -46132,7 +47307,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
46132
47307
  if (!entry.isDirectory()) continue;
46133
47308
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
46134
47309
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
46135
- scan(path14.join(d, entry.name));
47310
+ scan(path17.join(d, entry.name));
46136
47311
  }
46137
47312
  }
46138
47313
  };
@@ -46167,9 +47342,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
46167
47342
  }
46168
47343
  }
46169
47344
  compareVersions(a, b2) {
46170
- const normalize3 = (v2) => v2.split(/[-_+]/)[0].split(".").map((x) => parseInt(x, 10) || 0);
46171
- const pa2 = normalize3(a);
46172
- const pb = normalize3(b2);
47345
+ const normalize4 = (v2) => v2.split(/[-_+]/)[0].split(".").map((x) => parseInt(x, 10) || 0);
47346
+ const pa2 = normalize4(a);
47347
+ const pb = normalize4(b2);
46173
47348
  for (let i = 0; i < Math.max(pa2.length, pb.length); i++) {
46174
47349
  const va2 = pa2[i] || 0;
46175
47350
  const vb = pb[i] || 0;
@@ -46285,17 +47460,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
46285
47460
  throw new Error("No free port found");
46286
47461
  }
46287
47462
  function checkPortFree(port) {
46288
- return new Promise((resolve12) => {
47463
+ return new Promise((resolve15) => {
46289
47464
  const server = net3.createServer();
46290
47465
  server.unref();
46291
- server.on("error", () => resolve12(false));
47466
+ server.on("error", () => resolve15(false));
46292
47467
  server.listen(port, "127.0.0.1", () => {
46293
- server.close(() => resolve12(true));
47468
+ server.close(() => resolve15(true));
46294
47469
  });
46295
47470
  });
46296
47471
  }
46297
47472
  async function isCdpActive(port) {
46298
- return new Promise((resolve12) => {
47473
+ return new Promise((resolve15) => {
46299
47474
  const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
46300
47475
  timeout: 2e3
46301
47476
  }, (res) => {
@@ -46304,16 +47479,16 @@ Run 'adhdev doctor' for detailed diagnostics.`
46304
47479
  res.on("end", () => {
46305
47480
  try {
46306
47481
  const info = JSON.parse(data);
46307
- resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
47482
+ resolve15(!!info["WebKit-Version"] || !!info["Browser"]);
46308
47483
  } catch {
46309
- resolve12(false);
47484
+ resolve15(false);
46310
47485
  }
46311
47486
  });
46312
47487
  });
46313
- req.on("error", () => resolve12(false));
47488
+ req.on("error", () => resolve15(false));
46314
47489
  req.on("timeout", () => {
46315
47490
  req.destroy();
46316
- resolve12(false);
47491
+ resolve15(false);
46317
47492
  });
46318
47493
  });
46319
47494
  }
@@ -46453,8 +47628,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
46453
47628
  const appNameMap = getMacAppIdentifiers();
46454
47629
  const appName = appNameMap[ideId];
46455
47630
  if (appName) {
46456
- const storagePath = path15.join(
46457
- process.env.APPDATA || path15.join(os15.homedir(), "AppData", "Roaming"),
47631
+ const storagePath = path18.join(
47632
+ process.env.APPDATA || path18.join(os15.homedir(), "AppData", "Roaming"),
46458
47633
  appName,
46459
47634
  "storage.json"
46460
47635
  );
@@ -46628,9 +47803,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
46628
47803
  init_config();
46629
47804
  init_logger();
46630
47805
  var fs8 = __toESM2(require("fs"));
46631
- var path16 = __toESM2(require("path"));
47806
+ var path19 = __toESM2(require("path"));
46632
47807
  var os16 = __toESM2(require("os"));
46633
- 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");
47808
+ 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");
46634
47809
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
46635
47810
  var MAX_DAYS = 7;
46636
47811
  try {
@@ -46668,13 +47843,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
46668
47843
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
46669
47844
  }
46670
47845
  var currentDate2 = getDateStr2();
46671
- var currentFile = path16.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
47846
+ var currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
46672
47847
  var writeCount2 = 0;
46673
47848
  function checkRotation() {
46674
47849
  const today = getDateStr2();
46675
47850
  if (today !== currentDate2) {
46676
47851
  currentDate2 = today;
46677
- currentFile = path16.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
47852
+ currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
46678
47853
  cleanOldFiles();
46679
47854
  }
46680
47855
  }
@@ -46688,7 +47863,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
46688
47863
  const dateMatch = file2.match(/commands-(\d{4}-\d{2}-\d{2})/);
46689
47864
  if (dateMatch && dateMatch[1] < cutoffStr) {
46690
47865
  try {
46691
- fs8.unlinkSync(path16.join(LOG_DIR2, file2));
47866
+ fs8.unlinkSync(path19.join(LOG_DIR2, file2));
46692
47867
  } catch {
46693
47868
  }
46694
47869
  }
@@ -46698,8 +47873,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
46698
47873
  }
46699
47874
  function checkSize() {
46700
47875
  try {
46701
- const stat4 = fs8.statSync(currentFile);
46702
- if (stat4.size > MAX_FILE_SIZE) {
47876
+ const stat22 = fs8.statSync(currentFile);
47877
+ if (stat22.size > MAX_FILE_SIZE) {
46703
47878
  const backup = currentFile.replace(".jsonl", ".1.jsonl");
46704
47879
  try {
46705
47880
  fs8.unlinkSync(backup);
@@ -46981,12 +48156,18 @@ Run 'adhdev doctor' for detailed diagnostics.`
46981
48156
  const unreadSourceSessions = buildSessionEntries(
46982
48157
  options.allStates,
46983
48158
  options.cdpManagers,
46984
- { profile: "full" }
48159
+ {
48160
+ profile: "full",
48161
+ getGitSummaryForWorkspace: options.getGitSummaryForWorkspace
48162
+ }
46985
48163
  );
46986
48164
  const sessions = profile === "full" ? unreadSourceSessions : profile === "live" ? unreadSourceSessions.map(projectLiveSessionFromFull) : buildSessionEntries(
46987
48165
  options.allStates,
46988
48166
  options.cdpManagers,
46989
- { profile }
48167
+ {
48168
+ profile,
48169
+ getGitSummaryForWorkspace: options.getGitSummaryForWorkspace
48170
+ }
46990
48171
  );
46991
48172
  const sessionsById = new Map(sessions.map((session) => [session.id, session]));
46992
48173
  for (const sourceSession of unreadSourceSessions) {
@@ -47078,13 +48259,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
47078
48259
  var import_child_process9 = require("child_process");
47079
48260
  var fs9 = __toESM2(require("fs"));
47080
48261
  var os18 = __toESM2(require("os"));
47081
- var path17 = __toESM2(require("path"));
48262
+ var path20 = __toESM2(require("path"));
47082
48263
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
47083
48264
  function getUpgradeLogPath() {
47084
48265
  const home = os18.homedir();
47085
- const dir = path17.join(home, ".adhdev");
48266
+ const dir = path20.join(home, ".adhdev");
47086
48267
  fs9.mkdirSync(dir, { recursive: true });
47087
- return path17.join(dir, "daemon-upgrade.log");
48268
+ return path20.join(dir, "daemon-upgrade.log");
47088
48269
  }
47089
48270
  function appendUpgradeLog(message) {
47090
48271
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -47095,14 +48276,14 @@ Run 'adhdev doctor' for detailed diagnostics.`
47095
48276
  }
47096
48277
  }
47097
48278
  function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
47098
- const binDir = path17.dirname(nodeExecutable);
48279
+ const binDir = path20.dirname(nodeExecutable);
47099
48280
  if (platform10 === "win32") {
47100
- const npmCliPath = path17.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
48281
+ const npmCliPath = path20.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
47101
48282
  if (fs9.existsSync(npmCliPath)) {
47102
48283
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
47103
48284
  }
47104
48285
  for (const candidate of ["npm.exe", "npm"]) {
47105
- const candidatePath = path17.join(binDir, candidate);
48286
+ const candidatePath = path20.join(binDir, candidate);
47106
48287
  if (fs9.existsSync(candidatePath)) {
47107
48288
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
47108
48289
  }
@@ -47110,7 +48291,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
47110
48291
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
47111
48292
  }
47112
48293
  for (const candidate of ["npm"]) {
47113
- const candidatePath = path17.join(binDir, candidate);
48294
+ const candidatePath = path20.join(binDir, candidate);
47114
48295
  if (fs9.existsSync(candidatePath)) {
47115
48296
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
47116
48297
  }
@@ -47127,13 +48308,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
47127
48308
  let currentDir = resolvedPath;
47128
48309
  try {
47129
48310
  if (fs9.statSync(resolvedPath).isFile()) {
47130
- currentDir = path17.dirname(resolvedPath);
48311
+ currentDir = path20.dirname(resolvedPath);
47131
48312
  }
47132
48313
  } catch {
47133
- currentDir = path17.dirname(resolvedPath);
48314
+ currentDir = path20.dirname(resolvedPath);
47134
48315
  }
47135
48316
  while (true) {
47136
- const packageJsonPath = path17.join(currentDir, "package.json");
48317
+ const packageJsonPath = path20.join(currentDir, "package.json");
47137
48318
  try {
47138
48319
  if (fs9.existsSync(packageJsonPath)) {
47139
48320
  const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
@@ -47144,7 +48325,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
47144
48325
  }
47145
48326
  } catch {
47146
48327
  }
47147
- const parentDir = path17.dirname(currentDir);
48328
+ const parentDir = path20.dirname(currentDir);
47148
48329
  if (parentDir === currentDir) {
47149
48330
  return null;
47150
48331
  }
@@ -47152,13 +48333,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
47152
48333
  }
47153
48334
  }
47154
48335
  function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
47155
- const nodeModulesDir = packageName.startsWith("@") ? path17.dirname(path17.dirname(packageRoot)) : path17.dirname(packageRoot);
47156
- if (path17.basename(nodeModulesDir) !== "node_modules") {
48336
+ const nodeModulesDir = packageName.startsWith("@") ? path20.dirname(path20.dirname(packageRoot)) : path20.dirname(packageRoot);
48337
+ if (path20.basename(nodeModulesDir) !== "node_modules") {
47157
48338
  return null;
47158
48339
  }
47159
- const maybeLibDir = path17.dirname(nodeModulesDir);
47160
- if (path17.basename(maybeLibDir) === "lib") {
47161
- return path17.dirname(maybeLibDir);
48340
+ const maybeLibDir = path20.dirname(nodeModulesDir);
48341
+ if (path20.basename(maybeLibDir) === "lib") {
48342
+ return path20.dirname(maybeLibDir);
47162
48343
  }
47163
48344
  return maybeLibDir;
47164
48345
  }
@@ -47266,14 +48447,14 @@ Run 'adhdev doctor' for detailed diagnostics.`
47266
48447
  while (Date.now() - start < timeoutMs) {
47267
48448
  try {
47268
48449
  process.kill(pid, 0);
47269
- await new Promise((resolve12) => setTimeout(resolve12, 250));
48450
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
47270
48451
  } catch {
47271
48452
  return;
47272
48453
  }
47273
48454
  }
47274
48455
  }
47275
48456
  function stopSessionHostProcesses(appName) {
47276
- const pidFile = path17.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
48457
+ const pidFile = path20.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
47277
48458
  try {
47278
48459
  if (fs9.existsSync(pidFile)) {
47279
48460
  const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
@@ -47290,7 +48471,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
47290
48471
  }
47291
48472
  }
47292
48473
  function removeDaemonPidFile() {
47293
- const pidFile = path17.join(os18.homedir(), ".adhdev", "daemon.pid");
48474
+ const pidFile = path20.join(os18.homedir(), ".adhdev", "daemon.pid");
47294
48475
  try {
47295
48476
  fs9.unlinkSync(pidFile);
47296
48477
  } catch {
@@ -47301,7 +48482,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
47301
48482
  const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
47302
48483
  if (!npmRoot) return;
47303
48484
  const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
47304
- const binDir = process.platform === "win32" ? npmPrefix : path17.join(npmPrefix, "bin");
48485
+ const binDir = process.platform === "win32" ? npmPrefix : path20.join(npmPrefix, "bin");
47305
48486
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
47306
48487
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
47307
48488
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -47309,25 +48490,25 @@ Run 'adhdev doctor' for detailed diagnostics.`
47309
48490
  }
47310
48491
  if (pkgName.startsWith("@")) {
47311
48492
  const [scope, name] = pkgName.split("/");
47312
- const scopeDir = path17.join(npmRoot, scope);
48493
+ const scopeDir = path20.join(npmRoot, scope);
47313
48494
  if (!fs9.existsSync(scopeDir)) return;
47314
48495
  for (const entry of fs9.readdirSync(scopeDir)) {
47315
48496
  if (!entry.startsWith(`.${name}-`)) continue;
47316
- fs9.rmSync(path17.join(scopeDir, entry), { recursive: true, force: true });
47317
- appendUpgradeLog(`Removed stale scoped staging dir: ${path17.join(scopeDir, entry)}`);
48497
+ fs9.rmSync(path20.join(scopeDir, entry), { recursive: true, force: true });
48498
+ appendUpgradeLog(`Removed stale scoped staging dir: ${path20.join(scopeDir, entry)}`);
47318
48499
  }
47319
48500
  } else {
47320
48501
  for (const entry of fs9.readdirSync(npmRoot)) {
47321
48502
  if (!entry.startsWith(`.${pkgName}-`)) continue;
47322
- fs9.rmSync(path17.join(npmRoot, entry), { recursive: true, force: true });
47323
- appendUpgradeLog(`Removed stale staging dir: ${path17.join(npmRoot, entry)}`);
48503
+ fs9.rmSync(path20.join(npmRoot, entry), { recursive: true, force: true });
48504
+ appendUpgradeLog(`Removed stale staging dir: ${path20.join(npmRoot, entry)}`);
47324
48505
  }
47325
48506
  }
47326
48507
  if (fs9.existsSync(binDir)) {
47327
48508
  for (const entry of fs9.readdirSync(binDir)) {
47328
48509
  if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
47329
- fs9.rmSync(path17.join(binDir, entry), { recursive: true, force: true });
47330
- appendUpgradeLog(`Removed stale bin staging entry: ${path17.join(binDir, entry)}`);
48510
+ fs9.rmSync(path20.join(binDir, entry), { recursive: true, force: true });
48511
+ appendUpgradeLog(`Removed stale bin staging entry: ${path20.join(binDir, entry)}`);
47331
48512
  }
47332
48513
  }
47333
48514
  }
@@ -47377,7 +48558,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
47377
48558
  appendUpgradeLog(installOutput.trim());
47378
48559
  }
47379
48560
  if (process.platform === "win32") {
47380
- await new Promise((resolve12) => setTimeout(resolve12, 500));
48561
+ await new Promise((resolve15) => setTimeout(resolve15, 500));
47381
48562
  cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
47382
48563
  appendUpgradeLog("Post-install staging cleanup complete");
47383
48564
  }
@@ -48757,7 +49938,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
48757
49938
  const beforeCount = this.messageCount(before);
48758
49939
  const beforeSignature = this.lastMessageSignature(before);
48759
49940
  for (let attempt = 0; attempt < 12; attempt += 1) {
48760
- await new Promise((resolve12) => setTimeout(resolve12, 250));
49941
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
48761
49942
  let state;
48762
49943
  try {
48763
49944
  state = await this.readChat(evaluate);
@@ -48779,7 +49960,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
48779
49960
  if (this.messageCount(first) > 0 || this.lastMessageSignature(first)) {
48780
49961
  return first;
48781
49962
  }
48782
- await new Promise((resolve12) => setTimeout(resolve12, 150));
49963
+ await new Promise((resolve15) => setTimeout(resolve15, 150));
48783
49964
  const second = await this.readChat(evaluate);
48784
49965
  return this.messageCount(second) >= this.messageCount(first) ? second : first;
48785
49966
  }
@@ -48930,7 +50111,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
48930
50111
  if (typeof data.error === "string" && data.error.trim()) return false;
48931
50112
  }
48932
50113
  for (let attempt = 0; attempt < 6; attempt += 1) {
48933
- await new Promise((resolve12) => setTimeout(resolve12, 250));
50114
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
48934
50115
  const state = await this.readChat(evaluate);
48935
50116
  const title = this.getStateTitle(state);
48936
50117
  if (this.titlesMatch(title, sessionId)) return true;
@@ -49779,11 +50960,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
49779
50960
  init_io_contracts();
49780
50961
  init_chat_message_normalization();
49781
50962
  var fs11 = __toESM2(require("fs"));
49782
- var path18 = __toESM2(require("path"));
50963
+ var path21 = __toESM2(require("path"));
49783
50964
  var os19 = __toESM2(require("os"));
49784
50965
  var import_child_process10 = require("child_process");
49785
50966
  var import_os3 = require("os");
49786
- var ARCHIVE_PATH = path18.join(os19.homedir(), ".adhdev", "version-history.json");
50967
+ var ARCHIVE_PATH = path21.join(os19.homedir(), ".adhdev", "version-history.json");
49787
50968
  var MAX_ENTRIES_PER_PROVIDER = 20;
49788
50969
  var VersionArchive = class {
49789
50970
  history = {};
@@ -49830,7 +51011,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
49830
51011
  }
49831
51012
  save() {
49832
51013
  try {
49833
- fs11.mkdirSync(path18.dirname(ARCHIVE_PATH), { recursive: true });
51014
+ fs11.mkdirSync(path21.dirname(ARCHIVE_PATH), { recursive: true });
49834
51015
  fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
49835
51016
  } catch {
49836
51017
  }
@@ -49887,7 +51068,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
49887
51068
  for (const p of paths) {
49888
51069
  if (p.includes("*")) {
49889
51070
  const home = os19.homedir();
49890
- const resolved = p.replace(/\*/g, home.split(path18.sep).pop() || "");
51071
+ const resolved = p.replace(/\*/g, home.split(path21.sep).pop() || "");
49891
51072
  if (fs11.existsSync(resolved)) return resolved;
49892
51073
  } else {
49893
51074
  if (fs11.existsSync(p)) return p;
@@ -49897,7 +51078,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
49897
51078
  }
49898
51079
  function getMacAppVersion(appPath) {
49899
51080
  if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
49900
- const plistPath = path18.join(appPath, "Contents", "Info.plist");
51081
+ const plistPath = path21.join(appPath, "Contents", "Info.plist");
49901
51082
  if (!fs11.existsSync(plistPath)) return null;
49902
51083
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
49903
51084
  return raw || null;
@@ -49923,7 +51104,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
49923
51104
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
49924
51105
  let resolvedBin = cliBin;
49925
51106
  if (!resolvedBin && appPath && currentOs === "darwin") {
49926
- const bundled = path18.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
51107
+ const bundled = path21.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
49927
51108
  if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
49928
51109
  }
49929
51110
  info.installed = !!(appPath || resolvedBin);
@@ -49962,7 +51143,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
49962
51143
  }
49963
51144
  var http2 = __toESM2(require("http"));
49964
51145
  var fs15 = __toESM2(require("fs"));
49965
- var path222 = __toESM2(require("path"));
51146
+ var path25 = __toESM2(require("path"));
49966
51147
  init_config();
49967
51148
  function generateFiles(type, name, category, opts = {}) {
49968
51149
  const { cdpPorts, cli, processName, installPath, binary, extensionId, version: version2 = "0.1" } = opts;
@@ -50307,7 +51488,7 @@ async (params) => {
50307
51488
  }
50308
51489
  init_logger();
50309
51490
  var fs12 = __toESM2(require("fs"));
50310
- var path19 = __toESM2(require("path"));
51491
+ var path222 = __toESM2(require("path"));
50311
51492
  init_logger();
50312
51493
  async function handleCdpEvaluate(ctx, req, res) {
50313
51494
  const body = await ctx.readBody(req);
@@ -50486,17 +51667,17 @@ async (params) => {
50486
51667
  return;
50487
51668
  }
50488
51669
  let scriptsPath = "";
50489
- const directScripts = path19.join(dir, "scripts.js");
51670
+ const directScripts = path222.join(dir, "scripts.js");
50490
51671
  if (fs12.existsSync(directScripts)) {
50491
51672
  scriptsPath = directScripts;
50492
51673
  } else {
50493
- const scriptsDir = path19.join(dir, "scripts");
51674
+ const scriptsDir = path222.join(dir, "scripts");
50494
51675
  if (fs12.existsSync(scriptsDir)) {
50495
51676
  const versions = fs12.readdirSync(scriptsDir).filter((d) => {
50496
- return fs12.statSync(path19.join(scriptsDir, d)).isDirectory();
51677
+ return fs12.statSync(path222.join(scriptsDir, d)).isDirectory();
50497
51678
  }).sort().reverse();
50498
51679
  for (const ver of versions) {
50499
- const p = path19.join(scriptsDir, ver, "scripts.js");
51680
+ const p = path222.join(scriptsDir, ver, "scripts.js");
50500
51681
  if (fs12.existsSync(p)) {
50501
51682
  scriptsPath = p;
50502
51683
  break;
@@ -51323,7 +52504,7 @@ async (params) => {
51323
52504
  }
51324
52505
  }
51325
52506
  var fs13 = __toESM2(require("fs"));
51326
- var path20 = __toESM2(require("path"));
52507
+ var path232 = __toESM2(require("path"));
51327
52508
  function slugifyFixtureName(value) {
51328
52509
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
51329
52510
  return normalized || `fixture-${Date.now()}`;
@@ -51333,11 +52514,11 @@ async (params) => {
51333
52514
  if (!providerDir) {
51334
52515
  throw new Error(`Provider directory not found for '${type}'`);
51335
52516
  }
51336
- return path20.join(providerDir, "fixtures");
52517
+ return path232.join(providerDir, "fixtures");
51337
52518
  }
51338
52519
  function readCliFixture(ctx, type, name) {
51339
52520
  const fixtureDir = getCliFixtureDir(ctx, type);
51340
- const filePath = path20.join(fixtureDir, `${name}.json`);
52521
+ const filePath = path232.join(fixtureDir, `${name}.json`);
51341
52522
  if (!fs13.existsSync(filePath)) {
51342
52523
  throw new Error(`Fixture not found: ${filePath}`);
51343
52524
  }
@@ -51506,7 +52687,7 @@ async (params) => {
51506
52687
  return { target, instance, adapter };
51507
52688
  }
51508
52689
  function sleep(ms2) {
51509
- return new Promise((resolve12) => setTimeout(resolve12, ms2));
52690
+ return new Promise((resolve15) => setTimeout(resolve15, ms2));
51510
52691
  }
51511
52692
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
51512
52693
  const startedAt = Date.now();
@@ -51804,7 +52985,7 @@ async (params) => {
51804
52985
  return {
51805
52986
  mode: "fixture_replay_suite",
51806
52987
  pass: results.every((item) => item.pass),
51807
- failures: results.flatMap((item) => item.failures.map((failure) => `${item.fixtureName}: ${failure}`)),
52988
+ failures: results.flatMap((item) => item.failures.map((failure2) => `${item.fixtureName}: ${failure2}`)),
51808
52989
  result: firstFailure.result,
51809
52990
  assertions: firstFailure.assertions,
51810
52991
  fixture: firstFailure.fixture,
@@ -52104,7 +53285,7 @@ async (params) => {
52104
53285
  },
52105
53286
  notes: typeof body?.notes === "string" ? body.notes : void 0
52106
53287
  };
52107
- const filePath = path20.join(fixtureDir, `${name}.json`);
53288
+ const filePath = path232.join(fixtureDir, `${name}.json`);
52108
53289
  fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
52109
53290
  ctx.json(res, 200, {
52110
53291
  saved: true,
@@ -52128,7 +53309,7 @@ async (params) => {
52128
53309
  return;
52129
53310
  }
52130
53311
  const fixtures = fs13.readdirSync(fixtureDir).filter((file2) => file2.endsWith(".json")).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file2) => {
52131
- const fullPath = path20.join(fixtureDir, file2);
53312
+ const fullPath = path232.join(fixtureDir, file2);
52132
53313
  try {
52133
53314
  const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
52134
53315
  return {
@@ -52262,7 +53443,7 @@ async (params) => {
52262
53443
  }
52263
53444
  }
52264
53445
  var fs14 = __toESM2(require("fs"));
52265
- var path21 = __toESM2(require("path"));
53446
+ var path24 = __toESM2(require("path"));
52266
53447
  var os20 = __toESM2(require("os"));
52267
53448
  function getAutoImplPid(ctx) {
52268
53449
  const pid = ctx.autoImplProcess?.pid;
@@ -52312,22 +53493,22 @@ async (params) => {
52312
53493
  if (!fs14.existsSync(scriptsDir)) return null;
52313
53494
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
52314
53495
  try {
52315
- return fs14.statSync(path21.join(scriptsDir, d)).isDirectory();
53496
+ return fs14.statSync(path24.join(scriptsDir, d)).isDirectory();
52316
53497
  } catch {
52317
53498
  return false;
52318
53499
  }
52319
53500
  }).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
52320
53501
  if (versions.length === 0) return null;
52321
- return path21.join(scriptsDir, versions[0]);
53502
+ return path24.join(scriptsDir, versions[0]);
52322
53503
  }
52323
53504
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
52324
- const canonicalUserDir = path21.resolve(ctx.providerLoader.getUserProviderDir(category, type));
52325
- const desiredDir = requestedDir ? path21.resolve(requestedDir) : canonicalUserDir;
52326
- const upstreamRoot = path21.resolve(ctx.providerLoader.getUpstreamDir());
52327
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path21.sep}`)) {
53505
+ const canonicalUserDir = path24.resolve(ctx.providerLoader.getUserProviderDir(category, type));
53506
+ const desiredDir = requestedDir ? path24.resolve(requestedDir) : canonicalUserDir;
53507
+ const upstreamRoot = path24.resolve(ctx.providerLoader.getUpstreamDir());
53508
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path24.sep}`)) {
52328
53509
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
52329
53510
  }
52330
- if (path21.basename(desiredDir) !== type) {
53511
+ if (path24.basename(desiredDir) !== type) {
52331
53512
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
52332
53513
  }
52333
53514
  const sourceDir = ctx.findProviderDir(type);
@@ -52335,11 +53516,11 @@ async (params) => {
52335
53516
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
52336
53517
  }
52337
53518
  if (!fs14.existsSync(desiredDir)) {
52338
- fs14.mkdirSync(path21.dirname(desiredDir), { recursive: true });
53519
+ fs14.mkdirSync(path24.dirname(desiredDir), { recursive: true });
52339
53520
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
52340
53521
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
52341
53522
  }
52342
- const providerJson = path21.join(desiredDir, "provider.json");
53523
+ const providerJson = path24.join(desiredDir, "provider.json");
52343
53524
  if (!fs14.existsSync(providerJson)) {
52344
53525
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
52345
53526
  }
@@ -52350,13 +53531,13 @@ async (params) => {
52350
53531
  const refDir = ctx.findProviderDir(referenceType);
52351
53532
  if (!refDir || !fs14.existsSync(refDir)) return {};
52352
53533
  const referenceScripts = {};
52353
- const scriptsDir = path21.join(refDir, "scripts");
53534
+ const scriptsDir = path24.join(refDir, "scripts");
52354
53535
  const latestDir = getLatestScriptVersionDir(scriptsDir);
52355
53536
  if (!latestDir) return referenceScripts;
52356
53537
  for (const file2 of fs14.readdirSync(latestDir)) {
52357
53538
  if (!file2.endsWith(".js")) continue;
52358
53539
  try {
52359
- referenceScripts[file2] = fs14.readFileSync(path21.join(latestDir, file2), "utf-8");
53540
+ referenceScripts[file2] = fs14.readFileSync(path24.join(latestDir, file2), "utf-8");
52360
53541
  } catch {
52361
53542
  }
52362
53543
  }
@@ -52464,9 +53645,9 @@ async (params) => {
52464
53645
  });
52465
53646
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
52466
53647
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
52467
- const tmpDir = path21.join(os20.tmpdir(), "adhdev-autoimpl");
53648
+ const tmpDir = path24.join(os20.tmpdir(), "adhdev-autoimpl");
52468
53649
  if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
52469
- const promptFile = path21.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
53650
+ const promptFile = path24.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
52470
53651
  fs14.writeFileSync(promptFile, prompt, "utf-8");
52471
53652
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
52472
53653
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -52898,7 +54079,7 @@ async (params) => {
52898
54079
  setMode: "set_mode.js"
52899
54080
  };
52900
54081
  const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
52901
- const scriptsDir = path21.join(providerDir, "scripts");
54082
+ const scriptsDir = path24.join(providerDir, "scripts");
52902
54083
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
52903
54084
  if (latestScriptsDir) {
52904
54085
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -52909,7 +54090,7 @@ async (params) => {
52909
54090
  for (const file2 of fs14.readdirSync(latestScriptsDir)) {
52910
54091
  if (file2.endsWith(".js") && targetFileNames.has(file2)) {
52911
54092
  try {
52912
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file2), "utf-8");
54093
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file2), "utf-8");
52913
54094
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
52914
54095
  lines.push("```javascript");
52915
54096
  lines.push(content);
@@ -52926,7 +54107,7 @@ async (params) => {
52926
54107
  lines.push("");
52927
54108
  for (const file2 of refFiles) {
52928
54109
  try {
52929
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file2), "utf-8");
54110
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file2), "utf-8");
52930
54111
  lines.push(`### \`${file2}\` \u{1F512}`);
52931
54112
  lines.push("```javascript");
52932
54113
  lines.push(content);
@@ -52967,10 +54148,10 @@ async (params) => {
52967
54148
  lines.push("");
52968
54149
  }
52969
54150
  }
52970
- const docsDir = path21.join(providerDir, "../../docs");
54151
+ const docsDir = path24.join(providerDir, "../../docs");
52971
54152
  const loadGuide = (name) => {
52972
54153
  try {
52973
- const p = path21.join(docsDir, name);
54154
+ const p = path24.join(docsDir, name);
52974
54155
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
52975
54156
  } catch {
52976
54157
  }
@@ -53207,7 +54388,7 @@ async (params) => {
53207
54388
  parseApproval: "parse_approval.js"
53208
54389
  };
53209
54390
  const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
53210
- const scriptsDir = path21.join(providerDir, "scripts");
54391
+ const scriptsDir = path24.join(providerDir, "scripts");
53211
54392
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
53212
54393
  if (latestScriptsDir) {
53213
54394
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -53219,7 +54400,7 @@ async (params) => {
53219
54400
  if (!file2.endsWith(".js")) continue;
53220
54401
  if (!targetFileNames.has(file2)) continue;
53221
54402
  try {
53222
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file2), "utf-8");
54403
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file2), "utf-8");
53223
54404
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
53224
54405
  lines.push("```javascript");
53225
54406
  lines.push(content);
@@ -53235,7 +54416,7 @@ async (params) => {
53235
54416
  lines.push("");
53236
54417
  for (const file2 of refFiles) {
53237
54418
  try {
53238
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file2), "utf-8");
54419
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file2), "utf-8");
53239
54420
  lines.push(`### \`${file2}\` \u{1F512}`);
53240
54421
  lines.push("```javascript");
53241
54422
  lines.push(content);
@@ -53268,10 +54449,10 @@ async (params) => {
53268
54449
  lines.push("");
53269
54450
  }
53270
54451
  }
53271
- const docsDir = path21.join(providerDir, "../../docs");
54452
+ const docsDir = path24.join(providerDir, "../../docs");
53272
54453
  const loadGuide = (name) => {
53273
54454
  try {
53274
- const p = path21.join(docsDir, name);
54455
+ const p = path24.join(docsDir, name);
53275
54456
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
53276
54457
  } catch {
53277
54458
  }
@@ -53716,8 +54897,8 @@ data: ${JSON.stringify(msg.data)}
53716
54897
  }
53717
54898
  getEndpointList() {
53718
54899
  return this.routes.map((r) => {
53719
- const path232 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
53720
- return `${r.method.padEnd(5)} ${path232}`;
54900
+ const path26 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
54901
+ return `${r.method.padEnd(5)} ${path26}`;
53721
54902
  });
53722
54903
  }
53723
54904
  async start(port = DEV_SERVER_PORT) {
@@ -53748,15 +54929,15 @@ data: ${JSON.stringify(msg.data)}
53748
54929
  this.json(res, 500, { error: e.message });
53749
54930
  }
53750
54931
  });
53751
- return new Promise((resolve12, reject) => {
54932
+ return new Promise((resolve15, reject) => {
53752
54933
  this.server.listen(port, "127.0.0.1", () => {
53753
54934
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
53754
- resolve12();
54935
+ resolve15();
53755
54936
  });
53756
54937
  this.server.on("error", (e) => {
53757
54938
  if (e.code === "EADDRINUSE") {
53758
54939
  this.log(`Port ${port} in use, skipping dev server`);
53759
- resolve12();
54940
+ resolve15();
53760
54941
  } else {
53761
54942
  reject(e);
53762
54943
  }
@@ -53838,20 +55019,20 @@ data: ${JSON.stringify(msg.data)}
53838
55019
  child.stderr?.on("data", (d) => {
53839
55020
  stderr += d.toString().slice(0, 2e3);
53840
55021
  });
53841
- await new Promise((resolve12) => {
55022
+ await new Promise((resolve15) => {
53842
55023
  const timer = setTimeout(() => {
53843
55024
  child.kill();
53844
- resolve12();
55025
+ resolve15();
53845
55026
  }, 3e3);
53846
55027
  child.on("exit", () => {
53847
55028
  clearTimeout(timer);
53848
- resolve12();
55029
+ resolve15();
53849
55030
  });
53850
55031
  child.stdout?.once("data", () => {
53851
55032
  setTimeout(() => {
53852
55033
  child.kill();
53853
55034
  clearTimeout(timer);
53854
- resolve12();
55035
+ resolve15();
53855
55036
  }, 500);
53856
55037
  });
53857
55038
  });
@@ -54005,12 +55186,12 @@ data: ${JSON.stringify(msg.data)}
54005
55186
  // ─── DevConsole SPA ───
54006
55187
  getConsoleDistDir() {
54007
55188
  const candidates = [
54008
- path222.resolve(__dirname, "../../web-devconsole/dist"),
54009
- path222.resolve(__dirname, "../../../web-devconsole/dist"),
54010
- path222.join(process.cwd(), "packages/web-devconsole/dist")
55189
+ path25.resolve(__dirname, "../../web-devconsole/dist"),
55190
+ path25.resolve(__dirname, "../../../web-devconsole/dist"),
55191
+ path25.join(process.cwd(), "packages/web-devconsole/dist")
54011
55192
  ];
54012
55193
  for (const dir of candidates) {
54013
- if (fs15.existsSync(path222.join(dir, "index.html"))) return dir;
55194
+ if (fs15.existsSync(path25.join(dir, "index.html"))) return dir;
54014
55195
  }
54015
55196
  return null;
54016
55197
  }
@@ -54020,7 +55201,7 @@ data: ${JSON.stringify(msg.data)}
54020
55201
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
54021
55202
  return;
54022
55203
  }
54023
- const htmlPath = path222.join(distDir, "index.html");
55204
+ const htmlPath = path25.join(distDir, "index.html");
54024
55205
  try {
54025
55206
  const html = fs15.readFileSync(htmlPath, "utf-8");
54026
55207
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -54045,15 +55226,15 @@ data: ${JSON.stringify(msg.data)}
54045
55226
  this.json(res, 404, { error: "Not found" });
54046
55227
  return;
54047
55228
  }
54048
- const safePath = path222.normalize(pathname).replace(/^\.\.\//, "");
54049
- const filePath = path222.join(distDir, safePath);
55229
+ const safePath = path25.normalize(pathname).replace(/^\.\.\//, "");
55230
+ const filePath = path25.join(distDir, safePath);
54050
55231
  if (!filePath.startsWith(distDir)) {
54051
55232
  this.json(res, 403, { error: "Forbidden" });
54052
55233
  return;
54053
55234
  }
54054
55235
  try {
54055
55236
  const content = fs15.readFileSync(filePath);
54056
- const ext = path222.extname(filePath);
55237
+ const ext = path25.extname(filePath);
54057
55238
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
54058
55239
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
54059
55240
  res.end(content);
@@ -54166,10 +55347,10 @@ data: ${JSON.stringify(msg.data)}
54166
55347
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
54167
55348
  if (entry.isDirectory()) {
54168
55349
  files.push({ path: rel, size: 0, type: "dir" });
54169
- scan(path222.join(d, entry.name), rel);
55350
+ scan(path25.join(d, entry.name), rel);
54170
55351
  } else {
54171
- const stat4 = fs15.statSync(path222.join(d, entry.name));
54172
- files.push({ path: rel, size: stat4.size, type: "file" });
55352
+ const stat22 = fs15.statSync(path25.join(d, entry.name));
55353
+ files.push({ path: rel, size: stat22.size, type: "file" });
54173
55354
  }
54174
55355
  }
54175
55356
  } catch {
@@ -54191,7 +55372,7 @@ data: ${JSON.stringify(msg.data)}
54191
55372
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
54192
55373
  return;
54193
55374
  }
54194
- const fullPath = path222.resolve(dir, path222.normalize(filePath));
55375
+ const fullPath = path25.resolve(dir, path25.normalize(filePath));
54195
55376
  if (!fullPath.startsWith(dir)) {
54196
55377
  this.json(res, 403, { error: "Forbidden" });
54197
55378
  return;
@@ -54216,14 +55397,14 @@ data: ${JSON.stringify(msg.data)}
54216
55397
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
54217
55398
  return;
54218
55399
  }
54219
- const fullPath = path222.resolve(dir, path222.normalize(filePath));
55400
+ const fullPath = path25.resolve(dir, path25.normalize(filePath));
54220
55401
  if (!fullPath.startsWith(dir)) {
54221
55402
  this.json(res, 403, { error: "Forbidden" });
54222
55403
  return;
54223
55404
  }
54224
55405
  try {
54225
55406
  if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
54226
- fs15.mkdirSync(path222.dirname(fullPath), { recursive: true });
55407
+ fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
54227
55408
  fs15.writeFileSync(fullPath, content, "utf-8");
54228
55409
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
54229
55410
  this.providerLoader.reload();
@@ -54240,7 +55421,7 @@ data: ${JSON.stringify(msg.data)}
54240
55421
  return;
54241
55422
  }
54242
55423
  for (const name of ["scripts.js", "provider.json"]) {
54243
- const p = path222.join(dir, name);
55424
+ const p = path25.join(dir, name);
54244
55425
  if (fs15.existsSync(p)) {
54245
55426
  const source = fs15.readFileSync(p, "utf-8");
54246
55427
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -54261,8 +55442,8 @@ data: ${JSON.stringify(msg.data)}
54261
55442
  this.json(res, 404, { error: `Provider not found: ${type}` });
54262
55443
  return;
54263
55444
  }
54264
- const target = fs15.existsSync(path222.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
54265
- const targetPath = path222.join(dir, target);
55445
+ const target = fs15.existsSync(path25.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
55446
+ const targetPath = path25.join(dir, target);
54266
55447
  try {
54267
55448
  if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
54268
55449
  fs15.writeFileSync(targetPath, source, "utf-8");
@@ -54354,14 +55535,14 @@ data: ${JSON.stringify(msg.data)}
54354
55535
  child.stderr?.on("data", (d) => {
54355
55536
  stderr += d.toString();
54356
55537
  });
54357
- await new Promise((resolve12) => {
55538
+ await new Promise((resolve15) => {
54358
55539
  const timer = setTimeout(() => {
54359
55540
  child.kill();
54360
- resolve12();
55541
+ resolve15();
54361
55542
  }, timeout);
54362
55543
  child.on("exit", () => {
54363
55544
  clearTimeout(timer);
54364
- resolve12();
55545
+ resolve15();
54365
55546
  });
54366
55547
  });
54367
55548
  const elapsed = Date.now() - start;
@@ -54409,7 +55590,7 @@ data: ${JSON.stringify(msg.data)}
54409
55590
  }
54410
55591
  let targetDir;
54411
55592
  targetDir = this.providerLoader.getUserProviderDir(category, type);
54412
- const jsonPath = path222.join(targetDir, "provider.json");
55593
+ const jsonPath = path25.join(targetDir, "provider.json");
54413
55594
  if (fs15.existsSync(jsonPath)) {
54414
55595
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
54415
55596
  return;
@@ -54421,8 +55602,8 @@ data: ${JSON.stringify(msg.data)}
54421
55602
  const createdFiles = ["provider.json"];
54422
55603
  if (result.files) {
54423
55604
  for (const [relPath, content] of Object.entries(result.files)) {
54424
- const fullPath = path222.join(targetDir, relPath);
54425
- fs15.mkdirSync(path222.dirname(fullPath), { recursive: true });
55605
+ const fullPath = path25.join(targetDir, relPath);
55606
+ fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
54426
55607
  fs15.writeFileSync(fullPath, content, "utf-8");
54427
55608
  createdFiles.push(relPath);
54428
55609
  }
@@ -54475,22 +55656,22 @@ data: ${JSON.stringify(msg.data)}
54475
55656
  if (!fs15.existsSync(scriptsDir)) return null;
54476
55657
  const versions = fs15.readdirSync(scriptsDir).filter((d) => {
54477
55658
  try {
54478
- return fs15.statSync(path222.join(scriptsDir, d)).isDirectory();
55659
+ return fs15.statSync(path25.join(scriptsDir, d)).isDirectory();
54479
55660
  } catch {
54480
55661
  return false;
54481
55662
  }
54482
55663
  }).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
54483
55664
  if (versions.length === 0) return null;
54484
- return path222.join(scriptsDir, versions[0]);
55665
+ return path25.join(scriptsDir, versions[0]);
54485
55666
  }
54486
55667
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
54487
- const canonicalUserDir = path222.resolve(this.providerLoader.getUserProviderDir(category, type));
54488
- const desiredDir = requestedDir ? path222.resolve(requestedDir) : canonicalUserDir;
54489
- const upstreamRoot = path222.resolve(this.providerLoader.getUpstreamDir());
54490
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path222.sep}`)) {
55668
+ const canonicalUserDir = path25.resolve(this.providerLoader.getUserProviderDir(category, type));
55669
+ const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
55670
+ const upstreamRoot = path25.resolve(this.providerLoader.getUpstreamDir());
55671
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
54491
55672
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
54492
55673
  }
54493
- if (path222.basename(desiredDir) !== type) {
55674
+ if (path25.basename(desiredDir) !== type) {
54494
55675
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
54495
55676
  }
54496
55677
  const sourceDir = this.findProviderDir(type);
@@ -54498,11 +55679,11 @@ data: ${JSON.stringify(msg.data)}
54498
55679
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
54499
55680
  }
54500
55681
  if (!fs15.existsSync(desiredDir)) {
54501
- fs15.mkdirSync(path222.dirname(desiredDir), { recursive: true });
55682
+ fs15.mkdirSync(path25.dirname(desiredDir), { recursive: true });
54502
55683
  fs15.cpSync(sourceDir, desiredDir, { recursive: true });
54503
55684
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
54504
55685
  }
54505
- const providerJson = path222.join(desiredDir, "provider.json");
55686
+ const providerJson = path25.join(desiredDir, "provider.json");
54506
55687
  if (!fs15.existsSync(providerJson)) {
54507
55688
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
54508
55689
  }
@@ -54538,7 +55719,7 @@ data: ${JSON.stringify(msg.data)}
54538
55719
  setMode: "set_mode.js"
54539
55720
  };
54540
55721
  const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
54541
- const scriptsDir = path222.join(providerDir, "scripts");
55722
+ const scriptsDir = path25.join(providerDir, "scripts");
54542
55723
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
54543
55724
  if (latestScriptsDir) {
54544
55725
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -54549,7 +55730,7 @@ data: ${JSON.stringify(msg.data)}
54549
55730
  for (const file2 of fs15.readdirSync(latestScriptsDir)) {
54550
55731
  if (file2.endsWith(".js") && targetFileNames.has(file2)) {
54551
55732
  try {
54552
- const content = fs15.readFileSync(path222.join(latestScriptsDir, file2), "utf-8");
55733
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file2), "utf-8");
54553
55734
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
54554
55735
  lines.push("```javascript");
54555
55736
  lines.push(content);
@@ -54566,7 +55747,7 @@ data: ${JSON.stringify(msg.data)}
54566
55747
  lines.push("");
54567
55748
  for (const file2 of refFiles) {
54568
55749
  try {
54569
- const content = fs15.readFileSync(path222.join(latestScriptsDir, file2), "utf-8");
55750
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file2), "utf-8");
54570
55751
  lines.push(`### \`${file2}\` \u{1F512}`);
54571
55752
  lines.push("```javascript");
54572
55753
  lines.push(content);
@@ -54607,10 +55788,10 @@ data: ${JSON.stringify(msg.data)}
54607
55788
  lines.push("");
54608
55789
  }
54609
55790
  }
54610
- const docsDir = path222.join(providerDir, "../../docs");
55791
+ const docsDir = path25.join(providerDir, "../../docs");
54611
55792
  const loadGuide = (name) => {
54612
55793
  try {
54613
- const p = path222.join(docsDir, name);
55794
+ const p = path25.join(docsDir, name);
54614
55795
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
54615
55796
  } catch {
54616
55797
  }
@@ -54784,7 +55965,7 @@ data: ${JSON.stringify(msg.data)}
54784
55965
  parseApproval: "parse_approval.js"
54785
55966
  };
54786
55967
  const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
54787
- const scriptsDir = path222.join(providerDir, "scripts");
55968
+ const scriptsDir = path25.join(providerDir, "scripts");
54788
55969
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
54789
55970
  if (latestScriptsDir) {
54790
55971
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -54796,7 +55977,7 @@ data: ${JSON.stringify(msg.data)}
54796
55977
  if (!file2.endsWith(".js")) continue;
54797
55978
  if (!targetFileNames.has(file2)) continue;
54798
55979
  try {
54799
- const content = fs15.readFileSync(path222.join(latestScriptsDir, file2), "utf-8");
55980
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file2), "utf-8");
54800
55981
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
54801
55982
  lines.push("```javascript");
54802
55983
  lines.push(content);
@@ -54812,7 +55993,7 @@ data: ${JSON.stringify(msg.data)}
54812
55993
  lines.push("");
54813
55994
  for (const file2 of refFiles) {
54814
55995
  try {
54815
- const content = fs15.readFileSync(path222.join(latestScriptsDir, file2), "utf-8");
55996
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file2), "utf-8");
54816
55997
  lines.push(`### \`${file2}\` \u{1F512}`);
54817
55998
  lines.push("```javascript");
54818
55999
  lines.push(content);
@@ -54845,10 +56026,10 @@ data: ${JSON.stringify(msg.data)}
54845
56026
  lines.push("");
54846
56027
  }
54847
56028
  }
54848
- const docsDir = path222.join(providerDir, "../../docs");
56029
+ const docsDir = path25.join(providerDir, "../../docs");
54849
56030
  const loadGuide = (name) => {
54850
56031
  try {
54851
- const p = path222.join(docsDir, name);
56032
+ const p = path25.join(docsDir, name);
54852
56033
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
54853
56034
  } catch {
54854
56035
  }
@@ -55031,14 +56212,14 @@ data: ${JSON.stringify(msg.data)}
55031
56212
  res.end(JSON.stringify(data, null, 2));
55032
56213
  }
55033
56214
  async readBody(req) {
55034
- return new Promise((resolve12) => {
56215
+ return new Promise((resolve15) => {
55035
56216
  let body = "";
55036
56217
  req.on("data", (chunk) => body += chunk);
55037
56218
  req.on("end", () => {
55038
56219
  try {
55039
- resolve12(JSON.parse(body));
56220
+ resolve15(JSON.parse(body));
55040
56221
  } catch {
55041
- resolve12({});
56222
+ resolve15({});
55042
56223
  }
55043
56224
  });
55044
56225
  });
@@ -55540,7 +56721,7 @@ data: ${JSON.stringify(msg.data)}
55540
56721
  const deadline = Date.now() + timeoutMs;
55541
56722
  while (Date.now() < deadline) {
55542
56723
  if (await canConnect(endpoint)) return;
55543
- await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
56724
+ await new Promise((resolve15) => setTimeout(resolve15, STARTUP_POLL_MS));
55544
56725
  }
55545
56726
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
55546
56727
  }
@@ -55714,10 +56895,10 @@ data: ${JSON.stringify(msg.data)}
55714
56895
  const buffer = Buffer.from(await res.arrayBuffer());
55715
56896
  const fs16 = await import("fs");
55716
56897
  fs16.writeFileSync(vsixPath, buffer);
55717
- return new Promise((resolve12) => {
56898
+ return new Promise((resolve15) => {
55718
56899
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
55719
56900
  (0, import_child_process11.exec)(cmd, { timeout: 6e4 }, (error48, _stdout, stderr) => {
55720
- resolve12({
56901
+ resolve15({
55721
56902
  extensionId: extension.id,
55722
56903
  marketplaceId: extension.marketplaceId,
55723
56904
  success: !error48,
@@ -55730,11 +56911,11 @@ data: ${JSON.stringify(msg.data)}
55730
56911
  } catch (e) {
55731
56912
  }
55732
56913
  }
55733
- return new Promise((resolve12) => {
56914
+ return new Promise((resolve15) => {
55734
56915
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
55735
56916
  (0, import_child_process11.exec)(cmd, { timeout: 6e4 }, (error48, stdout, stderr) => {
55736
56917
  if (error48) {
55737
- resolve12({
56918
+ resolve15({
55738
56919
  extensionId: extension.id,
55739
56920
  marketplaceId: extension.marketplaceId,
55740
56921
  success: false,
@@ -55742,7 +56923,7 @@ data: ${JSON.stringify(msg.data)}
55742
56923
  error: stderr || error48.message
55743
56924
  });
55744
56925
  } else {
55745
- resolve12({
56926
+ resolve15({
55746
56927
  extensionId: extension.id,
55747
56928
  marketplaceId: extension.marketplaceId,
55748
56929
  success: true,
@@ -56852,6 +58033,8 @@ var StandaloneServer = class {
56852
58033
  wsSessionHostDiagnosticsSubscriptions = /* @__PURE__ */ new Map();
56853
58034
  wsSessionModalSubscriptions = /* @__PURE__ */ new Map();
56854
58035
  wsDaemonMetadataSubscriptions = /* @__PURE__ */ new Map();
58036
+ wsGitSubscriptions = /* @__PURE__ */ new Map();
58037
+ gitWorkspaceMonitor = (0, import_daemon_core2.createGitWorkspaceMonitor)();
56855
58038
  authToken = null;
56856
58039
  passwordConfigPath = getStandalonePasswordConfigPath();
56857
58040
  passwordConfig = null;
@@ -57117,6 +58300,7 @@ var StandaloneServer = class {
57117
58300
  void this.flushWsMachineRuntimeSubscriptions();
57118
58301
  void this.flushWsSessionHostDiagnosticsSubscriptions();
57119
58302
  void this.flushWsSessionModalSubscriptions();
58303
+ if (this.hasWsGitSubscriptions()) void this.flushWsGitSubscriptions();
57120
58304
  }, STATUS_INTERVAL);
57121
58305
  this.running = true;
57122
58306
  await new Promise((resolve4) => {
@@ -57605,6 +58789,7 @@ var StandaloneServer = class {
57605
58789
  this.wsSessionHostDiagnosticsSubscriptions.set(ws2, /* @__PURE__ */ new Map());
57606
58790
  this.wsSessionModalSubscriptions.set(ws2, /* @__PURE__ */ new Map());
57607
58791
  this.wsDaemonMetadataSubscriptions.set(ws2, /* @__PURE__ */ new Map());
58792
+ this.wsGitSubscriptions.set(ws2, /* @__PURE__ */ new Map());
57608
58793
  console.log(`[WS] Client connected (total: ${this.clients.size})`);
57609
58794
  const status = this.getWsStatus(this.buildSharedSnapshot("live"));
57610
58795
  this.lastWsStatusSignature = this.buildWsStatusSignature(status);
@@ -57648,6 +58833,7 @@ var StandaloneServer = class {
57648
58833
  this.wsSessionHostDiagnosticsSubscriptions.delete(ws2);
57649
58834
  this.wsSessionModalSubscriptions.delete(ws2);
57650
58835
  this.wsDaemonMetadataSubscriptions.delete(ws2);
58836
+ this.clearWsGitSubscriptions(ws2);
57651
58837
  console.log(`[WS] Client disconnected (total: ${this.clients.size})`);
57652
58838
  });
57653
58839
  ws2.on("error", () => {
@@ -57657,8 +58843,19 @@ var StandaloneServer = class {
57657
58843
  this.wsSessionHostDiagnosticsSubscriptions.delete(ws2);
57658
58844
  this.wsSessionModalSubscriptions.delete(ws2);
57659
58845
  this.wsDaemonMetadataSubscriptions.delete(ws2);
58846
+ this.clearWsGitSubscriptions(ws2);
57660
58847
  });
57661
58848
  }
58849
+ clearWsGitSubscriptions(ws2) {
58850
+ const subs = this.wsGitSubscriptions.get(ws2);
58851
+ if (subs) {
58852
+ subs.forEach((sub) => {
58853
+ sub.subscription.dispose();
58854
+ });
58855
+ subs.clear();
58856
+ }
58857
+ this.wsGitSubscriptions.delete(ws2);
58858
+ }
57662
58859
  async handleWsSubscribe(ws2, msg) {
57663
58860
  if (msg.topic === "session.chat_tail") {
57664
58861
  const params = msg.params;
@@ -57746,6 +58943,25 @@ var StandaloneServer = class {
57746
58943
  lastSentAt: 0
57747
58944
  });
57748
58945
  await this.flushWsDaemonMetadataSubscriptions(ws2);
58946
+ return;
58947
+ }
58948
+ if (msg.topic === "workspace.git") {
58949
+ const params = msg.params;
58950
+ if (!params?.workspace) return;
58951
+ const normalized = (0, import_daemon_core2.normalizeGitWorkspaceSubscriptionParams)(params);
58952
+ const subs = this.wsGitSubscriptions.get(ws2) || /* @__PURE__ */ new Map();
58953
+ this.wsGitSubscriptions.set(ws2, subs);
58954
+ subs.get(msg.key)?.subscription.dispose();
58955
+ subs.set(msg.key, {
58956
+ request: {
58957
+ ...msg,
58958
+ topic: "workspace.git",
58959
+ params: normalized
58960
+ },
58961
+ subscription: this.gitWorkspaceMonitor.createSubscription(normalized),
58962
+ lastSentAt: 0
58963
+ });
58964
+ await this.flushWsGitSubscriptions(ws2);
57749
58965
  }
57750
58966
  }
57751
58967
  handleWsUnsubscribe(ws2, msg) {
@@ -57767,6 +58983,12 @@ var StandaloneServer = class {
57767
58983
  }
57768
58984
  if (msg.topic === "daemon.metadata") {
57769
58985
  this.wsDaemonMetadataSubscriptions.get(ws2)?.delete(msg.key);
58986
+ return;
58987
+ }
58988
+ if (msg.topic === "workspace.git") {
58989
+ const sub = this.wsGitSubscriptions.get(ws2)?.get(msg.key);
58990
+ sub?.subscription.dispose();
58991
+ this.wsGitSubscriptions.get(ws2)?.delete(msg.key);
57770
58992
  }
57771
58993
  }
57772
58994
  async buildChatTailUpdate(request, state, key) {
@@ -57990,6 +59212,45 @@ var StandaloneServer = class {
57990
59212
  }
57991
59213
  }
57992
59214
  }
59215
+ hasWsGitSubscriptions(targetWs) {
59216
+ const targets = targetWs ? [targetWs] : Array.from(this.clients);
59217
+ for (const ws2 of targets) {
59218
+ const subs = this.wsGitSubscriptions.get(ws2);
59219
+ if (subs && subs.size > 0) return true;
59220
+ }
59221
+ return false;
59222
+ }
59223
+ async flushWsGitSubscriptions(targetWs) {
59224
+ if (!this.hasWsGitSubscriptions(targetWs)) return;
59225
+ const targets = targetWs ? [targetWs] : Array.from(this.clients);
59226
+ const now = Date.now();
59227
+ const tasks = [];
59228
+ for (const ws2 of targets) {
59229
+ if (ws2.readyState !== import_ws.WebSocket.OPEN) continue;
59230
+ const subs = this.wsGitSubscriptions.get(ws2);
59231
+ if (!subs || subs.size === 0) continue;
59232
+ subs.forEach((sub, key) => {
59233
+ const intervalMs = Math.max(1, Number(sub.subscription.params.intervalMs || sub.request.params.intervalMs || 0));
59234
+ if (sub.lastSentAt > 0 && now - sub.lastSentAt < intervalMs) return;
59235
+ tasks.push({ ws: ws2, key, sub });
59236
+ });
59237
+ }
59238
+ await (0, import_daemon_core2.runAsyncBatch)(tasks, async ({ ws: ws2, key, sub }) => {
59239
+ try {
59240
+ const monitorUpdate = await sub.subscription.refresh();
59241
+ const current = this.wsGitSubscriptions.get(ws2)?.get(key);
59242
+ if (current !== sub || ws2.readyState !== import_ws.WebSocket.OPEN) return;
59243
+ sub.lastSentAt = monitorUpdate.timestamp;
59244
+ const update = {
59245
+ ...monitorUpdate,
59246
+ key
59247
+ };
59248
+ ws2.send(JSON.stringify({ type: "topic_update", update }));
59249
+ } catch (error48) {
59250
+ import_daemon_core2.LOG.warn("Standalone", `[workspace.git] skipped workspace=${sub.request.params.workspace} key=${key} error=${error48?.message || error48}`);
59251
+ }
59252
+ }, { concurrency: 2 });
59253
+ }
57993
59254
  // ─── Core Logic ───
57994
59255
  buildSharedSnapshot(profile = "full") {
57995
59256
  const cfgSnap = (0, import_daemon_core2.loadConfig)();
@@ -58114,6 +59375,7 @@ var StandaloneServer = class {
58114
59375
  }
58115
59376
  if (type.startsWith("session_host_")) void this.flushWsSessionHostDiagnosticsSubscriptions();
58116
59377
  if (type === "resolve_action" || type === "send_chat" || type === "read_chat") void this.flushWsSessionModalSubscriptions();
59378
+ if (type.startsWith("git_") && this.hasWsGitSubscriptions()) void this.flushWsGitSubscriptions();
58117
59379
  return result;
58118
59380
  }
58119
59381
  scheduleBroadcastStatus() {