@adhdev/daemon-standalone 0.9.53 → 0.9.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -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
  }
@@ -35998,13 +37123,13 @@ ${cleanBody}`;
35998
37123
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
35999
37124
  try {
36000
37125
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
36001
- const dir = path7.join(HISTORY_DIR, sanitized);
37126
+ const dir = path10.join(HISTORY_DIR, sanitized);
36002
37127
  if (!fs32.existsSync(dir)) return { messages: [], hasMore: false };
36003
37128
  const files = listHistoryFiles(dir, historySessionId);
36004
37129
  const allMessages = [];
36005
37130
  const seen = /* @__PURE__ */ new Set();
36006
37131
  for (const file2 of files) {
36007
- const filePath = path7.join(dir, file2);
37132
+ const filePath = path10.join(dir, file2);
36008
37133
  const content = fs32.readFileSync(filePath, "utf-8");
36009
37134
  const lines = content.trim().split("\n").filter(Boolean);
36010
37135
  for (let i = 0; i < lines.length; i++) {
@@ -36028,7 +37153,7 @@ ${cleanBody}`;
36028
37153
  function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
36029
37154
  try {
36030
37155
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
36031
- const dir = path7.join(HISTORY_DIR, sanitized);
37156
+ const dir = path10.join(HISTORY_DIR, sanitized);
36032
37157
  if (!fs32.existsSync(dir)) {
36033
37158
  savedHistorySessionCache.delete(sanitized);
36034
37159
  return { sessions: [], hasMore: false };
@@ -36089,11 +37214,11 @@ ${cleanBody}`;
36089
37214
  }
36090
37215
  function readExistingSessionStartRecord(agentType, historySessionId) {
36091
37216
  try {
36092
- const dir = path7.join(HISTORY_DIR, agentType);
37217
+ const dir = path10.join(HISTORY_DIR, agentType);
36093
37218
  if (!fs32.existsSync(dir)) return null;
36094
37219
  const files = listHistoryFiles(dir, historySessionId).sort();
36095
37220
  for (const file2 of files) {
36096
- 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);
36097
37222
  for (const line of lines) {
36098
37223
  try {
36099
37224
  const parsed = JSON.parse(line);
@@ -36113,16 +37238,16 @@ ${cleanBody}`;
36113
37238
  function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
36114
37239
  if (records.length === 0) return false;
36115
37240
  try {
36116
- const dir = path7.join(HISTORY_DIR, agentType);
37241
+ const dir = path10.join(HISTORY_DIR, agentType);
36117
37242
  fs32.mkdirSync(dir, { recursive: true });
36118
37243
  const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
36119
37244
  for (const file2 of fs32.readdirSync(dir)) {
36120
37245
  if (file2.startsWith(prefix) && file2.endsWith(".jsonl")) {
36121
- fs32.unlinkSync(path7.join(dir, file2));
37246
+ fs32.unlinkSync(path10.join(dir, file2));
36122
37247
  }
36123
37248
  }
36124
37249
  const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
36125
- const filePath = path7.join(dir, `${prefix}${targetDate}.jsonl`);
37250
+ const filePath = path10.join(dir, `${prefix}${targetDate}.jsonl`);
36126
37251
  fs32.writeFileSync(filePath, `${records.map((record2) => JSON.stringify(record2)).join("\n")}
36127
37252
  `, "utf-8");
36128
37253
  invalidatePersistedSavedHistoryIndex(agentType, dir);
@@ -37966,6 +39091,10 @@ ${effect.notification.body || ""}`.trim();
37966
39091
  function shouldIncludeRuntimeMetadata(profile) {
37967
39092
  return true;
37968
39093
  }
39094
+ function getGitSummaryForWorkspace(workspace, options) {
39095
+ if (!workspace) return void 0;
39096
+ return options.getGitSummaryForWorkspace?.(workspace) || void 0;
39097
+ }
37969
39098
  function findCdpManager(cdpManagers, key) {
37970
39099
  const exact = cdpManagers.get(key);
37971
39100
  if (exact) return exact.isConnected ? exact : null;
@@ -38021,6 +39150,8 @@ ${effect.notification.body || ""}`.trim();
38021
39150
  const controlValues = normalizeProviderStateControlValues(state.controlValues);
38022
39151
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
38023
39152
  const includeSessionControls = shouldIncludeSessionControls(profile);
39153
+ const workspace = state.workspace || null;
39154
+ const git = getGitSummaryForWorkspace(workspace, options);
38024
39155
  const title = activeChat?.title || state.name;
38025
39156
  return {
38026
39157
  id: state.instanceId || state.type,
@@ -38033,7 +39164,8 @@ ${effect.notification.body || ""}`.trim();
38033
39164
  activeModal: activeChat?.activeModal || null
38034
39165
  }),
38035
39166
  title,
38036
- workspace: state.workspace || null,
39167
+ workspace,
39168
+ ...git && { git },
38037
39169
  activeChat,
38038
39170
  ...summaryMetadata && { summaryMetadata },
38039
39171
  ...includeSessionMetadata && { capabilities: state.sessionCapabilities || IDE_SESSION_CAPABILITIES },
@@ -38054,6 +39186,8 @@ ${effect.notification.body || ""}`.trim();
38054
39186
  const controlValues = normalizeProviderStateControlValues(ext.controlValues);
38055
39187
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
38056
39188
  const includeSessionControls = shouldIncludeSessionControls(profile);
39189
+ const workspace = parent.workspace || null;
39190
+ const git = getGitSummaryForWorkspace(workspace, options);
38057
39191
  return {
38058
39192
  id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
38059
39193
  parentId: parent.instanceId || parent.type,
@@ -38066,7 +39200,8 @@ ${effect.notification.body || ""}`.trim();
38066
39200
  activeModal: activeChat?.activeModal || null
38067
39201
  }),
38068
39202
  title: activeChat?.title || ext.name,
38069
- workspace: parent.workspace || null,
39203
+ workspace,
39204
+ ...git && { git },
38070
39205
  activeChat,
38071
39206
  ...summaryMetadata && { summaryMetadata },
38072
39207
  ...includeSessionMetadata && { capabilities: ext.sessionCapabilities || EXTENSION_SESSION_CAPABILITIES },
@@ -38102,6 +39237,8 @@ ${effect.notification.body || ""}`.trim();
38102
39237
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
38103
39238
  const includeRuntimeMetadata = shouldIncludeRuntimeMetadata(profile);
38104
39239
  const includeSessionControls = shouldIncludeSessionControls(profile);
39240
+ const workspace = state.workspace || null;
39241
+ const git = getGitSummaryForWorkspace(workspace, options);
38105
39242
  return {
38106
39243
  id: state.instanceId,
38107
39244
  parentId: null,
@@ -38114,7 +39251,8 @@ ${effect.notification.body || ""}`.trim();
38114
39251
  activeModal: activeChat?.activeModal || null
38115
39252
  }),
38116
39253
  title: activeChat?.title || state.name,
38117
- workspace: state.workspace || null,
39254
+ workspace,
39255
+ ...git && { git },
38118
39256
  ...includeRuntimeMetadata && {
38119
39257
  runtimeKey: state.runtime?.runtimeKey,
38120
39258
  runtimeDisplayName: state.runtime?.displayName,
@@ -38149,6 +39287,8 @@ ${effect.notification.body || ""}`.trim();
38149
39287
  const controlValues = normalizeProviderStateControlValues(state.controlValues);
38150
39288
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
38151
39289
  const includeSessionControls = shouldIncludeSessionControls(profile);
39290
+ const workspace = state.workspace || null;
39291
+ const git = getGitSummaryForWorkspace(workspace, options);
38152
39292
  return {
38153
39293
  id: state.instanceId,
38154
39294
  parentId: null,
@@ -38160,7 +39300,8 @@ ${effect.notification.body || ""}`.trim();
38160
39300
  activeModal: activeChat?.activeModal || null
38161
39301
  }),
38162
39302
  title: activeChat?.title || state.name,
38163
- workspace: state.workspace || null,
39303
+ workspace,
39304
+ ...git && { git },
38164
39305
  activeChat,
38165
39306
  ...summaryMetadata && { summaryMetadata },
38166
39307
  ...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES },
@@ -38271,7 +39412,7 @@ ${effect.notification.body || ""}`.trim();
38271
39412
  }
38272
39413
  var fs42 = __toESM2(require("fs"));
38273
39414
  var os62 = __toESM2(require("os"));
38274
- var path8 = __toESM2(require("path"));
39415
+ var path11 = __toESM2(require("path"));
38275
39416
  var import_node_crypto = require("crypto");
38276
39417
  init_contracts();
38277
39418
  var VALID_INPUT_MEDIA_TYPES = /* @__PURE__ */ new Set(["text", "image", "audio", "video", "resource"]);
@@ -38954,7 +40095,7 @@ ${effect.notification.body || ""}`.trim();
38954
40095
  }
38955
40096
  function getChatDebugBundleDir() {
38956
40097
  const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
38957
- return override || path8.join(os62.homedir(), ".adhdev", "debug-bundles", "chat");
40098
+ return override || path11.join(os62.homedir(), ".adhdev", "debug-bundles", "chat");
38958
40099
  }
38959
40100
  function safeBundleIdSegment(value, fallback) {
38960
40101
  const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
@@ -38987,7 +40128,7 @@ ${effect.notification.body || ""}`.trim();
38987
40128
  const bundleId = createChatDebugBundleId(targetSessionId);
38988
40129
  const dir = getChatDebugBundleDir();
38989
40130
  fs42.mkdirSync(dir, { recursive: true });
38990
- const savedPath = path8.join(dir, `${bundleId}.json`);
40131
+ const savedPath = path11.join(dir, `${bundleId}.json`);
38991
40132
  const json2 = `${JSON.stringify(bundle, null, 2)}
38992
40133
  `;
38993
40134
  fs42.writeFileSync(savedPath, json2, { encoding: "utf8", mode: 384 });
@@ -39181,7 +40322,7 @@ ${effect.notification.body || ""}`.trim();
39181
40322
  async function getStableExtensionBaseline(h) {
39182
40323
  const first = await readExtensionChatState(h);
39183
40324
  if (getStateMessageCount(first) > 0 || getStateLastSignature(first)) return first;
39184
- await new Promise((resolve12) => setTimeout(resolve12, 150));
40325
+ await new Promise((resolve15) => setTimeout(resolve15, 150));
39185
40326
  const second = await readExtensionChatState(h);
39186
40327
  return getStateMessageCount(second) >= getStateMessageCount(first) ? second : first;
39187
40328
  }
@@ -39189,7 +40330,7 @@ ${effect.notification.body || ""}`.trim();
39189
40330
  const beforeCount = getStateMessageCount(before);
39190
40331
  const beforeSignature = getStateLastSignature(before);
39191
40332
  for (let attempt = 0; attempt < 12; attempt += 1) {
39192
- await new Promise((resolve12) => setTimeout(resolve12, 250));
40333
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
39193
40334
  const state = await readExtensionChatState(h);
39194
40335
  if (state?.status === "waiting_approval") return true;
39195
40336
  const afterCount = getStateMessageCount(state);
@@ -40123,7 +41264,7 @@ ${effect.notification.body || ""}`.trim();
40123
41264
  return { success: false, error: "resolveAction script not available for this provider" };
40124
41265
  }
40125
41266
  var fs52 = __toESM2(require("fs"));
40126
- var path9 = __toESM2(require("path"));
41267
+ var path12 = __toESM2(require("path"));
40127
41268
  var os7 = __toESM2(require("os"));
40128
41269
  var KEY_TO_VK = {
40129
41270
  Backspace: 8,
@@ -40380,25 +41521,25 @@ ${effect.notification.body || ""}`.trim();
40380
41521
  const inputPath = rawPath || ".";
40381
41522
  const home = os7.homedir();
40382
41523
  if (inputPath.startsWith("~")) {
40383
- return path9.resolve(path9.join(home, inputPath.slice(1)));
41524
+ return path12.resolve(path12.join(home, inputPath.slice(1)));
40384
41525
  }
40385
41526
  if (process.platform === "win32") {
40386
41527
  const normalized = normalizeWindowsRequestedPath(inputPath);
40387
- if (path9.win32.isAbsolute(normalized)) {
40388
- return path9.win32.normalize(normalized);
41528
+ if (path12.win32.isAbsolute(normalized)) {
41529
+ return path12.win32.normalize(normalized);
40389
41530
  }
40390
- return path9.win32.resolve(normalized);
41531
+ return path12.win32.resolve(normalized);
40391
41532
  }
40392
- if (path9.isAbsolute(inputPath)) {
40393
- return path9.normalize(inputPath);
41533
+ if (path12.isAbsolute(inputPath)) {
41534
+ return path12.normalize(inputPath);
40394
41535
  }
40395
- return path9.resolve(inputPath);
41536
+ return path12.resolve(inputPath);
40396
41537
  }
40397
41538
  function listDirectoryEntriesSafe(dirPath) {
40398
41539
  const entries = fs52.readdirSync(dirPath, { withFileTypes: true });
40399
41540
  const files = [];
40400
41541
  for (const entry of entries) {
40401
- const entryPath = path9.join(dirPath, entry.name);
41542
+ const entryPath = path12.join(dirPath, entry.name);
40402
41543
  try {
40403
41544
  if (entry.isDirectory()) {
40404
41545
  files.push({ name: entry.name, type: "directory" });
@@ -40414,11 +41555,11 @@ ${effect.notification.body || ""}`.trim();
40414
41555
  files.push({ name: entry.name, type: "file", size });
40415
41556
  continue;
40416
41557
  }
40417
- const stat4 = fs52.statSync(entryPath);
41558
+ const stat22 = fs52.statSync(entryPath);
40418
41559
  files.push({
40419
41560
  name: entry.name,
40420
- type: stat4.isDirectory() ? "directory" : "file",
40421
- size: stat4.isFile() ? stat4.size : void 0
41561
+ type: stat22.isDirectory() ? "directory" : "file",
41562
+ size: stat22.isFile() ? stat22.size : void 0
40422
41563
  });
40423
41564
  } catch {
40424
41565
  }
@@ -40452,7 +41593,7 @@ ${effect.notification.body || ""}`.trim();
40452
41593
  async function handleFileWrite(h, args) {
40453
41594
  try {
40454
41595
  const filePath = resolveSafePath(args?.path);
40455
- fs52.mkdirSync(path9.dirname(filePath), { recursive: true });
41596
+ fs52.mkdirSync(path12.dirname(filePath), { recursive: true });
40456
41597
  fs52.writeFileSync(filePath, args?.content || "", "utf-8");
40457
41598
  return { success: true, path: filePath };
40458
41599
  } catch (e) {
@@ -40793,7 +41934,7 @@ ${effect.notification.body || ""}`.trim();
40793
41934
  const enterCount = cliCommand.enterCount || 1;
40794
41935
  await adapter.writeRaw(cliCommand.text + "\r");
40795
41936
  for (let i = 1; i < enterCount; i += 1) {
40796
- await new Promise((resolve12) => setTimeout(resolve12, 50));
41937
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
40797
41938
  await adapter.writeRaw("\r");
40798
41939
  }
40799
41940
  }
@@ -41283,6 +42424,12 @@ ${effect.notification.body || ""}`.trim();
41283
42424
  this._currentRoute = this.resolveRoute(args);
41284
42425
  const startedAt = Date.now();
41285
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
+ }
41286
42433
  const sessionScopedCommands = /* @__PURE__ */ new Set([
41287
42434
  "read_chat",
41288
42435
  "get_chat_debug_bundle",
@@ -41308,7 +42455,6 @@ ${effect.notification.body || ""}`.trim();
41308
42455
  this.logCommandEnd(cmd, result2, startedAt);
41309
42456
  return result2;
41310
42457
  }
41311
- let result;
41312
42458
  if (!this._currentRoute.session && !this._currentRoute.managerKey && !this._currentRoute.providerType) {
41313
42459
  const cdpCommands = ["send_chat", "read_chat", "list_chats", "new_chat", "switch_chat", "set_mode", "change_model", "set_thought_level", "resolve_action"];
41314
42460
  if (cdpCommands.includes(cmd)) {
@@ -41459,7 +42605,7 @@ ${effect.notification.body || ""}`.trim();
41459
42605
  try {
41460
42606
  const http3 = await import("http");
41461
42607
  const postData = JSON.stringify(body);
41462
- const result = await new Promise((resolve12, reject) => {
42608
+ const result = await new Promise((resolve15, reject) => {
41463
42609
  const req = http3.request({
41464
42610
  hostname: "127.0.0.1",
41465
42611
  port: 19280,
@@ -41471,9 +42617,9 @@ ${effect.notification.body || ""}`.trim();
41471
42617
  res.on("data", (chunk) => data += chunk);
41472
42618
  res.on("end", () => {
41473
42619
  try {
41474
- resolve12(JSON.parse(data));
42620
+ resolve15(JSON.parse(data));
41475
42621
  } catch {
41476
- resolve12({ raw: data });
42622
+ resolve15({ raw: data });
41477
42623
  }
41478
42624
  });
41479
42625
  });
@@ -41491,15 +42637,15 @@ ${effect.notification.body || ""}`.trim();
41491
42637
  if (!providerType) return { success: false, error: "providerType required" };
41492
42638
  try {
41493
42639
  const http3 = await import("http");
41494
- const result = await new Promise((resolve12, reject) => {
42640
+ const result = await new Promise((resolve15, reject) => {
41495
42641
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
41496
42642
  let data = "";
41497
42643
  res.on("data", (chunk) => data += chunk);
41498
42644
  res.on("end", () => {
41499
42645
  try {
41500
- resolve12(JSON.parse(data));
42646
+ resolve15(JSON.parse(data));
41501
42647
  } catch {
41502
- resolve12({ raw: data });
42648
+ resolve15({ raw: data });
41503
42649
  }
41504
42650
  });
41505
42651
  }).on("error", reject);
@@ -41513,7 +42659,7 @@ ${effect.notification.body || ""}`.trim();
41513
42659
  try {
41514
42660
  const http3 = await import("http");
41515
42661
  const postData = JSON.stringify(args || {});
41516
- const result = await new Promise((resolve12, reject) => {
42662
+ const result = await new Promise((resolve15, reject) => {
41517
42663
  const req = http3.request({
41518
42664
  hostname: "127.0.0.1",
41519
42665
  port: 19280,
@@ -41525,9 +42671,9 @@ ${effect.notification.body || ""}`.trim();
41525
42671
  res.on("data", (chunk) => data += chunk);
41526
42672
  res.on("end", () => {
41527
42673
  try {
41528
- resolve12(JSON.parse(data));
42674
+ resolve15(JSON.parse(data));
41529
42675
  } catch {
41530
- resolve12({ raw: data });
42676
+ resolve15({ raw: data });
41531
42677
  }
41532
42678
  });
41533
42679
  });
@@ -41542,7 +42688,7 @@ ${effect.notification.body || ""}`.trim();
41542
42688
  }
41543
42689
  };
41544
42690
  var os13 = __toESM2(require("os"));
41545
- var path13 = __toESM2(require("path"));
42691
+ var path16 = __toESM2(require("path"));
41546
42692
  var crypto4 = __toESM2(require("crypto"));
41547
42693
  var import_fs5 = require("fs");
41548
42694
  var import_child_process6 = require("child_process");
@@ -41550,7 +42696,7 @@ ${effect.notification.body || ""}`.trim();
41550
42696
  init_provider_cli_adapter();
41551
42697
  init_config();
41552
42698
  var os12 = __toESM2(require("os"));
41553
- var path12 = __toESM2(require("path"));
42699
+ var path15 = __toESM2(require("path"));
41554
42700
  var crypto3 = __toESM2(require("crypto"));
41555
42701
  var fs6 = __toESM2(require("fs"));
41556
42702
  var import_node_module = require("module");
@@ -41607,7 +42753,7 @@ ${effect.notification.body || ""}`.trim();
41607
42753
  var CachedDatabaseSync = null;
41608
42754
  function getDatabaseSync() {
41609
42755
  if (CachedDatabaseSync) return CachedDatabaseSync;
41610
- 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"));
41611
42757
  const sqliteModule = requireFn(`node:${"sqlite"}`);
41612
42758
  CachedDatabaseSync = sqliteModule.DatabaseSync;
41613
42759
  if (!CachedDatabaseSync) {
@@ -41645,7 +42791,7 @@ ${effect.notification.body || ""}`.trim();
41645
42791
  if (status === "stopped") {
41646
42792
  throw new Error("CLI runtime stopped before it became ready");
41647
42793
  }
41648
- await new Promise((resolve12) => setTimeout(resolve12, pollMs));
42794
+ await new Promise((resolve15) => setTimeout(resolve15, pollMs));
41649
42795
  }
41650
42796
  throw new Error(`CLI runtime did not become ready within ${timeoutMs}ms`);
41651
42797
  }
@@ -41996,7 +43142,7 @@ ${effect.notification.body || ""}`.trim();
41996
43142
  const enterCount = cliCommand.enterCount || 1;
41997
43143
  await this.adapter.writeRaw(cliCommand.text + "\r");
41998
43144
  for (let i = 1; i < enterCount; i += 1) {
41999
- await new Promise((resolve12) => setTimeout(resolve12, 50));
43145
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
42000
43146
  await this.adapter.writeRaw("\r");
42001
43147
  }
42002
43148
  }
@@ -43108,13 +44254,13 @@ ${effect.notification.body || ""}`.trim();
43108
44254
  }
43109
44255
  this.currentStatus = "waiting_approval";
43110
44256
  this.detectStatusTransition();
43111
- const approved = await new Promise((resolve12) => {
43112
- this.permissionResolvers.push(resolve12);
44257
+ const approved = await new Promise((resolve15) => {
44258
+ this.permissionResolvers.push(resolve15);
43113
44259
  setTimeout(() => {
43114
- const idx = this.permissionResolvers.indexOf(resolve12);
44260
+ const idx = this.permissionResolvers.indexOf(resolve15);
43115
44261
  if (idx >= 0) {
43116
44262
  this.permissionResolvers.splice(idx, 1);
43117
- resolve12(false);
44263
+ resolve15(false);
43118
44264
  }
43119
44265
  }, 3e5);
43120
44266
  });
@@ -43683,11 +44829,11 @@ ${rawInput}` : rawInput;
43683
44829
  }
43684
44830
  function isExplicitCommand(command) {
43685
44831
  const trimmed = command.trim();
43686
- return path13.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
44832
+ return path16.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
43687
44833
  }
43688
44834
  function expandExecutable(command) {
43689
44835
  const trimmed = command.trim();
43690
- return trimmed.startsWith("~") ? path13.join(os13.homedir(), trimmed.slice(1)) : trimmed;
44836
+ return trimmed.startsWith("~") ? path16.join(os13.homedir(), trimmed.slice(1)) : trimmed;
43691
44837
  }
43692
44838
  function commandExists(command) {
43693
44839
  const trimmed = command.trim();
@@ -43968,7 +45114,7 @@ ${rawInput}` : rawInput;
43968
45114
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
43969
45115
  const trimmed = (workingDir || "").trim();
43970
45116
  if (!trimmed) throw new Error("working directory required");
43971
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path13.resolve(trimmed);
45117
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path16.resolve(trimmed);
43972
45118
  const normalizedType = this.providerLoader.resolveAlias(cliType);
43973
45119
  const rawProvider = this.providerLoader.getByAlias(cliType);
43974
45120
  const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
@@ -44467,9 +45613,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
44467
45613
  var import_child_process7 = require("child_process");
44468
45614
  var net3 = __toESM2(require("net"));
44469
45615
  var os15 = __toESM2(require("os"));
44470
- var path15 = __toESM2(require("path"));
45616
+ var path18 = __toESM2(require("path"));
44471
45617
  var fs7 = __toESM2(require("fs"));
44472
- var path14 = __toESM2(require("path"));
45618
+ var path17 = __toESM2(require("path"));
44473
45619
  var os14 = __toESM2(require("os"));
44474
45620
  var chokidar = __toESM2((init_chokidar(), __toCommonJS(chokidar_exports)));
44475
45621
  init_logger();
@@ -44730,7 +45876,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44730
45876
  try {
44731
45877
  if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
44732
45878
  return ["ide", "extension", "cli", "acp"].some(
44733
- (category) => fs7.existsSync(path14.join(candidate, category))
45879
+ (category) => fs7.existsSync(path17.join(candidate, category))
44734
45880
  );
44735
45881
  } catch {
44736
45882
  return false;
@@ -44738,20 +45884,20 @@ Run 'adhdev doctor' for detailed diagnostics.`
44738
45884
  }
44739
45885
  static hasProviderRootMarker(candidate) {
44740
45886
  try {
44741
- return fs7.existsSync(path14.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
45887
+ return fs7.existsSync(path17.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
44742
45888
  } catch {
44743
45889
  return false;
44744
45890
  }
44745
45891
  }
44746
45892
  detectDefaultUserDir() {
44747
- const fallback = path14.join(os14.homedir(), ".adhdev", "providers");
45893
+ const fallback = path17.join(os14.homedir(), ".adhdev", "providers");
44748
45894
  const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
44749
45895
  const visited = /* @__PURE__ */ new Set();
44750
45896
  for (const start of this.probeStarts) {
44751
- let current = path14.resolve(start);
45897
+ let current = path17.resolve(start);
44752
45898
  while (!visited.has(current)) {
44753
45899
  visited.add(current);
44754
- const siblingCandidate = path14.join(path14.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
45900
+ const siblingCandidate = path17.join(path17.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
44755
45901
  if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
44756
45902
  const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
44757
45903
  if (envOptIn || hasMarker) {
@@ -44773,7 +45919,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44773
45919
  return { path: siblingCandidate, source };
44774
45920
  }
44775
45921
  }
44776
- const parent = path14.dirname(current);
45922
+ const parent = path17.dirname(current);
44777
45923
  if (parent === current) break;
44778
45924
  current = parent;
44779
45925
  }
@@ -44783,11 +45929,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
44783
45929
  constructor(options) {
44784
45930
  this.logFn = options?.logFn || LOG2.forComponent("Provider").asLogFn();
44785
45931
  this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
44786
- this.defaultProvidersDir = path14.join(os14.homedir(), ".adhdev", "providers");
45932
+ this.defaultProvidersDir = path17.join(os14.homedir(), ".adhdev", "providers");
44787
45933
  const detected = this.detectDefaultUserDir();
44788
45934
  this.userDir = detected.path;
44789
45935
  this.userDirSource = detected.source;
44790
- this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
45936
+ this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
44791
45937
  this.disableUpstream = false;
44792
45938
  this.applySourceConfig({
44793
45939
  userDir: options?.userDir,
@@ -44846,7 +45992,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44846
45992
  this.userDir = detected.path;
44847
45993
  this.userDirSource = detected.source;
44848
45994
  }
44849
- this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
45995
+ this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
44850
45996
  this.disableUpstream = this.sourceMode === "no-upstream";
44851
45997
  if (this.explicitProviderDir) {
44852
45998
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
@@ -44860,7 +46006,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44860
46006
  * Canonical provider directory shape for a given root.
44861
46007
  */
44862
46008
  getProviderDir(root, category, type) {
44863
- return path14.join(root, category, type);
46009
+ return path17.join(root, category, type);
44864
46010
  }
44865
46011
  /**
44866
46012
  * Canonical user override directory for a provider.
@@ -44887,7 +46033,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44887
46033
  resolveProviderFile(type, ...segments) {
44888
46034
  const dir = this.findProviderDirInternal(type);
44889
46035
  if (!dir) return null;
44890
- return path14.join(dir, ...segments);
46036
+ return path17.join(dir, ...segments);
44891
46037
  }
44892
46038
  /**
44893
46039
  * Load all providers (3-tier priority)
@@ -44926,7 +46072,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44926
46072
  if (!fs7.existsSync(this.upstreamDir)) return false;
44927
46073
  try {
44928
46074
  return fs7.readdirSync(this.upstreamDir).some(
44929
- (d) => fs7.statSync(path14.join(this.upstreamDir, d)).isDirectory()
46075
+ (d) => fs7.statSync(path17.join(this.upstreamDir, d)).isDirectory()
44930
46076
  );
44931
46077
  } catch {
44932
46078
  return false;
@@ -45423,8 +46569,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
45423
46569
  resolved._resolvedScriptDir = entry.scriptDir;
45424
46570
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
45425
46571
  if (providerDir) {
45426
- const fullDir = path14.join(providerDir, entry.scriptDir);
45427
- 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;
45428
46574
  }
45429
46575
  matched = true;
45430
46576
  }
@@ -45439,8 +46585,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
45439
46585
  resolved._resolvedScriptDir = base.defaultScriptDir;
45440
46586
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
45441
46587
  if (providerDir) {
45442
- const fullDir = path14.join(providerDir, base.defaultScriptDir);
45443
- 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;
45444
46590
  }
45445
46591
  }
45446
46592
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -45457,8 +46603,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
45457
46603
  resolved._resolvedScriptDir = dirOverride;
45458
46604
  resolved._resolvedScriptsSource = `versions:${range}`;
45459
46605
  if (providerDir) {
45460
- const fullDir = path14.join(providerDir, dirOverride);
45461
- 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;
45462
46608
  }
45463
46609
  }
45464
46610
  } else if (override.scripts) {
@@ -45474,8 +46620,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
45474
46620
  resolved._resolvedScriptDir = base.defaultScriptDir;
45475
46621
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
45476
46622
  if (providerDir) {
45477
- const fullDir = path14.join(providerDir, base.defaultScriptDir);
45478
- 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;
45479
46625
  }
45480
46626
  }
45481
46627
  }
@@ -45507,14 +46653,14 @@ Run 'adhdev doctor' for detailed diagnostics.`
45507
46653
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
45508
46654
  return null;
45509
46655
  }
45510
- const dir = path14.join(providerDir, scriptDir);
46656
+ const dir = path17.join(providerDir, scriptDir);
45511
46657
  if (!fs7.existsSync(dir)) {
45512
46658
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
45513
46659
  return null;
45514
46660
  }
45515
46661
  const cached2 = this.scriptsCache.get(dir);
45516
46662
  if (cached2) return cached2;
45517
- const scriptsJs = path14.join(dir, "scripts.js");
46663
+ const scriptsJs = path17.join(dir, "scripts.js");
45518
46664
  if (fs7.existsSync(scriptsJs)) {
45519
46665
  try {
45520
46666
  delete require.cache[require.resolve(scriptsJs)];
@@ -45556,7 +46702,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45556
46702
  return;
45557
46703
  }
45558
46704
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
45559
- this.log(`File changed: ${path14.basename(filePath)}, reloading...`);
46705
+ this.log(`File changed: ${path17.basename(filePath)}, reloading...`);
45560
46706
  this.reload();
45561
46707
  }
45562
46708
  };
@@ -45611,7 +46757,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45611
46757
  }
45612
46758
  const https = require("https");
45613
46759
  const { execSync: execSync7 } = require("child_process");
45614
- const metaPath = path14.join(this.upstreamDir, _ProviderLoader.META_FILE);
46760
+ const metaPath = path17.join(this.upstreamDir, _ProviderLoader.META_FILE);
45615
46761
  let prevEtag = "";
45616
46762
  let prevTimestamp = 0;
45617
46763
  try {
@@ -45628,7 +46774,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45628
46774
  return { updated: false };
45629
46775
  }
45630
46776
  try {
45631
- const etag = await new Promise((resolve12, reject) => {
46777
+ const etag = await new Promise((resolve15, reject) => {
45632
46778
  const options = {
45633
46779
  method: "HEAD",
45634
46780
  hostname: "github.com",
@@ -45646,7 +46792,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45646
46792
  headers: { "User-Agent": "adhdev-launcher" },
45647
46793
  timeout: 1e4
45648
46794
  }, (res2) => {
45649
- resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
46795
+ resolve15(res2.headers.etag || res2.headers["last-modified"] || "");
45650
46796
  });
45651
46797
  req2.on("error", reject);
45652
46798
  req2.on("timeout", () => {
@@ -45655,7 +46801,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45655
46801
  });
45656
46802
  req2.end();
45657
46803
  } else {
45658
- resolve12(res.headers.etag || res.headers["last-modified"] || "");
46804
+ resolve15(res.headers.etag || res.headers["last-modified"] || "");
45659
46805
  }
45660
46806
  });
45661
46807
  req.on("error", reject);
@@ -45671,17 +46817,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
45671
46817
  return { updated: false };
45672
46818
  }
45673
46819
  this.log("Downloading latest providers from GitHub...");
45674
- const tmpTar = path14.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
45675
- 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()}`);
45676
46822
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
45677
46823
  fs7.mkdirSync(tmpExtract, { recursive: true });
45678
46824
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
45679
46825
  const extracted = fs7.readdirSync(tmpExtract);
45680
46826
  const rootDir = extracted.find(
45681
- (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")
45682
46828
  );
45683
46829
  if (!rootDir) throw new Error("Unexpected tarball structure");
45684
- const sourceDir = path14.join(tmpExtract, rootDir);
46830
+ const sourceDir = path17.join(tmpExtract, rootDir);
45685
46831
  const backupDir = this.upstreamDir + ".bak";
45686
46832
  if (fs7.existsSync(this.upstreamDir)) {
45687
46833
  if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
@@ -45719,7 +46865,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45719
46865
  downloadFile(url2, destPath) {
45720
46866
  const https = require("https");
45721
46867
  const http3 = require("http");
45722
- return new Promise((resolve12, reject) => {
46868
+ return new Promise((resolve15, reject) => {
45723
46869
  const doRequest = (reqUrl, redirectCount = 0) => {
45724
46870
  if (redirectCount > 5) {
45725
46871
  reject(new Error("Too many redirects"));
@@ -45739,7 +46885,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45739
46885
  res.pipe(ws2);
45740
46886
  ws2.on("finish", () => {
45741
46887
  ws2.close();
45742
- resolve12();
46888
+ resolve15();
45743
46889
  });
45744
46890
  ws2.on("error", reject);
45745
46891
  });
@@ -45756,8 +46902,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
45756
46902
  copyDirRecursive(src, dest) {
45757
46903
  fs7.mkdirSync(dest, { recursive: true });
45758
46904
  for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
45759
- const srcPath = path14.join(src, entry.name);
45760
- const destPath = path14.join(dest, entry.name);
46905
+ const srcPath = path17.join(src, entry.name);
46906
+ const destPath = path17.join(dest, entry.name);
45761
46907
  if (entry.isDirectory()) {
45762
46908
  this.copyDirRecursive(srcPath, destPath);
45763
46909
  } else {
@@ -45768,7 +46914,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45768
46914
  /** .meta.json save */
45769
46915
  writeMeta(metaPath, etag, timestamp) {
45770
46916
  try {
45771
- fs7.mkdirSync(path14.dirname(metaPath), { recursive: true });
46917
+ fs7.mkdirSync(path17.dirname(metaPath), { recursive: true });
45772
46918
  fs7.writeFileSync(metaPath, JSON.stringify({
45773
46919
  etag,
45774
46920
  timestamp,
@@ -45785,7 +46931,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45785
46931
  const scan = (d) => {
45786
46932
  try {
45787
46933
  for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
45788
- if (entry.isDirectory()) scan(path14.join(d, entry.name));
46934
+ if (entry.isDirectory()) scan(path17.join(d, entry.name));
45789
46935
  else if (entry.name === "provider.json") count++;
45790
46936
  }
45791
46937
  } catch {
@@ -46013,17 +47159,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
46013
47159
  for (const root of searchRoots) {
46014
47160
  if (!fs7.existsSync(root)) continue;
46015
47161
  const candidate = this.getProviderDir(root, cat, type);
46016
- if (fs7.existsSync(path14.join(candidate, "provider.json"))) return candidate;
46017
- const catDir = path14.join(root, cat);
47162
+ if (fs7.existsSync(path17.join(candidate, "provider.json"))) return candidate;
47163
+ const catDir = path17.join(root, cat);
46018
47164
  if (fs7.existsSync(catDir)) {
46019
47165
  try {
46020
47166
  for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
46021
47167
  if (!entry.isDirectory()) continue;
46022
- const jsonPath = path14.join(catDir, entry.name, "provider.json");
47168
+ const jsonPath = path17.join(catDir, entry.name, "provider.json");
46023
47169
  if (fs7.existsSync(jsonPath)) {
46024
47170
  try {
46025
47171
  const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
46026
- if (data.type === type) return path14.join(catDir, entry.name);
47172
+ if (data.type === type) return path17.join(catDir, entry.name);
46027
47173
  } catch {
46028
47174
  }
46029
47175
  }
@@ -46040,7 +47186,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
46040
47186
  * (template substitution is NOT applied here — scripts.js handles that)
46041
47187
  */
46042
47188
  buildScriptWrappersFromDir(dir) {
46043
- const scriptsJs = path14.join(dir, "scripts.js");
47189
+ const scriptsJs = path17.join(dir, "scripts.js");
46044
47190
  if (fs7.existsSync(scriptsJs)) {
46045
47191
  try {
46046
47192
  delete require.cache[require.resolve(scriptsJs)];
@@ -46054,7 +47200,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
46054
47200
  for (const file2 of fs7.readdirSync(dir)) {
46055
47201
  if (!file2.endsWith(".js")) continue;
46056
47202
  const scriptName = toCamel(file2.replace(".js", ""));
46057
- const filePath = path14.join(dir, file2);
47203
+ const filePath = path17.join(dir, file2);
46058
47204
  result[scriptName] = (...args) => {
46059
47205
  try {
46060
47206
  let content = fs7.readFileSync(filePath, "utf-8");
@@ -46114,7 +47260,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
46114
47260
  }
46115
47261
  const hasJson = entries.some((e) => e.name === "provider.json");
46116
47262
  if (hasJson) {
46117
- const jsonPath = path14.join(d, "provider.json");
47263
+ const jsonPath = path17.join(d, "provider.json");
46118
47264
  try {
46119
47265
  const raw = fs7.readFileSync(jsonPath, "utf-8");
46120
47266
  const mod = JSON.parse(raw);
@@ -46135,7 +47281,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
46135
47281
  this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
46136
47282
  } else {
46137
47283
  const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
46138
- const scriptsPath = path14.join(d, "scripts.js");
47284
+ const scriptsPath = path17.join(d, "scripts.js");
46139
47285
  if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
46140
47286
  try {
46141
47287
  delete require.cache[require.resolve(scriptsPath)];
@@ -46161,7 +47307,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
46161
47307
  if (!entry.isDirectory()) continue;
46162
47308
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
46163
47309
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
46164
- scan(path14.join(d, entry.name));
47310
+ scan(path17.join(d, entry.name));
46165
47311
  }
46166
47312
  }
46167
47313
  };
@@ -46196,9 +47342,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
46196
47342
  }
46197
47343
  }
46198
47344
  compareVersions(a, b2) {
46199
- const normalize3 = (v2) => v2.split(/[-_+]/)[0].split(".").map((x) => parseInt(x, 10) || 0);
46200
- const pa2 = normalize3(a);
46201
- 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);
46202
47348
  for (let i = 0; i < Math.max(pa2.length, pb.length); i++) {
46203
47349
  const va2 = pa2[i] || 0;
46204
47350
  const vb = pb[i] || 0;
@@ -46314,17 +47460,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
46314
47460
  throw new Error("No free port found");
46315
47461
  }
46316
47462
  function checkPortFree(port) {
46317
- return new Promise((resolve12) => {
47463
+ return new Promise((resolve15) => {
46318
47464
  const server = net3.createServer();
46319
47465
  server.unref();
46320
- server.on("error", () => resolve12(false));
47466
+ server.on("error", () => resolve15(false));
46321
47467
  server.listen(port, "127.0.0.1", () => {
46322
- server.close(() => resolve12(true));
47468
+ server.close(() => resolve15(true));
46323
47469
  });
46324
47470
  });
46325
47471
  }
46326
47472
  async function isCdpActive(port) {
46327
- return new Promise((resolve12) => {
47473
+ return new Promise((resolve15) => {
46328
47474
  const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
46329
47475
  timeout: 2e3
46330
47476
  }, (res) => {
@@ -46333,16 +47479,16 @@ Run 'adhdev doctor' for detailed diagnostics.`
46333
47479
  res.on("end", () => {
46334
47480
  try {
46335
47481
  const info = JSON.parse(data);
46336
- resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
47482
+ resolve15(!!info["WebKit-Version"] || !!info["Browser"]);
46337
47483
  } catch {
46338
- resolve12(false);
47484
+ resolve15(false);
46339
47485
  }
46340
47486
  });
46341
47487
  });
46342
- req.on("error", () => resolve12(false));
47488
+ req.on("error", () => resolve15(false));
46343
47489
  req.on("timeout", () => {
46344
47490
  req.destroy();
46345
- resolve12(false);
47491
+ resolve15(false);
46346
47492
  });
46347
47493
  });
46348
47494
  }
@@ -46482,8 +47628,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
46482
47628
  const appNameMap = getMacAppIdentifiers();
46483
47629
  const appName = appNameMap[ideId];
46484
47630
  if (appName) {
46485
- const storagePath = path15.join(
46486
- process.env.APPDATA || path15.join(os15.homedir(), "AppData", "Roaming"),
47631
+ const storagePath = path18.join(
47632
+ process.env.APPDATA || path18.join(os15.homedir(), "AppData", "Roaming"),
46487
47633
  appName,
46488
47634
  "storage.json"
46489
47635
  );
@@ -46657,9 +47803,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
46657
47803
  init_config();
46658
47804
  init_logger();
46659
47805
  var fs8 = __toESM2(require("fs"));
46660
- var path16 = __toESM2(require("path"));
47806
+ var path19 = __toESM2(require("path"));
46661
47807
  var os16 = __toESM2(require("os"));
46662
- 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");
46663
47809
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
46664
47810
  var MAX_DAYS = 7;
46665
47811
  try {
@@ -46697,13 +47843,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
46697
47843
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
46698
47844
  }
46699
47845
  var currentDate2 = getDateStr2();
46700
- var currentFile = path16.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
47846
+ var currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
46701
47847
  var writeCount2 = 0;
46702
47848
  function checkRotation() {
46703
47849
  const today = getDateStr2();
46704
47850
  if (today !== currentDate2) {
46705
47851
  currentDate2 = today;
46706
- currentFile = path16.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
47852
+ currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
46707
47853
  cleanOldFiles();
46708
47854
  }
46709
47855
  }
@@ -46717,7 +47863,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
46717
47863
  const dateMatch = file2.match(/commands-(\d{4}-\d{2}-\d{2})/);
46718
47864
  if (dateMatch && dateMatch[1] < cutoffStr) {
46719
47865
  try {
46720
- fs8.unlinkSync(path16.join(LOG_DIR2, file2));
47866
+ fs8.unlinkSync(path19.join(LOG_DIR2, file2));
46721
47867
  } catch {
46722
47868
  }
46723
47869
  }
@@ -46727,8 +47873,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
46727
47873
  }
46728
47874
  function checkSize() {
46729
47875
  try {
46730
- const stat4 = fs8.statSync(currentFile);
46731
- if (stat4.size > MAX_FILE_SIZE) {
47876
+ const stat22 = fs8.statSync(currentFile);
47877
+ if (stat22.size > MAX_FILE_SIZE) {
46732
47878
  const backup = currentFile.replace(".jsonl", ".1.jsonl");
46733
47879
  try {
46734
47880
  fs8.unlinkSync(backup);
@@ -47010,12 +48156,18 @@ Run 'adhdev doctor' for detailed diagnostics.`
47010
48156
  const unreadSourceSessions = buildSessionEntries(
47011
48157
  options.allStates,
47012
48158
  options.cdpManagers,
47013
- { profile: "full" }
48159
+ {
48160
+ profile: "full",
48161
+ getGitSummaryForWorkspace: options.getGitSummaryForWorkspace
48162
+ }
47014
48163
  );
47015
48164
  const sessions = profile === "full" ? unreadSourceSessions : profile === "live" ? unreadSourceSessions.map(projectLiveSessionFromFull) : buildSessionEntries(
47016
48165
  options.allStates,
47017
48166
  options.cdpManagers,
47018
- { profile }
48167
+ {
48168
+ profile,
48169
+ getGitSummaryForWorkspace: options.getGitSummaryForWorkspace
48170
+ }
47019
48171
  );
47020
48172
  const sessionsById = new Map(sessions.map((session) => [session.id, session]));
47021
48173
  for (const sourceSession of unreadSourceSessions) {
@@ -47107,13 +48259,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
47107
48259
  var import_child_process9 = require("child_process");
47108
48260
  var fs9 = __toESM2(require("fs"));
47109
48261
  var os18 = __toESM2(require("os"));
47110
- var path17 = __toESM2(require("path"));
48262
+ var path20 = __toESM2(require("path"));
47111
48263
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
47112
48264
  function getUpgradeLogPath() {
47113
48265
  const home = os18.homedir();
47114
- const dir = path17.join(home, ".adhdev");
48266
+ const dir = path20.join(home, ".adhdev");
47115
48267
  fs9.mkdirSync(dir, { recursive: true });
47116
- return path17.join(dir, "daemon-upgrade.log");
48268
+ return path20.join(dir, "daemon-upgrade.log");
47117
48269
  }
47118
48270
  function appendUpgradeLog(message) {
47119
48271
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -47124,14 +48276,14 @@ Run 'adhdev doctor' for detailed diagnostics.`
47124
48276
  }
47125
48277
  }
47126
48278
  function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
47127
- const binDir = path17.dirname(nodeExecutable);
48279
+ const binDir = path20.dirname(nodeExecutable);
47128
48280
  if (platform10 === "win32") {
47129
- 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");
47130
48282
  if (fs9.existsSync(npmCliPath)) {
47131
48283
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
47132
48284
  }
47133
48285
  for (const candidate of ["npm.exe", "npm"]) {
47134
- const candidatePath = path17.join(binDir, candidate);
48286
+ const candidatePath = path20.join(binDir, candidate);
47135
48287
  if (fs9.existsSync(candidatePath)) {
47136
48288
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
47137
48289
  }
@@ -47139,7 +48291,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
47139
48291
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
47140
48292
  }
47141
48293
  for (const candidate of ["npm"]) {
47142
- const candidatePath = path17.join(binDir, candidate);
48294
+ const candidatePath = path20.join(binDir, candidate);
47143
48295
  if (fs9.existsSync(candidatePath)) {
47144
48296
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
47145
48297
  }
@@ -47156,13 +48308,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
47156
48308
  let currentDir = resolvedPath;
47157
48309
  try {
47158
48310
  if (fs9.statSync(resolvedPath).isFile()) {
47159
- currentDir = path17.dirname(resolvedPath);
48311
+ currentDir = path20.dirname(resolvedPath);
47160
48312
  }
47161
48313
  } catch {
47162
- currentDir = path17.dirname(resolvedPath);
48314
+ currentDir = path20.dirname(resolvedPath);
47163
48315
  }
47164
48316
  while (true) {
47165
- const packageJsonPath = path17.join(currentDir, "package.json");
48317
+ const packageJsonPath = path20.join(currentDir, "package.json");
47166
48318
  try {
47167
48319
  if (fs9.existsSync(packageJsonPath)) {
47168
48320
  const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
@@ -47173,7 +48325,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
47173
48325
  }
47174
48326
  } catch {
47175
48327
  }
47176
- const parentDir = path17.dirname(currentDir);
48328
+ const parentDir = path20.dirname(currentDir);
47177
48329
  if (parentDir === currentDir) {
47178
48330
  return null;
47179
48331
  }
@@ -47181,13 +48333,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
47181
48333
  }
47182
48334
  }
47183
48335
  function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
47184
- const nodeModulesDir = packageName.startsWith("@") ? path17.dirname(path17.dirname(packageRoot)) : path17.dirname(packageRoot);
47185
- 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") {
47186
48338
  return null;
47187
48339
  }
47188
- const maybeLibDir = path17.dirname(nodeModulesDir);
47189
- if (path17.basename(maybeLibDir) === "lib") {
47190
- return path17.dirname(maybeLibDir);
48340
+ const maybeLibDir = path20.dirname(nodeModulesDir);
48341
+ if (path20.basename(maybeLibDir) === "lib") {
48342
+ return path20.dirname(maybeLibDir);
47191
48343
  }
47192
48344
  return maybeLibDir;
47193
48345
  }
@@ -47295,14 +48447,14 @@ Run 'adhdev doctor' for detailed diagnostics.`
47295
48447
  while (Date.now() - start < timeoutMs) {
47296
48448
  try {
47297
48449
  process.kill(pid, 0);
47298
- await new Promise((resolve12) => setTimeout(resolve12, 250));
48450
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
47299
48451
  } catch {
47300
48452
  return;
47301
48453
  }
47302
48454
  }
47303
48455
  }
47304
48456
  function stopSessionHostProcesses(appName) {
47305
- const pidFile = path17.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
48457
+ const pidFile = path20.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
47306
48458
  try {
47307
48459
  if (fs9.existsSync(pidFile)) {
47308
48460
  const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
@@ -47319,7 +48471,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
47319
48471
  }
47320
48472
  }
47321
48473
  function removeDaemonPidFile() {
47322
- const pidFile = path17.join(os18.homedir(), ".adhdev", "daemon.pid");
48474
+ const pidFile = path20.join(os18.homedir(), ".adhdev", "daemon.pid");
47323
48475
  try {
47324
48476
  fs9.unlinkSync(pidFile);
47325
48477
  } catch {
@@ -47330,7 +48482,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
47330
48482
  const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
47331
48483
  if (!npmRoot) return;
47332
48484
  const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
47333
- const binDir = process.platform === "win32" ? npmPrefix : path17.join(npmPrefix, "bin");
48485
+ const binDir = process.platform === "win32" ? npmPrefix : path20.join(npmPrefix, "bin");
47334
48486
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
47335
48487
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
47336
48488
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -47338,25 +48490,25 @@ Run 'adhdev doctor' for detailed diagnostics.`
47338
48490
  }
47339
48491
  if (pkgName.startsWith("@")) {
47340
48492
  const [scope, name] = pkgName.split("/");
47341
- const scopeDir = path17.join(npmRoot, scope);
48493
+ const scopeDir = path20.join(npmRoot, scope);
47342
48494
  if (!fs9.existsSync(scopeDir)) return;
47343
48495
  for (const entry of fs9.readdirSync(scopeDir)) {
47344
48496
  if (!entry.startsWith(`.${name}-`)) continue;
47345
- fs9.rmSync(path17.join(scopeDir, entry), { recursive: true, force: true });
47346
- 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)}`);
47347
48499
  }
47348
48500
  } else {
47349
48501
  for (const entry of fs9.readdirSync(npmRoot)) {
47350
48502
  if (!entry.startsWith(`.${pkgName}-`)) continue;
47351
- fs9.rmSync(path17.join(npmRoot, entry), { recursive: true, force: true });
47352
- 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)}`);
47353
48505
  }
47354
48506
  }
47355
48507
  if (fs9.existsSync(binDir)) {
47356
48508
  for (const entry of fs9.readdirSync(binDir)) {
47357
48509
  if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
47358
- fs9.rmSync(path17.join(binDir, entry), { recursive: true, force: true });
47359
- 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)}`);
47360
48512
  }
47361
48513
  }
47362
48514
  }
@@ -47406,7 +48558,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
47406
48558
  appendUpgradeLog(installOutput.trim());
47407
48559
  }
47408
48560
  if (process.platform === "win32") {
47409
- await new Promise((resolve12) => setTimeout(resolve12, 500));
48561
+ await new Promise((resolve15) => setTimeout(resolve15, 500));
47410
48562
  cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
47411
48563
  appendUpgradeLog("Post-install staging cleanup complete");
47412
48564
  }
@@ -48786,7 +49938,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
48786
49938
  const beforeCount = this.messageCount(before);
48787
49939
  const beforeSignature = this.lastMessageSignature(before);
48788
49940
  for (let attempt = 0; attempt < 12; attempt += 1) {
48789
- await new Promise((resolve12) => setTimeout(resolve12, 250));
49941
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
48790
49942
  let state;
48791
49943
  try {
48792
49944
  state = await this.readChat(evaluate);
@@ -48808,7 +49960,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
48808
49960
  if (this.messageCount(first) > 0 || this.lastMessageSignature(first)) {
48809
49961
  return first;
48810
49962
  }
48811
- await new Promise((resolve12) => setTimeout(resolve12, 150));
49963
+ await new Promise((resolve15) => setTimeout(resolve15, 150));
48812
49964
  const second = await this.readChat(evaluate);
48813
49965
  return this.messageCount(second) >= this.messageCount(first) ? second : first;
48814
49966
  }
@@ -48959,7 +50111,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
48959
50111
  if (typeof data.error === "string" && data.error.trim()) return false;
48960
50112
  }
48961
50113
  for (let attempt = 0; attempt < 6; attempt += 1) {
48962
- await new Promise((resolve12) => setTimeout(resolve12, 250));
50114
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
48963
50115
  const state = await this.readChat(evaluate);
48964
50116
  const title = this.getStateTitle(state);
48965
50117
  if (this.titlesMatch(title, sessionId)) return true;
@@ -49808,11 +50960,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
49808
50960
  init_io_contracts();
49809
50961
  init_chat_message_normalization();
49810
50962
  var fs11 = __toESM2(require("fs"));
49811
- var path18 = __toESM2(require("path"));
50963
+ var path21 = __toESM2(require("path"));
49812
50964
  var os19 = __toESM2(require("os"));
49813
50965
  var import_child_process10 = require("child_process");
49814
50966
  var import_os3 = require("os");
49815
- var ARCHIVE_PATH = path18.join(os19.homedir(), ".adhdev", "version-history.json");
50967
+ var ARCHIVE_PATH = path21.join(os19.homedir(), ".adhdev", "version-history.json");
49816
50968
  var MAX_ENTRIES_PER_PROVIDER = 20;
49817
50969
  var VersionArchive = class {
49818
50970
  history = {};
@@ -49859,7 +51011,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
49859
51011
  }
49860
51012
  save() {
49861
51013
  try {
49862
- fs11.mkdirSync(path18.dirname(ARCHIVE_PATH), { recursive: true });
51014
+ fs11.mkdirSync(path21.dirname(ARCHIVE_PATH), { recursive: true });
49863
51015
  fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
49864
51016
  } catch {
49865
51017
  }
@@ -49916,7 +51068,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
49916
51068
  for (const p of paths) {
49917
51069
  if (p.includes("*")) {
49918
51070
  const home = os19.homedir();
49919
- const resolved = p.replace(/\*/g, home.split(path18.sep).pop() || "");
51071
+ const resolved = p.replace(/\*/g, home.split(path21.sep).pop() || "");
49920
51072
  if (fs11.existsSync(resolved)) return resolved;
49921
51073
  } else {
49922
51074
  if (fs11.existsSync(p)) return p;
@@ -49926,7 +51078,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
49926
51078
  }
49927
51079
  function getMacAppVersion(appPath) {
49928
51080
  if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
49929
- const plistPath = path18.join(appPath, "Contents", "Info.plist");
51081
+ const plistPath = path21.join(appPath, "Contents", "Info.plist");
49930
51082
  if (!fs11.existsSync(plistPath)) return null;
49931
51083
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
49932
51084
  return raw || null;
@@ -49952,7 +51104,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
49952
51104
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
49953
51105
  let resolvedBin = cliBin;
49954
51106
  if (!resolvedBin && appPath && currentOs === "darwin") {
49955
- const bundled = path18.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
51107
+ const bundled = path21.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
49956
51108
  if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
49957
51109
  }
49958
51110
  info.installed = !!(appPath || resolvedBin);
@@ -49991,7 +51143,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
49991
51143
  }
49992
51144
  var http2 = __toESM2(require("http"));
49993
51145
  var fs15 = __toESM2(require("fs"));
49994
- var path222 = __toESM2(require("path"));
51146
+ var path25 = __toESM2(require("path"));
49995
51147
  init_config();
49996
51148
  function generateFiles(type, name, category, opts = {}) {
49997
51149
  const { cdpPorts, cli, processName, installPath, binary, extensionId, version: version2 = "0.1" } = opts;
@@ -50336,7 +51488,7 @@ async (params) => {
50336
51488
  }
50337
51489
  init_logger();
50338
51490
  var fs12 = __toESM2(require("fs"));
50339
- var path19 = __toESM2(require("path"));
51491
+ var path222 = __toESM2(require("path"));
50340
51492
  init_logger();
50341
51493
  async function handleCdpEvaluate(ctx, req, res) {
50342
51494
  const body = await ctx.readBody(req);
@@ -50515,17 +51667,17 @@ async (params) => {
50515
51667
  return;
50516
51668
  }
50517
51669
  let scriptsPath = "";
50518
- const directScripts = path19.join(dir, "scripts.js");
51670
+ const directScripts = path222.join(dir, "scripts.js");
50519
51671
  if (fs12.existsSync(directScripts)) {
50520
51672
  scriptsPath = directScripts;
50521
51673
  } else {
50522
- const scriptsDir = path19.join(dir, "scripts");
51674
+ const scriptsDir = path222.join(dir, "scripts");
50523
51675
  if (fs12.existsSync(scriptsDir)) {
50524
51676
  const versions = fs12.readdirSync(scriptsDir).filter((d) => {
50525
- return fs12.statSync(path19.join(scriptsDir, d)).isDirectory();
51677
+ return fs12.statSync(path222.join(scriptsDir, d)).isDirectory();
50526
51678
  }).sort().reverse();
50527
51679
  for (const ver of versions) {
50528
- const p = path19.join(scriptsDir, ver, "scripts.js");
51680
+ const p = path222.join(scriptsDir, ver, "scripts.js");
50529
51681
  if (fs12.existsSync(p)) {
50530
51682
  scriptsPath = p;
50531
51683
  break;
@@ -51352,7 +52504,7 @@ async (params) => {
51352
52504
  }
51353
52505
  }
51354
52506
  var fs13 = __toESM2(require("fs"));
51355
- var path20 = __toESM2(require("path"));
52507
+ var path232 = __toESM2(require("path"));
51356
52508
  function slugifyFixtureName(value) {
51357
52509
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
51358
52510
  return normalized || `fixture-${Date.now()}`;
@@ -51362,11 +52514,11 @@ async (params) => {
51362
52514
  if (!providerDir) {
51363
52515
  throw new Error(`Provider directory not found for '${type}'`);
51364
52516
  }
51365
- return path20.join(providerDir, "fixtures");
52517
+ return path232.join(providerDir, "fixtures");
51366
52518
  }
51367
52519
  function readCliFixture(ctx, type, name) {
51368
52520
  const fixtureDir = getCliFixtureDir(ctx, type);
51369
- const filePath = path20.join(fixtureDir, `${name}.json`);
52521
+ const filePath = path232.join(fixtureDir, `${name}.json`);
51370
52522
  if (!fs13.existsSync(filePath)) {
51371
52523
  throw new Error(`Fixture not found: ${filePath}`);
51372
52524
  }
@@ -51535,7 +52687,7 @@ async (params) => {
51535
52687
  return { target, instance, adapter };
51536
52688
  }
51537
52689
  function sleep(ms2) {
51538
- return new Promise((resolve12) => setTimeout(resolve12, ms2));
52690
+ return new Promise((resolve15) => setTimeout(resolve15, ms2));
51539
52691
  }
51540
52692
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
51541
52693
  const startedAt = Date.now();
@@ -51833,7 +52985,7 @@ async (params) => {
51833
52985
  return {
51834
52986
  mode: "fixture_replay_suite",
51835
52987
  pass: results.every((item) => item.pass),
51836
- failures: results.flatMap((item) => item.failures.map((failure) => `${item.fixtureName}: ${failure}`)),
52988
+ failures: results.flatMap((item) => item.failures.map((failure2) => `${item.fixtureName}: ${failure2}`)),
51837
52989
  result: firstFailure.result,
51838
52990
  assertions: firstFailure.assertions,
51839
52991
  fixture: firstFailure.fixture,
@@ -52133,7 +53285,7 @@ async (params) => {
52133
53285
  },
52134
53286
  notes: typeof body?.notes === "string" ? body.notes : void 0
52135
53287
  };
52136
- const filePath = path20.join(fixtureDir, `${name}.json`);
53288
+ const filePath = path232.join(fixtureDir, `${name}.json`);
52137
53289
  fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
52138
53290
  ctx.json(res, 200, {
52139
53291
  saved: true,
@@ -52157,7 +53309,7 @@ async (params) => {
52157
53309
  return;
52158
53310
  }
52159
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) => {
52160
- const fullPath = path20.join(fixtureDir, file2);
53312
+ const fullPath = path232.join(fixtureDir, file2);
52161
53313
  try {
52162
53314
  const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
52163
53315
  return {
@@ -52291,7 +53443,7 @@ async (params) => {
52291
53443
  }
52292
53444
  }
52293
53445
  var fs14 = __toESM2(require("fs"));
52294
- var path21 = __toESM2(require("path"));
53446
+ var path24 = __toESM2(require("path"));
52295
53447
  var os20 = __toESM2(require("os"));
52296
53448
  function getAutoImplPid(ctx) {
52297
53449
  const pid = ctx.autoImplProcess?.pid;
@@ -52341,22 +53493,22 @@ async (params) => {
52341
53493
  if (!fs14.existsSync(scriptsDir)) return null;
52342
53494
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
52343
53495
  try {
52344
- return fs14.statSync(path21.join(scriptsDir, d)).isDirectory();
53496
+ return fs14.statSync(path24.join(scriptsDir, d)).isDirectory();
52345
53497
  } catch {
52346
53498
  return false;
52347
53499
  }
52348
53500
  }).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
52349
53501
  if (versions.length === 0) return null;
52350
- return path21.join(scriptsDir, versions[0]);
53502
+ return path24.join(scriptsDir, versions[0]);
52351
53503
  }
52352
53504
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
52353
- const canonicalUserDir = path21.resolve(ctx.providerLoader.getUserProviderDir(category, type));
52354
- const desiredDir = requestedDir ? path21.resolve(requestedDir) : canonicalUserDir;
52355
- const upstreamRoot = path21.resolve(ctx.providerLoader.getUpstreamDir());
52356
- 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}`)) {
52357
53509
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
52358
53510
  }
52359
- if (path21.basename(desiredDir) !== type) {
53511
+ if (path24.basename(desiredDir) !== type) {
52360
53512
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
52361
53513
  }
52362
53514
  const sourceDir = ctx.findProviderDir(type);
@@ -52364,11 +53516,11 @@ async (params) => {
52364
53516
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
52365
53517
  }
52366
53518
  if (!fs14.existsSync(desiredDir)) {
52367
- fs14.mkdirSync(path21.dirname(desiredDir), { recursive: true });
53519
+ fs14.mkdirSync(path24.dirname(desiredDir), { recursive: true });
52368
53520
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
52369
53521
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
52370
53522
  }
52371
- const providerJson = path21.join(desiredDir, "provider.json");
53523
+ const providerJson = path24.join(desiredDir, "provider.json");
52372
53524
  if (!fs14.existsSync(providerJson)) {
52373
53525
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
52374
53526
  }
@@ -52379,13 +53531,13 @@ async (params) => {
52379
53531
  const refDir = ctx.findProviderDir(referenceType);
52380
53532
  if (!refDir || !fs14.existsSync(refDir)) return {};
52381
53533
  const referenceScripts = {};
52382
- const scriptsDir = path21.join(refDir, "scripts");
53534
+ const scriptsDir = path24.join(refDir, "scripts");
52383
53535
  const latestDir = getLatestScriptVersionDir(scriptsDir);
52384
53536
  if (!latestDir) return referenceScripts;
52385
53537
  for (const file2 of fs14.readdirSync(latestDir)) {
52386
53538
  if (!file2.endsWith(".js")) continue;
52387
53539
  try {
52388
- referenceScripts[file2] = fs14.readFileSync(path21.join(latestDir, file2), "utf-8");
53540
+ referenceScripts[file2] = fs14.readFileSync(path24.join(latestDir, file2), "utf-8");
52389
53541
  } catch {
52390
53542
  }
52391
53543
  }
@@ -52493,9 +53645,9 @@ async (params) => {
52493
53645
  });
52494
53646
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
52495
53647
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
52496
- const tmpDir = path21.join(os20.tmpdir(), "adhdev-autoimpl");
53648
+ const tmpDir = path24.join(os20.tmpdir(), "adhdev-autoimpl");
52497
53649
  if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
52498
- const promptFile = path21.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
53650
+ const promptFile = path24.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
52499
53651
  fs14.writeFileSync(promptFile, prompt, "utf-8");
52500
53652
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
52501
53653
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -52927,7 +54079,7 @@ async (params) => {
52927
54079
  setMode: "set_mode.js"
52928
54080
  };
52929
54081
  const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
52930
- const scriptsDir = path21.join(providerDir, "scripts");
54082
+ const scriptsDir = path24.join(providerDir, "scripts");
52931
54083
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
52932
54084
  if (latestScriptsDir) {
52933
54085
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -52938,7 +54090,7 @@ async (params) => {
52938
54090
  for (const file2 of fs14.readdirSync(latestScriptsDir)) {
52939
54091
  if (file2.endsWith(".js") && targetFileNames.has(file2)) {
52940
54092
  try {
52941
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file2), "utf-8");
54093
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file2), "utf-8");
52942
54094
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
52943
54095
  lines.push("```javascript");
52944
54096
  lines.push(content);
@@ -52955,7 +54107,7 @@ async (params) => {
52955
54107
  lines.push("");
52956
54108
  for (const file2 of refFiles) {
52957
54109
  try {
52958
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file2), "utf-8");
54110
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file2), "utf-8");
52959
54111
  lines.push(`### \`${file2}\` \u{1F512}`);
52960
54112
  lines.push("```javascript");
52961
54113
  lines.push(content);
@@ -52996,10 +54148,10 @@ async (params) => {
52996
54148
  lines.push("");
52997
54149
  }
52998
54150
  }
52999
- const docsDir = path21.join(providerDir, "../../docs");
54151
+ const docsDir = path24.join(providerDir, "../../docs");
53000
54152
  const loadGuide = (name) => {
53001
54153
  try {
53002
- const p = path21.join(docsDir, name);
54154
+ const p = path24.join(docsDir, name);
53003
54155
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
53004
54156
  } catch {
53005
54157
  }
@@ -53236,7 +54388,7 @@ async (params) => {
53236
54388
  parseApproval: "parse_approval.js"
53237
54389
  };
53238
54390
  const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
53239
- const scriptsDir = path21.join(providerDir, "scripts");
54391
+ const scriptsDir = path24.join(providerDir, "scripts");
53240
54392
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
53241
54393
  if (latestScriptsDir) {
53242
54394
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -53248,7 +54400,7 @@ async (params) => {
53248
54400
  if (!file2.endsWith(".js")) continue;
53249
54401
  if (!targetFileNames.has(file2)) continue;
53250
54402
  try {
53251
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file2), "utf-8");
54403
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file2), "utf-8");
53252
54404
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
53253
54405
  lines.push("```javascript");
53254
54406
  lines.push(content);
@@ -53264,7 +54416,7 @@ async (params) => {
53264
54416
  lines.push("");
53265
54417
  for (const file2 of refFiles) {
53266
54418
  try {
53267
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file2), "utf-8");
54419
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file2), "utf-8");
53268
54420
  lines.push(`### \`${file2}\` \u{1F512}`);
53269
54421
  lines.push("```javascript");
53270
54422
  lines.push(content);
@@ -53297,10 +54449,10 @@ async (params) => {
53297
54449
  lines.push("");
53298
54450
  }
53299
54451
  }
53300
- const docsDir = path21.join(providerDir, "../../docs");
54452
+ const docsDir = path24.join(providerDir, "../../docs");
53301
54453
  const loadGuide = (name) => {
53302
54454
  try {
53303
- const p = path21.join(docsDir, name);
54455
+ const p = path24.join(docsDir, name);
53304
54456
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
53305
54457
  } catch {
53306
54458
  }
@@ -53745,8 +54897,8 @@ data: ${JSON.stringify(msg.data)}
53745
54897
  }
53746
54898
  getEndpointList() {
53747
54899
  return this.routes.map((r) => {
53748
- const path232 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
53749
- 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}`;
53750
54902
  });
53751
54903
  }
53752
54904
  async start(port = DEV_SERVER_PORT) {
@@ -53777,15 +54929,15 @@ data: ${JSON.stringify(msg.data)}
53777
54929
  this.json(res, 500, { error: e.message });
53778
54930
  }
53779
54931
  });
53780
- return new Promise((resolve12, reject) => {
54932
+ return new Promise((resolve15, reject) => {
53781
54933
  this.server.listen(port, "127.0.0.1", () => {
53782
54934
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
53783
- resolve12();
54935
+ resolve15();
53784
54936
  });
53785
54937
  this.server.on("error", (e) => {
53786
54938
  if (e.code === "EADDRINUSE") {
53787
54939
  this.log(`Port ${port} in use, skipping dev server`);
53788
- resolve12();
54940
+ resolve15();
53789
54941
  } else {
53790
54942
  reject(e);
53791
54943
  }
@@ -53867,20 +55019,20 @@ data: ${JSON.stringify(msg.data)}
53867
55019
  child.stderr?.on("data", (d) => {
53868
55020
  stderr += d.toString().slice(0, 2e3);
53869
55021
  });
53870
- await new Promise((resolve12) => {
55022
+ await new Promise((resolve15) => {
53871
55023
  const timer = setTimeout(() => {
53872
55024
  child.kill();
53873
- resolve12();
55025
+ resolve15();
53874
55026
  }, 3e3);
53875
55027
  child.on("exit", () => {
53876
55028
  clearTimeout(timer);
53877
- resolve12();
55029
+ resolve15();
53878
55030
  });
53879
55031
  child.stdout?.once("data", () => {
53880
55032
  setTimeout(() => {
53881
55033
  child.kill();
53882
55034
  clearTimeout(timer);
53883
- resolve12();
55035
+ resolve15();
53884
55036
  }, 500);
53885
55037
  });
53886
55038
  });
@@ -54034,12 +55186,12 @@ data: ${JSON.stringify(msg.data)}
54034
55186
  // ─── DevConsole SPA ───
54035
55187
  getConsoleDistDir() {
54036
55188
  const candidates = [
54037
- path222.resolve(__dirname, "../../web-devconsole/dist"),
54038
- path222.resolve(__dirname, "../../../web-devconsole/dist"),
54039
- 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")
54040
55192
  ];
54041
55193
  for (const dir of candidates) {
54042
- if (fs15.existsSync(path222.join(dir, "index.html"))) return dir;
55194
+ if (fs15.existsSync(path25.join(dir, "index.html"))) return dir;
54043
55195
  }
54044
55196
  return null;
54045
55197
  }
@@ -54049,7 +55201,7 @@ data: ${JSON.stringify(msg.data)}
54049
55201
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
54050
55202
  return;
54051
55203
  }
54052
- const htmlPath = path222.join(distDir, "index.html");
55204
+ const htmlPath = path25.join(distDir, "index.html");
54053
55205
  try {
54054
55206
  const html = fs15.readFileSync(htmlPath, "utf-8");
54055
55207
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -54074,15 +55226,15 @@ data: ${JSON.stringify(msg.data)}
54074
55226
  this.json(res, 404, { error: "Not found" });
54075
55227
  return;
54076
55228
  }
54077
- const safePath = path222.normalize(pathname).replace(/^\.\.\//, "");
54078
- const filePath = path222.join(distDir, safePath);
55229
+ const safePath = path25.normalize(pathname).replace(/^\.\.\//, "");
55230
+ const filePath = path25.join(distDir, safePath);
54079
55231
  if (!filePath.startsWith(distDir)) {
54080
55232
  this.json(res, 403, { error: "Forbidden" });
54081
55233
  return;
54082
55234
  }
54083
55235
  try {
54084
55236
  const content = fs15.readFileSync(filePath);
54085
- const ext = path222.extname(filePath);
55237
+ const ext = path25.extname(filePath);
54086
55238
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
54087
55239
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
54088
55240
  res.end(content);
@@ -54195,10 +55347,10 @@ data: ${JSON.stringify(msg.data)}
54195
55347
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
54196
55348
  if (entry.isDirectory()) {
54197
55349
  files.push({ path: rel, size: 0, type: "dir" });
54198
- scan(path222.join(d, entry.name), rel);
55350
+ scan(path25.join(d, entry.name), rel);
54199
55351
  } else {
54200
- const stat4 = fs15.statSync(path222.join(d, entry.name));
54201
- 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" });
54202
55354
  }
54203
55355
  }
54204
55356
  } catch {
@@ -54220,7 +55372,7 @@ data: ${JSON.stringify(msg.data)}
54220
55372
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
54221
55373
  return;
54222
55374
  }
54223
- const fullPath = path222.resolve(dir, path222.normalize(filePath));
55375
+ const fullPath = path25.resolve(dir, path25.normalize(filePath));
54224
55376
  if (!fullPath.startsWith(dir)) {
54225
55377
  this.json(res, 403, { error: "Forbidden" });
54226
55378
  return;
@@ -54245,14 +55397,14 @@ data: ${JSON.stringify(msg.data)}
54245
55397
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
54246
55398
  return;
54247
55399
  }
54248
- const fullPath = path222.resolve(dir, path222.normalize(filePath));
55400
+ const fullPath = path25.resolve(dir, path25.normalize(filePath));
54249
55401
  if (!fullPath.startsWith(dir)) {
54250
55402
  this.json(res, 403, { error: "Forbidden" });
54251
55403
  return;
54252
55404
  }
54253
55405
  try {
54254
55406
  if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
54255
- fs15.mkdirSync(path222.dirname(fullPath), { recursive: true });
55407
+ fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
54256
55408
  fs15.writeFileSync(fullPath, content, "utf-8");
54257
55409
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
54258
55410
  this.providerLoader.reload();
@@ -54269,7 +55421,7 @@ data: ${JSON.stringify(msg.data)}
54269
55421
  return;
54270
55422
  }
54271
55423
  for (const name of ["scripts.js", "provider.json"]) {
54272
- const p = path222.join(dir, name);
55424
+ const p = path25.join(dir, name);
54273
55425
  if (fs15.existsSync(p)) {
54274
55426
  const source = fs15.readFileSync(p, "utf-8");
54275
55427
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -54290,8 +55442,8 @@ data: ${JSON.stringify(msg.data)}
54290
55442
  this.json(res, 404, { error: `Provider not found: ${type}` });
54291
55443
  return;
54292
55444
  }
54293
- const target = fs15.existsSync(path222.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
54294
- 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);
54295
55447
  try {
54296
55448
  if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
54297
55449
  fs15.writeFileSync(targetPath, source, "utf-8");
@@ -54383,14 +55535,14 @@ data: ${JSON.stringify(msg.data)}
54383
55535
  child.stderr?.on("data", (d) => {
54384
55536
  stderr += d.toString();
54385
55537
  });
54386
- await new Promise((resolve12) => {
55538
+ await new Promise((resolve15) => {
54387
55539
  const timer = setTimeout(() => {
54388
55540
  child.kill();
54389
- resolve12();
55541
+ resolve15();
54390
55542
  }, timeout);
54391
55543
  child.on("exit", () => {
54392
55544
  clearTimeout(timer);
54393
- resolve12();
55545
+ resolve15();
54394
55546
  });
54395
55547
  });
54396
55548
  const elapsed = Date.now() - start;
@@ -54438,7 +55590,7 @@ data: ${JSON.stringify(msg.data)}
54438
55590
  }
54439
55591
  let targetDir;
54440
55592
  targetDir = this.providerLoader.getUserProviderDir(category, type);
54441
- const jsonPath = path222.join(targetDir, "provider.json");
55593
+ const jsonPath = path25.join(targetDir, "provider.json");
54442
55594
  if (fs15.existsSync(jsonPath)) {
54443
55595
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
54444
55596
  return;
@@ -54450,8 +55602,8 @@ data: ${JSON.stringify(msg.data)}
54450
55602
  const createdFiles = ["provider.json"];
54451
55603
  if (result.files) {
54452
55604
  for (const [relPath, content] of Object.entries(result.files)) {
54453
- const fullPath = path222.join(targetDir, relPath);
54454
- fs15.mkdirSync(path222.dirname(fullPath), { recursive: true });
55605
+ const fullPath = path25.join(targetDir, relPath);
55606
+ fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
54455
55607
  fs15.writeFileSync(fullPath, content, "utf-8");
54456
55608
  createdFiles.push(relPath);
54457
55609
  }
@@ -54504,22 +55656,22 @@ data: ${JSON.stringify(msg.data)}
54504
55656
  if (!fs15.existsSync(scriptsDir)) return null;
54505
55657
  const versions = fs15.readdirSync(scriptsDir).filter((d) => {
54506
55658
  try {
54507
- return fs15.statSync(path222.join(scriptsDir, d)).isDirectory();
55659
+ return fs15.statSync(path25.join(scriptsDir, d)).isDirectory();
54508
55660
  } catch {
54509
55661
  return false;
54510
55662
  }
54511
55663
  }).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
54512
55664
  if (versions.length === 0) return null;
54513
- return path222.join(scriptsDir, versions[0]);
55665
+ return path25.join(scriptsDir, versions[0]);
54514
55666
  }
54515
55667
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
54516
- const canonicalUserDir = path222.resolve(this.providerLoader.getUserProviderDir(category, type));
54517
- const desiredDir = requestedDir ? path222.resolve(requestedDir) : canonicalUserDir;
54518
- const upstreamRoot = path222.resolve(this.providerLoader.getUpstreamDir());
54519
- 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}`)) {
54520
55672
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
54521
55673
  }
54522
- if (path222.basename(desiredDir) !== type) {
55674
+ if (path25.basename(desiredDir) !== type) {
54523
55675
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
54524
55676
  }
54525
55677
  const sourceDir = this.findProviderDir(type);
@@ -54527,11 +55679,11 @@ data: ${JSON.stringify(msg.data)}
54527
55679
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
54528
55680
  }
54529
55681
  if (!fs15.existsSync(desiredDir)) {
54530
- fs15.mkdirSync(path222.dirname(desiredDir), { recursive: true });
55682
+ fs15.mkdirSync(path25.dirname(desiredDir), { recursive: true });
54531
55683
  fs15.cpSync(sourceDir, desiredDir, { recursive: true });
54532
55684
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
54533
55685
  }
54534
- const providerJson = path222.join(desiredDir, "provider.json");
55686
+ const providerJson = path25.join(desiredDir, "provider.json");
54535
55687
  if (!fs15.existsSync(providerJson)) {
54536
55688
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
54537
55689
  }
@@ -54567,7 +55719,7 @@ data: ${JSON.stringify(msg.data)}
54567
55719
  setMode: "set_mode.js"
54568
55720
  };
54569
55721
  const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
54570
- const scriptsDir = path222.join(providerDir, "scripts");
55722
+ const scriptsDir = path25.join(providerDir, "scripts");
54571
55723
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
54572
55724
  if (latestScriptsDir) {
54573
55725
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -54578,7 +55730,7 @@ data: ${JSON.stringify(msg.data)}
54578
55730
  for (const file2 of fs15.readdirSync(latestScriptsDir)) {
54579
55731
  if (file2.endsWith(".js") && targetFileNames.has(file2)) {
54580
55732
  try {
54581
- const content = fs15.readFileSync(path222.join(latestScriptsDir, file2), "utf-8");
55733
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file2), "utf-8");
54582
55734
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
54583
55735
  lines.push("```javascript");
54584
55736
  lines.push(content);
@@ -54595,7 +55747,7 @@ data: ${JSON.stringify(msg.data)}
54595
55747
  lines.push("");
54596
55748
  for (const file2 of refFiles) {
54597
55749
  try {
54598
- const content = fs15.readFileSync(path222.join(latestScriptsDir, file2), "utf-8");
55750
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file2), "utf-8");
54599
55751
  lines.push(`### \`${file2}\` \u{1F512}`);
54600
55752
  lines.push("```javascript");
54601
55753
  lines.push(content);
@@ -54636,10 +55788,10 @@ data: ${JSON.stringify(msg.data)}
54636
55788
  lines.push("");
54637
55789
  }
54638
55790
  }
54639
- const docsDir = path222.join(providerDir, "../../docs");
55791
+ const docsDir = path25.join(providerDir, "../../docs");
54640
55792
  const loadGuide = (name) => {
54641
55793
  try {
54642
- const p = path222.join(docsDir, name);
55794
+ const p = path25.join(docsDir, name);
54643
55795
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
54644
55796
  } catch {
54645
55797
  }
@@ -54813,7 +55965,7 @@ data: ${JSON.stringify(msg.data)}
54813
55965
  parseApproval: "parse_approval.js"
54814
55966
  };
54815
55967
  const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
54816
- const scriptsDir = path222.join(providerDir, "scripts");
55968
+ const scriptsDir = path25.join(providerDir, "scripts");
54817
55969
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
54818
55970
  if (latestScriptsDir) {
54819
55971
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -54825,7 +55977,7 @@ data: ${JSON.stringify(msg.data)}
54825
55977
  if (!file2.endsWith(".js")) continue;
54826
55978
  if (!targetFileNames.has(file2)) continue;
54827
55979
  try {
54828
- const content = fs15.readFileSync(path222.join(latestScriptsDir, file2), "utf-8");
55980
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file2), "utf-8");
54829
55981
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
54830
55982
  lines.push("```javascript");
54831
55983
  lines.push(content);
@@ -54841,7 +55993,7 @@ data: ${JSON.stringify(msg.data)}
54841
55993
  lines.push("");
54842
55994
  for (const file2 of refFiles) {
54843
55995
  try {
54844
- const content = fs15.readFileSync(path222.join(latestScriptsDir, file2), "utf-8");
55996
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file2), "utf-8");
54845
55997
  lines.push(`### \`${file2}\` \u{1F512}`);
54846
55998
  lines.push("```javascript");
54847
55999
  lines.push(content);
@@ -54874,10 +56026,10 @@ data: ${JSON.stringify(msg.data)}
54874
56026
  lines.push("");
54875
56027
  }
54876
56028
  }
54877
- const docsDir = path222.join(providerDir, "../../docs");
56029
+ const docsDir = path25.join(providerDir, "../../docs");
54878
56030
  const loadGuide = (name) => {
54879
56031
  try {
54880
- const p = path222.join(docsDir, name);
56032
+ const p = path25.join(docsDir, name);
54881
56033
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
54882
56034
  } catch {
54883
56035
  }
@@ -55060,14 +56212,14 @@ data: ${JSON.stringify(msg.data)}
55060
56212
  res.end(JSON.stringify(data, null, 2));
55061
56213
  }
55062
56214
  async readBody(req) {
55063
- return new Promise((resolve12) => {
56215
+ return new Promise((resolve15) => {
55064
56216
  let body = "";
55065
56217
  req.on("data", (chunk) => body += chunk);
55066
56218
  req.on("end", () => {
55067
56219
  try {
55068
- resolve12(JSON.parse(body));
56220
+ resolve15(JSON.parse(body));
55069
56221
  } catch {
55070
- resolve12({});
56222
+ resolve15({});
55071
56223
  }
55072
56224
  });
55073
56225
  });
@@ -55569,7 +56721,7 @@ data: ${JSON.stringify(msg.data)}
55569
56721
  const deadline = Date.now() + timeoutMs;
55570
56722
  while (Date.now() < deadline) {
55571
56723
  if (await canConnect(endpoint)) return;
55572
- await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
56724
+ await new Promise((resolve15) => setTimeout(resolve15, STARTUP_POLL_MS));
55573
56725
  }
55574
56726
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
55575
56727
  }
@@ -55743,10 +56895,10 @@ data: ${JSON.stringify(msg.data)}
55743
56895
  const buffer = Buffer.from(await res.arrayBuffer());
55744
56896
  const fs16 = await import("fs");
55745
56897
  fs16.writeFileSync(vsixPath, buffer);
55746
- return new Promise((resolve12) => {
56898
+ return new Promise((resolve15) => {
55747
56899
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
55748
56900
  (0, import_child_process11.exec)(cmd, { timeout: 6e4 }, (error48, _stdout, stderr) => {
55749
- resolve12({
56901
+ resolve15({
55750
56902
  extensionId: extension.id,
55751
56903
  marketplaceId: extension.marketplaceId,
55752
56904
  success: !error48,
@@ -55759,11 +56911,11 @@ data: ${JSON.stringify(msg.data)}
55759
56911
  } catch (e) {
55760
56912
  }
55761
56913
  }
55762
- return new Promise((resolve12) => {
56914
+ return new Promise((resolve15) => {
55763
56915
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
55764
56916
  (0, import_child_process11.exec)(cmd, { timeout: 6e4 }, (error48, stdout, stderr) => {
55765
56917
  if (error48) {
55766
- resolve12({
56918
+ resolve15({
55767
56919
  extensionId: extension.id,
55768
56920
  marketplaceId: extension.marketplaceId,
55769
56921
  success: false,
@@ -55771,7 +56923,7 @@ data: ${JSON.stringify(msg.data)}
55771
56923
  error: stderr || error48.message
55772
56924
  });
55773
56925
  } else {
55774
- resolve12({
56926
+ resolve15({
55775
56927
  extensionId: extension.id,
55776
56928
  marketplaceId: extension.marketplaceId,
55777
56929
  success: true,
@@ -56881,6 +58033,8 @@ var StandaloneServer = class {
56881
58033
  wsSessionHostDiagnosticsSubscriptions = /* @__PURE__ */ new Map();
56882
58034
  wsSessionModalSubscriptions = /* @__PURE__ */ new Map();
56883
58035
  wsDaemonMetadataSubscriptions = /* @__PURE__ */ new Map();
58036
+ wsGitSubscriptions = /* @__PURE__ */ new Map();
58037
+ gitWorkspaceMonitor = (0, import_daemon_core2.createGitWorkspaceMonitor)();
56884
58038
  authToken = null;
56885
58039
  passwordConfigPath = getStandalonePasswordConfigPath();
56886
58040
  passwordConfig = null;
@@ -57146,6 +58300,7 @@ var StandaloneServer = class {
57146
58300
  void this.flushWsMachineRuntimeSubscriptions();
57147
58301
  void this.flushWsSessionHostDiagnosticsSubscriptions();
57148
58302
  void this.flushWsSessionModalSubscriptions();
58303
+ if (this.hasWsGitSubscriptions()) void this.flushWsGitSubscriptions();
57149
58304
  }, STATUS_INTERVAL);
57150
58305
  this.running = true;
57151
58306
  await new Promise((resolve4) => {
@@ -57634,6 +58789,7 @@ var StandaloneServer = class {
57634
58789
  this.wsSessionHostDiagnosticsSubscriptions.set(ws2, /* @__PURE__ */ new Map());
57635
58790
  this.wsSessionModalSubscriptions.set(ws2, /* @__PURE__ */ new Map());
57636
58791
  this.wsDaemonMetadataSubscriptions.set(ws2, /* @__PURE__ */ new Map());
58792
+ this.wsGitSubscriptions.set(ws2, /* @__PURE__ */ new Map());
57637
58793
  console.log(`[WS] Client connected (total: ${this.clients.size})`);
57638
58794
  const status = this.getWsStatus(this.buildSharedSnapshot("live"));
57639
58795
  this.lastWsStatusSignature = this.buildWsStatusSignature(status);
@@ -57677,6 +58833,7 @@ var StandaloneServer = class {
57677
58833
  this.wsSessionHostDiagnosticsSubscriptions.delete(ws2);
57678
58834
  this.wsSessionModalSubscriptions.delete(ws2);
57679
58835
  this.wsDaemonMetadataSubscriptions.delete(ws2);
58836
+ this.clearWsGitSubscriptions(ws2);
57680
58837
  console.log(`[WS] Client disconnected (total: ${this.clients.size})`);
57681
58838
  });
57682
58839
  ws2.on("error", () => {
@@ -57686,8 +58843,19 @@ var StandaloneServer = class {
57686
58843
  this.wsSessionHostDiagnosticsSubscriptions.delete(ws2);
57687
58844
  this.wsSessionModalSubscriptions.delete(ws2);
57688
58845
  this.wsDaemonMetadataSubscriptions.delete(ws2);
58846
+ this.clearWsGitSubscriptions(ws2);
57689
58847
  });
57690
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
+ }
57691
58859
  async handleWsSubscribe(ws2, msg) {
57692
58860
  if (msg.topic === "session.chat_tail") {
57693
58861
  const params = msg.params;
@@ -57775,6 +58943,25 @@ var StandaloneServer = class {
57775
58943
  lastSentAt: 0
57776
58944
  });
57777
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);
57778
58965
  }
57779
58966
  }
57780
58967
  handleWsUnsubscribe(ws2, msg) {
@@ -57796,6 +58983,12 @@ var StandaloneServer = class {
57796
58983
  }
57797
58984
  if (msg.topic === "daemon.metadata") {
57798
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);
57799
58992
  }
57800
58993
  }
57801
58994
  async buildChatTailUpdate(request, state, key) {
@@ -58019,6 +59212,45 @@ var StandaloneServer = class {
58019
59212
  }
58020
59213
  }
58021
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
+ }
58022
59254
  // ─── Core Logic ───
58023
59255
  buildSharedSnapshot(profile = "full") {
58024
59256
  const cfgSnap = (0, import_daemon_core2.loadConfig)();
@@ -58143,6 +59375,7 @@ var StandaloneServer = class {
58143
59375
  }
58144
59376
  if (type.startsWith("session_host_")) void this.flushWsSessionHostDiagnosticsSubscriptions();
58145
59377
  if (type === "resolve_action" || type === "send_chat" || type === "read_chat") void this.flushWsSessionModalSubscriptions();
59378
+ if (type.startsWith("git_") && this.hasWsGitSubscriptions()) void this.flushWsGitSubscriptions();
58146
59379
  return result;
58147
59380
  }
58148
59381
  scheduleBroadcastStatus() {