@adhdev/daemon-standalone 0.9.53 → 0.9.55

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;
@@ -29812,6 +29812,7 @@ var require_dist2 = __commonJS({
29812
29812
  sendDelayMs: typeof provider.sendDelayMs === "number" ? Math.max(0, provider.sendDelayMs) : 0,
29813
29813
  sendKey: typeof provider.sendKey === "string" && provider.sendKey.length > 0 ? provider.sendKey : "\r",
29814
29814
  submitStrategy: provider.submitStrategy === "immediate" ? "immediate" : "wait_for_echo",
29815
+ requirePromptEchoBeforeSubmit: provider.requirePromptEchoBeforeSubmit === true,
29815
29816
  providerResolutionMeta: {
29816
29817
  type: provider.type,
29817
29818
  name: provider.name,
@@ -29839,9 +29840,9 @@ var require_dist2 = __commonJS({
29839
29840
  const allArgs = [...spawnConfig.args, ...extraArgs];
29840
29841
  let shellCmd;
29841
29842
  let shellArgs;
29842
- const useShellUnix = !isWin && (!!spawnConfig.shell || !path11.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
29843
+ const useShellUnix = !isWin && (!!spawnConfig.shell || !path14.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
29843
29844
  const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
29844
- const useShellWin = !!spawnConfig.shell || isCmdShim || !path11.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
29845
+ const useShellWin = !!spawnConfig.shell || isCmdShim || !path14.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
29845
29846
  const useShell = isWin ? useShellWin : useShellUnix;
29846
29847
  if (useShell) {
29847
29848
  shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
@@ -29918,13 +29919,13 @@ var require_dist2 = __commonJS({
29918
29919
  return "";
29919
29920
  }
29920
29921
  var os10;
29921
- var path11;
29922
+ var path14;
29922
29923
  var import_session_host_core22;
29923
29924
  var init_provider_cli_runtime = __esm2({
29924
29925
  "src/cli-adapters/provider-cli-runtime.ts"() {
29925
29926
  "use strict";
29926
29927
  os10 = __toESM2(require("os"));
29927
- path11 = __toESM2(require("path"));
29928
+ path14 = __toESM2(require("path"));
29928
29929
  import_session_host_core22 = require_dist();
29929
29930
  init_provider_cli_shared();
29930
29931
  }
@@ -30077,6 +30078,7 @@ var require_dist2 = __commonJS({
30077
30078
  this.sendDelayMs = resolvedConfig.sendDelayMs;
30078
30079
  this.sendKey = resolvedConfig.sendKey;
30079
30080
  this.submitStrategy = resolvedConfig.submitStrategy;
30081
+ this.requirePromptEchoBeforeSubmit = resolvedConfig.requirePromptEchoBeforeSubmit;
30080
30082
  this.providerResolutionMeta = resolvedConfig.providerResolutionMeta;
30081
30083
  this.cliScripts = provider.scripts || {};
30082
30084
  const scriptNames = listCliScriptNames(this.cliScripts);
@@ -30373,6 +30375,7 @@ var require_dist2 = __commonJS({
30373
30375
  sendDelayMs;
30374
30376
  sendKey;
30375
30377
  submitStrategy;
30378
+ requirePromptEchoBeforeSubmit;
30376
30379
  static SCRIPT_STATUS_DEBOUNCE_MS = 3e3;
30377
30380
  /** Inject CLI scripts after construction (e.g. when resolved by ProviderLoader) */
30378
30381
  setCliScripts(scripts) {
@@ -30724,7 +30727,7 @@ var require_dist2 = __commonJS({
30724
30727
  `[${this.cliType}] Waiting for interactive prompt: status=${status} stableMs=${stableMs} recentOutputMs=${recentlyOutput} screen=${JSON.stringify(summarizeCliTraceText(screenText, 220)).slice(0, 260)}`
30725
30728
  );
30726
30729
  }
30727
- await new Promise((resolve12) => setTimeout(resolve12, 50));
30730
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
30728
30731
  }
30729
30732
  const finalScreenText = this.terminalScreen.getText() || "";
30730
30733
  LOG2.warn(
@@ -31893,6 +31896,22 @@ var require_dist2 = __commonJS({
31893
31896
  }
31894
31897
  }
31895
31898
  if (elapsed >= state.maxEchoWaitMs) {
31899
+ const diagnostic = {
31900
+ elapsed,
31901
+ maxEchoWaitMs: state.maxEchoWaitMs,
31902
+ submitDelayMs: state.submitDelayMs,
31903
+ promptSnippet: state.normalizedPromptSnippet,
31904
+ requirePromptEchoBeforeSubmit: this.requirePromptEchoBeforeSubmit,
31905
+ screenText: summarizeCliTraceText(screenText, 1e3)
31906
+ };
31907
+ this.recordTrace("submit_echo_missing", diagnostic);
31908
+ if (this.requirePromptEchoBeforeSubmit) {
31909
+ const message = `${this.cliName} prompt echo was not observed on the PTY screen before submit`;
31910
+ LOG2.warn("CLI", `[${this.cliType}] ${message} elapsed=${elapsed}ms maxEchoWaitMs=${state.maxEchoWaitMs} screen=${JSON.stringify(diagnostic.screenText).slice(0, 240)}`);
31911
+ completion.rejectOnce(new Error(message));
31912
+ return;
31913
+ }
31914
+ LOG2.warn("CLI", `[${this.cliType}] prompt echo was not observed before submit; sending submit key anyway elapsed=${elapsed}ms maxEchoWaitMs=${state.maxEchoWaitMs}`);
31896
31915
  this.submitSendKey(state, completion);
31897
31916
  return;
31898
31917
  }
@@ -31912,7 +31931,7 @@ var require_dist2 = __commonJS({
31912
31931
  const deadline = Date.now() + 1e4;
31913
31932
  while (this.startupParseGate && Date.now() < deadline) {
31914
31933
  this.resolveStartupState("send_wait");
31915
- await new Promise((resolve12) => setTimeout(resolve12, 50));
31934
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
31916
31935
  }
31917
31936
  }
31918
31937
  if (!allowInterventionPrompt) {
@@ -31993,13 +32012,13 @@ var require_dist2 = __commonJS({
31993
32012
  }
31994
32013
  this.responseEpoch += 1;
31995
32014
  this.responseSettleIgnoreUntil = Date.now() + submitDelayMs + this.timeouts.outputSettle + 250;
31996
- await new Promise((resolve12, reject) => {
32015
+ await new Promise((resolve15, reject) => {
31997
32016
  let resolved = false;
31998
32017
  const completion = {
31999
32018
  resolveOnce: () => {
32000
32019
  if (resolved) return;
32001
32020
  resolved = true;
32002
- resolve12();
32021
+ resolve15();
32003
32022
  },
32004
32023
  rejectOnce: (error48) => {
32005
32024
  if (resolved) return;
@@ -32161,17 +32180,17 @@ var require_dist2 = __commonJS({
32161
32180
  }
32162
32181
  }
32163
32182
  waitForStopped(timeoutMs) {
32164
- return new Promise((resolve12) => {
32183
+ return new Promise((resolve15) => {
32165
32184
  const startedAt = Date.now();
32166
32185
  const timer = setInterval(() => {
32167
32186
  if (!this.ptyProcess || this.currentStatus === "stopped") {
32168
32187
  clearInterval(timer);
32169
- resolve12(true);
32188
+ resolve15(true);
32170
32189
  return;
32171
32190
  }
32172
32191
  if (Date.now() - startedAt >= timeoutMs) {
32173
32192
  clearInterval(timer);
32174
- resolve12(false);
32193
+ resolve15(false);
32175
32194
  }
32176
32195
  }, 100);
32177
32196
  });
@@ -32357,6 +32376,7 @@ var require_dist2 = __commonJS({
32357
32376
  sendDelayMs: this.sendDelayMs,
32358
32377
  sendKey: this.sendKey,
32359
32378
  submitStrategy: this.submitStrategy,
32379
+ requirePromptEchoBeforeSubmit: this.requirePromptEchoBeforeSubmit,
32360
32380
  submitPendingUntil: this.submitPendingUntil,
32361
32381
  responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
32362
32382
  resizeSuppressUntil: this.resizeSuppressUntil,
@@ -32409,6 +32429,7 @@ var require_dist2 = __commonJS({
32409
32429
  DEFAULT_CDP_SCAN_INTERVAL_MS: () => DEFAULT_CDP_SCAN_INTERVAL_MS,
32410
32430
  DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS: () => DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS2,
32411
32431
  DEFAULT_DAEMON_PORT: () => DEFAULT_DAEMON_PORT,
32432
+ DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS: () => DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS,
32412
32433
  DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS: () => DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS2,
32413
32434
  DEFAULT_SESSION_HOST_APP_NAME: () => DEFAULT_SESSION_HOST_APP_NAME,
32414
32435
  DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS: () => DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS2,
@@ -32427,8 +32448,12 @@ var require_dist2 = __commonJS({
32427
32448
  DaemonCommandRouter: () => DaemonCommandRouter,
32428
32449
  DaemonStatusReporter: () => DaemonStatusReporter,
32429
32450
  DevServer: () => DevServer,
32451
+ GitCommandError: () => GitCommandError,
32452
+ GitWorkspaceMonitor: () => GitWorkspaceMonitor,
32430
32453
  IdeProviderInstance: () => IdeProviderInstance,
32454
+ InMemoryGitSnapshotStore: () => InMemoryGitSnapshotStore,
32431
32455
  LOG: () => LOG2,
32456
+ MIN_GIT_WORKSPACE_POLL_INTERVAL_MS: () => MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
32432
32457
  MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS: () => MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS2,
32433
32458
  MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS: () => MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS2,
32434
32459
  NodePtyTransportFactory: () => NodePtyTransportFactory,
@@ -32437,6 +32462,7 @@ var require_dist2 = __commonJS({
32437
32462
  ProviderLoader: () => ProviderLoader,
32438
32463
  STANDALONE_CDP_SCAN_INTERVAL_MS: () => STANDALONE_CDP_SCAN_INTERVAL_MS2,
32439
32464
  SessionHostPtyTransportFactory: () => SessionHostPtyTransportFactory2,
32465
+ TurnSnapshotTracker: () => TurnSnapshotTracker,
32440
32466
  VersionArchive: () => VersionArchive,
32441
32467
  appendRecentActivity: () => appendRecentActivity,
32442
32468
  buildAssistantChatMessage: () => buildAssistantChatMessage,
@@ -32456,9 +32482,14 @@ var require_dist2 = __commonJS({
32456
32482
  buildUserChatMessage: () => buildUserChatMessage,
32457
32483
  classifyHotChatSessionsForSubscriptionFlush: () => classifyHotChatSessionsForSubscriptionFlush2,
32458
32484
  clearDebugTrace: () => clearDebugTrace,
32485
+ compareGitSnapshots: () => compareGitSnapshots,
32459
32486
  configureDebugTraceStore: () => configureDebugTraceStore,
32460
32487
  connectCdpManager: () => connectCdpManager,
32461
32488
  createDebugTraceStore: () => createDebugTraceStore,
32489
+ createDefaultGitCommandServices: () => createDefaultGitCommandServices,
32490
+ createGitCompactSummary: () => createGitCompactSummary,
32491
+ createGitSnapshotStore: () => createGitSnapshotStore,
32492
+ createGitWorkspaceMonitor: () => createGitWorkspaceMonitor2,
32462
32493
  createInteractionId: () => createInteractionId,
32463
32494
  detectAllVersions: () => detectAllVersions,
32464
32495
  detectCLIs: () => detectCLIs,
@@ -32473,6 +32504,9 @@ var require_dist2 = __commonJS({
32473
32504
  getCurrentDaemonLogPath: () => getCurrentDaemonLogPath,
32474
32505
  getDaemonLogDir: () => getDaemonLogDir,
32475
32506
  getDebugRuntimeConfig: () => getDebugRuntimeConfig,
32507
+ getGitDiffSummary: () => getGitDiffSummary,
32508
+ getGitFileDiff: () => getGitFileDiff,
32509
+ getGitRepoStatus: () => getGitRepoStatus,
32476
32510
  getHostMemorySnapshot: () => getHostMemorySnapshot,
32477
32511
  getLogLevel: () => getLogLevel,
32478
32512
  getNpmExecOptions: () => getNpmExecOptions,
@@ -32484,6 +32518,7 @@ var require_dist2 = __commonJS({
32484
32518
  getSessionHostRecoveryLabel: () => getSessionHostRecoveryLabel,
32485
32519
  getSessionHostSurfaceKind: () => getSessionHostSurfaceKind,
32486
32520
  getWorkspaceState: () => getWorkspaceState2,
32521
+ handleGitCommand: () => handleGitCommand,
32487
32522
  hasCdpManager: () => hasCdpManager,
32488
32523
  hashSignatureParts: () => hashSignatureParts,
32489
32524
  initDaemonComponents: () => initDaemonComponents2,
@@ -32492,9 +32527,11 @@ var require_dist2 = __commonJS({
32492
32527
  isBuiltinChatMessageKind: () => isBuiltinChatMessageKind,
32493
32528
  isCdpConnected: () => isCdpConnected,
32494
32529
  isExtensionInstalled: () => isExtensionInstalled,
32530
+ isGitCommandName: () => isGitCommandName,
32495
32531
  isIdeRunning: () => isIdeRunning,
32496
32532
  isManagedStatusWaiting: () => isManagedStatusWaiting,
32497
32533
  isManagedStatusWorking: () => isManagedStatusWorking,
32534
+ isPathInside: () => isPathInside,
32498
32535
  isSessionHostLiveRuntime: () => isSessionHostLiveRuntime,
32499
32536
  isSessionHostRecoverySnapshot: () => isSessionHostRecoverySnapshot,
32500
32537
  isSetupComplete: () => isSetupComplete,
@@ -32512,10 +32549,13 @@ var require_dist2 = __commonJS({
32512
32549
  normalizeChatMessageKind: () => normalizeChatMessageKind,
32513
32550
  normalizeChatMessages: () => normalizeChatMessages,
32514
32551
  normalizeChatTailActiveModal: () => normalizeChatTailActiveModal,
32552
+ normalizeGitOutput: () => normalizeGitOutput,
32553
+ normalizeGitWorkspaceSubscriptionParams: () => normalizeGitWorkspaceSubscriptionParams2,
32515
32554
  normalizeInputEnvelope: () => normalizeInputEnvelope,
32516
32555
  normalizeManagedStatus: () => normalizeManagedStatus,
32517
32556
  normalizeMessageParts: () => normalizeMessageParts,
32518
32557
  normalizeSessionModalFields: () => normalizeSessionModalFields,
32558
+ parsePorcelainV2Status: () => parsePorcelainV2Status,
32519
32559
  parseProviderSourceConfigUpdate: () => parseProviderSourceConfigUpdate,
32520
32560
  partitionSessionHostDiagnosticsSessions: () => partitionSessionHostDiagnosticsSessions,
32521
32561
  partitionSessionHostRecords: () => partitionSessionHostRecords,
@@ -32531,9 +32571,11 @@ var require_dist2 = __commonJS({
32531
32571
  resolveChatMessageKind: () => resolveChatMessageKind,
32532
32572
  resolveCurrentGlobalInstallSurface: () => resolveCurrentGlobalInstallSurface,
32533
32573
  resolveDebugRuntimeConfig: () => resolveDebugRuntimeConfig,
32574
+ resolveGitRepository: () => resolveGitRepository,
32534
32575
  resolveSessionHostAppName: () => resolveSessionHostAppName,
32535
32576
  resolveSessionHostAppNameResolution: () => resolveSessionHostAppNameResolution2,
32536
32577
  runAsyncBatch: () => runAsyncBatch2,
32578
+ runGit: () => runGit,
32537
32579
  saveConfig: () => saveConfig,
32538
32580
  saveState: () => saveState,
32539
32581
  setDebugRuntimeConfig: () => setDebugRuntimeConfig,
@@ -32544,21 +32586,1284 @@ var require_dist2 = __commonJS({
32544
32586
  shutdownDaemonComponents: () => shutdownDaemonComponents2,
32545
32587
  spawnDetachedDaemonUpgradeHelper: () => spawnDetachedDaemonUpgradeHelper,
32546
32588
  startDaemonDevSupport: () => startDaemonDevSupport2,
32589
+ summarizeGitStatus: () => summarizeGitStatus,
32547
32590
  updateConfig: () => updateConfig,
32548
32591
  upsertSavedProviderSession: () => upsertSavedProviderSession
32549
32592
  });
32550
32593
  module2.exports = __toCommonJS2(index_exports);
32594
+ var import_node_child_process = require("child_process");
32595
+ var import_node_fs3 = require("fs");
32596
+ var import_promises4 = require("fs/promises");
32597
+ var path5 = __toESM2(require("path"));
32598
+ var import_node_util = require("util");
32599
+ var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
32600
+ var DEFAULT_TIMEOUT_MS = 5e3;
32601
+ var DEFAULT_MAX_BUFFER = 1024 * 1024;
32602
+ var GitCommandError = class extends Error {
32603
+ reason;
32604
+ stdout;
32605
+ stderr;
32606
+ exitCode;
32607
+ signal;
32608
+ argv;
32609
+ cwd;
32610
+ constructor(reason, message, details = {}) {
32611
+ super(message);
32612
+ if (details.cause !== void 0) {
32613
+ this.cause = details.cause;
32614
+ }
32615
+ this.name = "GitCommandError";
32616
+ this.reason = reason;
32617
+ this.stdout = normalizeGitOutput(details.stdout);
32618
+ this.stderr = normalizeGitOutput(details.stderr);
32619
+ this.exitCode = details.exitCode;
32620
+ this.signal = details.signal;
32621
+ this.argv = details.argv ? [...details.argv] : void 0;
32622
+ this.cwd = details.cwd;
32623
+ }
32624
+ };
32625
+ async function resolveGitRepository(workspace, options = {}) {
32626
+ const normalizedWorkspace = await validateWorkspace(workspace);
32627
+ const result = await execGitRaw(normalizedWorkspace, ["rev-parse", "--show-toplevel"], options, {
32628
+ mapNotGitRepo: true
32629
+ });
32630
+ const repoRoot = path5.resolve(result.stdout.trim());
32631
+ if (!repoRoot) {
32632
+ throw new GitCommandError("not_git_repo", "Git did not return a repository root", {
32633
+ stdout: result.stdout,
32634
+ stderr: result.stderr,
32635
+ argv: ["rev-parse", "--show-toplevel"],
32636
+ cwd: normalizedWorkspace
32637
+ });
32638
+ }
32639
+ return {
32640
+ workspace: normalizedWorkspace,
32641
+ repoRoot,
32642
+ isGitRepo: true
32643
+ };
32644
+ }
32645
+ async function runGit(repoOrWorkspace, argv, options = {}) {
32646
+ validateGitArgv(argv);
32647
+ const repo = typeof repoOrWorkspace === "string" ? await resolveGitRepository(repoOrWorkspace, options) : repoOrWorkspace;
32648
+ if (!repo.repoRoot || !repo.isGitRepo) {
32649
+ throw new GitCommandError("not_git_repo", "Workspace is not a Git repository", {
32650
+ argv,
32651
+ cwd: repo.workspace
32652
+ });
32653
+ }
32654
+ const cwd = options.cwd ? await validateWorkspace(options.cwd) : await validateWorkspace(repo.workspace);
32655
+ const canonicalRepoRoot = await (0, import_promises4.realpath)(repo.repoRoot);
32656
+ const canonicalCwd = await (0, import_promises4.realpath)(cwd);
32657
+ if (!isPathInside(canonicalRepoRoot, canonicalCwd)) {
32658
+ throw new GitCommandError("path_outside_repo", "Git cwd is outside the repository root", {
32659
+ argv,
32660
+ cwd
32661
+ });
32662
+ }
32663
+ return execGitRaw(cwd, argv, options);
32664
+ }
32665
+ function normalizeGitOutput(value) {
32666
+ if (typeof value === "string") return value.replace(/\r\n/g, "\n");
32667
+ if (Buffer.isBuffer(value)) return value.toString("utf8").replace(/\r\n/g, "\n");
32668
+ if (value == null) return "";
32669
+ return String(value).replace(/\r\n/g, "\n");
32670
+ }
32671
+ function isPathInside(parent, child) {
32672
+ const relative3 = path5.relative(path5.resolve(parent), path5.resolve(child));
32673
+ return relative3 === "" || !relative3.startsWith("..") && !path5.isAbsolute(relative3);
32674
+ }
32675
+ async function validateWorkspace(workspace) {
32676
+ if (typeof workspace !== "string" || workspace.length === 0 || workspace.includes("\0")) {
32677
+ throw new GitCommandError("invalid_args", "Workspace must be a non-empty path");
32678
+ }
32679
+ if (!path5.isAbsolute(workspace)) {
32680
+ throw new GitCommandError("invalid_args", "Workspace must be an absolute path", { cwd: workspace });
32681
+ }
32682
+ const normalizedWorkspace = path5.resolve(workspace);
32683
+ try {
32684
+ const info = await (0, import_promises4.stat)(normalizedWorkspace);
32685
+ if (!info.isDirectory()) {
32686
+ throw new GitCommandError("invalid_args", "Workspace must be an existing directory", {
32687
+ cwd: normalizedWorkspace
32688
+ });
32689
+ }
32690
+ await (0, import_promises4.access)(normalizedWorkspace, import_node_fs3.constants.R_OK);
32691
+ } catch (error48) {
32692
+ if (error48 instanceof GitCommandError) throw error48;
32693
+ throw new GitCommandError("invalid_args", "Workspace must be an existing directory", {
32694
+ cwd: normalizedWorkspace,
32695
+ cause: error48
32696
+ });
32697
+ }
32698
+ return normalizedWorkspace;
32699
+ }
32700
+ function validateGitArgv(argv) {
32701
+ if (!Array.isArray(argv) || argv.length === 0) {
32702
+ throw new GitCommandError("invalid_args", "Git argv must be a non-empty string array", { argv });
32703
+ }
32704
+ for (const arg of argv) {
32705
+ if (typeof arg !== "string" || arg.length === 0 || arg.includes("\0")) {
32706
+ throw new GitCommandError("invalid_args", "Git argv contains an invalid argument", { argv });
32707
+ }
32708
+ }
32709
+ if (argv.includes("-C") || argv.some((arg) => arg.startsWith("--git-dir") || arg.startsWith("--work-tree"))) {
32710
+ throw new GitCommandError("invalid_args", "Git argv contains unsafe repository override arguments", {
32711
+ argv
32712
+ });
32713
+ }
32714
+ }
32715
+ async function execGitRaw(cwd, argv, options, behavior = {}) {
32716
+ validateGitArgv(argv);
32717
+ try {
32718
+ const result = await execFileAsync("git", [...argv], {
32719
+ cwd,
32720
+ encoding: "utf8",
32721
+ timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
32722
+ maxBuffer: options.maxBuffer ?? DEFAULT_MAX_BUFFER,
32723
+ windowsHide: true
32724
+ });
32725
+ return {
32726
+ stdout: normalizeGitOutput(result.stdout),
32727
+ stderr: normalizeGitOutput(result.stderr)
32728
+ };
32729
+ } catch (error48) {
32730
+ throw mapExecError(error48, cwd, argv, behavior);
32731
+ }
32732
+ }
32733
+ function mapExecError(error48, cwd, argv, behavior) {
32734
+ const execError = error48;
32735
+ const stdout = normalizeGitOutput(execError.stdout);
32736
+ const stderr = normalizeGitOutput(execError.stderr);
32737
+ const code = execError.code;
32738
+ const signal = execError.signal;
32739
+ const message = [stderr.trim(), execError.message].filter(Boolean).join("\n");
32740
+ if (code === "ENOENT") {
32741
+ return new GitCommandError("git_not_installed", "Git executable was not found", {
32742
+ stdout,
32743
+ stderr,
32744
+ exitCode: code,
32745
+ signal,
32746
+ argv,
32747
+ cwd,
32748
+ cause: error48
32749
+ });
32750
+ }
32751
+ if (execError.killed || /timed out/i.test(execError.message)) {
32752
+ return new GitCommandError("timeout", "Git command timed out", {
32753
+ stdout,
32754
+ stderr,
32755
+ exitCode: code,
32756
+ signal,
32757
+ argv,
32758
+ cwd,
32759
+ cause: error48
32760
+ });
32761
+ }
32762
+ if (behavior.mapNotGitRepo && /not a git repository/i.test(stderr + "\n" + execError.message)) {
32763
+ return new GitCommandError("not_git_repo", "Workspace is not a Git repository", {
32764
+ stdout,
32765
+ stderr,
32766
+ exitCode: code,
32767
+ signal,
32768
+ argv,
32769
+ cwd,
32770
+ cause: error48
32771
+ });
32772
+ }
32773
+ return new GitCommandError("git_command_failed", message || "Git command failed", {
32774
+ stdout,
32775
+ stderr,
32776
+ exitCode: code,
32777
+ signal,
32778
+ argv,
32779
+ cwd,
32780
+ cause: error48
32781
+ });
32782
+ }
32783
+ async function getGitRepoStatus(workspace, options = {}) {
32784
+ const lastCheckedAt = Date.now();
32785
+ try {
32786
+ const repo = await resolveGitRepository(workspace, options);
32787
+ const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
32788
+ const parsed = parsePorcelainV2Status(statusOutput.stdout);
32789
+ const head = await readHead(repo, options);
32790
+ const stashCount = await readStashCount(repo, options);
32791
+ return {
32792
+ workspace: repo.workspace,
32793
+ repoRoot: repo.repoRoot,
32794
+ isGitRepo: true,
32795
+ branch: parsed.branch,
32796
+ headCommit: head.commit,
32797
+ headMessage: head.message,
32798
+ upstream: parsed.upstream,
32799
+ ahead: parsed.ahead,
32800
+ behind: parsed.behind,
32801
+ staged: parsed.staged,
32802
+ modified: parsed.modified,
32803
+ untracked: parsed.untracked,
32804
+ deleted: parsed.deleted,
32805
+ renamed: parsed.renamed,
32806
+ hasConflicts: parsed.conflictFiles.length > 0,
32807
+ conflictFiles: parsed.conflictFiles,
32808
+ stashCount,
32809
+ lastCheckedAt
32810
+ };
32811
+ } catch (error48) {
32812
+ if (error48 instanceof GitCommandError) {
32813
+ return emptyStatus(workspace, lastCheckedAt, error48);
32814
+ }
32815
+ return emptyStatus(
32816
+ workspace,
32817
+ lastCheckedAt,
32818
+ new GitCommandError("git_command_failed", "Failed to read Git status", { cause: error48 })
32819
+ );
32820
+ }
32821
+ }
32822
+ function parsePorcelainV2Status(output) {
32823
+ const parsed = {
32824
+ branch: null,
32825
+ upstream: null,
32826
+ ahead: 0,
32827
+ behind: 0,
32828
+ staged: 0,
32829
+ modified: 0,
32830
+ untracked: 0,
32831
+ deleted: 0,
32832
+ renamed: 0,
32833
+ conflictFiles: []
32834
+ };
32835
+ for (const line of output.split("\n")) {
32836
+ if (!line) continue;
32837
+ if (line.startsWith("# branch.head ")) {
32838
+ const branch = line.slice("# branch.head ".length).trim();
32839
+ parsed.branch = branch && branch !== "(detached)" ? branch : null;
32840
+ continue;
32841
+ }
32842
+ if (line.startsWith("# branch.upstream ")) {
32843
+ parsed.upstream = line.slice("# branch.upstream ".length).trim() || null;
32844
+ continue;
32845
+ }
32846
+ if (line.startsWith("# branch.ab ")) {
32847
+ const match = line.match(/\+(-?\d+)\s+-(-?\d+)/);
32848
+ if (match) {
32849
+ parsed.ahead = Number.parseInt(match[1] ?? "0", 10) || 0;
32850
+ parsed.behind = Number.parseInt(match[2] ?? "0", 10) || 0;
32851
+ }
32852
+ continue;
32853
+ }
32854
+ if (line.startsWith("? ")) {
32855
+ parsed.untracked += 1;
32856
+ continue;
32857
+ }
32858
+ if (line.startsWith("u ")) {
32859
+ const fields = line.split(" ");
32860
+ const filePath = fields.slice(10).join(" ");
32861
+ if (filePath) parsed.conflictFiles.push(filePath);
32862
+ continue;
32863
+ }
32864
+ if (line.startsWith("1 ") || line.startsWith("2 ")) {
32865
+ const fields = line.split(" ");
32866
+ const xy = fields[1] ?? "..";
32867
+ const indexStatus = xy[0] ?? ".";
32868
+ const worktreeStatus = xy[1] ?? ".";
32869
+ if (isStagedStatus(indexStatus)) parsed.staged += 1;
32870
+ if (worktreeStatus === "M" || worktreeStatus === "T") parsed.modified += 1;
32871
+ if (indexStatus === "D" || worktreeStatus === "D") parsed.deleted += 1;
32872
+ if (indexStatus === "R" || worktreeStatus === "R") parsed.renamed += 1;
32873
+ if (xy.includes("U")) {
32874
+ const filePath = fields.slice(line.startsWith("2 ") ? 9 : 8).join(" ").split(" ")[0] ?? "";
32875
+ if (filePath) parsed.conflictFiles.push(filePath);
32876
+ }
32877
+ }
32878
+ }
32879
+ parsed.conflictFiles = Array.from(new Set(parsed.conflictFiles));
32880
+ return parsed;
32881
+ }
32882
+ async function readHead(repo, options) {
32883
+ try {
32884
+ const result = await runGit(repo, ["log", "-1", "--pretty=%h%x00%s"], options);
32885
+ const text = result.stdout.trimEnd();
32886
+ if (!text) return { commit: null, message: null };
32887
+ const [commit, ...messageParts] = text.split("\0");
32888
+ return {
32889
+ commit: commit || null,
32890
+ message: messageParts.join("\0") || null
32891
+ };
32892
+ } catch {
32893
+ return { commit: null, message: null };
32894
+ }
32895
+ }
32896
+ async function readStashCount(repo, options) {
32897
+ try {
32898
+ const result = await runGit(repo, ["stash", "list", "--format=%gd"], options);
32899
+ return result.stdout.split("\n").filter((line) => line.trim().length > 0).length;
32900
+ } catch {
32901
+ return 0;
32902
+ }
32903
+ }
32904
+ function isStagedStatus(status) {
32905
+ return status !== "." && status !== "?" && status !== "U";
32906
+ }
32907
+ function emptyStatus(workspace, lastCheckedAt, error48) {
32908
+ return {
32909
+ workspace,
32910
+ repoRoot: null,
32911
+ isGitRepo: false,
32912
+ branch: null,
32913
+ headCommit: null,
32914
+ headMessage: null,
32915
+ upstream: null,
32916
+ ahead: 0,
32917
+ behind: 0,
32918
+ staged: 0,
32919
+ modified: 0,
32920
+ untracked: 0,
32921
+ deleted: 0,
32922
+ renamed: 0,
32923
+ hasConflicts: false,
32924
+ conflictFiles: [],
32925
+ stashCount: 0,
32926
+ lastCheckedAt,
32927
+ error: error48.stderr || error48.message,
32928
+ reason: error48.reason
32929
+ };
32930
+ }
32931
+ var import_promises22 = require("fs/promises");
32932
+ var path23 = __toESM2(require("path"));
32933
+ var DEFAULT_MAX_FILES = 200;
32934
+ var DEFAULT_MAX_BYTES = 2e5;
32935
+ async function getGitDiffSummary(workspace, options = {}) {
32936
+ const lastCheckedAt = Date.now();
32937
+ try {
32938
+ const repo = await resolveGitRepository(workspace, options);
32939
+ const repoRoot = repo.repoRoot;
32940
+ const [unstagedNameStatus, unstagedNumstat, stagedNameStatus, stagedNumstat, untracked] = await Promise.all([
32941
+ runGit(repo, ["diff", "--no-ext-diff", "--name-status"], { ...options, cwd: repoRoot }),
32942
+ runGit(repo, ["diff", "--no-ext-diff", "--numstat"], { ...options, cwd: repoRoot }),
32943
+ runGit(repo, ["diff", "--cached", "--no-ext-diff", "--name-status"], { ...options, cwd: repoRoot }),
32944
+ runGit(repo, ["diff", "--cached", "--no-ext-diff", "--numstat"], { ...options, cwd: repoRoot }),
32945
+ runGit(repo, ["ls-files", "--others", "--exclude-standard"], { ...options, cwd: repoRoot })
32946
+ ]);
32947
+ const outputBytes = byteLength(
32948
+ unstagedNameStatus.stdout + unstagedNumstat.stdout + stagedNameStatus.stdout + stagedNumstat.stdout + untracked.stdout
32949
+ );
32950
+ const changes = [
32951
+ ...combineDiffEntries(unstagedNameStatus.stdout, unstagedNumstat.stdout, false),
32952
+ ...combineDiffEntries(stagedNameStatus.stdout, stagedNumstat.stdout, true),
32953
+ ...parseUntrackedFiles(untracked.stdout)
32954
+ ];
32955
+ const maxFiles = normalizePositiveInteger(options.maxFiles, DEFAULT_MAX_FILES);
32956
+ const maxBytes = normalizePositiveInteger(options.maxBytes, DEFAULT_MAX_BYTES);
32957
+ const files = changes.slice(0, maxFiles);
32958
+ const truncated = changes.length > files.length || outputBytes > maxBytes;
32959
+ return {
32960
+ workspace: repo.workspace,
32961
+ repoRoot,
32962
+ isGitRepo: true,
32963
+ files,
32964
+ totalInsertions: files.reduce((sum, file2) => sum + file2.insertions, 0),
32965
+ totalDeletions: files.reduce((sum, file2) => sum + file2.deletions, 0),
32966
+ truncated,
32967
+ lastCheckedAt
32968
+ };
32969
+ } catch (error48) {
32970
+ const gitError = error48 instanceof GitCommandError ? error48 : new GitCommandError("git_command_failed", "Failed to read Git diff summary", { cause: error48 });
32971
+ return {
32972
+ workspace,
32973
+ repoRoot: null,
32974
+ isGitRepo: false,
32975
+ files: [],
32976
+ totalInsertions: 0,
32977
+ totalDeletions: 0,
32978
+ truncated: false,
32979
+ lastCheckedAt,
32980
+ error: gitError.stderr || gitError.message,
32981
+ reason: gitError.reason
32982
+ };
32983
+ }
32984
+ }
32985
+ async function getGitFileDiff(workspace, filePath, options = {}) {
32986
+ const lastCheckedAt = Date.now();
32987
+ const repo = await resolveGitRepository(workspace, options);
32988
+ const repoRoot = repo.repoRoot;
32989
+ const selected = await resolveRepoFilePath(repoRoot, filePath);
32990
+ const maxBytes = normalizePositiveInteger(options.maxBytes, DEFAULT_MAX_BYTES);
32991
+ const [unstaged, staged] = await Promise.all([
32992
+ runGit(repo, ["diff", "--no-ext-diff", "--", selected.relativePath], { ...options, cwd: repoRoot }),
32993
+ runGit(repo, ["diff", "--cached", "--no-ext-diff", "--", selected.relativePath], { ...options, cwd: repoRoot })
32994
+ ]);
32995
+ let diff = [unstaged.stdout, staged.stdout].filter((part) => part.length > 0).join("\n");
32996
+ if (!diff) {
32997
+ const untracked = await runGit(repo, ["ls-files", "--others", "--exclude-standard", "--", selected.relativePath], {
32998
+ ...options,
32999
+ cwd: repoRoot
33000
+ });
33001
+ const untrackedFiles = untracked.stdout.split("\n").filter(Boolean);
33002
+ if (untrackedFiles.includes(selected.relativePath)) {
33003
+ diff = await buildUntrackedDiff(selected.absolutePath, selected.relativePath, maxBytes + 1);
33004
+ }
33005
+ }
33006
+ const bounded = truncateText(diff, maxBytes);
33007
+ return {
33008
+ workspace: repo.workspace,
33009
+ repoRoot,
33010
+ isGitRepo: true,
33011
+ path: selected.relativePath,
33012
+ diff: bounded.text,
33013
+ truncated: bounded.truncated,
33014
+ lastCheckedAt
33015
+ };
33016
+ }
33017
+ function combineDiffEntries(nameStatusOutput, numstatOutput, staged) {
33018
+ const statusEntries = parseNameStatus(nameStatusOutput);
33019
+ const numstatEntries = parseNumstat(numstatOutput);
33020
+ return statusEntries.map((entry, index) => {
33021
+ const stats = numstatEntries[index];
33022
+ return {
33023
+ path: entry.path,
33024
+ oldPath: entry.oldPath,
33025
+ status: entry.status,
33026
+ staged,
33027
+ insertions: stats?.insertions ?? 0,
33028
+ deletions: stats?.deletions ?? 0,
33029
+ binary: stats?.binary || void 0
33030
+ };
33031
+ });
33032
+ }
33033
+ function parseNameStatus(output) {
33034
+ return output.split("\n").filter(Boolean).map((line) => {
33035
+ const fields = line.split(" ");
33036
+ const code = fields[0] ?? "";
33037
+ const statusLetter = code[0] ?? "M";
33038
+ if (statusLetter === "R") {
33039
+ return {
33040
+ oldPath: fields[1] ?? "",
33041
+ path: fields[2] ?? fields[1] ?? "",
33042
+ status: "renamed"
33043
+ };
33044
+ }
33045
+ if (statusLetter === "C") {
33046
+ return {
33047
+ oldPath: fields[1] ?? "",
33048
+ path: fields[2] ?? fields[1] ?? "",
33049
+ status: "copied"
33050
+ };
33051
+ }
33052
+ return {
33053
+ path: fields[1] ?? "",
33054
+ status: mapNameStatus(statusLetter)
33055
+ };
33056
+ }).filter((entry) => entry.path.length > 0);
33057
+ }
33058
+ function parseNumstat(output) {
33059
+ return output.split("\n").filter(Boolean).map((line) => {
33060
+ const fields = line.split(" ");
33061
+ const insertionsText = fields[0] ?? "0";
33062
+ const deletionsText = fields[1] ?? "0";
33063
+ const binary = insertionsText === "-" || deletionsText === "-";
33064
+ return {
33065
+ path: fields.slice(2).join(" "),
33066
+ insertions: binary ? 0 : Number.parseInt(insertionsText, 10) || 0,
33067
+ deletions: binary ? 0 : Number.parseInt(deletionsText, 10) || 0,
33068
+ binary
33069
+ };
33070
+ });
33071
+ }
33072
+ function parseUntrackedFiles(output) {
33073
+ return output.split("\n").filter(Boolean).map((filePath) => ({
33074
+ path: filePath,
33075
+ status: "untracked",
33076
+ staged: false,
33077
+ insertions: 0,
33078
+ deletions: 0
33079
+ }));
33080
+ }
33081
+ function mapNameStatus(status) {
33082
+ switch (status) {
33083
+ case "A":
33084
+ return "added";
33085
+ case "D":
33086
+ return "deleted";
33087
+ case "R":
33088
+ return "renamed";
33089
+ case "C":
33090
+ return "copied";
33091
+ case "U":
33092
+ return "conflict";
33093
+ case "M":
33094
+ case "T":
33095
+ default:
33096
+ return "modified";
33097
+ }
33098
+ }
33099
+ async function resolveRepoFilePath(repoRoot, filePath) {
33100
+ if (typeof filePath !== "string" || filePath.length === 0 || filePath.includes("\0")) {
33101
+ throw new GitCommandError("invalid_args", "File path must be a non-empty path");
33102
+ }
33103
+ const canonicalRepoRoot = await (0, import_promises22.realpath)(repoRoot).catch(() => path23.resolve(repoRoot));
33104
+ const absolutePath = path23.isAbsolute(filePath) ? path23.resolve(filePath) : path23.resolve(repoRoot, filePath);
33105
+ const checkPath = await (0, import_promises22.realpath)(absolutePath).catch(() => absolutePath);
33106
+ const relativeBase = isPathInside(canonicalRepoRoot, checkPath) ? canonicalRepoRoot : path23.resolve(repoRoot);
33107
+ if (!isPathInside(canonicalRepoRoot, checkPath) && !isPathInside(repoRoot, absolutePath)) {
33108
+ throw new GitCommandError("path_outside_repo", "Selected file path is outside the repository root", {
33109
+ cwd: repoRoot
33110
+ });
33111
+ }
33112
+ const relativePath = path23.relative(relativeBase, checkPath).split(path23.sep).join("/");
33113
+ if (!relativePath || relativePath.startsWith("..") || path23.isAbsolute(relativePath)) {
33114
+ throw new GitCommandError("path_outside_repo", "Selected file path is outside the repository root", {
33115
+ cwd: repoRoot
33116
+ });
33117
+ }
33118
+ return { absolutePath, relativePath };
33119
+ }
33120
+ async function buildUntrackedDiff(absolutePath, relativePath, readLimit) {
33121
+ const content = await (0, import_promises22.readFile)(absolutePath, "utf8");
33122
+ const limitedContent = content.length > readLimit ? content.slice(0, readLimit) : content;
33123
+ const lines = limitedContent.length > 0 ? limitedContent.split("\n") : [];
33124
+ const plusLines = lines.filter((line, index) => index < lines.length - 1 || line.length > 0).map((line) => `+${line}`).join("\n");
33125
+ const lineCount = plusLines ? plusLines.split("\n").length : 0;
33126
+ return [
33127
+ `diff --git a/${relativePath} b/${relativePath}`,
33128
+ "new file mode 100644",
33129
+ "index 0000000..0000000",
33130
+ "--- /dev/null",
33131
+ `+++ b/${relativePath}`,
33132
+ `@@ -0,0 +1,${lineCount} @@`,
33133
+ plusLines
33134
+ ].filter((line) => line.length > 0).join("\n");
33135
+ }
33136
+ function truncateText(text, maxBytes) {
33137
+ if (byteLength(text) <= maxBytes) return { text, truncated: false };
33138
+ return { text: Buffer.from(text, "utf8").subarray(0, maxBytes).toString("utf8"), truncated: true };
33139
+ }
33140
+ function byteLength(text) {
33141
+ return Buffer.byteLength(text, "utf8");
33142
+ }
33143
+ function normalizePositiveInteger(value, fallback) {
33144
+ if (!Number.isFinite(value) || value == null || value <= 0) return fallback;
33145
+ return Math.floor(value);
33146
+ }
33147
+ function countStatusChangedFiles(status) {
33148
+ const conflictCount = status.conflictFiles.length > 0 ? status.conflictFiles.length : status.hasConflicts ? 1 : 0;
33149
+ return status.staged + status.modified + status.untracked + status.deleted + status.renamed + conflictCount;
33150
+ }
33151
+ function createGitCompactSummary(status, diffSummary) {
33152
+ const statusChangedFiles = countStatusChangedFiles(status);
33153
+ const diffChangedFiles = diffSummary?.files.length ?? 0;
33154
+ const changedFiles = Math.max(statusChangedFiles, diffChangedFiles);
33155
+ const conflictCount = status.conflictFiles.length > 0 ? status.conflictFiles.length : status.hasConflicts ? 1 : 0;
33156
+ return {
33157
+ isGitRepo: status.isGitRepo,
33158
+ repoRoot: status.repoRoot,
33159
+ branch: status.branch,
33160
+ dirty: status.staged > 0 || status.modified > 0 || status.untracked > 0 || status.deleted > 0 || status.renamed > 0 || conflictCount > 0 || changedFiles > 0,
33161
+ changedFiles,
33162
+ ahead: status.ahead,
33163
+ behind: status.behind,
33164
+ hasConflicts: status.hasConflicts || conflictCount > 0,
33165
+ lastCheckedAt: Math.max(status.lastCheckedAt, diffSummary?.lastCheckedAt ?? status.lastCheckedAt),
33166
+ error: status.error ?? diffSummary?.error,
33167
+ reason: status.reason ?? diffSummary?.reason
33168
+ };
33169
+ }
33170
+ var summarizeGitStatus = createGitCompactSummary;
33171
+ function normalizeCapacity(capacity) {
33172
+ return Math.max(1, Math.floor(capacity ?? 100));
33173
+ }
33174
+ function createEmptyDiffSummary(status) {
33175
+ return {
33176
+ workspace: status.workspace,
33177
+ repoRoot: status.repoRoot,
33178
+ isGitRepo: status.isGitRepo,
33179
+ files: [],
33180
+ totalInsertions: 0,
33181
+ totalDeletions: 0,
33182
+ truncated: false,
33183
+ lastCheckedAt: status.lastCheckedAt,
33184
+ error: status.error,
33185
+ reason: status.reason
33186
+ };
33187
+ }
33188
+ function changedFileKey(file2) {
33189
+ return `${file2.oldPath ?? ""}\0${file2.path}`;
33190
+ }
33191
+ function uniqueSorted(values) {
33192
+ return Array.from(new Set(Array.from(values).filter(Boolean))).sort((a, b2) => a.localeCompare(b2));
33193
+ }
33194
+ function plural(count, singular, pluralText = `${singular}s`) {
33195
+ return count === 1 ? singular : pluralText;
33196
+ }
33197
+ function compareGitSnapshots(before, after) {
33198
+ const beforeFileKeys = new Set(before.diffSummary.files.map(changedFileKey));
33199
+ const changedAfterFiles = after.diffSummary.files.filter((file2) => !beforeFileKeys.has(changedFileKey(file2)));
33200
+ const addedFiles = [];
33201
+ const modifiedFiles = [];
33202
+ const deletedFiles = [];
33203
+ const renamedFiles = [];
33204
+ const untrackedFiles = [];
33205
+ const conflictFilesFromDiff = [];
33206
+ let totalInsertions = 0;
33207
+ let totalDeletions = 0;
33208
+ for (const file2 of changedAfterFiles) {
33209
+ totalInsertions += file2.insertions;
33210
+ totalDeletions += file2.deletions;
33211
+ switch (file2.status) {
33212
+ case "added":
33213
+ case "copied":
33214
+ addedFiles.push(file2.path);
33215
+ break;
33216
+ case "modified":
33217
+ modifiedFiles.push(file2.path);
33218
+ break;
33219
+ case "deleted":
33220
+ deletedFiles.push(file2.path);
33221
+ break;
33222
+ case "renamed":
33223
+ renamedFiles.push({ oldPath: file2.oldPath ?? file2.path, path: file2.path });
33224
+ break;
33225
+ case "untracked":
33226
+ untrackedFiles.push(file2.path);
33227
+ break;
33228
+ case "conflict":
33229
+ conflictFilesFromDiff.push(file2.path);
33230
+ break;
33231
+ }
33232
+ }
33233
+ renamedFiles.sort((a, b2) => `${a.oldPath}\0${a.path}`.localeCompare(`${b2.oldPath}\0${b2.path}`));
33234
+ const conflictFiles = uniqueSorted([...after.status.conflictFiles, ...conflictFilesFromDiff]);
33235
+ const changedFiles = changedAfterFiles.length;
33236
+ const hasConflicts = after.status.hasConflicts || conflictFiles.length > 0;
33237
+ const summaryParts = [];
33238
+ if (changedFiles > 0) summaryParts.push(`${changedFiles} ${plural(changedFiles, "file")} changed`);
33239
+ if (addedFiles.length > 0) summaryParts.push(`${addedFiles.length} added`);
33240
+ if (modifiedFiles.length > 0) summaryParts.push(`${modifiedFiles.length} modified`);
33241
+ if (deletedFiles.length > 0) summaryParts.push(`${deletedFiles.length} deleted`);
33242
+ if (renamedFiles.length > 0) summaryParts.push(`${renamedFiles.length} renamed`);
33243
+ if (untrackedFiles.length > 0) summaryParts.push(`${untrackedFiles.length} untracked`);
33244
+ if (hasConflicts) summaryParts.push(`${conflictFiles.length || 1} ${plural(conflictFiles.length || 1, "conflict")}`);
33245
+ return {
33246
+ beforeSnapshotId: before.id,
33247
+ afterSnapshotId: after.id,
33248
+ workspace: after.workspace,
33249
+ repoRoot: after.repoRoot,
33250
+ changedFiles,
33251
+ addedFiles: uniqueSorted(addedFiles),
33252
+ modifiedFiles: uniqueSorted(modifiedFiles),
33253
+ deletedFiles: uniqueSorted(deletedFiles),
33254
+ renamedFiles,
33255
+ untrackedFiles: uniqueSorted(untrackedFiles),
33256
+ conflictFiles,
33257
+ totalInsertions,
33258
+ totalDeletions,
33259
+ hasConflicts,
33260
+ currentStatus: after.status,
33261
+ summaryText: summaryParts.length > 0 ? summaryParts.join(", ") : "No file-set changes between snapshots."
33262
+ };
33263
+ }
33264
+ var InMemoryGitSnapshotStore = class {
33265
+ snapshots = /* @__PURE__ */ new Map();
33266
+ order = [];
33267
+ capacity;
33268
+ now;
33269
+ idPrefix;
33270
+ getStatusProvider;
33271
+ getDiffSummaryProvider;
33272
+ counter = 0;
33273
+ constructor(options = {}) {
33274
+ this.capacity = normalizeCapacity(options.capacity);
33275
+ this.now = options.now ?? Date.now;
33276
+ this.idPrefix = options.idPrefix ?? "git-snapshot";
33277
+ this.getStatusProvider = options.getStatus;
33278
+ this.getDiffSummaryProvider = options.getDiffSummary;
33279
+ }
33280
+ async create(input) {
33281
+ const getStatus = input.getStatus ?? this.getStatusProvider;
33282
+ if (!getStatus) {
33283
+ throw new Error("GitSnapshotStore requires an injected getStatus provider");
33284
+ }
33285
+ const status = await getStatus(input.workspace);
33286
+ const getDiffSummary = input.getDiffSummary ?? this.getDiffSummaryProvider;
33287
+ const diffSummary = getDiffSummary ? await getDiffSummary(input.workspace, status) : createEmptyDiffSummary(status);
33288
+ const createdAt = this.now();
33289
+ const id = `${this.idPrefix}-${createdAt}-${++this.counter}`;
33290
+ const snapshot = {
33291
+ id,
33292
+ workspace: input.workspace,
33293
+ repoRoot: status.repoRoot ?? input.workspace,
33294
+ sessionId: input.sessionId,
33295
+ turnId: input.turnId,
33296
+ reason: input.reason,
33297
+ status,
33298
+ diffSummary,
33299
+ createdAt
33300
+ };
33301
+ this.snapshots.set(id, snapshot);
33302
+ this.order.push(id);
33303
+ this.enforceCapacity();
33304
+ return snapshot;
33305
+ }
33306
+ get(id) {
33307
+ return this.snapshots.get(id);
33308
+ }
33309
+ compare(beforeSnapshotId, afterSnapshotId) {
33310
+ const before = this.snapshots.get(beforeSnapshotId);
33311
+ if (!before) throw new Error(`Unknown before snapshot: ${beforeSnapshotId}`);
33312
+ const after = this.snapshots.get(afterSnapshotId);
33313
+ if (!after) throw new Error(`Unknown after snapshot: ${afterSnapshotId}`);
33314
+ return compareGitSnapshots(before, after);
33315
+ }
33316
+ list(query = {}) {
33317
+ const limit = Math.max(1, Math.floor(query.limit ?? this.capacity));
33318
+ 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);
33319
+ }
33320
+ clear() {
33321
+ this.snapshots.clear();
33322
+ this.order.splice(0, this.order.length);
33323
+ }
33324
+ enforceCapacity() {
33325
+ while (this.order.length > this.capacity) {
33326
+ const evictedId = this.order.shift();
33327
+ if (evictedId) this.snapshots.delete(evictedId);
33328
+ }
33329
+ }
33330
+ };
33331
+ function createGitSnapshotStore(options = {}) {
33332
+ return new InMemoryGitSnapshotStore(options);
33333
+ }
33334
+ var DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS = 5e3;
33335
+ var MIN_GIT_WORKSPACE_POLL_INTERVAL_MS = 1e3;
33336
+ function defaultStatusProvider(workspace) {
33337
+ return getGitRepoStatus(workspace);
33338
+ }
33339
+ function defaultDiffSummaryProvider(workspace) {
33340
+ return getGitDiffSummary(workspace);
33341
+ }
33342
+ function normalizeIntervalMs(value, defaultIntervalMs, minIntervalMs) {
33343
+ const requested = Number.isFinite(value) ? Math.floor(value) : defaultIntervalMs;
33344
+ return Math.max(minIntervalMs, requested > 0 ? requested : defaultIntervalMs);
33345
+ }
33346
+ function normalizeGitWorkspaceSubscriptionParams2(params, options = {}) {
33347
+ const minIntervalMs = Math.max(1, Math.floor(options.minIntervalMs ?? MIN_GIT_WORKSPACE_POLL_INTERVAL_MS));
33348
+ const defaultIntervalMs = Math.max(minIntervalMs, Math.floor(options.defaultIntervalMs ?? DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS));
33349
+ return {
33350
+ workspace: params.workspace,
33351
+ includeDiffSummary: Boolean(params.includeDiffSummary),
33352
+ intervalMs: normalizeIntervalMs(params.intervalMs, defaultIntervalMs, minIntervalMs)
33353
+ };
33354
+ }
33355
+ var GitWorkspaceMonitor = class {
33356
+ getStatusProvider;
33357
+ getDiffSummaryProvider;
33358
+ now;
33359
+ minIntervalMs;
33360
+ defaultIntervalMs;
33361
+ keyPrefix;
33362
+ cache = /* @__PURE__ */ new Map();
33363
+ listeners = /* @__PURE__ */ new Set();
33364
+ seq = 0;
33365
+ constructor(options = {}) {
33366
+ this.getStatusProvider = options.getStatus ?? defaultStatusProvider;
33367
+ this.getDiffSummaryProvider = options.getDiffSummary ?? defaultDiffSummaryProvider;
33368
+ this.now = options.now ?? Date.now;
33369
+ this.minIntervalMs = Math.max(1, Math.floor(options.minIntervalMs ?? MIN_GIT_WORKSPACE_POLL_INTERVAL_MS));
33370
+ this.defaultIntervalMs = Math.max(
33371
+ this.minIntervalMs,
33372
+ Math.floor(options.defaultIntervalMs ?? DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS)
33373
+ );
33374
+ this.keyPrefix = options.keyPrefix ?? "git";
33375
+ }
33376
+ async refresh(params) {
33377
+ const normalized = this.normalize(typeof params === "string" ? { workspace: params } : params);
33378
+ const status = await this.getStatusProvider(normalized.workspace);
33379
+ const diffSummary = normalized.includeDiffSummary ? await this.getDiffSummaryProvider(normalized.workspace, status) : void 0;
33380
+ const compactSummary = createGitCompactSummary(status, diffSummary);
33381
+ const timestamp = this.now();
33382
+ const seq = ++this.seq;
33383
+ const key = this.keyForWorkspace(normalized.workspace);
33384
+ const update = {
33385
+ topic: "workspace.git",
33386
+ key,
33387
+ workspace: normalized.workspace,
33388
+ status,
33389
+ diffSummary,
33390
+ seq,
33391
+ timestamp
33392
+ };
33393
+ const cacheEntry = {
33394
+ key,
33395
+ workspace: normalized.workspace,
33396
+ status,
33397
+ diffSummary,
33398
+ compactSummary,
33399
+ seq,
33400
+ timestamp
33401
+ };
33402
+ this.cache.set(normalized.workspace, cacheEntry);
33403
+ this.emit(update, cacheEntry);
33404
+ return update;
33405
+ }
33406
+ poll(params) {
33407
+ return this.refresh(params);
33408
+ }
33409
+ getCached(workspace) {
33410
+ return this.cache.get(workspace);
33411
+ }
33412
+ getCompactSummary(workspace) {
33413
+ return this.cache.get(workspace)?.compactSummary;
33414
+ }
33415
+ onUpdate(listener) {
33416
+ this.listeners.add(listener);
33417
+ return () => {
33418
+ this.listeners.delete(listener);
33419
+ };
33420
+ }
33421
+ createSubscription(params, listener) {
33422
+ const normalized = this.normalize(params);
33423
+ const scopedListener = listener ? (update, cacheEntry) => {
33424
+ if (update.workspace === normalized.workspace) listener(update, cacheEntry);
33425
+ } : void 0;
33426
+ const unsubscribe = scopedListener ? this.onUpdate(scopedListener) : () => void 0;
33427
+ return {
33428
+ params: normalized,
33429
+ refresh: () => this.refresh(normalized),
33430
+ getCached: () => this.getCached(normalized.workspace),
33431
+ dispose: unsubscribe
33432
+ };
33433
+ }
33434
+ normalize(params) {
33435
+ return normalizeGitWorkspaceSubscriptionParams2(params, {
33436
+ defaultIntervalMs: this.defaultIntervalMs,
33437
+ minIntervalMs: this.minIntervalMs
33438
+ });
33439
+ }
33440
+ keyForWorkspace(workspace) {
33441
+ return `${this.keyPrefix}:${workspace}`;
33442
+ }
33443
+ emit(update, cacheEntry) {
33444
+ for (const listener of this.listeners) {
33445
+ listener(update, cacheEntry);
33446
+ }
33447
+ }
33448
+ };
33449
+ function createGitWorkspaceMonitor2(options = {}) {
33450
+ return new GitWorkspaceMonitor(options);
33451
+ }
33452
+ var path32 = __toESM2(require("path"));
33453
+ var GIT_COMMAND_NAMES = /* @__PURE__ */ new Set([
33454
+ "git_status",
33455
+ "git_diff_summary",
33456
+ "git_diff_file",
33457
+ "git_snapshot_create",
33458
+ "git_snapshot_compare",
33459
+ "git_log",
33460
+ "git_checkpoint",
33461
+ "git_stash_push",
33462
+ "git_stash_pop",
33463
+ "git_checkout_files",
33464
+ "git_remote_url"
33465
+ ]);
33466
+ var SNAPSHOT_REASONS = /* @__PURE__ */ new Set([
33467
+ "session_baseline",
33468
+ "before_user_input_dispatch",
33469
+ "before_agent_work",
33470
+ "after_agent_work",
33471
+ "manual"
33472
+ ]);
33473
+ var FAILURE_REASONS = /* @__PURE__ */ new Set([
33474
+ "not_git_repo",
33475
+ "git_not_installed",
33476
+ "timeout",
33477
+ "path_outside_repo",
33478
+ "dirty_index_required",
33479
+ "conflict",
33480
+ "invalid_args",
33481
+ "git_command_failed"
33482
+ ]);
33483
+ function failure(reason, error48) {
33484
+ return { success: false, reason, error: error48 };
33485
+ }
33486
+ function serviceNotImplemented(command) {
33487
+ return failure("invalid_args", `${command} is not implemented: daemon-core Git service is not configured`);
33488
+ }
33489
+ var defaultSnapshotStore = createGitSnapshotStore({
33490
+ getStatus: (workspace) => getGitRepoStatus(workspace),
33491
+ getDiffSummary: (workspace) => getGitDiffSummary(workspace)
33492
+ });
33493
+ function createDefaultGitCommandServices() {
33494
+ return {
33495
+ getStatus: ({ workspace }) => getGitRepoStatus(workspace),
33496
+ getDiffSummary: ({ workspace }) => getGitDiffSummary(workspace),
33497
+ getDiffFile: ({ workspace, path: filePath }) => getGitFileDiff(workspace, filePath),
33498
+ createSnapshot: ({ workspace, reason, sessionId, turnId }) => defaultSnapshotStore.create({
33499
+ workspace,
33500
+ reason,
33501
+ sessionId,
33502
+ turnId
33503
+ }),
33504
+ compareSnapshots: ({ beforeSnapshotId, afterSnapshotId }) => defaultSnapshotStore.compare(beforeSnapshotId, afterSnapshotId),
33505
+ getLog: ({ workspace, limit, path: filePath, since, until }) => getGitLog(workspace, { limit, path: filePath, since, until }),
33506
+ checkpoint: async ({ workspace, message, includeUntracked = false }) => gitCheckpoint(workspace, message, includeUntracked),
33507
+ stashPush: async ({ workspace, message, includeUntracked = false }) => gitStashPush(workspace, message, includeUntracked),
33508
+ stashPop: async ({ workspace, stashRef }) => gitStashPop(workspace, stashRef),
33509
+ checkoutFiles: async ({ workspace, paths }) => gitCheckoutFiles(workspace, paths),
33510
+ getRemoteUrl: async ({ workspace, remote = "origin" }) => gitGetRemoteUrl(workspace, remote)
33511
+ };
33512
+ }
33513
+ var defaultGitCommandServices = createDefaultGitCommandServices();
33514
+ function validateWorkspace2(args) {
33515
+ if (typeof args?.workspace !== "string") {
33516
+ return failure("invalid_args", "workspace must be a non-empty absolute path");
33517
+ }
33518
+ const workspace = args.workspace.trim();
33519
+ if (!workspace || !path32.isAbsolute(workspace)) {
33520
+ return failure("invalid_args", "workspace must be a non-empty absolute path");
33521
+ }
33522
+ return { workspace };
33523
+ }
33524
+ function validateRepoPath(args) {
33525
+ if (typeof args?.path !== "string" || !args.path.trim()) {
33526
+ return failure("invalid_args", "path must be a non-empty repository-relative path");
33527
+ }
33528
+ return { path: args.path.trim() };
33529
+ }
33530
+ function validateSnapshotId(args, key) {
33531
+ if (typeof args?.[key] !== "string" || !args[key].trim()) {
33532
+ return failure("invalid_args", `${key} must be a non-empty string`);
33533
+ }
33534
+ return args[key].trim();
33535
+ }
33536
+ function parseSnapshotReason(args) {
33537
+ if (args?.reason === void 0 || args?.reason === null || args?.reason === "") {
33538
+ return "manual";
33539
+ }
33540
+ if (typeof args.reason !== "string" || !SNAPSHOT_REASONS.has(args.reason)) {
33541
+ return failure("invalid_args", "reason must be a valid GitSnapshotReason");
33542
+ }
33543
+ return args.reason;
33544
+ }
33545
+ function optionalString(value) {
33546
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
33547
+ }
33548
+ function optionalBoolean(value) {
33549
+ return typeof value === "boolean" ? value : void 0;
33550
+ }
33551
+ function boundedLogLimit(value) {
33552
+ if (value === void 0 || value === null || value === "") return 50;
33553
+ const numeric = typeof value === "number" ? value : Number(value);
33554
+ if (!Number.isFinite(numeric)) return 50;
33555
+ return Math.max(1, Math.min(200, Math.floor(numeric)));
33556
+ }
33557
+ function failureReasonFromError(error48) {
33558
+ return typeof error48?.reason === "string" && FAILURE_REASONS.has(error48.reason) ? error48.reason : "git_command_failed";
33559
+ }
33560
+ async function runService(fn2) {
33561
+ try {
33562
+ return await fn2();
33563
+ } catch (error48) {
33564
+ return failure(failureReasonFromError(error48), error48?.message || "Git command failed");
33565
+ }
33566
+ }
33567
+ function isGitCommandName(command) {
33568
+ return GIT_COMMAND_NAMES.has(command);
33569
+ }
33570
+ async function handleGitCommand(command, args, services = defaultGitCommandServices) {
33571
+ if (!isGitCommandName(command)) {
33572
+ return failure("invalid_args", `Unknown Git command: ${command}`);
33573
+ }
33574
+ const workspaceResult = validateWorkspace2(args);
33575
+ if ("success" in workspaceResult) return workspaceResult;
33576
+ const { workspace } = workspaceResult;
33577
+ switch (command) {
33578
+ case "git_status": {
33579
+ if (!services.getStatus) return serviceNotImplemented(command);
33580
+ const status = await runService(() => services.getStatus({ workspace }));
33581
+ return "success" in status ? status : { success: true, status };
33582
+ }
33583
+ case "git_diff_summary": {
33584
+ if (!services.getDiffSummary) return serviceNotImplemented(command);
33585
+ const diffSummary = await runService(() => services.getDiffSummary({ workspace, staged: optionalBoolean(args?.staged) }));
33586
+ return "success" in diffSummary ? diffSummary : { success: true, diffSummary };
33587
+ }
33588
+ case "git_diff_file": {
33589
+ if (!services.getDiffFile) return serviceNotImplemented(command);
33590
+ const pathResult = validateRepoPath(args);
33591
+ if (typeof pathResult !== "object" || "success" in pathResult) return pathResult;
33592
+ const diff = await runService(() => services.getDiffFile({
33593
+ workspace,
33594
+ path: pathResult.path,
33595
+ staged: optionalBoolean(args?.staged)
33596
+ }));
33597
+ return "success" in diff ? diff : { success: true, diff };
33598
+ }
33599
+ case "git_snapshot_create": {
33600
+ if (!services.createSnapshot) return serviceNotImplemented(command);
33601
+ const reason = parseSnapshotReason(args);
33602
+ if (typeof reason !== "string") return reason;
33603
+ const snapshot = await runService(() => services.createSnapshot({
33604
+ workspace,
33605
+ reason,
33606
+ sessionId: optionalString(args?.sessionId),
33607
+ turnId: optionalString(args?.turnId)
33608
+ }));
33609
+ return "success" in snapshot ? snapshot : { success: true, snapshot };
33610
+ }
33611
+ case "git_snapshot_compare": {
33612
+ if (!services.compareSnapshots) return serviceNotImplemented(command);
33613
+ const beforeSnapshotId = validateSnapshotId(args, "beforeSnapshotId");
33614
+ if (typeof beforeSnapshotId !== "string") return beforeSnapshotId;
33615
+ const afterSnapshotId = validateSnapshotId(args, "afterSnapshotId");
33616
+ if (typeof afterSnapshotId !== "string") return afterSnapshotId;
33617
+ const compare = await runService(() => services.compareSnapshots({ workspace, beforeSnapshotId, afterSnapshotId }));
33618
+ return "success" in compare ? compare : { success: true, compare };
33619
+ }
33620
+ case "git_log": {
33621
+ if (!services.getLog) {
33622
+ return failure("invalid_args", "git_log is not implemented: bounded daemon-core Git log service is not configured");
33623
+ }
33624
+ const log = await runService(() => services.getLog({
33625
+ workspace,
33626
+ limit: boundedLogLimit(args?.limit),
33627
+ path: optionalString(args?.path),
33628
+ since: optionalString(args?.since),
33629
+ until: optionalString(args?.until)
33630
+ }));
33631
+ return "success" in log ? log : { success: true, log };
33632
+ }
33633
+ case "git_checkpoint": {
33634
+ if (!services.checkpoint) return serviceNotImplemented(command);
33635
+ const msg = validateMutatingMessage(args?.message);
33636
+ if (typeof msg !== "string") return msg;
33637
+ const includeUntracked = Boolean(args?.includeUntracked);
33638
+ const checkpoint = await runService(() => services.checkpoint({ workspace, message: msg, includeUntracked }));
33639
+ return "success" in checkpoint ? checkpoint : { success: true, checkpoint };
33640
+ }
33641
+ case "git_stash_push": {
33642
+ if (!services.stashPush) return serviceNotImplemented(command);
33643
+ const msg = validateMutatingMessage(args?.message);
33644
+ if (typeof msg !== "string") return msg;
33645
+ const includeUntracked = Boolean(args?.includeUntracked);
33646
+ const stash = await runService(() => services.stashPush({ workspace, message: msg, includeUntracked }));
33647
+ return "success" in stash ? stash : { success: true, stash };
33648
+ }
33649
+ case "git_stash_pop": {
33650
+ if (!services.stashPop) return serviceNotImplemented(command);
33651
+ const stashRef = optionalString(args?.stashRef);
33652
+ if (stashRef !== void 0 && !/^stash@\{\d+\}$/.test(stashRef)) {
33653
+ return failure("invalid_args", "stashRef must match stash@{N} format");
33654
+ }
33655
+ const popResult = await runService(() => services.stashPop({ workspace, stashRef }));
33656
+ if (popResult !== void 0 && "success" in popResult) return popResult;
33657
+ return { success: true, stashPopped: true };
33658
+ }
33659
+ case "git_checkout_files": {
33660
+ if (!services.checkoutFiles) return serviceNotImplemented(command);
33661
+ const paths = args?.paths;
33662
+ if (!Array.isArray(paths) || paths.length === 0) {
33663
+ return failure("invalid_args", "paths must be a non-empty array");
33664
+ }
33665
+ if (paths.length > 50) {
33666
+ return failure("invalid_args", "paths array exceeds maximum of 50 entries");
33667
+ }
33668
+ const checkoutResult = await runService(() => services.checkoutFiles({ workspace, paths }));
33669
+ return "success" in checkoutResult ? checkoutResult : { success: true, checkedOut: checkoutResult.checkedOut };
33670
+ }
33671
+ case "git_remote_url": {
33672
+ if (!services.getRemoteUrl) return serviceNotImplemented(command);
33673
+ const remote = typeof args?.remote === "string" && args.remote.trim() ? args.remote.trim() : "origin";
33674
+ const remoteResult = await runService(() => services.getRemoteUrl({ workspace, remote }));
33675
+ if ("success" in remoteResult) return remoteResult;
33676
+ return { success: true, remoteUrl: remoteResult.remoteUrl, remote: remoteResult.remote };
33677
+ }
33678
+ default:
33679
+ return failure("invalid_args", `Unknown Git command: ${command}`);
33680
+ }
33681
+ }
33682
+ function validateMutatingMessage(value) {
33683
+ if (typeof value !== "string" || !value.trim()) {
33684
+ return failure("invalid_args", "message must be a non-empty string");
33685
+ }
33686
+ const msg = value.trim();
33687
+ if (msg.length > 200) {
33688
+ return failure("invalid_args", "message must be 200 characters or fewer");
33689
+ }
33690
+ return msg;
33691
+ }
33692
+ async function gitCheckpoint(workspace, message, includeUntracked) {
33693
+ const repo = await resolveGitRepository(workspace);
33694
+ const repoRoot = repo.repoRoot;
33695
+ const statusResult = await getGitRepoStatus(workspace);
33696
+ if (statusResult.hasConflicts) {
33697
+ throw new GitCommandError("conflict", "Repository has conflicts \u2014 resolve before checkpointing");
33698
+ }
33699
+ const addArgs = includeUntracked ? ["-A"] : ["-u"];
33700
+ await runGit(repo, ["add", ...addArgs], { cwd: repoRoot });
33701
+ const fullMsg = `adhdev: checkpoint ${message}`;
33702
+ let commitSha;
33703
+ try {
33704
+ await runGit(repo, ["commit", "-m", fullMsg], { cwd: repoRoot });
33705
+ const revResult = await runGit(repo, ["rev-parse", "HEAD"], { cwd: repoRoot });
33706
+ commitSha = revResult.stdout.trim();
33707
+ } catch (err) {
33708
+ const output = (err?.stdout || "") + (err?.stderr || "");
33709
+ if (/nothing to commit/i.test(output)) {
33710
+ throw new GitCommandError("git_command_failed", "Nothing to commit");
33711
+ }
33712
+ throw err;
33713
+ }
33714
+ return {
33715
+ workspace: repo.workspace,
33716
+ repoRoot,
33717
+ isGitRepo: true,
33718
+ commit: commitSha,
33719
+ message: fullMsg,
33720
+ lastCheckedAt: Date.now()
33721
+ };
33722
+ }
33723
+ async function gitStashPush(workspace, message, includeUntracked) {
33724
+ const repo = await resolveGitRepository(workspace);
33725
+ const repoRoot = repo.repoRoot;
33726
+ const stashArgs = ["stash", "push", "-m", message];
33727
+ if (includeUntracked) stashArgs.push("--include-untracked");
33728
+ const result = await runGit(repo, stashArgs, { cwd: repoRoot });
33729
+ if (/No local changes to save/i.test(result.stdout + result.stderr)) {
33730
+ throw new GitCommandError("git_command_failed", "Nothing to stash");
33731
+ }
33732
+ return {
33733
+ workspace: repo.workspace,
33734
+ repoRoot,
33735
+ isGitRepo: true,
33736
+ stashRef: "stash@{0}",
33737
+ message,
33738
+ lastCheckedAt: Date.now()
33739
+ };
33740
+ }
33741
+ async function gitStashPop(workspace, stashRef) {
33742
+ const repo = await resolveGitRepository(workspace);
33743
+ const repoRoot = repo.repoRoot;
33744
+ const popArgs = stashRef ? ["stash", "pop", stashRef] : ["stash", "pop"];
33745
+ await runGit(repo, popArgs, { cwd: repoRoot });
33746
+ }
33747
+ async function gitCheckoutFiles(workspace, paths) {
33748
+ const repo = await resolveGitRepository(workspace);
33749
+ const repoRoot = repo.repoRoot;
33750
+ const normalizedPaths = [];
33751
+ for (const p of paths) {
33752
+ if (typeof p !== "string" || !p.trim() || p.includes("\0")) {
33753
+ throw new GitCommandError("invalid_args", `Invalid path: ${String(p)}`);
33754
+ }
33755
+ if (path32.isAbsolute(p)) {
33756
+ throw new GitCommandError("invalid_args", `Path must be repository-relative, not absolute: ${p}`);
33757
+ }
33758
+ const normalized = path32.normalize(p.trim()).split(path32.sep).join("/");
33759
+ if (normalized.startsWith("../") || normalized === "..") {
33760
+ throw new GitCommandError("path_outside_repo", `Path is outside repository root: ${p}`);
33761
+ }
33762
+ const absolutePath = path32.resolve(repoRoot, normalized);
33763
+ if (!isPathInside(repoRoot, absolutePath)) {
33764
+ throw new GitCommandError("path_outside_repo", `Path is outside repository root: ${p}`);
33765
+ }
33766
+ normalizedPaths.push(normalized);
33767
+ }
33768
+ await runGit(repo, ["checkout", "--", ...normalizedPaths], { cwd: repoRoot });
33769
+ return { checkedOut: normalizedPaths };
33770
+ }
33771
+ async function gitGetRemoteUrl(workspace, remote) {
33772
+ const repo = await resolveGitRepository(workspace);
33773
+ const result = await runGit(repo, ["remote", "get-url", remote], { cwd: repo.repoRoot });
33774
+ const remoteUrl = result.stdout.trim();
33775
+ if (!remoteUrl) {
33776
+ throw new GitCommandError("git_command_failed", `Remote '${remote}' has no URL`);
33777
+ }
33778
+ return { remoteUrl, remote };
33779
+ }
33780
+ function formatOptionalGitLogRangeArg(flag, value) {
33781
+ return value ? [`${flag}=${value}`] : [];
33782
+ }
33783
+ async function getGitLog(workspace, options) {
33784
+ const lastCheckedAt = Date.now();
33785
+ const repo = await resolveGitRepository(workspace);
33786
+ const repoRoot = repo.repoRoot;
33787
+ const boundedLimit = Math.max(1, Math.min(200, Math.floor(options.limit || 50)));
33788
+ const selectedPath = options.path ? validateGitLogPath(repoRoot, options.path) : void 0;
33789
+ const result = await runGit(
33790
+ repo,
33791
+ [
33792
+ "log",
33793
+ `--max-count=${boundedLimit}`,
33794
+ "--format=%H%x00%an%x00%ae%x00%at%x00%ct%x00%s",
33795
+ ...formatOptionalGitLogRangeArg("--since", options.since),
33796
+ ...formatOptionalGitLogRangeArg("--until", options.until),
33797
+ "--",
33798
+ ...selectedPath ? [selectedPath] : []
33799
+ ],
33800
+ { cwd: repoRoot }
33801
+ );
33802
+ const entries = result.stdout.split("\n").filter((line) => line.trim().length > 0).map((line) => {
33803
+ const [commit = "", authorName, authorEmail, authoredAt, committedAt, ...messageParts] = line.split("\0");
33804
+ return {
33805
+ commit,
33806
+ message: messageParts.join("\0"),
33807
+ authorName: authorName || void 0,
33808
+ authorEmail: authorEmail || void 0,
33809
+ authoredAt: authoredAt ? Number.parseInt(authoredAt, 10) * 1e3 : void 0,
33810
+ committedAt: committedAt ? Number.parseInt(committedAt, 10) * 1e3 : void 0
33811
+ };
33812
+ }).filter((entry) => entry.commit.length > 0);
33813
+ return {
33814
+ workspace: repo.workspace,
33815
+ repoRoot,
33816
+ isGitRepo: true,
33817
+ entries,
33818
+ limit: boundedLimit,
33819
+ truncated: entries.length >= boundedLimit,
33820
+ lastCheckedAt
33821
+ };
33822
+ }
33823
+ function validateGitLogPath(repoRoot, filePath) {
33824
+ if (!filePath.trim() || filePath.includes("\0")) {
33825
+ throw new GitCommandError("invalid_args", "path must be a non-empty repository-relative path");
33826
+ }
33827
+ if (path32.isAbsolute(filePath)) {
33828
+ throw new GitCommandError("invalid_args", "path must be repository-relative");
33829
+ }
33830
+ const normalized = path32.normalize(filePath).split(path32.sep).join("/");
33831
+ const absolutePath = path32.resolve(repoRoot, normalized);
33832
+ if (!isPathInside(repoRoot, absolutePath) || normalized.startsWith("../") || normalized === "..") {
33833
+ throw new GitCommandError("path_outside_repo", "Git log path is outside the repository root");
33834
+ }
33835
+ return normalized;
33836
+ }
33837
+ var BUSY_STATUSES = /* @__PURE__ */ new Set(["streaming", "waiting_approval"]);
33838
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["idle", "error"]);
33839
+ var TurnSnapshotTracker = class {
33840
+ lastStatus = /* @__PURE__ */ new Map();
33841
+ onTurnCompleted;
33842
+ constructor(onTurnCompleted) {
33843
+ this.onTurnCompleted = onTurnCompleted;
33844
+ }
33845
+ record(sessionId, status, workspace) {
33846
+ const prev = this.lastStatus.get(sessionId);
33847
+ this.lastStatus.set(sessionId, status);
33848
+ if (workspace && prev && BUSY_STATUSES.has(prev) && TERMINAL_STATUSES.has(status)) {
33849
+ this.onTurnCompleted({ sessionId, workspace });
33850
+ }
33851
+ }
33852
+ forget(sessionId) {
33853
+ this.lastStatus.delete(sessionId);
33854
+ }
33855
+ };
32551
33856
  init_config();
32552
33857
  var fs5 = __toESM2(require("fs"));
32553
33858
  var os6 = __toESM2(require("os"));
32554
- var path5 = __toESM2(require("path"));
33859
+ var path42 = __toESM2(require("path"));
32555
33860
  var import_crypto22 = require("crypto");
32556
33861
  var MAX_WORKSPACES = 50;
32557
33862
  function expandPath(p) {
32558
33863
  const t = (p || "").trim();
32559
33864
  if (!t) return "";
32560
- if (t.startsWith("~")) return path5.join(os6.homedir(), t.slice(1).replace(/^\//, ""));
32561
- return path5.resolve(t);
33865
+ if (t.startsWith("~")) return path42.join(os6.homedir(), t.slice(1).replace(/^\//, ""));
33866
+ return path42.resolve(t);
32562
33867
  }
32563
33868
  function validateWorkspacePath(absPath) {
32564
33869
  try {
@@ -32572,7 +33877,7 @@ var require_dist2 = __commonJS({
32572
33877
  }
32573
33878
  }
32574
33879
  function defaultWorkspaceLabel(absPath) {
32575
- const base = path5.basename(absPath) || absPath;
33880
+ const base = path42.basename(absPath) || absPath;
32576
33881
  return base;
32577
33882
  }
32578
33883
  function getDefaultWorkspacePath(config2) {
@@ -32663,9 +33968,9 @@ var require_dist2 = __commonJS({
32663
33968
  return getDefaultWorkspacePath(config2) || void 0;
32664
33969
  }
32665
33970
  function findWorkspaceByPath(config2, rawPath) {
32666
- const abs = path5.resolve(expandPath(rawPath));
33971
+ const abs = path42.resolve(expandPath(rawPath));
32667
33972
  if (!abs) return void 0;
32668
- return (config2.workspaces || []).find((w) => path5.resolve(expandPath(w.path)) === abs);
33973
+ return (config2.workspaces || []).find((w) => path42.resolve(expandPath(w.path)) === abs);
32669
33974
  }
32670
33975
  function addWorkspaceEntry(config2, rawPath, label, options) {
32671
33976
  const abs = expandPath(rawPath);
@@ -32681,7 +33986,7 @@ var require_dist2 = __commonJS({
32681
33986
  const v2 = validateWorkspacePath(abs);
32682
33987
  if (!v2.ok) return { error: v2.error };
32683
33988
  const list = [...config2.workspaces || []];
32684
- if (list.some((w) => path5.resolve(w.path) === abs)) {
33989
+ if (list.some((w) => path42.resolve(w.path) === abs)) {
32685
33990
  return { error: "Workspace already in list" };
32686
33991
  }
32687
33992
  if (list.length >= MAX_WORKSPACES) {
@@ -32713,7 +34018,7 @@ var require_dist2 = __commonJS({
32713
34018
  if (validateWorkspacePath(abs).ok !== true) return { error: "Workspace path is no longer valid" };
32714
34019
  return { config: { ...config2, defaultWorkspaceId: id } };
32715
34020
  }
32716
- var path23 = __toESM2(require("path"));
34021
+ var path52 = __toESM2(require("path"));
32717
34022
  function normalizeSummaryItem(item) {
32718
34023
  if (!item || typeof item !== "object") return null;
32719
34024
  const id = String(item.id || "").trim();
@@ -32778,9 +34083,9 @@ var require_dist2 = __commonJS({
32778
34083
  function normalizeWorkspace(workspace) {
32779
34084
  if (!workspace) return "";
32780
34085
  try {
32781
- return path23.resolve(expandPath(workspace));
34086
+ return path52.resolve(expandPath(workspace));
32782
34087
  } catch {
32783
- return path23.resolve(workspace);
34088
+ return path52.resolve(workspace);
32784
34089
  }
32785
34090
  }
32786
34091
  function buildRecentActivityKey(entry) {
@@ -32946,14 +34251,14 @@ var require_dist2 = __commonJS({
32946
34251
  sessionNotificationUnreadOverrides: nextSessionNotificationUnreadOverrides
32947
34252
  };
32948
34253
  }
32949
- var path32 = __toESM2(require("path"));
34254
+ var path6 = __toESM2(require("path"));
32950
34255
  var MAX_SAVED_SESSIONS = 500;
32951
34256
  function normalizeWorkspace2(workspace) {
32952
34257
  if (!workspace) return "";
32953
34258
  try {
32954
- return path32.resolve(expandPath(workspace));
34259
+ return path6.resolve(expandPath(workspace));
32955
34260
  } catch {
32956
- return path32.resolve(workspace);
34261
+ return path6.resolve(workspace);
32957
34262
  }
32958
34263
  }
32959
34264
  function buildSavedProviderSessionKey(providerSessionId) {
@@ -33068,7 +34373,7 @@ var require_dist2 = __commonJS({
33068
34373
  var import_child_process = require("child_process");
33069
34374
  var import_fs3 = require("fs");
33070
34375
  var import_os22 = require("os");
33071
- var path42 = __toESM2(require("path"));
34376
+ var path7 = __toESM2(require("path"));
33072
34377
  var BUILTIN_IDE_DEFINITIONS = [];
33073
34378
  var registeredIDEs = /* @__PURE__ */ new Map();
33074
34379
  function registerIDEDefinition(def) {
@@ -33087,9 +34392,9 @@ var require_dist2 = __commonJS({
33087
34392
  function findCliCommand(command) {
33088
34393
  const trimmed = String(command || "").trim();
33089
34394
  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);
34395
+ if (path7.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
34396
+ const candidate = trimmed.startsWith("~") ? path7.join((0, import_os22.homedir)(), trimmed.slice(1)) : trimmed;
34397
+ const resolved = path7.isAbsolute(candidate) ? candidate : path7.resolve(candidate);
33093
34398
  return (0, import_fs3.existsSync)(resolved) ? resolved : null;
33094
34399
  }
33095
34400
  try {
@@ -33117,7 +34422,7 @@ var require_dist2 = __commonJS({
33117
34422
  function checkPathExists(paths) {
33118
34423
  const home = (0, import_os22.homedir)();
33119
34424
  for (const p of paths) {
33120
- const normalized = p.startsWith("~") ? path42.join(home, p.slice(1)) : p;
34425
+ const normalized = p.startsWith("~") ? path7.join(home, p.slice(1)) : p;
33121
34426
  if (normalized.includes("*")) {
33122
34427
  const username = home.split(/[\\/]/).pop() || "";
33123
34428
  const resolved = normalized.replace("*", username);
@@ -33173,7 +34478,7 @@ var require_dist2 = __commonJS({
33173
34478
  }
33174
34479
  var import_child_process2 = require("child_process");
33175
34480
  var os22 = __toESM2(require("os"));
33176
- var path52 = __toESM2(require("path"));
34481
+ var path8 = __toESM2(require("path"));
33177
34482
  var import_fs4 = require("fs");
33178
34483
  function parseVersion(raw) {
33179
34484
  const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
@@ -33186,36 +34491,36 @@ var require_dist2 = __commonJS({
33186
34491
  function expandHome(value) {
33187
34492
  const trimmed = value.trim();
33188
34493
  if (!trimmed.startsWith("~")) return trimmed;
33189
- return path52.join(os22.homedir(), trimmed.slice(1));
34494
+ return path8.join(os22.homedir(), trimmed.slice(1));
33190
34495
  }
33191
34496
  function isExplicitCommandPath(command) {
33192
34497
  const trimmed = command.trim();
33193
- return path52.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
34498
+ return path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
33194
34499
  }
33195
34500
  function resolveCommandPath(command) {
33196
34501
  const trimmed = command.trim();
33197
34502
  if (!trimmed) return null;
33198
34503
  if (isExplicitCommandPath(trimmed)) {
33199
34504
  const expanded = expandHome(trimmed);
33200
- const candidate = path52.isAbsolute(expanded) ? expanded : path52.resolve(expanded);
34505
+ const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
33201
34506
  return (0, import_fs4.existsSync)(candidate) ? candidate : null;
33202
34507
  }
33203
34508
  return null;
33204
34509
  }
33205
34510
  function execAsync(cmd, timeoutMs = 5e3) {
33206
- return new Promise((resolve12) => {
34511
+ return new Promise((resolve15) => {
33207
34512
  const child = (0, import_child_process2.exec)(cmd, {
33208
34513
  encoding: "utf-8",
33209
34514
  timeout: timeoutMs,
33210
34515
  ...process.platform === "win32" ? { windowsHide: true } : {}
33211
34516
  }, (err, stdout) => {
33212
34517
  if (err || !stdout?.trim()) {
33213
- resolve12(null);
34518
+ resolve15(null);
33214
34519
  } else {
33215
- resolve12(stdout.trim());
34520
+ resolve15(stdout.trim());
33216
34521
  }
33217
34522
  });
33218
- child.on("error", () => resolve12(null));
34523
+ child.on("error", () => resolve15(null));
33219
34524
  });
33220
34525
  }
33221
34526
  async function detectCLIs(providerLoader, options) {
@@ -33572,7 +34877,7 @@ var require_dist2 = __commonJS({
33572
34877
  * Returns multiple entries if multiple IDE windows are open on same port
33573
34878
  */
33574
34879
  static listAllTargets(port) {
33575
- return new Promise((resolve12) => {
34880
+ return new Promise((resolve15) => {
33576
34881
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
33577
34882
  let data = "";
33578
34883
  res.on("data", (chunk) => data += chunk.toString());
@@ -33588,16 +34893,16 @@ var require_dist2 = __commonJS({
33588
34893
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
33589
34894
  );
33590
34895
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
33591
- resolve12(mainPages.length > 0 ? mainPages : fallbackPages);
34896
+ resolve15(mainPages.length > 0 ? mainPages : fallbackPages);
33592
34897
  } catch {
33593
- resolve12([]);
34898
+ resolve15([]);
33594
34899
  }
33595
34900
  });
33596
34901
  });
33597
- req.on("error", () => resolve12([]));
34902
+ req.on("error", () => resolve15([]));
33598
34903
  req.setTimeout(2e3, () => {
33599
34904
  req.destroy();
33600
- resolve12([]);
34905
+ resolve15([]);
33601
34906
  });
33602
34907
  });
33603
34908
  }
@@ -33637,7 +34942,7 @@ var require_dist2 = __commonJS({
33637
34942
  }
33638
34943
  }
33639
34944
  findTargetOnPort(port) {
33640
- return new Promise((resolve12) => {
34945
+ return new Promise((resolve15) => {
33641
34946
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
33642
34947
  let data = "";
33643
34948
  res.on("data", (chunk) => data += chunk.toString());
@@ -33648,7 +34953,7 @@ var require_dist2 = __commonJS({
33648
34953
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
33649
34954
  );
33650
34955
  if (pages.length === 0) {
33651
- resolve12(targets.find((t) => t.webSocketDebuggerUrl) || null);
34956
+ resolve15(targets.find((t) => t.webSocketDebuggerUrl) || null);
33652
34957
  return;
33653
34958
  }
33654
34959
  const titleFilteredPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -33667,25 +34972,25 @@ var require_dist2 = __commonJS({
33667
34972
  this._targetId = selected.target.id;
33668
34973
  }
33669
34974
  this._pageTitle = selected.target.title || "";
33670
- resolve12(selected.target);
34975
+ resolve15(selected.target);
33671
34976
  return;
33672
34977
  }
33673
34978
  if (previousTargetId) {
33674
34979
  this.log(`[CDP] Target ${previousTargetId} not found in page list`);
33675
- resolve12(null);
34980
+ resolve15(null);
33676
34981
  return;
33677
34982
  }
33678
34983
  this._pageTitle = list[0]?.title || "";
33679
- resolve12(list[0]);
34984
+ resolve15(list[0]);
33680
34985
  } catch {
33681
- resolve12(null);
34986
+ resolve15(null);
33682
34987
  }
33683
34988
  });
33684
34989
  });
33685
- req.on("error", () => resolve12(null));
34990
+ req.on("error", () => resolve15(null));
33686
34991
  req.setTimeout(2e3, () => {
33687
34992
  req.destroy();
33688
- resolve12(null);
34993
+ resolve15(null);
33689
34994
  });
33690
34995
  });
33691
34996
  }
@@ -33696,7 +35001,7 @@ var require_dist2 = __commonJS({
33696
35001
  this.extensionProviders = providers;
33697
35002
  }
33698
35003
  connectToTarget(wsUrl) {
33699
- return new Promise((resolve12) => {
35004
+ return new Promise((resolve15) => {
33700
35005
  this.ws = new import_ws2.default(wsUrl);
33701
35006
  this.ws.on("open", async () => {
33702
35007
  this._connected = true;
@@ -33706,17 +35011,17 @@ var require_dist2 = __commonJS({
33706
35011
  }
33707
35012
  this.connectBrowserWs().catch(() => {
33708
35013
  });
33709
- resolve12(true);
35014
+ resolve15(true);
33710
35015
  });
33711
35016
  this.ws.on("message", (data) => {
33712
35017
  try {
33713
35018
  const msg = JSON.parse(data.toString());
33714
35019
  if (msg.id && this.pending.has(msg.id)) {
33715
- const { resolve: resolve13, reject } = this.pending.get(msg.id);
35020
+ const { resolve: resolve16, reject } = this.pending.get(msg.id);
33716
35021
  this.pending.delete(msg.id);
33717
35022
  this.failureCount = 0;
33718
35023
  if (msg.error) reject(new Error(msg.error.message));
33719
- else resolve13(msg.result);
35024
+ else resolve16(msg.result);
33720
35025
  } else if (msg.method === "Runtime.executionContextCreated") {
33721
35026
  this.contexts.add(msg.params.context.id);
33722
35027
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -33739,7 +35044,7 @@ var require_dist2 = __commonJS({
33739
35044
  this.ws.on("error", (err) => {
33740
35045
  this.log(`[CDP] WebSocket error: ${err.message}`);
33741
35046
  this._connected = false;
33742
- resolve12(false);
35047
+ resolve15(false);
33743
35048
  });
33744
35049
  });
33745
35050
  }
@@ -33753,7 +35058,7 @@ var require_dist2 = __commonJS({
33753
35058
  return;
33754
35059
  }
33755
35060
  this.log(`[CDP] Connecting browser WS for target discovery...`);
33756
- await new Promise((resolve12, reject) => {
35061
+ await new Promise((resolve15, reject) => {
33757
35062
  this.browserWs = new import_ws2.default(browserWsUrl);
33758
35063
  this.browserWs.on("open", async () => {
33759
35064
  this._browserConnected = true;
@@ -33763,16 +35068,16 @@ var require_dist2 = __commonJS({
33763
35068
  } catch (e) {
33764
35069
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
33765
35070
  }
33766
- resolve12();
35071
+ resolve15();
33767
35072
  });
33768
35073
  this.browserWs.on("message", (data) => {
33769
35074
  try {
33770
35075
  const msg = JSON.parse(data.toString());
33771
35076
  if (msg.id && this.browserPending.has(msg.id)) {
33772
- const { resolve: resolve13, reject: reject2 } = this.browserPending.get(msg.id);
35077
+ const { resolve: resolve16, reject: reject2 } = this.browserPending.get(msg.id);
33773
35078
  this.browserPending.delete(msg.id);
33774
35079
  if (msg.error) reject2(new Error(msg.error.message));
33775
- else resolve13(msg.result);
35080
+ else resolve16(msg.result);
33776
35081
  }
33777
35082
  } catch {
33778
35083
  }
@@ -33792,31 +35097,31 @@ var require_dist2 = __commonJS({
33792
35097
  }
33793
35098
  }
33794
35099
  getBrowserWsUrl() {
33795
- return new Promise((resolve12) => {
35100
+ return new Promise((resolve15) => {
33796
35101
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
33797
35102
  let data = "";
33798
35103
  res.on("data", (chunk) => data += chunk.toString());
33799
35104
  res.on("end", () => {
33800
35105
  try {
33801
35106
  const info = JSON.parse(data);
33802
- resolve12(info.webSocketDebuggerUrl || null);
35107
+ resolve15(info.webSocketDebuggerUrl || null);
33803
35108
  } catch {
33804
- resolve12(null);
35109
+ resolve15(null);
33805
35110
  }
33806
35111
  });
33807
35112
  });
33808
- req.on("error", () => resolve12(null));
35113
+ req.on("error", () => resolve15(null));
33809
35114
  req.setTimeout(3e3, () => {
33810
35115
  req.destroy();
33811
- resolve12(null);
35116
+ resolve15(null);
33812
35117
  });
33813
35118
  });
33814
35119
  }
33815
35120
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
33816
- return new Promise((resolve12, reject) => {
35121
+ return new Promise((resolve15, reject) => {
33817
35122
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
33818
35123
  const id = this.browserMsgId++;
33819
- this.browserPending.set(id, { resolve: resolve12, reject });
35124
+ this.browserPending.set(id, { resolve: resolve15, reject });
33820
35125
  this.browserWs.send(JSON.stringify({ id, method, params }));
33821
35126
  setTimeout(() => {
33822
35127
  if (this.browserPending.has(id)) {
@@ -33856,11 +35161,11 @@ var require_dist2 = __commonJS({
33856
35161
  }
33857
35162
  // ─── CDP Protocol ────────────────────────────────────────
33858
35163
  sendInternal(method, params = {}, timeoutMs = 15e3) {
33859
- return new Promise((resolve12, reject) => {
35164
+ return new Promise((resolve15, reject) => {
33860
35165
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
33861
35166
  if (this.ws.readyState !== import_ws2.default.OPEN) return reject(new Error("WebSocket not open"));
33862
35167
  const id = this.msgId++;
33863
- this.pending.set(id, { resolve: resolve12, reject });
35168
+ this.pending.set(id, { resolve: resolve15, reject });
33864
35169
  this.ws.send(JSON.stringify({ id, method, params }));
33865
35170
  setTimeout(() => {
33866
35171
  if (this.pending.has(id)) {
@@ -34109,7 +35414,7 @@ var require_dist2 = __commonJS({
34109
35414
  const browserWs = this.browserWs;
34110
35415
  let msgId = this.browserMsgId;
34111
35416
  const sendWs = (method, params = {}, sessionId) => {
34112
- return new Promise((resolve12, reject) => {
35417
+ return new Promise((resolve15, reject) => {
34113
35418
  const mid = msgId++;
34114
35419
  this.browserMsgId = msgId;
34115
35420
  const handler = (raw) => {
@@ -34118,7 +35423,7 @@ var require_dist2 = __commonJS({
34118
35423
  if (msg.id === mid) {
34119
35424
  browserWs.removeListener("message", handler);
34120
35425
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
34121
- else resolve12(msg.result);
35426
+ else resolve15(msg.result);
34122
35427
  }
34123
35428
  } catch {
34124
35429
  }
@@ -34319,14 +35624,14 @@ var require_dist2 = __commonJS({
34319
35624
  if (!ws2 || ws2.readyState !== import_ws2.default.OPEN) {
34320
35625
  throw new Error("CDP not connected");
34321
35626
  }
34322
- return new Promise((resolve12, reject) => {
35627
+ return new Promise((resolve15, reject) => {
34323
35628
  const id = getNextId();
34324
35629
  pendingMap.set(id, {
34325
35630
  resolve: (result) => {
34326
35631
  if (result?.result?.subtype === "error") {
34327
35632
  reject(new Error(result.result.description));
34328
35633
  } else {
34329
- resolve12(result?.result?.value);
35634
+ resolve15(result?.result?.value);
34330
35635
  }
34331
35636
  },
34332
35637
  reject
@@ -34358,10 +35663,10 @@ var require_dist2 = __commonJS({
34358
35663
  throw new Error("CDP not connected");
34359
35664
  }
34360
35665
  const sendViaSession = (method, params = {}) => {
34361
- return new Promise((resolve12, reject) => {
35666
+ return new Promise((resolve15, reject) => {
34362
35667
  const pendingMap = this._browserConnected ? this.browserPending : this.pending;
34363
35668
  const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
34364
- pendingMap.set(id, { resolve: resolve12, reject });
35669
+ pendingMap.set(id, { resolve: resolve15, reject });
34365
35670
  ws2.send(JSON.stringify({ id, sessionId, method, params }));
34366
35671
  setTimeout(() => {
34367
35672
  if (pendingMap.has(id)) {
@@ -35095,10 +36400,10 @@ ${cleanBody}`;
35095
36400
  return cleanTitle || cleanBody;
35096
36401
  }
35097
36402
  var fs32 = __toESM2(require("fs"));
35098
- var path7 = __toESM2(require("path"));
36403
+ var path10 = __toESM2(require("path"));
35099
36404
  var os52 = __toESM2(require("os"));
35100
36405
  init_chat_message_normalization();
35101
- var HISTORY_DIR = path7.join(os52.homedir(), ".adhdev", "history");
36406
+ var HISTORY_DIR = path10.join(os52.homedir(), ".adhdev", "history");
35102
36407
  var RETAIN_DAYS = 30;
35103
36408
  var SAVED_HISTORY_INDEX_VERSION = 1;
35104
36409
  var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
@@ -35261,8 +36566,8 @@ ${cleanBody}`;
35261
36566
  function buildSavedHistoryFileSignatureMap(dir, files) {
35262
36567
  return new Map(files.map((file2) => {
35263
36568
  try {
35264
- const stat4 = fs32.statSync(path7.join(dir, file2));
35265
- return [file2, `${file2}:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`];
36569
+ const stat22 = fs32.statSync(path10.join(dir, file2));
36570
+ return [file2, `${file2}:${stat22.size}:${Math.trunc(stat22.mtimeMs)}`];
35266
36571
  } catch {
35267
36572
  return [file2, `${file2}:missing`];
35268
36573
  }
@@ -35272,7 +36577,7 @@ ${cleanBody}`;
35272
36577
  return files.map((file2) => fileSignatures.get(file2) || `${file2}:missing`).join("|");
35273
36578
  }
35274
36579
  function getSavedHistoryIndexFilePath(dir) {
35275
- return path7.join(dir, SAVED_HISTORY_INDEX_FILE);
36580
+ return path10.join(dir, SAVED_HISTORY_INDEX_FILE);
35276
36581
  }
35277
36582
  function getSavedHistoryIndexLockPath(dir) {
35278
36583
  return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
@@ -35325,8 +36630,8 @@ ${cleanBody}`;
35325
36630
  } catch (error48) {
35326
36631
  if (error48?.code !== "EEXIST") return null;
35327
36632
  try {
35328
- const stat4 = fs32.statSync(lockPath);
35329
- if (Date.now() - stat4.mtimeMs > SAVED_HISTORY_INDEX_LOCK_STALE_MS) {
36633
+ const stat22 = fs32.statSync(lockPath);
36634
+ if (Date.now() - stat22.mtimeMs > SAVED_HISTORY_INDEX_LOCK_STALE_MS) {
35330
36635
  fs32.rmSync(lockPath, { recursive: true, force: true });
35331
36636
  continue;
35332
36637
  }
@@ -35374,7 +36679,7 @@ ${cleanBody}`;
35374
36679
  }
35375
36680
  for (const file2 of Array.from(currentEntries.keys())) {
35376
36681
  if (incomingFiles.has(file2)) continue;
35377
- if (!fs32.existsSync(path7.join(dir, file2))) {
36682
+ if (!fs32.existsSync(path10.join(dir, file2))) {
35378
36683
  currentEntries.delete(file2);
35379
36684
  }
35380
36685
  }
@@ -35389,8 +36694,8 @@ ${cleanBody}`;
35389
36694
  }
35390
36695
  function buildSavedHistoryIndexFileSignature(dir) {
35391
36696
  try {
35392
- const stat4 = fs32.statSync(getSavedHistoryIndexFilePath(dir));
35393
- return `index:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`;
36697
+ const stat22 = fs32.statSync(getSavedHistoryIndexFilePath(dir));
36698
+ return `index:${stat22.size}:${Math.trunc(stat22.mtimeMs)}`;
35394
36699
  } catch {
35395
36700
  return "index:missing";
35396
36701
  }
@@ -35400,8 +36705,8 @@ ${cleanBody}`;
35400
36705
  const indexStat = fs32.statSync(getSavedHistoryIndexFilePath(dir));
35401
36706
  const files = listHistoryFiles(dir);
35402
36707
  for (const file2 of files) {
35403
- const stat4 = fs32.statSync(path7.join(dir, file2));
35404
- if (stat4.mtimeMs > indexStat.mtimeMs) return true;
36708
+ const stat22 = fs32.statSync(path10.join(dir, file2));
36709
+ if (stat22.mtimeMs > indexStat.mtimeMs) return true;
35405
36710
  }
35406
36711
  return false;
35407
36712
  } catch {
@@ -35410,14 +36715,14 @@ ${cleanBody}`;
35410
36715
  }
35411
36716
  function buildSavedHistoryFileSignature(dir, file2) {
35412
36717
  try {
35413
- const stat4 = fs32.statSync(path7.join(dir, file2));
35414
- return `${file2}:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`;
36718
+ const stat22 = fs32.statSync(path10.join(dir, file2));
36719
+ return `${file2}:${stat22.size}:${Math.trunc(stat22.mtimeMs)}`;
35415
36720
  } catch {
35416
36721
  return `${file2}:missing`;
35417
36722
  }
35418
36723
  }
35419
36724
  function persistSavedHistoryFileSummaryEntry(agentType, dir, file2, updater) {
35420
- const filePath = path7.join(dir, file2);
36725
+ const filePath = path10.join(dir, file2);
35421
36726
  const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
35422
36727
  const currentEntry = entries.get(file2) || null;
35423
36728
  const nextSummary = updater(currentEntry?.summary || null);
@@ -35490,7 +36795,7 @@ ${cleanBody}`;
35490
36795
  function computeSavedHistoryFileSummary(dir, file2) {
35491
36796
  const historySessionId = extractSavedHistorySessionIdFromFile(file2);
35492
36797
  if (!historySessionId) return null;
35493
- const filePath = path7.join(dir, file2);
36798
+ const filePath = path10.join(dir, file2);
35494
36799
  const content = fs32.readFileSync(filePath, "utf-8");
35495
36800
  const lines = content.split("\n").filter(Boolean);
35496
36801
  let messageCount = 0;
@@ -35577,7 +36882,7 @@ ${cleanBody}`;
35577
36882
  const summaryBySessionId = /* @__PURE__ */ new Map();
35578
36883
  const nextPersistedEntries = /* @__PURE__ */ new Map();
35579
36884
  for (const file2 of files.slice().sort()) {
35580
- const filePath = path7.join(dir, file2);
36885
+ const filePath = path10.join(dir, file2);
35581
36886
  const signature = fileSignatures.get(file2) || `${file2}:missing`;
35582
36887
  const cached2 = savedHistoryFileSummaryCache.get(filePath);
35583
36888
  const persisted = persistedEntries.get(file2);
@@ -35697,12 +37002,12 @@ ${cleanBody}`;
35697
37002
  });
35698
37003
  }
35699
37004
  if (newMessages.length === 0) return;
35700
- const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
37005
+ const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
35701
37006
  fs32.mkdirSync(dir, { recursive: true });
35702
37007
  const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
35703
37008
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
35704
37009
  const fileName = `${filePrefix}${date5}.jsonl`;
35705
- const filePath = path7.join(dir, fileName);
37010
+ const filePath = path10.join(dir, fileName);
35706
37011
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
35707
37012
  fs32.appendFileSync(filePath, lines, "utf-8");
35708
37013
  updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
@@ -35793,11 +37098,11 @@ ${cleanBody}`;
35793
37098
  const ws2 = String(workspace || "").trim();
35794
37099
  if (!id || !ws2) return;
35795
37100
  try {
35796
- const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
37101
+ const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
35797
37102
  fs32.mkdirSync(dir, { recursive: true });
35798
37103
  const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
35799
37104
  const fileName = `${this.sanitize(id)}_${date5}.jsonl`;
35800
- const filePath = path7.join(dir, fileName);
37105
+ const filePath = path10.join(dir, fileName);
35801
37106
  const record2 = {
35802
37107
  ts: (/* @__PURE__ */ new Date()).toISOString(),
35803
37108
  receivedAt: Date.now(),
@@ -35843,14 +37148,14 @@ ${cleanBody}`;
35843
37148
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
35844
37149
  this.lastSeenCounts.delete(fromDedupKey);
35845
37150
  }
35846
- const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
37151
+ const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
35847
37152
  if (!fs32.existsSync(dir)) return;
35848
37153
  const fromPrefix = `${this.sanitize(fromId)}_`;
35849
37154
  const toPrefix = `${this.sanitize(toId)}_`;
35850
37155
  const files = fs32.readdirSync(dir).filter((file2) => file2.startsWith(fromPrefix) && file2.endsWith(".jsonl"));
35851
37156
  for (const file2 of files) {
35852
- const sourcePath = path7.join(dir, file2);
35853
- const targetPath = path7.join(dir, `${toPrefix}${file2.slice(fromPrefix.length)}`);
37157
+ const sourcePath = path10.join(dir, file2);
37158
+ const targetPath = path10.join(dir, `${toPrefix}${file2.slice(fromPrefix.length)}`);
35854
37159
  const sourceLines = fs32.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
35855
37160
  const rewritten = sourceLines.map((line) => {
35856
37161
  try {
@@ -35884,13 +37189,13 @@ ${cleanBody}`;
35884
37189
  const sessionId = String(historySessionId || "").trim();
35885
37190
  if (!sessionId) return;
35886
37191
  try {
35887
- const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
37192
+ const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
35888
37193
  if (!fs32.existsSync(dir)) return;
35889
37194
  const prefix = `${this.sanitize(sessionId)}_`;
35890
37195
  const files = fs32.readdirSync(dir).filter((file2) => file2.startsWith(prefix) && file2.endsWith(".jsonl")).sort();
35891
37196
  const seen = /* @__PURE__ */ new Set();
35892
37197
  for (const file2 of files) {
35893
- const filePath = path7.join(dir, file2);
37198
+ const filePath = path10.join(dir, file2);
35894
37199
  const lines = fs32.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
35895
37200
  const next = [];
35896
37201
  for (const line of lines) {
@@ -35944,13 +37249,13 @@ ${cleanBody}`;
35944
37249
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
35945
37250
  const agentDirs = fs32.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
35946
37251
  for (const dir of agentDirs) {
35947
- const dirPath = path7.join(HISTORY_DIR, dir.name);
37252
+ const dirPath = path10.join(HISTORY_DIR, dir.name);
35948
37253
  const files = fs32.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
35949
37254
  let removedAny = false;
35950
37255
  for (const file2 of files) {
35951
- const filePath = path7.join(dirPath, file2);
35952
- const stat4 = fs32.statSync(filePath);
35953
- if (stat4.mtimeMs < cutoff) {
37256
+ const filePath = path10.join(dirPath, file2);
37257
+ const stat22 = fs32.statSync(filePath);
37258
+ if (stat22.mtimeMs < cutoff) {
35954
37259
  fs32.unlinkSync(filePath);
35955
37260
  removedAny = true;
35956
37261
  }
@@ -35998,13 +37303,13 @@ ${cleanBody}`;
35998
37303
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
35999
37304
  try {
36000
37305
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
36001
- const dir = path7.join(HISTORY_DIR, sanitized);
37306
+ const dir = path10.join(HISTORY_DIR, sanitized);
36002
37307
  if (!fs32.existsSync(dir)) return { messages: [], hasMore: false };
36003
37308
  const files = listHistoryFiles(dir, historySessionId);
36004
37309
  const allMessages = [];
36005
37310
  const seen = /* @__PURE__ */ new Set();
36006
37311
  for (const file2 of files) {
36007
- const filePath = path7.join(dir, file2);
37312
+ const filePath = path10.join(dir, file2);
36008
37313
  const content = fs32.readFileSync(filePath, "utf-8");
36009
37314
  const lines = content.trim().split("\n").filter(Boolean);
36010
37315
  for (let i = 0; i < lines.length; i++) {
@@ -36028,7 +37333,7 @@ ${cleanBody}`;
36028
37333
  function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
36029
37334
  try {
36030
37335
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
36031
- const dir = path7.join(HISTORY_DIR, sanitized);
37336
+ const dir = path10.join(HISTORY_DIR, sanitized);
36032
37337
  if (!fs32.existsSync(dir)) {
36033
37338
  savedHistorySessionCache.delete(sanitized);
36034
37339
  return { sessions: [], hasMore: false };
@@ -36089,11 +37394,11 @@ ${cleanBody}`;
36089
37394
  }
36090
37395
  function readExistingSessionStartRecord(agentType, historySessionId) {
36091
37396
  try {
36092
- const dir = path7.join(HISTORY_DIR, agentType);
37397
+ const dir = path10.join(HISTORY_DIR, agentType);
36093
37398
  if (!fs32.existsSync(dir)) return null;
36094
37399
  const files = listHistoryFiles(dir, historySessionId).sort();
36095
37400
  for (const file2 of files) {
36096
- const lines = fs32.readFileSync(path7.join(dir, file2), "utf-8").split("\n").filter(Boolean);
37401
+ const lines = fs32.readFileSync(path10.join(dir, file2), "utf-8").split("\n").filter(Boolean);
36097
37402
  for (const line of lines) {
36098
37403
  try {
36099
37404
  const parsed = JSON.parse(line);
@@ -36113,16 +37418,16 @@ ${cleanBody}`;
36113
37418
  function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
36114
37419
  if (records.length === 0) return false;
36115
37420
  try {
36116
- const dir = path7.join(HISTORY_DIR, agentType);
37421
+ const dir = path10.join(HISTORY_DIR, agentType);
36117
37422
  fs32.mkdirSync(dir, { recursive: true });
36118
37423
  const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
36119
37424
  for (const file2 of fs32.readdirSync(dir)) {
36120
37425
  if (file2.startsWith(prefix) && file2.endsWith(".jsonl")) {
36121
- fs32.unlinkSync(path7.join(dir, file2));
37426
+ fs32.unlinkSync(path10.join(dir, file2));
36122
37427
  }
36123
37428
  }
36124
37429
  const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
36125
- const filePath = path7.join(dir, `${prefix}${targetDate}.jsonl`);
37430
+ const filePath = path10.join(dir, `${prefix}${targetDate}.jsonl`);
36126
37431
  fs32.writeFileSync(filePath, `${records.map((record2) => JSON.stringify(record2)).join("\n")}
36127
37432
  `, "utf-8");
36128
37433
  invalidatePersistedSavedHistoryIndex(agentType, dir);
@@ -37966,6 +39271,10 @@ ${effect.notification.body || ""}`.trim();
37966
39271
  function shouldIncludeRuntimeMetadata(profile) {
37967
39272
  return true;
37968
39273
  }
39274
+ function getGitSummaryForWorkspace(workspace, options) {
39275
+ if (!workspace) return void 0;
39276
+ return options.getGitSummaryForWorkspace?.(workspace) || void 0;
39277
+ }
37969
39278
  function findCdpManager(cdpManagers, key) {
37970
39279
  const exact = cdpManagers.get(key);
37971
39280
  if (exact) return exact.isConnected ? exact : null;
@@ -38021,6 +39330,8 @@ ${effect.notification.body || ""}`.trim();
38021
39330
  const controlValues = normalizeProviderStateControlValues(state.controlValues);
38022
39331
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
38023
39332
  const includeSessionControls = shouldIncludeSessionControls(profile);
39333
+ const workspace = state.workspace || null;
39334
+ const git = getGitSummaryForWorkspace(workspace, options);
38024
39335
  const title = activeChat?.title || state.name;
38025
39336
  return {
38026
39337
  id: state.instanceId || state.type,
@@ -38033,7 +39344,8 @@ ${effect.notification.body || ""}`.trim();
38033
39344
  activeModal: activeChat?.activeModal || null
38034
39345
  }),
38035
39346
  title,
38036
- workspace: state.workspace || null,
39347
+ workspace,
39348
+ ...git && { git },
38037
39349
  activeChat,
38038
39350
  ...summaryMetadata && { summaryMetadata },
38039
39351
  ...includeSessionMetadata && { capabilities: state.sessionCapabilities || IDE_SESSION_CAPABILITIES },
@@ -38054,6 +39366,8 @@ ${effect.notification.body || ""}`.trim();
38054
39366
  const controlValues = normalizeProviderStateControlValues(ext.controlValues);
38055
39367
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
38056
39368
  const includeSessionControls = shouldIncludeSessionControls(profile);
39369
+ const workspace = parent.workspace || null;
39370
+ const git = getGitSummaryForWorkspace(workspace, options);
38057
39371
  return {
38058
39372
  id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
38059
39373
  parentId: parent.instanceId || parent.type,
@@ -38066,7 +39380,8 @@ ${effect.notification.body || ""}`.trim();
38066
39380
  activeModal: activeChat?.activeModal || null
38067
39381
  }),
38068
39382
  title: activeChat?.title || ext.name,
38069
- workspace: parent.workspace || null,
39383
+ workspace,
39384
+ ...git && { git },
38070
39385
  activeChat,
38071
39386
  ...summaryMetadata && { summaryMetadata },
38072
39387
  ...includeSessionMetadata && { capabilities: ext.sessionCapabilities || EXTENSION_SESSION_CAPABILITIES },
@@ -38102,6 +39417,8 @@ ${effect.notification.body || ""}`.trim();
38102
39417
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
38103
39418
  const includeRuntimeMetadata = shouldIncludeRuntimeMetadata(profile);
38104
39419
  const includeSessionControls = shouldIncludeSessionControls(profile);
39420
+ const workspace = state.workspace || null;
39421
+ const git = getGitSummaryForWorkspace(workspace, options);
38105
39422
  return {
38106
39423
  id: state.instanceId,
38107
39424
  parentId: null,
@@ -38114,7 +39431,8 @@ ${effect.notification.body || ""}`.trim();
38114
39431
  activeModal: activeChat?.activeModal || null
38115
39432
  }),
38116
39433
  title: activeChat?.title || state.name,
38117
- workspace: state.workspace || null,
39434
+ workspace,
39435
+ ...git && { git },
38118
39436
  ...includeRuntimeMetadata && {
38119
39437
  runtimeKey: state.runtime?.runtimeKey,
38120
39438
  runtimeDisplayName: state.runtime?.displayName,
@@ -38149,6 +39467,8 @@ ${effect.notification.body || ""}`.trim();
38149
39467
  const controlValues = normalizeProviderStateControlValues(state.controlValues);
38150
39468
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
38151
39469
  const includeSessionControls = shouldIncludeSessionControls(profile);
39470
+ const workspace = state.workspace || null;
39471
+ const git = getGitSummaryForWorkspace(workspace, options);
38152
39472
  return {
38153
39473
  id: state.instanceId,
38154
39474
  parentId: null,
@@ -38160,7 +39480,8 @@ ${effect.notification.body || ""}`.trim();
38160
39480
  activeModal: activeChat?.activeModal || null
38161
39481
  }),
38162
39482
  title: activeChat?.title || state.name,
38163
- workspace: state.workspace || null,
39483
+ workspace,
39484
+ ...git && { git },
38164
39485
  activeChat,
38165
39486
  ...summaryMetadata && { summaryMetadata },
38166
39487
  ...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES },
@@ -38271,7 +39592,7 @@ ${effect.notification.body || ""}`.trim();
38271
39592
  }
38272
39593
  var fs42 = __toESM2(require("fs"));
38273
39594
  var os62 = __toESM2(require("os"));
38274
- var path8 = __toESM2(require("path"));
39595
+ var path11 = __toESM2(require("path"));
38275
39596
  var import_node_crypto = require("crypto");
38276
39597
  init_contracts();
38277
39598
  var VALID_INPUT_MEDIA_TYPES = /* @__PURE__ */ new Set(["text", "image", "audio", "video", "resource"]);
@@ -38954,7 +40275,7 @@ ${effect.notification.body || ""}`.trim();
38954
40275
  }
38955
40276
  function getChatDebugBundleDir() {
38956
40277
  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");
40278
+ return override || path11.join(os62.homedir(), ".adhdev", "debug-bundles", "chat");
38958
40279
  }
38959
40280
  function safeBundleIdSegment(value, fallback) {
38960
40281
  const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
@@ -38987,7 +40308,7 @@ ${effect.notification.body || ""}`.trim();
38987
40308
  const bundleId = createChatDebugBundleId(targetSessionId);
38988
40309
  const dir = getChatDebugBundleDir();
38989
40310
  fs42.mkdirSync(dir, { recursive: true });
38990
- const savedPath = path8.join(dir, `${bundleId}.json`);
40311
+ const savedPath = path11.join(dir, `${bundleId}.json`);
38991
40312
  const json2 = `${JSON.stringify(bundle, null, 2)}
38992
40313
  `;
38993
40314
  fs42.writeFileSync(savedPath, json2, { encoding: "utf8", mode: 384 });
@@ -39181,7 +40502,7 @@ ${effect.notification.body || ""}`.trim();
39181
40502
  async function getStableExtensionBaseline(h) {
39182
40503
  const first = await readExtensionChatState(h);
39183
40504
  if (getStateMessageCount(first) > 0 || getStateLastSignature(first)) return first;
39184
- await new Promise((resolve12) => setTimeout(resolve12, 150));
40505
+ await new Promise((resolve15) => setTimeout(resolve15, 150));
39185
40506
  const second = await readExtensionChatState(h);
39186
40507
  return getStateMessageCount(second) >= getStateMessageCount(first) ? second : first;
39187
40508
  }
@@ -39189,7 +40510,7 @@ ${effect.notification.body || ""}`.trim();
39189
40510
  const beforeCount = getStateMessageCount(before);
39190
40511
  const beforeSignature = getStateLastSignature(before);
39191
40512
  for (let attempt = 0; attempt < 12; attempt += 1) {
39192
- await new Promise((resolve12) => setTimeout(resolve12, 250));
40513
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
39193
40514
  const state = await readExtensionChatState(h);
39194
40515
  if (state?.status === "waiting_approval") return true;
39195
40516
  const afterCount = getStateMessageCount(state);
@@ -40123,7 +41444,7 @@ ${effect.notification.body || ""}`.trim();
40123
41444
  return { success: false, error: "resolveAction script not available for this provider" };
40124
41445
  }
40125
41446
  var fs52 = __toESM2(require("fs"));
40126
- var path9 = __toESM2(require("path"));
41447
+ var path12 = __toESM2(require("path"));
40127
41448
  var os7 = __toESM2(require("os"));
40128
41449
  var KEY_TO_VK = {
40129
41450
  Backspace: 8,
@@ -40380,25 +41701,25 @@ ${effect.notification.body || ""}`.trim();
40380
41701
  const inputPath = rawPath || ".";
40381
41702
  const home = os7.homedir();
40382
41703
  if (inputPath.startsWith("~")) {
40383
- return path9.resolve(path9.join(home, inputPath.slice(1)));
41704
+ return path12.resolve(path12.join(home, inputPath.slice(1)));
40384
41705
  }
40385
41706
  if (process.platform === "win32") {
40386
41707
  const normalized = normalizeWindowsRequestedPath(inputPath);
40387
- if (path9.win32.isAbsolute(normalized)) {
40388
- return path9.win32.normalize(normalized);
41708
+ if (path12.win32.isAbsolute(normalized)) {
41709
+ return path12.win32.normalize(normalized);
40389
41710
  }
40390
- return path9.win32.resolve(normalized);
41711
+ return path12.win32.resolve(normalized);
40391
41712
  }
40392
- if (path9.isAbsolute(inputPath)) {
40393
- return path9.normalize(inputPath);
41713
+ if (path12.isAbsolute(inputPath)) {
41714
+ return path12.normalize(inputPath);
40394
41715
  }
40395
- return path9.resolve(inputPath);
41716
+ return path12.resolve(inputPath);
40396
41717
  }
40397
41718
  function listDirectoryEntriesSafe(dirPath) {
40398
41719
  const entries = fs52.readdirSync(dirPath, { withFileTypes: true });
40399
41720
  const files = [];
40400
41721
  for (const entry of entries) {
40401
- const entryPath = path9.join(dirPath, entry.name);
41722
+ const entryPath = path12.join(dirPath, entry.name);
40402
41723
  try {
40403
41724
  if (entry.isDirectory()) {
40404
41725
  files.push({ name: entry.name, type: "directory" });
@@ -40414,11 +41735,11 @@ ${effect.notification.body || ""}`.trim();
40414
41735
  files.push({ name: entry.name, type: "file", size });
40415
41736
  continue;
40416
41737
  }
40417
- const stat4 = fs52.statSync(entryPath);
41738
+ const stat22 = fs52.statSync(entryPath);
40418
41739
  files.push({
40419
41740
  name: entry.name,
40420
- type: stat4.isDirectory() ? "directory" : "file",
40421
- size: stat4.isFile() ? stat4.size : void 0
41741
+ type: stat22.isDirectory() ? "directory" : "file",
41742
+ size: stat22.isFile() ? stat22.size : void 0
40422
41743
  });
40423
41744
  } catch {
40424
41745
  }
@@ -40452,7 +41773,7 @@ ${effect.notification.body || ""}`.trim();
40452
41773
  async function handleFileWrite(h, args) {
40453
41774
  try {
40454
41775
  const filePath = resolveSafePath(args?.path);
40455
- fs52.mkdirSync(path9.dirname(filePath), { recursive: true });
41776
+ fs52.mkdirSync(path12.dirname(filePath), { recursive: true });
40456
41777
  fs52.writeFileSync(filePath, args?.content || "", "utf-8");
40457
41778
  return { success: true, path: filePath };
40458
41779
  } catch (e) {
@@ -40793,7 +42114,7 @@ ${effect.notification.body || ""}`.trim();
40793
42114
  const enterCount = cliCommand.enterCount || 1;
40794
42115
  await adapter.writeRaw(cliCommand.text + "\r");
40795
42116
  for (let i = 1; i < enterCount; i += 1) {
40796
- await new Promise((resolve12) => setTimeout(resolve12, 50));
42117
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
40797
42118
  await adapter.writeRaw("\r");
40798
42119
  }
40799
42120
  }
@@ -41283,6 +42604,12 @@ ${effect.notification.body || ""}`.trim();
41283
42604
  this._currentRoute = this.resolveRoute(args);
41284
42605
  const startedAt = Date.now();
41285
42606
  this.logCommandStart(cmd, args);
42607
+ let result;
42608
+ if (isGitCommandName(cmd)) {
42609
+ result = await handleGitCommand(cmd, args, this._ctx.gitCommandServices);
42610
+ this.logCommandEnd(cmd, result, startedAt);
42611
+ return result;
42612
+ }
41286
42613
  const sessionScopedCommands = /* @__PURE__ */ new Set([
41287
42614
  "read_chat",
41288
42615
  "get_chat_debug_bundle",
@@ -41308,7 +42635,6 @@ ${effect.notification.body || ""}`.trim();
41308
42635
  this.logCommandEnd(cmd, result2, startedAt);
41309
42636
  return result2;
41310
42637
  }
41311
- let result;
41312
42638
  if (!this._currentRoute.session && !this._currentRoute.managerKey && !this._currentRoute.providerType) {
41313
42639
  const cdpCommands = ["send_chat", "read_chat", "list_chats", "new_chat", "switch_chat", "set_mode", "change_model", "set_thought_level", "resolve_action"];
41314
42640
  if (cdpCommands.includes(cmd)) {
@@ -41317,6 +42643,16 @@ ${effect.notification.body || ""}`.trim();
41317
42643
  return result;
41318
42644
  }
41319
42645
  }
42646
+ if (cmd === "send_chat" && this._ctx.onBeforeSendChat) {
42647
+ const sessionId = this._currentRoute.session?.sessionId;
42648
+ const workspace = sessionId ? this._ctx.instanceManager?.getInstance(sessionId)?.getState?.()?.workspace : void 0;
42649
+ if (workspace && sessionId) {
42650
+ try {
42651
+ this._ctx.onBeforeSendChat({ workspace, sessionId });
42652
+ } catch {
42653
+ }
42654
+ }
42655
+ }
41320
42656
  try {
41321
42657
  result = await this.dispatch(cmd, args);
41322
42658
  this.logCommandEnd(cmd, result, startedAt);
@@ -41459,7 +42795,7 @@ ${effect.notification.body || ""}`.trim();
41459
42795
  try {
41460
42796
  const http3 = await import("http");
41461
42797
  const postData = JSON.stringify(body);
41462
- const result = await new Promise((resolve12, reject) => {
42798
+ const result = await new Promise((resolve15, reject) => {
41463
42799
  const req = http3.request({
41464
42800
  hostname: "127.0.0.1",
41465
42801
  port: 19280,
@@ -41471,9 +42807,9 @@ ${effect.notification.body || ""}`.trim();
41471
42807
  res.on("data", (chunk) => data += chunk);
41472
42808
  res.on("end", () => {
41473
42809
  try {
41474
- resolve12(JSON.parse(data));
42810
+ resolve15(JSON.parse(data));
41475
42811
  } catch {
41476
- resolve12({ raw: data });
42812
+ resolve15({ raw: data });
41477
42813
  }
41478
42814
  });
41479
42815
  });
@@ -41491,15 +42827,15 @@ ${effect.notification.body || ""}`.trim();
41491
42827
  if (!providerType) return { success: false, error: "providerType required" };
41492
42828
  try {
41493
42829
  const http3 = await import("http");
41494
- const result = await new Promise((resolve12, reject) => {
42830
+ const result = await new Promise((resolve15, reject) => {
41495
42831
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
41496
42832
  let data = "";
41497
42833
  res.on("data", (chunk) => data += chunk);
41498
42834
  res.on("end", () => {
41499
42835
  try {
41500
- resolve12(JSON.parse(data));
42836
+ resolve15(JSON.parse(data));
41501
42837
  } catch {
41502
- resolve12({ raw: data });
42838
+ resolve15({ raw: data });
41503
42839
  }
41504
42840
  });
41505
42841
  }).on("error", reject);
@@ -41513,7 +42849,7 @@ ${effect.notification.body || ""}`.trim();
41513
42849
  try {
41514
42850
  const http3 = await import("http");
41515
42851
  const postData = JSON.stringify(args || {});
41516
- const result = await new Promise((resolve12, reject) => {
42852
+ const result = await new Promise((resolve15, reject) => {
41517
42853
  const req = http3.request({
41518
42854
  hostname: "127.0.0.1",
41519
42855
  port: 19280,
@@ -41525,9 +42861,9 @@ ${effect.notification.body || ""}`.trim();
41525
42861
  res.on("data", (chunk) => data += chunk);
41526
42862
  res.on("end", () => {
41527
42863
  try {
41528
- resolve12(JSON.parse(data));
42864
+ resolve15(JSON.parse(data));
41529
42865
  } catch {
41530
- resolve12({ raw: data });
42866
+ resolve15({ raw: data });
41531
42867
  }
41532
42868
  });
41533
42869
  });
@@ -41542,7 +42878,7 @@ ${effect.notification.body || ""}`.trim();
41542
42878
  }
41543
42879
  };
41544
42880
  var os13 = __toESM2(require("os"));
41545
- var path13 = __toESM2(require("path"));
42881
+ var path16 = __toESM2(require("path"));
41546
42882
  var crypto4 = __toESM2(require("crypto"));
41547
42883
  var import_fs5 = require("fs");
41548
42884
  var import_child_process6 = require("child_process");
@@ -41550,7 +42886,7 @@ ${effect.notification.body || ""}`.trim();
41550
42886
  init_provider_cli_adapter();
41551
42887
  init_config();
41552
42888
  var os12 = __toESM2(require("os"));
41553
- var path12 = __toESM2(require("path"));
42889
+ var path15 = __toESM2(require("path"));
41554
42890
  var crypto3 = __toESM2(require("crypto"));
41555
42891
  var fs6 = __toESM2(require("fs"));
41556
42892
  var import_node_module = require("module");
@@ -41607,7 +42943,7 @@ ${effect.notification.body || ""}`.trim();
41607
42943
  var CachedDatabaseSync = null;
41608
42944
  function getDatabaseSync() {
41609
42945
  if (CachedDatabaseSync) return CachedDatabaseSync;
41610
- const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path12.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
42946
+ const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path15.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
41611
42947
  const sqliteModule = requireFn(`node:${"sqlite"}`);
41612
42948
  CachedDatabaseSync = sqliteModule.DatabaseSync;
41613
42949
  if (!CachedDatabaseSync) {
@@ -41645,7 +42981,7 @@ ${effect.notification.body || ""}`.trim();
41645
42981
  if (status === "stopped") {
41646
42982
  throw new Error("CLI runtime stopped before it became ready");
41647
42983
  }
41648
- await new Promise((resolve12) => setTimeout(resolve12, pollMs));
42984
+ await new Promise((resolve15) => setTimeout(resolve15, pollMs));
41649
42985
  }
41650
42986
  throw new Error(`CLI runtime did not become ready within ${timeoutMs}ms`);
41651
42987
  }
@@ -41996,7 +43332,7 @@ ${effect.notification.body || ""}`.trim();
41996
43332
  const enterCount = cliCommand.enterCount || 1;
41997
43333
  await this.adapter.writeRaw(cliCommand.text + "\r");
41998
43334
  for (let i = 1; i < enterCount; i += 1) {
41999
- await new Promise((resolve12) => setTimeout(resolve12, 50));
43335
+ await new Promise((resolve15) => setTimeout(resolve15, 50));
42000
43336
  await this.adapter.writeRaw("\r");
42001
43337
  }
42002
43338
  }
@@ -43108,13 +44444,13 @@ ${effect.notification.body || ""}`.trim();
43108
44444
  }
43109
44445
  this.currentStatus = "waiting_approval";
43110
44446
  this.detectStatusTransition();
43111
- const approved = await new Promise((resolve12) => {
43112
- this.permissionResolvers.push(resolve12);
44447
+ const approved = await new Promise((resolve15) => {
44448
+ this.permissionResolvers.push(resolve15);
43113
44449
  setTimeout(() => {
43114
- const idx = this.permissionResolvers.indexOf(resolve12);
44450
+ const idx = this.permissionResolvers.indexOf(resolve15);
43115
44451
  if (idx >= 0) {
43116
44452
  this.permissionResolvers.splice(idx, 1);
43117
- resolve12(false);
44453
+ resolve15(false);
43118
44454
  }
43119
44455
  }, 3e5);
43120
44456
  });
@@ -43683,11 +45019,11 @@ ${rawInput}` : rawInput;
43683
45019
  }
43684
45020
  function isExplicitCommand(command) {
43685
45021
  const trimmed = command.trim();
43686
- return path13.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
45022
+ return path16.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
43687
45023
  }
43688
45024
  function expandExecutable(command) {
43689
45025
  const trimmed = command.trim();
43690
- return trimmed.startsWith("~") ? path13.join(os13.homedir(), trimmed.slice(1)) : trimmed;
45026
+ return trimmed.startsWith("~") ? path16.join(os13.homedir(), trimmed.slice(1)) : trimmed;
43691
45027
  }
43692
45028
  function commandExists(command) {
43693
45029
  const trimmed = command.trim();
@@ -43968,7 +45304,7 @@ ${rawInput}` : rawInput;
43968
45304
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
43969
45305
  const trimmed = (workingDir || "").trim();
43970
45306
  if (!trimmed) throw new Error("working directory required");
43971
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path13.resolve(trimmed);
45307
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path16.resolve(trimmed);
43972
45308
  const normalizedType = this.providerLoader.resolveAlias(cliType);
43973
45309
  const rawProvider = this.providerLoader.getByAlias(cliType);
43974
45310
  const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
@@ -44467,9 +45803,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
44467
45803
  var import_child_process7 = require("child_process");
44468
45804
  var net3 = __toESM2(require("net"));
44469
45805
  var os15 = __toESM2(require("os"));
44470
- var path15 = __toESM2(require("path"));
45806
+ var path18 = __toESM2(require("path"));
44471
45807
  var fs7 = __toESM2(require("fs"));
44472
- var path14 = __toESM2(require("path"));
45808
+ var path17 = __toESM2(require("path"));
44473
45809
  var os14 = __toESM2(require("os"));
44474
45810
  var chokidar = __toESM2((init_chokidar(), __toCommonJS(chokidar_exports)));
44475
45811
  init_logger();
@@ -44530,6 +45866,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44530
45866
  "sendDelayMs",
44531
45867
  "sendKey",
44532
45868
  "submitStrategy",
45869
+ "requirePromptEchoBeforeSubmit",
44533
45870
  "timeouts",
44534
45871
  "disableUpstream"
44535
45872
  ]);
@@ -44730,7 +46067,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44730
46067
  try {
44731
46068
  if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
44732
46069
  return ["ide", "extension", "cli", "acp"].some(
44733
- (category) => fs7.existsSync(path14.join(candidate, category))
46070
+ (category) => fs7.existsSync(path17.join(candidate, category))
44734
46071
  );
44735
46072
  } catch {
44736
46073
  return false;
@@ -44738,20 +46075,20 @@ Run 'adhdev doctor' for detailed diagnostics.`
44738
46075
  }
44739
46076
  static hasProviderRootMarker(candidate) {
44740
46077
  try {
44741
- return fs7.existsSync(path14.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
46078
+ return fs7.existsSync(path17.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
44742
46079
  } catch {
44743
46080
  return false;
44744
46081
  }
44745
46082
  }
44746
46083
  detectDefaultUserDir() {
44747
- const fallback = path14.join(os14.homedir(), ".adhdev", "providers");
46084
+ const fallback = path17.join(os14.homedir(), ".adhdev", "providers");
44748
46085
  const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
44749
46086
  const visited = /* @__PURE__ */ new Set();
44750
46087
  for (const start of this.probeStarts) {
44751
- let current = path14.resolve(start);
46088
+ let current = path17.resolve(start);
44752
46089
  while (!visited.has(current)) {
44753
46090
  visited.add(current);
44754
- const siblingCandidate = path14.join(path14.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
46091
+ const siblingCandidate = path17.join(path17.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
44755
46092
  if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
44756
46093
  const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
44757
46094
  if (envOptIn || hasMarker) {
@@ -44773,7 +46110,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44773
46110
  return { path: siblingCandidate, source };
44774
46111
  }
44775
46112
  }
44776
- const parent = path14.dirname(current);
46113
+ const parent = path17.dirname(current);
44777
46114
  if (parent === current) break;
44778
46115
  current = parent;
44779
46116
  }
@@ -44783,11 +46120,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
44783
46120
  constructor(options) {
44784
46121
  this.logFn = options?.logFn || LOG2.forComponent("Provider").asLogFn();
44785
46122
  this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
44786
- this.defaultProvidersDir = path14.join(os14.homedir(), ".adhdev", "providers");
46123
+ this.defaultProvidersDir = path17.join(os14.homedir(), ".adhdev", "providers");
44787
46124
  const detected = this.detectDefaultUserDir();
44788
46125
  this.userDir = detected.path;
44789
46126
  this.userDirSource = detected.source;
44790
- this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
46127
+ this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
44791
46128
  this.disableUpstream = false;
44792
46129
  this.applySourceConfig({
44793
46130
  userDir: options?.userDir,
@@ -44846,7 +46183,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44846
46183
  this.userDir = detected.path;
44847
46184
  this.userDirSource = detected.source;
44848
46185
  }
44849
- this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
46186
+ this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
44850
46187
  this.disableUpstream = this.sourceMode === "no-upstream";
44851
46188
  if (this.explicitProviderDir) {
44852
46189
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
@@ -44860,7 +46197,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44860
46197
  * Canonical provider directory shape for a given root.
44861
46198
  */
44862
46199
  getProviderDir(root, category, type) {
44863
- return path14.join(root, category, type);
46200
+ return path17.join(root, category, type);
44864
46201
  }
44865
46202
  /**
44866
46203
  * Canonical user override directory for a provider.
@@ -44887,7 +46224,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44887
46224
  resolveProviderFile(type, ...segments) {
44888
46225
  const dir = this.findProviderDirInternal(type);
44889
46226
  if (!dir) return null;
44890
- return path14.join(dir, ...segments);
46227
+ return path17.join(dir, ...segments);
44891
46228
  }
44892
46229
  /**
44893
46230
  * Load all providers (3-tier priority)
@@ -44926,7 +46263,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44926
46263
  if (!fs7.existsSync(this.upstreamDir)) return false;
44927
46264
  try {
44928
46265
  return fs7.readdirSync(this.upstreamDir).some(
44929
- (d) => fs7.statSync(path14.join(this.upstreamDir, d)).isDirectory()
46266
+ (d) => fs7.statSync(path17.join(this.upstreamDir, d)).isDirectory()
44930
46267
  );
44931
46268
  } catch {
44932
46269
  return false;
@@ -45423,8 +46760,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
45423
46760
  resolved._resolvedScriptDir = entry.scriptDir;
45424
46761
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
45425
46762
  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;
46763
+ const fullDir = path17.join(providerDir, entry.scriptDir);
46764
+ resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
45428
46765
  }
45429
46766
  matched = true;
45430
46767
  }
@@ -45439,8 +46776,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
45439
46776
  resolved._resolvedScriptDir = base.defaultScriptDir;
45440
46777
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
45441
46778
  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;
46779
+ const fullDir = path17.join(providerDir, base.defaultScriptDir);
46780
+ resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
45444
46781
  }
45445
46782
  }
45446
46783
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -45457,8 +46794,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
45457
46794
  resolved._resolvedScriptDir = dirOverride;
45458
46795
  resolved._resolvedScriptsSource = `versions:${range}`;
45459
46796
  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;
46797
+ const fullDir = path17.join(providerDir, dirOverride);
46798
+ resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
45462
46799
  }
45463
46800
  }
45464
46801
  } else if (override.scripts) {
@@ -45474,8 +46811,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
45474
46811
  resolved._resolvedScriptDir = base.defaultScriptDir;
45475
46812
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
45476
46813
  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;
46814
+ const fullDir = path17.join(providerDir, base.defaultScriptDir);
46815
+ resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
45479
46816
  }
45480
46817
  }
45481
46818
  }
@@ -45507,14 +46844,14 @@ Run 'adhdev doctor' for detailed diagnostics.`
45507
46844
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
45508
46845
  return null;
45509
46846
  }
45510
- const dir = path14.join(providerDir, scriptDir);
46847
+ const dir = path17.join(providerDir, scriptDir);
45511
46848
  if (!fs7.existsSync(dir)) {
45512
46849
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
45513
46850
  return null;
45514
46851
  }
45515
46852
  const cached2 = this.scriptsCache.get(dir);
45516
46853
  if (cached2) return cached2;
45517
- const scriptsJs = path14.join(dir, "scripts.js");
46854
+ const scriptsJs = path17.join(dir, "scripts.js");
45518
46855
  if (fs7.existsSync(scriptsJs)) {
45519
46856
  try {
45520
46857
  delete require.cache[require.resolve(scriptsJs)];
@@ -45556,7 +46893,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45556
46893
  return;
45557
46894
  }
45558
46895
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
45559
- this.log(`File changed: ${path14.basename(filePath)}, reloading...`);
46896
+ this.log(`File changed: ${path17.basename(filePath)}, reloading...`);
45560
46897
  this.reload();
45561
46898
  }
45562
46899
  };
@@ -45611,7 +46948,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45611
46948
  }
45612
46949
  const https = require("https");
45613
46950
  const { execSync: execSync7 } = require("child_process");
45614
- const metaPath = path14.join(this.upstreamDir, _ProviderLoader.META_FILE);
46951
+ const metaPath = path17.join(this.upstreamDir, _ProviderLoader.META_FILE);
45615
46952
  let prevEtag = "";
45616
46953
  let prevTimestamp = 0;
45617
46954
  try {
@@ -45628,7 +46965,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45628
46965
  return { updated: false };
45629
46966
  }
45630
46967
  try {
45631
- const etag = await new Promise((resolve12, reject) => {
46968
+ const etag = await new Promise((resolve15, reject) => {
45632
46969
  const options = {
45633
46970
  method: "HEAD",
45634
46971
  hostname: "github.com",
@@ -45646,7 +46983,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45646
46983
  headers: { "User-Agent": "adhdev-launcher" },
45647
46984
  timeout: 1e4
45648
46985
  }, (res2) => {
45649
- resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
46986
+ resolve15(res2.headers.etag || res2.headers["last-modified"] || "");
45650
46987
  });
45651
46988
  req2.on("error", reject);
45652
46989
  req2.on("timeout", () => {
@@ -45655,7 +46992,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45655
46992
  });
45656
46993
  req2.end();
45657
46994
  } else {
45658
- resolve12(res.headers.etag || res.headers["last-modified"] || "");
46995
+ resolve15(res.headers.etag || res.headers["last-modified"] || "");
45659
46996
  }
45660
46997
  });
45661
46998
  req.on("error", reject);
@@ -45671,17 +47008,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
45671
47008
  return { updated: false };
45672
47009
  }
45673
47010
  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()}`);
47011
+ const tmpTar = path17.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
47012
+ const tmpExtract = path17.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
45676
47013
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
45677
47014
  fs7.mkdirSync(tmpExtract, { recursive: true });
45678
47015
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
45679
47016
  const extracted = fs7.readdirSync(tmpExtract);
45680
47017
  const rootDir = extracted.find(
45681
- (d) => fs7.statSync(path14.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
47018
+ (d) => fs7.statSync(path17.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
45682
47019
  );
45683
47020
  if (!rootDir) throw new Error("Unexpected tarball structure");
45684
- const sourceDir = path14.join(tmpExtract, rootDir);
47021
+ const sourceDir = path17.join(tmpExtract, rootDir);
45685
47022
  const backupDir = this.upstreamDir + ".bak";
45686
47023
  if (fs7.existsSync(this.upstreamDir)) {
45687
47024
  if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
@@ -45719,7 +47056,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45719
47056
  downloadFile(url2, destPath) {
45720
47057
  const https = require("https");
45721
47058
  const http3 = require("http");
45722
- return new Promise((resolve12, reject) => {
47059
+ return new Promise((resolve15, reject) => {
45723
47060
  const doRequest = (reqUrl, redirectCount = 0) => {
45724
47061
  if (redirectCount > 5) {
45725
47062
  reject(new Error("Too many redirects"));
@@ -45739,7 +47076,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45739
47076
  res.pipe(ws2);
45740
47077
  ws2.on("finish", () => {
45741
47078
  ws2.close();
45742
- resolve12();
47079
+ resolve15();
45743
47080
  });
45744
47081
  ws2.on("error", reject);
45745
47082
  });
@@ -45756,8 +47093,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
45756
47093
  copyDirRecursive(src, dest) {
45757
47094
  fs7.mkdirSync(dest, { recursive: true });
45758
47095
  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);
47096
+ const srcPath = path17.join(src, entry.name);
47097
+ const destPath = path17.join(dest, entry.name);
45761
47098
  if (entry.isDirectory()) {
45762
47099
  this.copyDirRecursive(srcPath, destPath);
45763
47100
  } else {
@@ -45768,7 +47105,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45768
47105
  /** .meta.json save */
45769
47106
  writeMeta(metaPath, etag, timestamp) {
45770
47107
  try {
45771
- fs7.mkdirSync(path14.dirname(metaPath), { recursive: true });
47108
+ fs7.mkdirSync(path17.dirname(metaPath), { recursive: true });
45772
47109
  fs7.writeFileSync(metaPath, JSON.stringify({
45773
47110
  etag,
45774
47111
  timestamp,
@@ -45785,7 +47122,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45785
47122
  const scan = (d) => {
45786
47123
  try {
45787
47124
  for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
45788
- if (entry.isDirectory()) scan(path14.join(d, entry.name));
47125
+ if (entry.isDirectory()) scan(path17.join(d, entry.name));
45789
47126
  else if (entry.name === "provider.json") count++;
45790
47127
  }
45791
47128
  } catch {
@@ -46013,17 +47350,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
46013
47350
  for (const root of searchRoots) {
46014
47351
  if (!fs7.existsSync(root)) continue;
46015
47352
  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);
47353
+ if (fs7.existsSync(path17.join(candidate, "provider.json"))) return candidate;
47354
+ const catDir = path17.join(root, cat);
46018
47355
  if (fs7.existsSync(catDir)) {
46019
47356
  try {
46020
47357
  for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
46021
47358
  if (!entry.isDirectory()) continue;
46022
- const jsonPath = path14.join(catDir, entry.name, "provider.json");
47359
+ const jsonPath = path17.join(catDir, entry.name, "provider.json");
46023
47360
  if (fs7.existsSync(jsonPath)) {
46024
47361
  try {
46025
47362
  const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
46026
- if (data.type === type) return path14.join(catDir, entry.name);
47363
+ if (data.type === type) return path17.join(catDir, entry.name);
46027
47364
  } catch {
46028
47365
  }
46029
47366
  }
@@ -46040,7 +47377,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
46040
47377
  * (template substitution is NOT applied here — scripts.js handles that)
46041
47378
  */
46042
47379
  buildScriptWrappersFromDir(dir) {
46043
- const scriptsJs = path14.join(dir, "scripts.js");
47380
+ const scriptsJs = path17.join(dir, "scripts.js");
46044
47381
  if (fs7.existsSync(scriptsJs)) {
46045
47382
  try {
46046
47383
  delete require.cache[require.resolve(scriptsJs)];
@@ -46054,7 +47391,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
46054
47391
  for (const file2 of fs7.readdirSync(dir)) {
46055
47392
  if (!file2.endsWith(".js")) continue;
46056
47393
  const scriptName = toCamel(file2.replace(".js", ""));
46057
- const filePath = path14.join(dir, file2);
47394
+ const filePath = path17.join(dir, file2);
46058
47395
  result[scriptName] = (...args) => {
46059
47396
  try {
46060
47397
  let content = fs7.readFileSync(filePath, "utf-8");
@@ -46114,7 +47451,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
46114
47451
  }
46115
47452
  const hasJson = entries.some((e) => e.name === "provider.json");
46116
47453
  if (hasJson) {
46117
- const jsonPath = path14.join(d, "provider.json");
47454
+ const jsonPath = path17.join(d, "provider.json");
46118
47455
  try {
46119
47456
  const raw = fs7.readFileSync(jsonPath, "utf-8");
46120
47457
  const mod = JSON.parse(raw);
@@ -46135,7 +47472,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
46135
47472
  this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
46136
47473
  } else {
46137
47474
  const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
46138
- const scriptsPath = path14.join(d, "scripts.js");
47475
+ const scriptsPath = path17.join(d, "scripts.js");
46139
47476
  if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
46140
47477
  try {
46141
47478
  delete require.cache[require.resolve(scriptsPath)];
@@ -46161,7 +47498,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
46161
47498
  if (!entry.isDirectory()) continue;
46162
47499
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
46163
47500
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
46164
- scan(path14.join(d, entry.name));
47501
+ scan(path17.join(d, entry.name));
46165
47502
  }
46166
47503
  }
46167
47504
  };
@@ -46196,9 +47533,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
46196
47533
  }
46197
47534
  }
46198
47535
  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);
47536
+ const normalize4 = (v2) => v2.split(/[-_+]/)[0].split(".").map((x) => parseInt(x, 10) || 0);
47537
+ const pa2 = normalize4(a);
47538
+ const pb = normalize4(b2);
46202
47539
  for (let i = 0; i < Math.max(pa2.length, pb.length); i++) {
46203
47540
  const va2 = pa2[i] || 0;
46204
47541
  const vb = pb[i] || 0;
@@ -46314,17 +47651,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
46314
47651
  throw new Error("No free port found");
46315
47652
  }
46316
47653
  function checkPortFree(port) {
46317
- return new Promise((resolve12) => {
47654
+ return new Promise((resolve15) => {
46318
47655
  const server = net3.createServer();
46319
47656
  server.unref();
46320
- server.on("error", () => resolve12(false));
47657
+ server.on("error", () => resolve15(false));
46321
47658
  server.listen(port, "127.0.0.1", () => {
46322
- server.close(() => resolve12(true));
47659
+ server.close(() => resolve15(true));
46323
47660
  });
46324
47661
  });
46325
47662
  }
46326
47663
  async function isCdpActive(port) {
46327
- return new Promise((resolve12) => {
47664
+ return new Promise((resolve15) => {
46328
47665
  const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
46329
47666
  timeout: 2e3
46330
47667
  }, (res) => {
@@ -46333,16 +47670,16 @@ Run 'adhdev doctor' for detailed diagnostics.`
46333
47670
  res.on("end", () => {
46334
47671
  try {
46335
47672
  const info = JSON.parse(data);
46336
- resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
47673
+ resolve15(!!info["WebKit-Version"] || !!info["Browser"]);
46337
47674
  } catch {
46338
- resolve12(false);
47675
+ resolve15(false);
46339
47676
  }
46340
47677
  });
46341
47678
  });
46342
- req.on("error", () => resolve12(false));
47679
+ req.on("error", () => resolve15(false));
46343
47680
  req.on("timeout", () => {
46344
47681
  req.destroy();
46345
- resolve12(false);
47682
+ resolve15(false);
46346
47683
  });
46347
47684
  });
46348
47685
  }
@@ -46482,8 +47819,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
46482
47819
  const appNameMap = getMacAppIdentifiers();
46483
47820
  const appName = appNameMap[ideId];
46484
47821
  if (appName) {
46485
- const storagePath = path15.join(
46486
- process.env.APPDATA || path15.join(os15.homedir(), "AppData", "Roaming"),
47822
+ const storagePath = path18.join(
47823
+ process.env.APPDATA || path18.join(os15.homedir(), "AppData", "Roaming"),
46487
47824
  appName,
46488
47825
  "storage.json"
46489
47826
  );
@@ -46657,9 +47994,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
46657
47994
  init_config();
46658
47995
  init_logger();
46659
47996
  var fs8 = __toESM2(require("fs"));
46660
- var path16 = __toESM2(require("path"));
47997
+ var path19 = __toESM2(require("path"));
46661
47998
  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");
47999
+ 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
48000
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
46664
48001
  var MAX_DAYS = 7;
46665
48002
  try {
@@ -46697,13 +48034,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
46697
48034
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
46698
48035
  }
46699
48036
  var currentDate2 = getDateStr2();
46700
- var currentFile = path16.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
48037
+ var currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
46701
48038
  var writeCount2 = 0;
46702
48039
  function checkRotation() {
46703
48040
  const today = getDateStr2();
46704
48041
  if (today !== currentDate2) {
46705
48042
  currentDate2 = today;
46706
- currentFile = path16.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
48043
+ currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
46707
48044
  cleanOldFiles();
46708
48045
  }
46709
48046
  }
@@ -46717,7 +48054,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
46717
48054
  const dateMatch = file2.match(/commands-(\d{4}-\d{2}-\d{2})/);
46718
48055
  if (dateMatch && dateMatch[1] < cutoffStr) {
46719
48056
  try {
46720
- fs8.unlinkSync(path16.join(LOG_DIR2, file2));
48057
+ fs8.unlinkSync(path19.join(LOG_DIR2, file2));
46721
48058
  } catch {
46722
48059
  }
46723
48060
  }
@@ -46727,8 +48064,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
46727
48064
  }
46728
48065
  function checkSize() {
46729
48066
  try {
46730
- const stat4 = fs8.statSync(currentFile);
46731
- if (stat4.size > MAX_FILE_SIZE) {
48067
+ const stat22 = fs8.statSync(currentFile);
48068
+ if (stat22.size > MAX_FILE_SIZE) {
46732
48069
  const backup = currentFile.replace(".jsonl", ".1.jsonl");
46733
48070
  try {
46734
48071
  fs8.unlinkSync(backup);
@@ -47010,12 +48347,18 @@ Run 'adhdev doctor' for detailed diagnostics.`
47010
48347
  const unreadSourceSessions = buildSessionEntries(
47011
48348
  options.allStates,
47012
48349
  options.cdpManagers,
47013
- { profile: "full" }
48350
+ {
48351
+ profile: "full",
48352
+ getGitSummaryForWorkspace: options.getGitSummaryForWorkspace
48353
+ }
47014
48354
  );
47015
48355
  const sessions = profile === "full" ? unreadSourceSessions : profile === "live" ? unreadSourceSessions.map(projectLiveSessionFromFull) : buildSessionEntries(
47016
48356
  options.allStates,
47017
48357
  options.cdpManagers,
47018
- { profile }
48358
+ {
48359
+ profile,
48360
+ getGitSummaryForWorkspace: options.getGitSummaryForWorkspace
48361
+ }
47019
48362
  );
47020
48363
  const sessionsById = new Map(sessions.map((session) => [session.id, session]));
47021
48364
  for (const sourceSession of unreadSourceSessions) {
@@ -47107,13 +48450,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
47107
48450
  var import_child_process9 = require("child_process");
47108
48451
  var fs9 = __toESM2(require("fs"));
47109
48452
  var os18 = __toESM2(require("os"));
47110
- var path17 = __toESM2(require("path"));
48453
+ var path20 = __toESM2(require("path"));
47111
48454
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
47112
48455
  function getUpgradeLogPath() {
47113
48456
  const home = os18.homedir();
47114
- const dir = path17.join(home, ".adhdev");
48457
+ const dir = path20.join(home, ".adhdev");
47115
48458
  fs9.mkdirSync(dir, { recursive: true });
47116
- return path17.join(dir, "daemon-upgrade.log");
48459
+ return path20.join(dir, "daemon-upgrade.log");
47117
48460
  }
47118
48461
  function appendUpgradeLog(message) {
47119
48462
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -47124,14 +48467,14 @@ Run 'adhdev doctor' for detailed diagnostics.`
47124
48467
  }
47125
48468
  }
47126
48469
  function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
47127
- const binDir = path17.dirname(nodeExecutable);
48470
+ const binDir = path20.dirname(nodeExecutable);
47128
48471
  if (platform10 === "win32") {
47129
- const npmCliPath = path17.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
48472
+ const npmCliPath = path20.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
47130
48473
  if (fs9.existsSync(npmCliPath)) {
47131
48474
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
47132
48475
  }
47133
48476
  for (const candidate of ["npm.exe", "npm"]) {
47134
- const candidatePath = path17.join(binDir, candidate);
48477
+ const candidatePath = path20.join(binDir, candidate);
47135
48478
  if (fs9.existsSync(candidatePath)) {
47136
48479
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
47137
48480
  }
@@ -47139,7 +48482,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
47139
48482
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
47140
48483
  }
47141
48484
  for (const candidate of ["npm"]) {
47142
- const candidatePath = path17.join(binDir, candidate);
48485
+ const candidatePath = path20.join(binDir, candidate);
47143
48486
  if (fs9.existsSync(candidatePath)) {
47144
48487
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
47145
48488
  }
@@ -47156,13 +48499,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
47156
48499
  let currentDir = resolvedPath;
47157
48500
  try {
47158
48501
  if (fs9.statSync(resolvedPath).isFile()) {
47159
- currentDir = path17.dirname(resolvedPath);
48502
+ currentDir = path20.dirname(resolvedPath);
47160
48503
  }
47161
48504
  } catch {
47162
- currentDir = path17.dirname(resolvedPath);
48505
+ currentDir = path20.dirname(resolvedPath);
47163
48506
  }
47164
48507
  while (true) {
47165
- const packageJsonPath = path17.join(currentDir, "package.json");
48508
+ const packageJsonPath = path20.join(currentDir, "package.json");
47166
48509
  try {
47167
48510
  if (fs9.existsSync(packageJsonPath)) {
47168
48511
  const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
@@ -47173,7 +48516,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
47173
48516
  }
47174
48517
  } catch {
47175
48518
  }
47176
- const parentDir = path17.dirname(currentDir);
48519
+ const parentDir = path20.dirname(currentDir);
47177
48520
  if (parentDir === currentDir) {
47178
48521
  return null;
47179
48522
  }
@@ -47181,13 +48524,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
47181
48524
  }
47182
48525
  }
47183
48526
  function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
47184
- const nodeModulesDir = packageName.startsWith("@") ? path17.dirname(path17.dirname(packageRoot)) : path17.dirname(packageRoot);
47185
- if (path17.basename(nodeModulesDir) !== "node_modules") {
48527
+ const nodeModulesDir = packageName.startsWith("@") ? path20.dirname(path20.dirname(packageRoot)) : path20.dirname(packageRoot);
48528
+ if (path20.basename(nodeModulesDir) !== "node_modules") {
47186
48529
  return null;
47187
48530
  }
47188
- const maybeLibDir = path17.dirname(nodeModulesDir);
47189
- if (path17.basename(maybeLibDir) === "lib") {
47190
- return path17.dirname(maybeLibDir);
48531
+ const maybeLibDir = path20.dirname(nodeModulesDir);
48532
+ if (path20.basename(maybeLibDir) === "lib") {
48533
+ return path20.dirname(maybeLibDir);
47191
48534
  }
47192
48535
  return maybeLibDir;
47193
48536
  }
@@ -47295,14 +48638,14 @@ Run 'adhdev doctor' for detailed diagnostics.`
47295
48638
  while (Date.now() - start < timeoutMs) {
47296
48639
  try {
47297
48640
  process.kill(pid, 0);
47298
- await new Promise((resolve12) => setTimeout(resolve12, 250));
48641
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
47299
48642
  } catch {
47300
48643
  return;
47301
48644
  }
47302
48645
  }
47303
48646
  }
47304
48647
  function stopSessionHostProcesses(appName) {
47305
- const pidFile = path17.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
48648
+ const pidFile = path20.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
47306
48649
  try {
47307
48650
  if (fs9.existsSync(pidFile)) {
47308
48651
  const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
@@ -47319,7 +48662,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
47319
48662
  }
47320
48663
  }
47321
48664
  function removeDaemonPidFile() {
47322
- const pidFile = path17.join(os18.homedir(), ".adhdev", "daemon.pid");
48665
+ const pidFile = path20.join(os18.homedir(), ".adhdev", "daemon.pid");
47323
48666
  try {
47324
48667
  fs9.unlinkSync(pidFile);
47325
48668
  } catch {
@@ -47330,7 +48673,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
47330
48673
  const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
47331
48674
  if (!npmRoot) return;
47332
48675
  const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
47333
- const binDir = process.platform === "win32" ? npmPrefix : path17.join(npmPrefix, "bin");
48676
+ const binDir = process.platform === "win32" ? npmPrefix : path20.join(npmPrefix, "bin");
47334
48677
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
47335
48678
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
47336
48679
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -47338,25 +48681,25 @@ Run 'adhdev doctor' for detailed diagnostics.`
47338
48681
  }
47339
48682
  if (pkgName.startsWith("@")) {
47340
48683
  const [scope, name] = pkgName.split("/");
47341
- const scopeDir = path17.join(npmRoot, scope);
48684
+ const scopeDir = path20.join(npmRoot, scope);
47342
48685
  if (!fs9.existsSync(scopeDir)) return;
47343
48686
  for (const entry of fs9.readdirSync(scopeDir)) {
47344
48687
  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)}`);
48688
+ fs9.rmSync(path20.join(scopeDir, entry), { recursive: true, force: true });
48689
+ appendUpgradeLog(`Removed stale scoped staging dir: ${path20.join(scopeDir, entry)}`);
47347
48690
  }
47348
48691
  } else {
47349
48692
  for (const entry of fs9.readdirSync(npmRoot)) {
47350
48693
  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)}`);
48694
+ fs9.rmSync(path20.join(npmRoot, entry), { recursive: true, force: true });
48695
+ appendUpgradeLog(`Removed stale staging dir: ${path20.join(npmRoot, entry)}`);
47353
48696
  }
47354
48697
  }
47355
48698
  if (fs9.existsSync(binDir)) {
47356
48699
  for (const entry of fs9.readdirSync(binDir)) {
47357
48700
  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)}`);
48701
+ fs9.rmSync(path20.join(binDir, entry), { recursive: true, force: true });
48702
+ appendUpgradeLog(`Removed stale bin staging entry: ${path20.join(binDir, entry)}`);
47360
48703
  }
47361
48704
  }
47362
48705
  }
@@ -47406,7 +48749,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
47406
48749
  appendUpgradeLog(installOutput.trim());
47407
48750
  }
47408
48751
  if (process.platform === "win32") {
47409
- await new Promise((resolve12) => setTimeout(resolve12, 500));
48752
+ await new Promise((resolve15) => setTimeout(resolve15, 500));
47410
48753
  cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
47411
48754
  appendUpgradeLog("Post-install staging cleanup complete");
47412
48755
  }
@@ -48786,7 +50129,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
48786
50129
  const beforeCount = this.messageCount(before);
48787
50130
  const beforeSignature = this.lastMessageSignature(before);
48788
50131
  for (let attempt = 0; attempt < 12; attempt += 1) {
48789
- await new Promise((resolve12) => setTimeout(resolve12, 250));
50132
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
48790
50133
  let state;
48791
50134
  try {
48792
50135
  state = await this.readChat(evaluate);
@@ -48808,7 +50151,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
48808
50151
  if (this.messageCount(first) > 0 || this.lastMessageSignature(first)) {
48809
50152
  return first;
48810
50153
  }
48811
- await new Promise((resolve12) => setTimeout(resolve12, 150));
50154
+ await new Promise((resolve15) => setTimeout(resolve15, 150));
48812
50155
  const second = await this.readChat(evaluate);
48813
50156
  return this.messageCount(second) >= this.messageCount(first) ? second : first;
48814
50157
  }
@@ -48959,7 +50302,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
48959
50302
  if (typeof data.error === "string" && data.error.trim()) return false;
48960
50303
  }
48961
50304
  for (let attempt = 0; attempt < 6; attempt += 1) {
48962
- await new Promise((resolve12) => setTimeout(resolve12, 250));
50305
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
48963
50306
  const state = await this.readChat(evaluate);
48964
50307
  const title = this.getStateTitle(state);
48965
50308
  if (this.titlesMatch(title, sessionId)) return true;
@@ -49808,11 +51151,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
49808
51151
  init_io_contracts();
49809
51152
  init_chat_message_normalization();
49810
51153
  var fs11 = __toESM2(require("fs"));
49811
- var path18 = __toESM2(require("path"));
51154
+ var path21 = __toESM2(require("path"));
49812
51155
  var os19 = __toESM2(require("os"));
49813
51156
  var import_child_process10 = require("child_process");
49814
51157
  var import_os3 = require("os");
49815
- var ARCHIVE_PATH = path18.join(os19.homedir(), ".adhdev", "version-history.json");
51158
+ var ARCHIVE_PATH = path21.join(os19.homedir(), ".adhdev", "version-history.json");
49816
51159
  var MAX_ENTRIES_PER_PROVIDER = 20;
49817
51160
  var VersionArchive = class {
49818
51161
  history = {};
@@ -49859,7 +51202,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
49859
51202
  }
49860
51203
  save() {
49861
51204
  try {
49862
- fs11.mkdirSync(path18.dirname(ARCHIVE_PATH), { recursive: true });
51205
+ fs11.mkdirSync(path21.dirname(ARCHIVE_PATH), { recursive: true });
49863
51206
  fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
49864
51207
  } catch {
49865
51208
  }
@@ -49916,7 +51259,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
49916
51259
  for (const p of paths) {
49917
51260
  if (p.includes("*")) {
49918
51261
  const home = os19.homedir();
49919
- const resolved = p.replace(/\*/g, home.split(path18.sep).pop() || "");
51262
+ const resolved = p.replace(/\*/g, home.split(path21.sep).pop() || "");
49920
51263
  if (fs11.existsSync(resolved)) return resolved;
49921
51264
  } else {
49922
51265
  if (fs11.existsSync(p)) return p;
@@ -49926,7 +51269,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
49926
51269
  }
49927
51270
  function getMacAppVersion(appPath) {
49928
51271
  if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
49929
- const plistPath = path18.join(appPath, "Contents", "Info.plist");
51272
+ const plistPath = path21.join(appPath, "Contents", "Info.plist");
49930
51273
  if (!fs11.existsSync(plistPath)) return null;
49931
51274
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
49932
51275
  return raw || null;
@@ -49952,7 +51295,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
49952
51295
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
49953
51296
  let resolvedBin = cliBin;
49954
51297
  if (!resolvedBin && appPath && currentOs === "darwin") {
49955
- const bundled = path18.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
51298
+ const bundled = path21.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
49956
51299
  if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
49957
51300
  }
49958
51301
  info.installed = !!(appPath || resolvedBin);
@@ -49991,7 +51334,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
49991
51334
  }
49992
51335
  var http2 = __toESM2(require("http"));
49993
51336
  var fs15 = __toESM2(require("fs"));
49994
- var path222 = __toESM2(require("path"));
51337
+ var path25 = __toESM2(require("path"));
49995
51338
  init_config();
49996
51339
  function generateFiles(type, name, category, opts = {}) {
49997
51340
  const { cdpPorts, cli, processName, installPath, binary, extensionId, version: version2 = "0.1" } = opts;
@@ -50336,7 +51679,7 @@ async (params) => {
50336
51679
  }
50337
51680
  init_logger();
50338
51681
  var fs12 = __toESM2(require("fs"));
50339
- var path19 = __toESM2(require("path"));
51682
+ var path222 = __toESM2(require("path"));
50340
51683
  init_logger();
50341
51684
  async function handleCdpEvaluate(ctx, req, res) {
50342
51685
  const body = await ctx.readBody(req);
@@ -50515,17 +51858,17 @@ async (params) => {
50515
51858
  return;
50516
51859
  }
50517
51860
  let scriptsPath = "";
50518
- const directScripts = path19.join(dir, "scripts.js");
51861
+ const directScripts = path222.join(dir, "scripts.js");
50519
51862
  if (fs12.existsSync(directScripts)) {
50520
51863
  scriptsPath = directScripts;
50521
51864
  } else {
50522
- const scriptsDir = path19.join(dir, "scripts");
51865
+ const scriptsDir = path222.join(dir, "scripts");
50523
51866
  if (fs12.existsSync(scriptsDir)) {
50524
51867
  const versions = fs12.readdirSync(scriptsDir).filter((d) => {
50525
- return fs12.statSync(path19.join(scriptsDir, d)).isDirectory();
51868
+ return fs12.statSync(path222.join(scriptsDir, d)).isDirectory();
50526
51869
  }).sort().reverse();
50527
51870
  for (const ver of versions) {
50528
- const p = path19.join(scriptsDir, ver, "scripts.js");
51871
+ const p = path222.join(scriptsDir, ver, "scripts.js");
50529
51872
  if (fs12.existsSync(p)) {
50530
51873
  scriptsPath = p;
50531
51874
  break;
@@ -51352,7 +52695,7 @@ async (params) => {
51352
52695
  }
51353
52696
  }
51354
52697
  var fs13 = __toESM2(require("fs"));
51355
- var path20 = __toESM2(require("path"));
52698
+ var path232 = __toESM2(require("path"));
51356
52699
  function slugifyFixtureName(value) {
51357
52700
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
51358
52701
  return normalized || `fixture-${Date.now()}`;
@@ -51362,11 +52705,11 @@ async (params) => {
51362
52705
  if (!providerDir) {
51363
52706
  throw new Error(`Provider directory not found for '${type}'`);
51364
52707
  }
51365
- return path20.join(providerDir, "fixtures");
52708
+ return path232.join(providerDir, "fixtures");
51366
52709
  }
51367
52710
  function readCliFixture(ctx, type, name) {
51368
52711
  const fixtureDir = getCliFixtureDir(ctx, type);
51369
- const filePath = path20.join(fixtureDir, `${name}.json`);
52712
+ const filePath = path232.join(fixtureDir, `${name}.json`);
51370
52713
  if (!fs13.existsSync(filePath)) {
51371
52714
  throw new Error(`Fixture not found: ${filePath}`);
51372
52715
  }
@@ -51535,7 +52878,7 @@ async (params) => {
51535
52878
  return { target, instance, adapter };
51536
52879
  }
51537
52880
  function sleep(ms2) {
51538
- return new Promise((resolve12) => setTimeout(resolve12, ms2));
52881
+ return new Promise((resolve15) => setTimeout(resolve15, ms2));
51539
52882
  }
51540
52883
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
51541
52884
  const startedAt = Date.now();
@@ -51833,7 +53176,7 @@ async (params) => {
51833
53176
  return {
51834
53177
  mode: "fixture_replay_suite",
51835
53178
  pass: results.every((item) => item.pass),
51836
- failures: results.flatMap((item) => item.failures.map((failure) => `${item.fixtureName}: ${failure}`)),
53179
+ failures: results.flatMap((item) => item.failures.map((failure2) => `${item.fixtureName}: ${failure2}`)),
51837
53180
  result: firstFailure.result,
51838
53181
  assertions: firstFailure.assertions,
51839
53182
  fixture: firstFailure.fixture,
@@ -52133,7 +53476,7 @@ async (params) => {
52133
53476
  },
52134
53477
  notes: typeof body?.notes === "string" ? body.notes : void 0
52135
53478
  };
52136
- const filePath = path20.join(fixtureDir, `${name}.json`);
53479
+ const filePath = path232.join(fixtureDir, `${name}.json`);
52137
53480
  fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
52138
53481
  ctx.json(res, 200, {
52139
53482
  saved: true,
@@ -52157,7 +53500,7 @@ async (params) => {
52157
53500
  return;
52158
53501
  }
52159
53502
  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);
53503
+ const fullPath = path232.join(fixtureDir, file2);
52161
53504
  try {
52162
53505
  const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
52163
53506
  return {
@@ -52291,7 +53634,7 @@ async (params) => {
52291
53634
  }
52292
53635
  }
52293
53636
  var fs14 = __toESM2(require("fs"));
52294
- var path21 = __toESM2(require("path"));
53637
+ var path24 = __toESM2(require("path"));
52295
53638
  var os20 = __toESM2(require("os"));
52296
53639
  function getAutoImplPid(ctx) {
52297
53640
  const pid = ctx.autoImplProcess?.pid;
@@ -52341,22 +53684,22 @@ async (params) => {
52341
53684
  if (!fs14.existsSync(scriptsDir)) return null;
52342
53685
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
52343
53686
  try {
52344
- return fs14.statSync(path21.join(scriptsDir, d)).isDirectory();
53687
+ return fs14.statSync(path24.join(scriptsDir, d)).isDirectory();
52345
53688
  } catch {
52346
53689
  return false;
52347
53690
  }
52348
53691
  }).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
52349
53692
  if (versions.length === 0) return null;
52350
- return path21.join(scriptsDir, versions[0]);
53693
+ return path24.join(scriptsDir, versions[0]);
52351
53694
  }
52352
53695
  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}`)) {
53696
+ const canonicalUserDir = path24.resolve(ctx.providerLoader.getUserProviderDir(category, type));
53697
+ const desiredDir = requestedDir ? path24.resolve(requestedDir) : canonicalUserDir;
53698
+ const upstreamRoot = path24.resolve(ctx.providerLoader.getUpstreamDir());
53699
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path24.sep}`)) {
52357
53700
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
52358
53701
  }
52359
- if (path21.basename(desiredDir) !== type) {
53702
+ if (path24.basename(desiredDir) !== type) {
52360
53703
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
52361
53704
  }
52362
53705
  const sourceDir = ctx.findProviderDir(type);
@@ -52364,11 +53707,11 @@ async (params) => {
52364
53707
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
52365
53708
  }
52366
53709
  if (!fs14.existsSync(desiredDir)) {
52367
- fs14.mkdirSync(path21.dirname(desiredDir), { recursive: true });
53710
+ fs14.mkdirSync(path24.dirname(desiredDir), { recursive: true });
52368
53711
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
52369
53712
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
52370
53713
  }
52371
- const providerJson = path21.join(desiredDir, "provider.json");
53714
+ const providerJson = path24.join(desiredDir, "provider.json");
52372
53715
  if (!fs14.existsSync(providerJson)) {
52373
53716
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
52374
53717
  }
@@ -52379,13 +53722,13 @@ async (params) => {
52379
53722
  const refDir = ctx.findProviderDir(referenceType);
52380
53723
  if (!refDir || !fs14.existsSync(refDir)) return {};
52381
53724
  const referenceScripts = {};
52382
- const scriptsDir = path21.join(refDir, "scripts");
53725
+ const scriptsDir = path24.join(refDir, "scripts");
52383
53726
  const latestDir = getLatestScriptVersionDir(scriptsDir);
52384
53727
  if (!latestDir) return referenceScripts;
52385
53728
  for (const file2 of fs14.readdirSync(latestDir)) {
52386
53729
  if (!file2.endsWith(".js")) continue;
52387
53730
  try {
52388
- referenceScripts[file2] = fs14.readFileSync(path21.join(latestDir, file2), "utf-8");
53731
+ referenceScripts[file2] = fs14.readFileSync(path24.join(latestDir, file2), "utf-8");
52389
53732
  } catch {
52390
53733
  }
52391
53734
  }
@@ -52493,9 +53836,9 @@ async (params) => {
52493
53836
  });
52494
53837
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
52495
53838
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
52496
- const tmpDir = path21.join(os20.tmpdir(), "adhdev-autoimpl");
53839
+ const tmpDir = path24.join(os20.tmpdir(), "adhdev-autoimpl");
52497
53840
  if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
52498
- const promptFile = path21.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
53841
+ const promptFile = path24.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
52499
53842
  fs14.writeFileSync(promptFile, prompt, "utf-8");
52500
53843
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
52501
53844
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -52927,7 +54270,7 @@ async (params) => {
52927
54270
  setMode: "set_mode.js"
52928
54271
  };
52929
54272
  const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
52930
- const scriptsDir = path21.join(providerDir, "scripts");
54273
+ const scriptsDir = path24.join(providerDir, "scripts");
52931
54274
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
52932
54275
  if (latestScriptsDir) {
52933
54276
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -52938,7 +54281,7 @@ async (params) => {
52938
54281
  for (const file2 of fs14.readdirSync(latestScriptsDir)) {
52939
54282
  if (file2.endsWith(".js") && targetFileNames.has(file2)) {
52940
54283
  try {
52941
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file2), "utf-8");
54284
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file2), "utf-8");
52942
54285
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
52943
54286
  lines.push("```javascript");
52944
54287
  lines.push(content);
@@ -52955,7 +54298,7 @@ async (params) => {
52955
54298
  lines.push("");
52956
54299
  for (const file2 of refFiles) {
52957
54300
  try {
52958
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file2), "utf-8");
54301
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file2), "utf-8");
52959
54302
  lines.push(`### \`${file2}\` \u{1F512}`);
52960
54303
  lines.push("```javascript");
52961
54304
  lines.push(content);
@@ -52996,10 +54339,10 @@ async (params) => {
52996
54339
  lines.push("");
52997
54340
  }
52998
54341
  }
52999
- const docsDir = path21.join(providerDir, "../../docs");
54342
+ const docsDir = path24.join(providerDir, "../../docs");
53000
54343
  const loadGuide = (name) => {
53001
54344
  try {
53002
- const p = path21.join(docsDir, name);
54345
+ const p = path24.join(docsDir, name);
53003
54346
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
53004
54347
  } catch {
53005
54348
  }
@@ -53236,7 +54579,7 @@ async (params) => {
53236
54579
  parseApproval: "parse_approval.js"
53237
54580
  };
53238
54581
  const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
53239
- const scriptsDir = path21.join(providerDir, "scripts");
54582
+ const scriptsDir = path24.join(providerDir, "scripts");
53240
54583
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
53241
54584
  if (latestScriptsDir) {
53242
54585
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -53248,7 +54591,7 @@ async (params) => {
53248
54591
  if (!file2.endsWith(".js")) continue;
53249
54592
  if (!targetFileNames.has(file2)) continue;
53250
54593
  try {
53251
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file2), "utf-8");
54594
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file2), "utf-8");
53252
54595
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
53253
54596
  lines.push("```javascript");
53254
54597
  lines.push(content);
@@ -53264,7 +54607,7 @@ async (params) => {
53264
54607
  lines.push("");
53265
54608
  for (const file2 of refFiles) {
53266
54609
  try {
53267
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file2), "utf-8");
54610
+ const content = fs14.readFileSync(path24.join(latestScriptsDir, file2), "utf-8");
53268
54611
  lines.push(`### \`${file2}\` \u{1F512}`);
53269
54612
  lines.push("```javascript");
53270
54613
  lines.push(content);
@@ -53297,10 +54640,10 @@ async (params) => {
53297
54640
  lines.push("");
53298
54641
  }
53299
54642
  }
53300
- const docsDir = path21.join(providerDir, "../../docs");
54643
+ const docsDir = path24.join(providerDir, "../../docs");
53301
54644
  const loadGuide = (name) => {
53302
54645
  try {
53303
- const p = path21.join(docsDir, name);
54646
+ const p = path24.join(docsDir, name);
53304
54647
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
53305
54648
  } catch {
53306
54649
  }
@@ -53745,8 +55088,8 @@ data: ${JSON.stringify(msg.data)}
53745
55088
  }
53746
55089
  getEndpointList() {
53747
55090
  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}`;
55091
+ const path26 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
55092
+ return `${r.method.padEnd(5)} ${path26}`;
53750
55093
  });
53751
55094
  }
53752
55095
  async start(port = DEV_SERVER_PORT) {
@@ -53777,15 +55120,15 @@ data: ${JSON.stringify(msg.data)}
53777
55120
  this.json(res, 500, { error: e.message });
53778
55121
  }
53779
55122
  });
53780
- return new Promise((resolve12, reject) => {
55123
+ return new Promise((resolve15, reject) => {
53781
55124
  this.server.listen(port, "127.0.0.1", () => {
53782
55125
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
53783
- resolve12();
55126
+ resolve15();
53784
55127
  });
53785
55128
  this.server.on("error", (e) => {
53786
55129
  if (e.code === "EADDRINUSE") {
53787
55130
  this.log(`Port ${port} in use, skipping dev server`);
53788
- resolve12();
55131
+ resolve15();
53789
55132
  } else {
53790
55133
  reject(e);
53791
55134
  }
@@ -53867,20 +55210,20 @@ data: ${JSON.stringify(msg.data)}
53867
55210
  child.stderr?.on("data", (d) => {
53868
55211
  stderr += d.toString().slice(0, 2e3);
53869
55212
  });
53870
- await new Promise((resolve12) => {
55213
+ await new Promise((resolve15) => {
53871
55214
  const timer = setTimeout(() => {
53872
55215
  child.kill();
53873
- resolve12();
55216
+ resolve15();
53874
55217
  }, 3e3);
53875
55218
  child.on("exit", () => {
53876
55219
  clearTimeout(timer);
53877
- resolve12();
55220
+ resolve15();
53878
55221
  });
53879
55222
  child.stdout?.once("data", () => {
53880
55223
  setTimeout(() => {
53881
55224
  child.kill();
53882
55225
  clearTimeout(timer);
53883
- resolve12();
55226
+ resolve15();
53884
55227
  }, 500);
53885
55228
  });
53886
55229
  });
@@ -54034,12 +55377,12 @@ data: ${JSON.stringify(msg.data)}
54034
55377
  // ─── DevConsole SPA ───
54035
55378
  getConsoleDistDir() {
54036
55379
  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")
55380
+ path25.resolve(__dirname, "../../web-devconsole/dist"),
55381
+ path25.resolve(__dirname, "../../../web-devconsole/dist"),
55382
+ path25.join(process.cwd(), "packages/web-devconsole/dist")
54040
55383
  ];
54041
55384
  for (const dir of candidates) {
54042
- if (fs15.existsSync(path222.join(dir, "index.html"))) return dir;
55385
+ if (fs15.existsSync(path25.join(dir, "index.html"))) return dir;
54043
55386
  }
54044
55387
  return null;
54045
55388
  }
@@ -54049,7 +55392,7 @@ data: ${JSON.stringify(msg.data)}
54049
55392
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
54050
55393
  return;
54051
55394
  }
54052
- const htmlPath = path222.join(distDir, "index.html");
55395
+ const htmlPath = path25.join(distDir, "index.html");
54053
55396
  try {
54054
55397
  const html = fs15.readFileSync(htmlPath, "utf-8");
54055
55398
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -54074,15 +55417,15 @@ data: ${JSON.stringify(msg.data)}
54074
55417
  this.json(res, 404, { error: "Not found" });
54075
55418
  return;
54076
55419
  }
54077
- const safePath = path222.normalize(pathname).replace(/^\.\.\//, "");
54078
- const filePath = path222.join(distDir, safePath);
55420
+ const safePath = path25.normalize(pathname).replace(/^\.\.\//, "");
55421
+ const filePath = path25.join(distDir, safePath);
54079
55422
  if (!filePath.startsWith(distDir)) {
54080
55423
  this.json(res, 403, { error: "Forbidden" });
54081
55424
  return;
54082
55425
  }
54083
55426
  try {
54084
55427
  const content = fs15.readFileSync(filePath);
54085
- const ext = path222.extname(filePath);
55428
+ const ext = path25.extname(filePath);
54086
55429
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
54087
55430
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
54088
55431
  res.end(content);
@@ -54195,10 +55538,10 @@ data: ${JSON.stringify(msg.data)}
54195
55538
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
54196
55539
  if (entry.isDirectory()) {
54197
55540
  files.push({ path: rel, size: 0, type: "dir" });
54198
- scan(path222.join(d, entry.name), rel);
55541
+ scan(path25.join(d, entry.name), rel);
54199
55542
  } else {
54200
- const stat4 = fs15.statSync(path222.join(d, entry.name));
54201
- files.push({ path: rel, size: stat4.size, type: "file" });
55543
+ const stat22 = fs15.statSync(path25.join(d, entry.name));
55544
+ files.push({ path: rel, size: stat22.size, type: "file" });
54202
55545
  }
54203
55546
  }
54204
55547
  } catch {
@@ -54220,7 +55563,7 @@ data: ${JSON.stringify(msg.data)}
54220
55563
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
54221
55564
  return;
54222
55565
  }
54223
- const fullPath = path222.resolve(dir, path222.normalize(filePath));
55566
+ const fullPath = path25.resolve(dir, path25.normalize(filePath));
54224
55567
  if (!fullPath.startsWith(dir)) {
54225
55568
  this.json(res, 403, { error: "Forbidden" });
54226
55569
  return;
@@ -54245,14 +55588,14 @@ data: ${JSON.stringify(msg.data)}
54245
55588
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
54246
55589
  return;
54247
55590
  }
54248
- const fullPath = path222.resolve(dir, path222.normalize(filePath));
55591
+ const fullPath = path25.resolve(dir, path25.normalize(filePath));
54249
55592
  if (!fullPath.startsWith(dir)) {
54250
55593
  this.json(res, 403, { error: "Forbidden" });
54251
55594
  return;
54252
55595
  }
54253
55596
  try {
54254
55597
  if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
54255
- fs15.mkdirSync(path222.dirname(fullPath), { recursive: true });
55598
+ fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
54256
55599
  fs15.writeFileSync(fullPath, content, "utf-8");
54257
55600
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
54258
55601
  this.providerLoader.reload();
@@ -54269,7 +55612,7 @@ data: ${JSON.stringify(msg.data)}
54269
55612
  return;
54270
55613
  }
54271
55614
  for (const name of ["scripts.js", "provider.json"]) {
54272
- const p = path222.join(dir, name);
55615
+ const p = path25.join(dir, name);
54273
55616
  if (fs15.existsSync(p)) {
54274
55617
  const source = fs15.readFileSync(p, "utf-8");
54275
55618
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -54290,8 +55633,8 @@ data: ${JSON.stringify(msg.data)}
54290
55633
  this.json(res, 404, { error: `Provider not found: ${type}` });
54291
55634
  return;
54292
55635
  }
54293
- const target = fs15.existsSync(path222.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
54294
- const targetPath = path222.join(dir, target);
55636
+ const target = fs15.existsSync(path25.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
55637
+ const targetPath = path25.join(dir, target);
54295
55638
  try {
54296
55639
  if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
54297
55640
  fs15.writeFileSync(targetPath, source, "utf-8");
@@ -54383,14 +55726,14 @@ data: ${JSON.stringify(msg.data)}
54383
55726
  child.stderr?.on("data", (d) => {
54384
55727
  stderr += d.toString();
54385
55728
  });
54386
- await new Promise((resolve12) => {
55729
+ await new Promise((resolve15) => {
54387
55730
  const timer = setTimeout(() => {
54388
55731
  child.kill();
54389
- resolve12();
55732
+ resolve15();
54390
55733
  }, timeout);
54391
55734
  child.on("exit", () => {
54392
55735
  clearTimeout(timer);
54393
- resolve12();
55736
+ resolve15();
54394
55737
  });
54395
55738
  });
54396
55739
  const elapsed = Date.now() - start;
@@ -54438,7 +55781,7 @@ data: ${JSON.stringify(msg.data)}
54438
55781
  }
54439
55782
  let targetDir;
54440
55783
  targetDir = this.providerLoader.getUserProviderDir(category, type);
54441
- const jsonPath = path222.join(targetDir, "provider.json");
55784
+ const jsonPath = path25.join(targetDir, "provider.json");
54442
55785
  if (fs15.existsSync(jsonPath)) {
54443
55786
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
54444
55787
  return;
@@ -54450,8 +55793,8 @@ data: ${JSON.stringify(msg.data)}
54450
55793
  const createdFiles = ["provider.json"];
54451
55794
  if (result.files) {
54452
55795
  for (const [relPath, content] of Object.entries(result.files)) {
54453
- const fullPath = path222.join(targetDir, relPath);
54454
- fs15.mkdirSync(path222.dirname(fullPath), { recursive: true });
55796
+ const fullPath = path25.join(targetDir, relPath);
55797
+ fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
54455
55798
  fs15.writeFileSync(fullPath, content, "utf-8");
54456
55799
  createdFiles.push(relPath);
54457
55800
  }
@@ -54504,22 +55847,22 @@ data: ${JSON.stringify(msg.data)}
54504
55847
  if (!fs15.existsSync(scriptsDir)) return null;
54505
55848
  const versions = fs15.readdirSync(scriptsDir).filter((d) => {
54506
55849
  try {
54507
- return fs15.statSync(path222.join(scriptsDir, d)).isDirectory();
55850
+ return fs15.statSync(path25.join(scriptsDir, d)).isDirectory();
54508
55851
  } catch {
54509
55852
  return false;
54510
55853
  }
54511
55854
  }).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
54512
55855
  if (versions.length === 0) return null;
54513
- return path222.join(scriptsDir, versions[0]);
55856
+ return path25.join(scriptsDir, versions[0]);
54514
55857
  }
54515
55858
  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}`)) {
55859
+ const canonicalUserDir = path25.resolve(this.providerLoader.getUserProviderDir(category, type));
55860
+ const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
55861
+ const upstreamRoot = path25.resolve(this.providerLoader.getUpstreamDir());
55862
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
54520
55863
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
54521
55864
  }
54522
- if (path222.basename(desiredDir) !== type) {
55865
+ if (path25.basename(desiredDir) !== type) {
54523
55866
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
54524
55867
  }
54525
55868
  const sourceDir = this.findProviderDir(type);
@@ -54527,11 +55870,11 @@ data: ${JSON.stringify(msg.data)}
54527
55870
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
54528
55871
  }
54529
55872
  if (!fs15.existsSync(desiredDir)) {
54530
- fs15.mkdirSync(path222.dirname(desiredDir), { recursive: true });
55873
+ fs15.mkdirSync(path25.dirname(desiredDir), { recursive: true });
54531
55874
  fs15.cpSync(sourceDir, desiredDir, { recursive: true });
54532
55875
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
54533
55876
  }
54534
- const providerJson = path222.join(desiredDir, "provider.json");
55877
+ const providerJson = path25.join(desiredDir, "provider.json");
54535
55878
  if (!fs15.existsSync(providerJson)) {
54536
55879
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
54537
55880
  }
@@ -54567,7 +55910,7 @@ data: ${JSON.stringify(msg.data)}
54567
55910
  setMode: "set_mode.js"
54568
55911
  };
54569
55912
  const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
54570
- const scriptsDir = path222.join(providerDir, "scripts");
55913
+ const scriptsDir = path25.join(providerDir, "scripts");
54571
55914
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
54572
55915
  if (latestScriptsDir) {
54573
55916
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -54578,7 +55921,7 @@ data: ${JSON.stringify(msg.data)}
54578
55921
  for (const file2 of fs15.readdirSync(latestScriptsDir)) {
54579
55922
  if (file2.endsWith(".js") && targetFileNames.has(file2)) {
54580
55923
  try {
54581
- const content = fs15.readFileSync(path222.join(latestScriptsDir, file2), "utf-8");
55924
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file2), "utf-8");
54582
55925
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
54583
55926
  lines.push("```javascript");
54584
55927
  lines.push(content);
@@ -54595,7 +55938,7 @@ data: ${JSON.stringify(msg.data)}
54595
55938
  lines.push("");
54596
55939
  for (const file2 of refFiles) {
54597
55940
  try {
54598
- const content = fs15.readFileSync(path222.join(latestScriptsDir, file2), "utf-8");
55941
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file2), "utf-8");
54599
55942
  lines.push(`### \`${file2}\` \u{1F512}`);
54600
55943
  lines.push("```javascript");
54601
55944
  lines.push(content);
@@ -54636,10 +55979,10 @@ data: ${JSON.stringify(msg.data)}
54636
55979
  lines.push("");
54637
55980
  }
54638
55981
  }
54639
- const docsDir = path222.join(providerDir, "../../docs");
55982
+ const docsDir = path25.join(providerDir, "../../docs");
54640
55983
  const loadGuide = (name) => {
54641
55984
  try {
54642
- const p = path222.join(docsDir, name);
55985
+ const p = path25.join(docsDir, name);
54643
55986
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
54644
55987
  } catch {
54645
55988
  }
@@ -54813,7 +56156,7 @@ data: ${JSON.stringify(msg.data)}
54813
56156
  parseApproval: "parse_approval.js"
54814
56157
  };
54815
56158
  const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
54816
- const scriptsDir = path222.join(providerDir, "scripts");
56159
+ const scriptsDir = path25.join(providerDir, "scripts");
54817
56160
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
54818
56161
  if (latestScriptsDir) {
54819
56162
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -54825,7 +56168,7 @@ data: ${JSON.stringify(msg.data)}
54825
56168
  if (!file2.endsWith(".js")) continue;
54826
56169
  if (!targetFileNames.has(file2)) continue;
54827
56170
  try {
54828
- const content = fs15.readFileSync(path222.join(latestScriptsDir, file2), "utf-8");
56171
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file2), "utf-8");
54829
56172
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
54830
56173
  lines.push("```javascript");
54831
56174
  lines.push(content);
@@ -54841,7 +56184,7 @@ data: ${JSON.stringify(msg.data)}
54841
56184
  lines.push("");
54842
56185
  for (const file2 of refFiles) {
54843
56186
  try {
54844
- const content = fs15.readFileSync(path222.join(latestScriptsDir, file2), "utf-8");
56187
+ const content = fs15.readFileSync(path25.join(latestScriptsDir, file2), "utf-8");
54845
56188
  lines.push(`### \`${file2}\` \u{1F512}`);
54846
56189
  lines.push("```javascript");
54847
56190
  lines.push(content);
@@ -54874,10 +56217,10 @@ data: ${JSON.stringify(msg.data)}
54874
56217
  lines.push("");
54875
56218
  }
54876
56219
  }
54877
- const docsDir = path222.join(providerDir, "../../docs");
56220
+ const docsDir = path25.join(providerDir, "../../docs");
54878
56221
  const loadGuide = (name) => {
54879
56222
  try {
54880
- const p = path222.join(docsDir, name);
56223
+ const p = path25.join(docsDir, name);
54881
56224
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
54882
56225
  } catch {
54883
56226
  }
@@ -55060,14 +56403,14 @@ data: ${JSON.stringify(msg.data)}
55060
56403
  res.end(JSON.stringify(data, null, 2));
55061
56404
  }
55062
56405
  async readBody(req) {
55063
- return new Promise((resolve12) => {
56406
+ return new Promise((resolve15) => {
55064
56407
  let body = "";
55065
56408
  req.on("data", (chunk) => body += chunk);
55066
56409
  req.on("end", () => {
55067
56410
  try {
55068
- resolve12(JSON.parse(body));
56411
+ resolve15(JSON.parse(body));
55069
56412
  } catch {
55070
- resolve12({});
56413
+ resolve15({});
55071
56414
  }
55072
56415
  });
55073
56416
  });
@@ -55569,7 +56912,7 @@ data: ${JSON.stringify(msg.data)}
55569
56912
  const deadline = Date.now() + timeoutMs;
55570
56913
  while (Date.now() < deadline) {
55571
56914
  if (await canConnect(endpoint)) return;
55572
- await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
56915
+ await new Promise((resolve15) => setTimeout(resolve15, STARTUP_POLL_MS));
55573
56916
  }
55574
56917
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
55575
56918
  }
@@ -55743,10 +57086,10 @@ data: ${JSON.stringify(msg.data)}
55743
57086
  const buffer = Buffer.from(await res.arrayBuffer());
55744
57087
  const fs16 = await import("fs");
55745
57088
  fs16.writeFileSync(vsixPath, buffer);
55746
- return new Promise((resolve12) => {
57089
+ return new Promise((resolve15) => {
55747
57090
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
55748
57091
  (0, import_child_process11.exec)(cmd, { timeout: 6e4 }, (error48, _stdout, stderr) => {
55749
- resolve12({
57092
+ resolve15({
55750
57093
  extensionId: extension.id,
55751
57094
  marketplaceId: extension.marketplaceId,
55752
57095
  success: !error48,
@@ -55759,11 +57102,11 @@ data: ${JSON.stringify(msg.data)}
55759
57102
  } catch (e) {
55760
57103
  }
55761
57104
  }
55762
- return new Promise((resolve12) => {
57105
+ return new Promise((resolve15) => {
55763
57106
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
55764
57107
  (0, import_child_process11.exec)(cmd, { timeout: 6e4 }, (error48, stdout, stderr) => {
55765
57108
  if (error48) {
55766
- resolve12({
57109
+ resolve15({
55767
57110
  extensionId: extension.id,
55768
57111
  marketplaceId: extension.marketplaceId,
55769
57112
  success: false,
@@ -55771,7 +57114,7 @@ data: ${JSON.stringify(msg.data)}
55771
57114
  error: stderr || error48.message
55772
57115
  });
55773
57116
  } else {
55774
- resolve12({
57117
+ resolve15({
55775
57118
  extensionId: extension.id,
55776
57119
  marketplaceId: extension.marketplaceId,
55777
57120
  success: true,
@@ -55971,6 +57314,7 @@ data: ${JSON.stringify(msg.data)}
55971
57314
  providerLoader,
55972
57315
  instanceManager,
55973
57316
  sessionRegistry,
57317
+ gitCommandServices: createDefaultGitCommandServices(),
55974
57318
  onProviderSettingChanged: async (providerType) => {
55975
57319
  await refreshProviderAvailability(providerType);
55976
57320
  config2.onStatusChange?.();
@@ -55978,7 +57322,8 @@ data: ${JSON.stringify(msg.data)}
55978
57322
  onProviderSourceConfigChanged: async () => {
55979
57323
  await refreshProviderAvailability();
55980
57324
  config2.onStatusChange?.();
55981
- }
57325
+ },
57326
+ onBeforeSendChat: config2.onBeforeSendChat
55982
57327
  });
55983
57328
  agentStreamManager = new DaemonAgentStreamManager(
55984
57329
  LOG2.forComponent("AgentStream").asLogFn(),
@@ -56881,6 +58226,8 @@ var StandaloneServer = class {
56881
58226
  wsSessionHostDiagnosticsSubscriptions = /* @__PURE__ */ new Map();
56882
58227
  wsSessionModalSubscriptions = /* @__PURE__ */ new Map();
56883
58228
  wsDaemonMetadataSubscriptions = /* @__PURE__ */ new Map();
58229
+ wsGitSubscriptions = /* @__PURE__ */ new Map();
58230
+ gitWorkspaceMonitor = (0, import_daemon_core2.createGitWorkspaceMonitor)();
56884
58231
  authToken = null;
56885
58232
  passwordConfigPath = getStandalonePasswordConfigPath();
56886
58233
  passwordConfig = null;
@@ -57146,6 +58493,7 @@ var StandaloneServer = class {
57146
58493
  void this.flushWsMachineRuntimeSubscriptions();
57147
58494
  void this.flushWsSessionHostDiagnosticsSubscriptions();
57148
58495
  void this.flushWsSessionModalSubscriptions();
58496
+ if (this.hasWsGitSubscriptions()) void this.flushWsGitSubscriptions();
57149
58497
  }, STATUS_INTERVAL);
57150
58498
  this.running = true;
57151
58499
  await new Promise((resolve4) => {
@@ -57634,6 +58982,7 @@ var StandaloneServer = class {
57634
58982
  this.wsSessionHostDiagnosticsSubscriptions.set(ws2, /* @__PURE__ */ new Map());
57635
58983
  this.wsSessionModalSubscriptions.set(ws2, /* @__PURE__ */ new Map());
57636
58984
  this.wsDaemonMetadataSubscriptions.set(ws2, /* @__PURE__ */ new Map());
58985
+ this.wsGitSubscriptions.set(ws2, /* @__PURE__ */ new Map());
57637
58986
  console.log(`[WS] Client connected (total: ${this.clients.size})`);
57638
58987
  const status = this.getWsStatus(this.buildSharedSnapshot("live"));
57639
58988
  this.lastWsStatusSignature = this.buildWsStatusSignature(status);
@@ -57677,6 +59026,7 @@ var StandaloneServer = class {
57677
59026
  this.wsSessionHostDiagnosticsSubscriptions.delete(ws2);
57678
59027
  this.wsSessionModalSubscriptions.delete(ws2);
57679
59028
  this.wsDaemonMetadataSubscriptions.delete(ws2);
59029
+ this.clearWsGitSubscriptions(ws2);
57680
59030
  console.log(`[WS] Client disconnected (total: ${this.clients.size})`);
57681
59031
  });
57682
59032
  ws2.on("error", () => {
@@ -57686,8 +59036,19 @@ var StandaloneServer = class {
57686
59036
  this.wsSessionHostDiagnosticsSubscriptions.delete(ws2);
57687
59037
  this.wsSessionModalSubscriptions.delete(ws2);
57688
59038
  this.wsDaemonMetadataSubscriptions.delete(ws2);
59039
+ this.clearWsGitSubscriptions(ws2);
57689
59040
  });
57690
59041
  }
59042
+ clearWsGitSubscriptions(ws2) {
59043
+ const subs = this.wsGitSubscriptions.get(ws2);
59044
+ if (subs) {
59045
+ subs.forEach((sub) => {
59046
+ sub.subscription.dispose();
59047
+ });
59048
+ subs.clear();
59049
+ }
59050
+ this.wsGitSubscriptions.delete(ws2);
59051
+ }
57691
59052
  async handleWsSubscribe(ws2, msg) {
57692
59053
  if (msg.topic === "session.chat_tail") {
57693
59054
  const params = msg.params;
@@ -57775,6 +59136,25 @@ var StandaloneServer = class {
57775
59136
  lastSentAt: 0
57776
59137
  });
57777
59138
  await this.flushWsDaemonMetadataSubscriptions(ws2);
59139
+ return;
59140
+ }
59141
+ if (msg.topic === "workspace.git") {
59142
+ const params = msg.params;
59143
+ if (!params?.workspace) return;
59144
+ const normalized = (0, import_daemon_core2.normalizeGitWorkspaceSubscriptionParams)(params);
59145
+ const subs = this.wsGitSubscriptions.get(ws2) || /* @__PURE__ */ new Map();
59146
+ this.wsGitSubscriptions.set(ws2, subs);
59147
+ subs.get(msg.key)?.subscription.dispose();
59148
+ subs.set(msg.key, {
59149
+ request: {
59150
+ ...msg,
59151
+ topic: "workspace.git",
59152
+ params: normalized
59153
+ },
59154
+ subscription: this.gitWorkspaceMonitor.createSubscription(normalized),
59155
+ lastSentAt: 0
59156
+ });
59157
+ await this.flushWsGitSubscriptions(ws2);
57778
59158
  }
57779
59159
  }
57780
59160
  handleWsUnsubscribe(ws2, msg) {
@@ -57796,6 +59176,12 @@ var StandaloneServer = class {
57796
59176
  }
57797
59177
  if (msg.topic === "daemon.metadata") {
57798
59178
  this.wsDaemonMetadataSubscriptions.get(ws2)?.delete(msg.key);
59179
+ return;
59180
+ }
59181
+ if (msg.topic === "workspace.git") {
59182
+ const sub = this.wsGitSubscriptions.get(ws2)?.get(msg.key);
59183
+ sub?.subscription.dispose();
59184
+ this.wsGitSubscriptions.get(ws2)?.delete(msg.key);
57799
59185
  }
57800
59186
  }
57801
59187
  async buildChatTailUpdate(request, state, key) {
@@ -58019,6 +59405,45 @@ var StandaloneServer = class {
58019
59405
  }
58020
59406
  }
58021
59407
  }
59408
+ hasWsGitSubscriptions(targetWs) {
59409
+ const targets = targetWs ? [targetWs] : Array.from(this.clients);
59410
+ for (const ws2 of targets) {
59411
+ const subs = this.wsGitSubscriptions.get(ws2);
59412
+ if (subs && subs.size > 0) return true;
59413
+ }
59414
+ return false;
59415
+ }
59416
+ async flushWsGitSubscriptions(targetWs) {
59417
+ if (!this.hasWsGitSubscriptions(targetWs)) return;
59418
+ const targets = targetWs ? [targetWs] : Array.from(this.clients);
59419
+ const now = Date.now();
59420
+ const tasks = [];
59421
+ for (const ws2 of targets) {
59422
+ if (ws2.readyState !== import_ws.WebSocket.OPEN) continue;
59423
+ const subs = this.wsGitSubscriptions.get(ws2);
59424
+ if (!subs || subs.size === 0) continue;
59425
+ subs.forEach((sub, key) => {
59426
+ const intervalMs = Math.max(1, Number(sub.subscription.params.intervalMs || sub.request.params.intervalMs || 0));
59427
+ if (sub.lastSentAt > 0 && now - sub.lastSentAt < intervalMs) return;
59428
+ tasks.push({ ws: ws2, key, sub });
59429
+ });
59430
+ }
59431
+ await (0, import_daemon_core2.runAsyncBatch)(tasks, async ({ ws: ws2, key, sub }) => {
59432
+ try {
59433
+ const monitorUpdate = await sub.subscription.refresh();
59434
+ const current = this.wsGitSubscriptions.get(ws2)?.get(key);
59435
+ if (current !== sub || ws2.readyState !== import_ws.WebSocket.OPEN) return;
59436
+ sub.lastSentAt = monitorUpdate.timestamp;
59437
+ const update = {
59438
+ ...monitorUpdate,
59439
+ key
59440
+ };
59441
+ ws2.send(JSON.stringify({ type: "topic_update", update }));
59442
+ } catch (error48) {
59443
+ import_daemon_core2.LOG.warn("Standalone", `[workspace.git] skipped workspace=${sub.request.params.workspace} key=${key} error=${error48?.message || error48}`);
59444
+ }
59445
+ }, { concurrency: 2 });
59446
+ }
58022
59447
  // ─── Core Logic ───
58023
59448
  buildSharedSnapshot(profile = "full") {
58024
59449
  const cfgSnap = (0, import_daemon_core2.loadConfig)();
@@ -58034,7 +59459,8 @@ var StandaloneServer = class {
58034
59459
  })),
58035
59460
  instanceId: `standalone_${machineId}`,
58036
59461
  version: pkgVersion,
58037
- profile
59462
+ profile,
59463
+ getGitSummaryForWorkspace: (workspace) => this.gitWorkspaceMonitor.getCompactSummary(workspace)
58038
59464
  });
58039
59465
  }
58040
59466
  async pushWsRuntimeSnapshots(ws2) {
@@ -58143,6 +59569,7 @@ var StandaloneServer = class {
58143
59569
  }
58144
59570
  if (type.startsWith("session_host_")) void this.flushWsSessionHostDiagnosticsSubscriptions();
58145
59571
  if (type === "resolve_action" || type === "send_chat" || type === "read_chat") void this.flushWsSessionModalSubscriptions();
59572
+ if (type.startsWith("git_") && this.hasWsGitSubscriptions()) void this.flushWsGitSubscriptions();
58146
59573
  return result;
58147
59574
  }
58148
59575
  scheduleBroadcastStatus() {