adhdev 0.8.28 → 0.8.29

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/cli/index.js CHANGED
@@ -649,17 +649,17 @@ function checkPathExists(paths) {
649
649
  return null;
650
650
  }
651
651
  async function detectIDEs(providerLoader) {
652
- const os24 = (0, import_os2.platform)();
652
+ const os25 = (0, import_os2.platform)();
653
653
  const results = [];
654
654
  for (const def of getMergedDefinitions()) {
655
655
  const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
656
- const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os24] || []) || []);
656
+ const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os25] || []) || []);
657
657
  let resolvedCli = cliPath;
658
- if (!resolvedCli && appPath && os24 === "darwin") {
658
+ if (!resolvedCli && appPath && os25 === "darwin") {
659
659
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
660
660
  if ((0, import_fs3.existsSync)(bundledCli)) resolvedCli = bundledCli;
661
661
  }
662
- if (!resolvedCli && appPath && os24 === "win32") {
662
+ if (!resolvedCli && appPath && os25 === "win32") {
663
663
  const { dirname: dirname9 } = await import("path");
664
664
  const appDir = dirname9(appPath);
665
665
  const candidates = [
@@ -676,7 +676,7 @@ async function detectIDEs(providerLoader) {
676
676
  }
677
677
  }
678
678
  }
679
- const installed = os24 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
679
+ const installed = os25 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
680
680
  const version2 = resolvedCli ? getIdeVersion(resolvedCli) : null;
681
681
  results.push({
682
682
  id: def.id,
@@ -2595,6 +2595,62 @@ var init_control_effects = __esm({
2595
2595
  });
2596
2596
 
2597
2597
  // ../../oss/packages/daemon-core/src/config/chat-history.ts
2598
+ function normalizeHistoryComparable(text) {
2599
+ return String(text || "").replace(/\s+/g, " ").trim();
2600
+ }
2601
+ function cleanupHistoryContent(agentType, role, content) {
2602
+ let value = String(content || "").replace(/\r\n/g, "\n").trim();
2603
+ if (!value) return "";
2604
+ if (agentType === "codex-cli" && role === "assistant") {
2605
+ const filtered = value.split("\n").filter((line) => !CODEX_STARTER_PROMPT_RE.test(line.trim())).join("\n").replace(/\n{3,}/g, "\n\n").trim();
2606
+ value = filtered;
2607
+ }
2608
+ return value;
2609
+ }
2610
+ function buildHistoryMessageHash(agentType, message) {
2611
+ if (message.historyDedupKey) return message.historyDedupKey;
2612
+ const cleaned = cleanupHistoryContent(agentType, message.role, message.content);
2613
+ return `${message.kind || "standard"}:${message.role}:${message.receivedAt || 0}:${normalizeHistoryComparable(cleaned)}`;
2614
+ }
2615
+ function buildHistoryMessageSignature(agentType, message) {
2616
+ const cleaned = cleanupHistoryContent(agentType, message.role, message.content);
2617
+ return `${message.kind || "standard"}:${message.role}:${normalizeHistoryComparable(cleaned)}`;
2618
+ }
2619
+ function isAdjacentHistoryDuplicate(agentType, previous, next) {
2620
+ if (!previous || !next) return false;
2621
+ return buildHistoryMessageSignature(agentType, previous) === buildHistoryMessageSignature(agentType, next);
2622
+ }
2623
+ function collapseReplayAssistantTurns(agentType, messages) {
2624
+ if (agentType !== "codex-cli") return messages;
2625
+ const collapsed = [];
2626
+ let sawAssistantSinceLastUser = false;
2627
+ for (const message of messages) {
2628
+ if (message.role === "user") {
2629
+ sawAssistantSinceLastUser = false;
2630
+ collapsed.push(message);
2631
+ continue;
2632
+ }
2633
+ if (message.role === "assistant") {
2634
+ if (sawAssistantSinceLastUser) continue;
2635
+ sawAssistantSinceLastUser = true;
2636
+ collapsed.push(message);
2637
+ continue;
2638
+ }
2639
+ collapsed.push(message);
2640
+ }
2641
+ return collapsed;
2642
+ }
2643
+ function sanitizeHistoryMessage(agentType, message) {
2644
+ if (!message || message.role !== "user" && message.role !== "assistant" && message.role !== "system") {
2645
+ return null;
2646
+ }
2647
+ const content = cleanupHistoryContent(agentType, message.role, message.content);
2648
+ if (!content) return null;
2649
+ return {
2650
+ ...message,
2651
+ content
2652
+ };
2653
+ }
2598
2654
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
2599
2655
  try {
2600
2656
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
@@ -2609,23 +2665,37 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
2609
2665
  return true;
2610
2666
  }).sort().reverse();
2611
2667
  const allMessages = [];
2612
- const needed = offset + limit + 1;
2668
+ const seen = /* @__PURE__ */ new Set();
2613
2669
  for (const file2 of files) {
2614
- if (allMessages.length >= needed) break;
2615
2670
  const filePath = path7.join(dir, file2);
2616
2671
  const content = fs3.readFileSync(filePath, "utf-8");
2617
2672
  const lines = content.trim().split("\n").filter(Boolean);
2618
- for (let i = lines.length - 1; i >= 0; i--) {
2619
- if (allMessages.length >= needed) break;
2673
+ for (let i = 0; i < lines.length; i++) {
2620
2674
  try {
2621
- allMessages.push(JSON.parse(lines[i]));
2675
+ const parsed = JSON.parse(lines[i]);
2676
+ const sanitizedMessage = sanitizeHistoryMessage(agentType, parsed);
2677
+ if (!sanitizedMessage) continue;
2678
+ const hash2 = buildHistoryMessageHash(agentType, sanitizedMessage);
2679
+ if (seen.has(hash2)) continue;
2680
+ seen.add(hash2);
2681
+ allMessages.push(sanitizedMessage);
2622
2682
  } catch {
2623
2683
  }
2624
2684
  }
2625
2685
  }
2626
- const sliced = allMessages.slice(offset, offset + limit);
2627
- const hasMore = allMessages.length > offset + limit;
2628
- sliced.reverse();
2686
+ allMessages.sort((a, b) => a.receivedAt - b.receivedAt);
2687
+ const chronological = [];
2688
+ let lastTurn = null;
2689
+ for (const message of allMessages) {
2690
+ const previous = chronological[chronological.length - 1];
2691
+ if (isAdjacentHistoryDuplicate(agentType, previous, message)) continue;
2692
+ if (message.role !== "system" && isAdjacentHistoryDuplicate(agentType, lastTurn, message)) continue;
2693
+ chronological.push(message);
2694
+ if (message.role !== "system") lastTurn = message;
2695
+ }
2696
+ const collapsed = collapseReplayAssistantTurns(agentType, chronological);
2697
+ const sliced = collapsed.slice(offset, offset + limit);
2698
+ const hasMore = collapsed.length > offset + limit;
2629
2699
  return { messages: sliced, hasMore };
2630
2700
  } catch {
2631
2701
  return { messages: [], hasMore: false };
@@ -2695,7 +2765,7 @@ function listSavedHistorySessions(agentType, options = {}) {
2695
2765
  return { sessions: [], hasMore: false };
2696
2766
  }
2697
2767
  }
2698
- var fs3, path7, os5, HISTORY_DIR, RETAIN_DAYS, ChatHistoryWriter;
2768
+ var fs3, path7, os5, HISTORY_DIR, RETAIN_DAYS, CODEX_STARTER_PROMPT_RE, ChatHistoryWriter;
2699
2769
  var init_chat_history = __esm({
2700
2770
  "../../oss/packages/daemon-core/src/config/chat-history.ts"() {
2701
2771
  "use strict";
@@ -2704,11 +2774,16 @@ var init_chat_history = __esm({
2704
2774
  os5 = __toESM(require("os"));
2705
2775
  HISTORY_DIR = path7.join(os5.homedir(), ".adhdev", "history");
2706
2776
  RETAIN_DAYS = 30;
2777
+ CODEX_STARTER_PROMPT_RE = /^(?:[›❯]\s*)?(?:Find and fix a bug in @filename|Improve documentation in @filename|Write tests for @filename|Explain this codebase|Summarize recent commits|Implement \{feature\}|Use \/skills(?: to list available skills)?|Run \/review on my current changes)$/i;
2707
2778
  ChatHistoryWriter = class {
2708
2779
  /** Last seen message count per agent (deduplication) */
2709
2780
  lastSeenCounts = /* @__PURE__ */ new Map();
2710
2781
  /** Last seen message hash per agent (deduplication) */
2711
2782
  lastSeenHashes = /* @__PURE__ */ new Map();
2783
+ /** Last appended normalized message signature per agent/session */
2784
+ lastSeenSignatures = /* @__PURE__ */ new Map();
2785
+ /** Last appended normalized non-system turn signature per agent/session */
2786
+ lastSeenTurnSignatures = /* @__PURE__ */ new Map();
2712
2787
  rotated = false;
2713
2788
  /**
2714
2789
  * Append new messages to history
@@ -2730,14 +2805,36 @@ var init_chat_history = __esm({
2730
2805
  }
2731
2806
  const newMessages = [];
2732
2807
  for (const msg of messages) {
2733
- const hash2 = msg.historyDedupKey || `${msg.kind || "standard"}:${msg.role}:${(msg.content || "").slice(0, 50)}`;
2808
+ const role = msg.role;
2809
+ if (role !== "user" && role !== "assistant" && role !== "system") continue;
2810
+ const content = cleanupHistoryContent(agentType, role, msg.content || "");
2811
+ if (!content) continue;
2812
+ const receivedAt = msg.receivedAt || Date.now();
2813
+ const hash2 = buildHistoryMessageHash(agentType, {
2814
+ role,
2815
+ content,
2816
+ receivedAt,
2817
+ kind: typeof msg.kind === "string" ? msg.kind : void 0,
2818
+ historyDedupKey: msg.historyDedupKey
2819
+ });
2820
+ const signature = buildHistoryMessageSignature(agentType, {
2821
+ role,
2822
+ content,
2823
+ kind: typeof msg.kind === "string" ? msg.kind : void 0
2824
+ });
2734
2825
  if (seenHashes.has(hash2)) continue;
2826
+ if (this.lastSeenSignatures.get(dedupKey) === signature) continue;
2827
+ if (role !== "system" && this.lastSeenTurnSignatures.get(dedupKey) === signature) continue;
2735
2828
  seenHashes.add(hash2);
2829
+ this.lastSeenSignatures.set(dedupKey, signature);
2830
+ if (role !== "system") {
2831
+ this.lastSeenTurnSignatures.set(dedupKey, signature);
2832
+ }
2736
2833
  newMessages.push({
2737
- ts: new Date(msg.receivedAt || Date.now()).toISOString(),
2738
- receivedAt: msg.receivedAt || Date.now(),
2739
- role: msg.role,
2740
- content: msg.content || "",
2834
+ ts: new Date(receivedAt).toISOString(),
2835
+ receivedAt,
2836
+ role,
2837
+ content,
2741
2838
  kind: typeof msg.kind === "string" ? msg.kind : void 0,
2742
2839
  senderName: typeof msg.senderName === "string" ? msg.senderName : void 0,
2743
2840
  agent: agentType,
@@ -2757,6 +2854,8 @@ var init_chat_history = __esm({
2757
2854
  const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
2758
2855
  if (messages.length < prevCount * 0.5 && prevCount > 3) {
2759
2856
  seenHashes.clear();
2857
+ this.lastSeenSignatures.delete(dedupKey);
2858
+ this.lastSeenTurnSignatures.delete(dedupKey);
2760
2859
  for (const msg of messages) {
2761
2860
  seenHashes.add(msg.historyDedupKey || `${msg.kind || "standard"}:${msg.role}:${(msg.content || "").slice(0, 50)}`);
2762
2861
  }
@@ -2770,6 +2869,54 @@ var init_chat_history = __esm({
2770
2869
  } catch {
2771
2870
  }
2772
2871
  }
2872
+ seedSessionHistory(agentType, messages = [], historySessionId, instanceId) {
2873
+ const effectiveHistoryKey = historySessionId || instanceId;
2874
+ const dedupKey = effectiveHistoryKey ? `${agentType}:${effectiveHistoryKey}` : agentType;
2875
+ const seenHashes = /* @__PURE__ */ new Set();
2876
+ for (const raw of messages) {
2877
+ const role = raw?.role;
2878
+ if (role !== "user" && role !== "assistant" && role !== "system") continue;
2879
+ const content = cleanupHistoryContent(agentType, role, raw?.content || "");
2880
+ if (!content) continue;
2881
+ seenHashes.add(buildHistoryMessageHash(agentType, {
2882
+ role,
2883
+ content,
2884
+ receivedAt: raw?.receivedAt || 0,
2885
+ kind: typeof raw?.kind === "string" ? raw.kind : void 0,
2886
+ historyDedupKey: raw?.historyDedupKey
2887
+ }));
2888
+ }
2889
+ this.lastSeenHashes.set(dedupKey, seenHashes);
2890
+ this.lastSeenCounts.set(dedupKey, messages.length);
2891
+ const lastMessage = [...messages].reverse().find((raw) => {
2892
+ const role = raw?.role;
2893
+ if (role !== "user" && role !== "assistant" && role !== "system") return false;
2894
+ return !!cleanupHistoryContent(agentType, role, raw?.content || "");
2895
+ });
2896
+ const lastTurnMessage = [...messages].reverse().find((raw) => {
2897
+ const role = raw?.role;
2898
+ if (role !== "user" && role !== "assistant") return false;
2899
+ return !!cleanupHistoryContent(agentType, role, raw?.content || "");
2900
+ });
2901
+ if (lastMessage) {
2902
+ this.lastSeenSignatures.set(dedupKey, buildHistoryMessageSignature(agentType, {
2903
+ role: lastMessage.role,
2904
+ content: lastMessage.content,
2905
+ kind: typeof lastMessage.kind === "string" ? lastMessage.kind : void 0
2906
+ }));
2907
+ } else {
2908
+ this.lastSeenSignatures.delete(dedupKey);
2909
+ }
2910
+ if (lastTurnMessage) {
2911
+ this.lastSeenTurnSignatures.set(dedupKey, buildHistoryMessageSignature(agentType, {
2912
+ role: lastTurnMessage.role,
2913
+ content: lastTurnMessage.content,
2914
+ kind: typeof lastTurnMessage.kind === "string" ? lastTurnMessage.kind : void 0
2915
+ }));
2916
+ } else {
2917
+ this.lastSeenTurnSignatures.delete(dedupKey);
2918
+ }
2919
+ }
2773
2920
  appendSystemMarker(agentType, content, options = {}) {
2774
2921
  this.appendNewMessages(
2775
2922
  agentType,
@@ -2800,6 +2947,16 @@ var init_chat_history = __esm({
2800
2947
  this.lastSeenHashes.set(toDedupKey, nextHashes);
2801
2948
  this.lastSeenHashes.delete(fromDedupKey);
2802
2949
  }
2950
+ const fromSignature = this.lastSeenSignatures.get(fromDedupKey);
2951
+ if (fromSignature) {
2952
+ this.lastSeenSignatures.set(toDedupKey, fromSignature);
2953
+ this.lastSeenSignatures.delete(fromDedupKey);
2954
+ }
2955
+ const fromTurnSignature = this.lastSeenTurnSignatures.get(fromDedupKey);
2956
+ if (fromTurnSignature) {
2957
+ this.lastSeenTurnSignatures.set(toDedupKey, fromTurnSignature);
2958
+ this.lastSeenTurnSignatures.delete(fromDedupKey);
2959
+ }
2803
2960
  const fromCount = this.lastSeenCounts.get(fromDedupKey);
2804
2961
  if (typeof fromCount === "number") {
2805
2962
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
@@ -2841,10 +2998,61 @@ var init_chat_history = __esm({
2841
2998
  } catch {
2842
2999
  }
2843
3000
  }
3001
+ compactHistorySession(agentType, historySessionId) {
3002
+ const sessionId = String(historySessionId || "").trim();
3003
+ if (!sessionId) return;
3004
+ try {
3005
+ const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
3006
+ if (!fs3.existsSync(dir)) return;
3007
+ const prefix = `${this.sanitize(sessionId)}_`;
3008
+ const files = fs3.readdirSync(dir).filter((file2) => file2.startsWith(prefix) && file2.endsWith(".jsonl")).sort();
3009
+ const seen = /* @__PURE__ */ new Set();
3010
+ for (const file2 of files) {
3011
+ const filePath = path7.join(dir, file2);
3012
+ const lines = fs3.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
3013
+ const next = [];
3014
+ for (const line of lines) {
3015
+ let parsed = null;
3016
+ try {
3017
+ parsed = JSON.parse(line);
3018
+ } catch {
3019
+ parsed = null;
3020
+ }
3021
+ if (!parsed || parsed.historySessionId !== sessionId) continue;
3022
+ const sanitized = sanitizeHistoryMessage(agentType, parsed);
3023
+ if (!sanitized) continue;
3024
+ const hash2 = buildHistoryMessageHash(agentType, sanitized);
3025
+ if (seen.has(hash2)) continue;
3026
+ seen.add(hash2);
3027
+ next.push(sanitized);
3028
+ }
3029
+ next.sort((a, b) => a.receivedAt - b.receivedAt);
3030
+ const dedupedAdjacent = [];
3031
+ let lastTurn = null;
3032
+ for (const entry of next) {
3033
+ const previous = dedupedAdjacent[dedupedAdjacent.length - 1];
3034
+ if (isAdjacentHistoryDuplicate(agentType, previous, entry)) continue;
3035
+ if (entry.role !== "system" && isAdjacentHistoryDuplicate(agentType, lastTurn, entry)) continue;
3036
+ dedupedAdjacent.push(entry);
3037
+ if (entry.role !== "system") lastTurn = entry;
3038
+ }
3039
+ const collapsed = collapseReplayAssistantTurns(agentType, dedupedAdjacent);
3040
+ if (collapsed.length === 0) {
3041
+ fs3.unlinkSync(filePath);
3042
+ continue;
3043
+ }
3044
+ fs3.writeFileSync(filePath, `${collapsed.map((entry) => JSON.stringify(entry)).join("\n")}
3045
+ `, "utf-8");
3046
+ }
3047
+ } catch {
3048
+ }
3049
+ }
2844
3050
  /** Called when agent session is explicitly changed */
2845
3051
  onSessionChange(agentType) {
2846
3052
  this.lastSeenHashes.delete(agentType);
2847
3053
  this.lastSeenCounts.delete(agentType);
3054
+ this.lastSeenSignatures.delete(agentType);
3055
+ this.lastSeenTurnSignatures.delete(agentType);
2848
3056
  }
2849
3057
  /** Delete history files older than 30 days */
2850
3058
  async rotateOldFiles() {
@@ -4713,6 +4921,46 @@ function didProviderConfirmSend(result) {
4713
4921
  if (!parsed || typeof parsed !== "object") return false;
4714
4922
  return parsed.sent === true || parsed.success === true || parsed.ok === true || parsed.submitted === true || parsed.dispatched === true;
4715
4923
  }
4924
+ async function readExtensionChatState(h) {
4925
+ try {
4926
+ const evalResult = await h.evaluateProviderScript("readChat", void 0, 5e4);
4927
+ if (!evalResult?.result) return null;
4928
+ const parsed = parseMaybeJson(evalResult.result);
4929
+ return parsed && typeof parsed === "object" ? parsed : null;
4930
+ } catch {
4931
+ return null;
4932
+ }
4933
+ }
4934
+ function getStateMessageCount(state) {
4935
+ return Array.isArray(state?.messages) ? state.messages.length : 0;
4936
+ }
4937
+ function getStateLastSignature(state) {
4938
+ const messages = Array.isArray(state?.messages) ? state.messages : [];
4939
+ const last = messages[messages.length - 1];
4940
+ if (!last) return "";
4941
+ return `${last.role || ""}:${String(last.content || "").replace(/\s+/g, " ").trim()}`;
4942
+ }
4943
+ async function getStableExtensionBaseline(h) {
4944
+ const first = await readExtensionChatState(h);
4945
+ if (getStateMessageCount(first) > 0 || getStateLastSignature(first)) return first;
4946
+ await new Promise((resolve17) => setTimeout(resolve17, 150));
4947
+ const second = await readExtensionChatState(h);
4948
+ return getStateMessageCount(second) >= getStateMessageCount(first) ? second : first;
4949
+ }
4950
+ async function verifyExtensionSendObserved(h, before) {
4951
+ const beforeCount = getStateMessageCount(before);
4952
+ const beforeSignature = getStateLastSignature(before);
4953
+ for (let attempt = 0; attempt < 12; attempt += 1) {
4954
+ await new Promise((resolve17) => setTimeout(resolve17, 250));
4955
+ const state = await readExtensionChatState(h);
4956
+ if (state?.status === "waiting_approval") return true;
4957
+ const afterCount = getStateMessageCount(state);
4958
+ const afterSignature = getStateLastSignature(state);
4959
+ if (afterCount > beforeCount) return true;
4960
+ if (afterSignature && afterSignature !== beforeSignature) return true;
4961
+ }
4962
+ return false;
4963
+ }
4716
4964
  async function handleChatHistory(h, args) {
4717
4965
  const { agentType, offset, limit } = args;
4718
4966
  const historySessionId = getHistorySessionId(h, args);
@@ -4893,12 +5141,17 @@ async function handleSendChat(h, args) {
4893
5141
  if (isExtensionTransport(transport)) {
4894
5142
  _log(`Extension: ${provider?.type || "unknown_extension"}`);
4895
5143
  try {
5144
+ const beforeState = await getStableExtensionBaseline(h);
4896
5145
  const evalResult = await h.evaluateProviderScript("sendMessage", { message: text }, 3e4);
4897
5146
  if (evalResult?.result) {
4898
5147
  const parsed = parseMaybeJson(evalResult.result);
4899
5148
  if (didProviderConfirmSend(parsed)) {
4900
- _log(`Extension script sent OK`);
4901
- return _logSendSuccess("extension-script");
5149
+ const observed = await verifyExtensionSendObserved(h, beforeState);
5150
+ if (observed) {
5151
+ _log(`Extension script sent OK`);
5152
+ return _logSendSuccess("extension-script");
5153
+ }
5154
+ _log(`Extension script reported send but no chat-state change was observed`);
4902
5155
  }
4903
5156
  if (parsed?.needsTypeAndSend) {
4904
5157
  _log(`Extension needsTypeAndSend \u2192 AgentStreamManager`);
@@ -5403,7 +5656,7 @@ async function handleResolveAction(h, args) {
5403
5656
  return { success: true, buttonIndex, button: buttons[buttonIndex] ?? button };
5404
5657
  }
5405
5658
  if (isExtensionTransport(transport) && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
5406
- const ok = await h.agentStream.resolveSessionAction(h.getCdp(), h.currentSession.sessionId, action);
5659
+ const ok = await h.agentStream.resolveSessionAction(h.getCdp(), h.currentSession.sessionId, action, button);
5407
5660
  return { success: ok };
5408
5661
  }
5409
5662
  if (transport === "acp") {
@@ -7188,10 +7441,12 @@ function sanitizeSpawnEnv(baseEnv, overrides) {
7188
7441
  env[key] = value;
7189
7442
  }
7190
7443
  for (const key of Object.keys(env)) {
7191
- if (key === "INIT_CWD" || key === "npm_command" || key === "npm_execpath" || key === "npm_node_execpath" || key.startsWith("npm_") || key.startsWith("npm_config_") || key.startsWith("npm_package_") || key.startsWith("npm_lifecycle_") || key.startsWith("PNPM_") || key.startsWith("YARN_") || key.startsWith("BUN_")) {
7444
+ if (key === "INIT_CWD" || key === "npm_command" || key === "npm_execpath" || key === "npm_node_execpath" || key.startsWith("npm_") || key.startsWith("npm_config_") || key.startsWith("npm_package_") || key.startsWith("npm_lifecycle_") || key.startsWith("PNPM_") || key.startsWith("YARN_") || key.startsWith("BUN_") || key.startsWith("VSCODE_") || key.startsWith("ELECTRON_")) {
7192
7445
  delete env[key];
7193
7446
  }
7194
7447
  }
7448
+ delete env.CODEX_THREAD_ID;
7449
+ delete env.CODEX_INTERNAL_ORIGINATOR_OVERRIDE;
7195
7450
  applyTerminalColorEnv(env);
7196
7451
  return env;
7197
7452
  }
@@ -7209,14 +7464,14 @@ function applyTerminalColorEnv(env) {
7209
7464
  function ensureNodePtySpawnHelperPermissions(logFn) {
7210
7465
  if (os22.platform() === "win32") return;
7211
7466
  try {
7212
- const fs19 = __require("fs");
7467
+ const fs20 = __require("fs");
7213
7468
  const ptyDir = path32.resolve(path32.dirname(__require.resolve("node-pty")), "..");
7214
7469
  const platformArch = `${os22.platform()}-${os22.arch()}`;
7215
7470
  const helper = path32.join(ptyDir, "prebuilds", platformArch, "spawn-helper");
7216
- if (fs19.existsSync(helper)) {
7217
- const stat4 = fs19.statSync(helper);
7471
+ if (fs20.existsSync(helper)) {
7472
+ const stat4 = fs20.statSync(helper);
7218
7473
  if (!(stat4.mode & 73)) {
7219
- fs19.chmodSync(helper, stat4.mode | 493);
7474
+ fs20.chmodSync(helper, stat4.mode | 493);
7220
7475
  logFn?.(`Fixed spawn-helper permissions: ${helper}`);
7221
7476
  }
7222
7477
  }
@@ -7493,6 +7748,9 @@ var init_dist = __esm({
7493
7748
  state.record.lastActivityAt = Date.now();
7494
7749
  return this.cloneRecord(state.record);
7495
7750
  }
7751
+ deleteSession(sessionId) {
7752
+ return this.sessions.delete(sessionId);
7753
+ }
7496
7754
  requireSession(sessionId) {
7497
7755
  const state = this.sessions.get(sessionId);
7498
7756
  if (!state) throw new Error(`Unknown session: ${sessionId}`);
@@ -7682,8 +7940,8 @@ var init_pty_transport = __esm({
7682
7940
  let cwd = options.cwd;
7683
7941
  if (cwd) {
7684
7942
  try {
7685
- const fs19 = require("fs");
7686
- const stat4 = fs19.statSync(cwd);
7943
+ const fs20 = require("fs");
7944
+ const stat4 = fs20.statSync(cwd);
7687
7945
  if (!stat4.isDirectory()) cwd = os8.homedir();
7688
7946
  } catch {
7689
7947
  cwd = os8.homedir();
@@ -7794,12 +8052,12 @@ function findBinary(name) {
7794
8052
  function isScriptBinary(binaryPath) {
7795
8053
  if (!path10.isAbsolute(binaryPath)) return false;
7796
8054
  try {
7797
- const fs19 = require("fs");
7798
- const resolved = fs19.realpathSync(binaryPath);
8055
+ const fs20 = require("fs");
8056
+ const resolved = fs20.realpathSync(binaryPath);
7799
8057
  const head = Buffer.alloc(8);
7800
- const fd = fs19.openSync(resolved, "r");
7801
- fs19.readSync(fd, head, 0, 8, 0);
7802
- fs19.closeSync(fd);
8058
+ const fd = fs20.openSync(resolved, "r");
8059
+ fs20.readSync(fd, head, 0, 8, 0);
8060
+ fs20.closeSync(fd);
7803
8061
  let i = 0;
7804
8062
  if (head[0] === 239 && head[1] === 187 && head[2] === 191) i = 3;
7805
8063
  return head[i] === 35 && head[i + 1] === 33;
@@ -7810,12 +8068,12 @@ function isScriptBinary(binaryPath) {
7810
8068
  function looksLikeMachOOrElf(filePath) {
7811
8069
  if (!path10.isAbsolute(filePath)) return false;
7812
8070
  try {
7813
- const fs19 = require("fs");
7814
- const resolved = fs19.realpathSync(filePath);
8071
+ const fs20 = require("fs");
8072
+ const resolved = fs20.realpathSync(filePath);
7815
8073
  const buf = Buffer.alloc(8);
7816
- const fd = fs19.openSync(resolved, "r");
7817
- fs19.readSync(fd, buf, 0, 8, 0);
7818
- fs19.closeSync(fd);
8074
+ const fd = fs20.openSync(resolved, "r");
8075
+ fs20.readSync(fd, buf, 0, 8, 0);
8076
+ fs20.closeSync(fd);
7819
8077
  let i = 0;
7820
8078
  if (buf[0] === 239 && buf[1] === 187 && buf[2] === 191) i = 3;
7821
8079
  const b = buf.subarray(i);
@@ -8547,6 +8805,9 @@ var init_provider_cli_adapter = __esm({
8547
8805
  looksLikeVisibleIdlePrompt(screenText) {
8548
8806
  const text = String(screenText || "");
8549
8807
  if (!text.trim()) return false;
8808
+ if (this.cliType === "codex-cli" && /(^|\n)\s*[❯›>]\s+(?:Find and fix a bug in @filename|Improve documentation in @filename|Use \/skills|Write tests for @filename|Explain this codebase|Summarize recent commits|Implement \{feature\}|Run \/review on my current changes)(?:\n|$)/im.test(text)) {
8809
+ return true;
8810
+ }
8550
8811
  return /(^|\n)\s*[❯›>]\s*(?:\n|$)/m.test(text) || /⏎\s+send/i.test(text) || /\?\s*for\s*shortcuts/i.test(text) || /Type your message(?:\s+or\s+@path\/to\/file)?/i.test(text) || /workspace\s*\(\/directory\)/i.test(text) || /for\s*shortcuts/i.test(text);
8551
8812
  }
8552
8813
  findLastMatchingLineIndex(lines, predicate) {
@@ -9765,6 +10026,7 @@ var init_cli_provider_instance = __esm({
9765
10026
  historyWriter;
9766
10027
  runtimeMessages = [];
9767
10028
  instanceId;
10029
+ suppressIdleHistoryReplay = false;
9768
10030
  presentationMode;
9769
10031
  providerSessionId;
9770
10032
  launchMode;
@@ -9792,7 +10054,15 @@ var init_cli_provider_instance = __esm({
9792
10054
  await this.adapter.spawn();
9793
10055
  this.maybeAppendRuntimeRecoveryMessage(this.adapter.getRuntimeMetadata());
9794
10056
  if (this.providerSessionId) {
10057
+ this.historyWriter.compactHistorySession(this.type, this.providerSessionId);
9795
10058
  const restoredHistory = readChatHistory(this.type, 0, 200, this.providerSessionId);
10059
+ this.historyWriter.seedSessionHistory(
10060
+ this.type,
10061
+ restoredHistory.messages,
10062
+ this.providerSessionId,
10063
+ this.instanceId
10064
+ );
10065
+ this.suppressIdleHistoryReplay = restoredHistory.messages.length > 0;
9796
10066
  if (restoredHistory.messages.length > 0) {
9797
10067
  this.adapter.seedCommittedMessages(
9798
10068
  restoredHistory.messages.map((message) => ({
@@ -9836,7 +10106,7 @@ var init_cli_provider_instance = __esm({
9836
10106
  } else if (this.type === "codex-cli") {
9837
10107
  probedSessionId = this.probeSessionIdFromConfig({
9838
10108
  dbPath: "~/.codex/state_5.sqlite",
9839
- query: "select id from threads where cwd in ({dirs}) and created_at >= ? and archived = 0 order by created_at desc limit 1",
10109
+ query: "select id from threads where cwd in ({dirs}) and updated_at >= ? and archived = 0 order by updated_at desc limit 1",
9840
10110
  timestampFormat: "unix_s"
9841
10111
  });
9842
10112
  } else if (this.type === "goose-cli") {
@@ -9896,6 +10166,7 @@ var init_cli_provider_instance = __esm({
9896
10166
  const mergedMessages = this.mergeConversationMessages(parsedMessages);
9897
10167
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
9898
10168
  if (parsedMessages.length > 0) {
10169
+ const shouldSkipReplayPersist = this.suppressIdleHistoryReplay && adapterStatus.status === "idle" && parsedStatus?.status === "idle";
9899
10170
  let messagesToSave = parsedMessages;
9900
10171
  if (parsedStatus?.status === "generating" || parsedStatus?.status === "long_generating") {
9901
10172
  const lastIdx = messagesToSave.length - 1;
@@ -9903,7 +10174,7 @@ var init_cli_provider_instance = __esm({
9903
10174
  messagesToSave = messagesToSave.slice(0, lastIdx);
9904
10175
  }
9905
10176
  }
9906
- if (messagesToSave.length > 0) {
10177
+ if (!shouldSkipReplayPersist && messagesToSave.length > 0) {
9907
10178
  this.historyWriter.appendNewMessages(
9908
10179
  this.type,
9909
10180
  messagesToSave,
@@ -9998,6 +10269,7 @@ var init_cli_provider_instance = __esm({
9998
10269
  if (newStatus !== this.lastStatus) {
9999
10270
  LOG.info("CLI", `[${this.type}] status: ${this.lastStatus} \u2192 ${newStatus}`);
10000
10271
  if (this.lastStatus === "idle" && newStatus === "generating") {
10272
+ this.suppressIdleHistoryReplay = false;
10001
10273
  if (this.completedDebouncePending) {
10002
10274
  LOG.info("CLI", `[${this.type}] cancelled pending completed (resumed generating)`);
10003
10275
  if (this.completedDebounceTimer) {
@@ -10017,6 +10289,7 @@ var init_cli_provider_instance = __esm({
10017
10289
  this.generatingDebounceTimer = null;
10018
10290
  }, 1e3);
10019
10291
  } else if (newStatus === "waiting_approval") {
10292
+ this.suppressIdleHistoryReplay = false;
10020
10293
  if (this.generatingDebouncePending) {
10021
10294
  if (this.generatingDebounceTimer) {
10022
10295
  clearTimeout(this.generatingDebounceTimer);
@@ -10592,10 +10865,10 @@ function mergeDefs(...defs) {
10592
10865
  function cloneDef(schema) {
10593
10866
  return mergeDefs(schema._zod.def);
10594
10867
  }
10595
- function getElementAtPath(obj, path27) {
10596
- if (!path27)
10868
+ function getElementAtPath(obj, path28) {
10869
+ if (!path28)
10597
10870
  return obj;
10598
- return path27.reduce((acc, key) => acc?.[key], obj);
10871
+ return path28.reduce((acc, key) => acc?.[key], obj);
10599
10872
  }
10600
10873
  function promiseAllObject(promisesObj) {
10601
10874
  const keys = Object.keys(promisesObj);
@@ -10907,11 +11180,11 @@ function aborted(x, startIndex = 0) {
10907
11180
  }
10908
11181
  return false;
10909
11182
  }
10910
- function prefixIssues(path27, issues) {
11183
+ function prefixIssues(path28, issues) {
10911
11184
  return issues.map((iss) => {
10912
11185
  var _a2;
10913
11186
  (_a2 = iss).path ?? (_a2.path = []);
10914
- iss.path.unshift(path27);
11187
+ iss.path.unshift(path28);
10915
11188
  return iss;
10916
11189
  });
10917
11190
  }
@@ -11154,7 +11427,7 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
11154
11427
  }
11155
11428
  function treeifyError(error48, mapper = (issue2) => issue2.message) {
11156
11429
  const result = { errors: [] };
11157
- const processError = (error49, path27 = []) => {
11430
+ const processError = (error49, path28 = []) => {
11158
11431
  var _a2, _b;
11159
11432
  for (const issue2 of error49.issues) {
11160
11433
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -11164,7 +11437,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
11164
11437
  } else if (issue2.code === "invalid_element") {
11165
11438
  processError({ issues: issue2.issues }, issue2.path);
11166
11439
  } else {
11167
- const fullpath = [...path27, ...issue2.path];
11440
+ const fullpath = [...path28, ...issue2.path];
11168
11441
  if (fullpath.length === 0) {
11169
11442
  result.errors.push(mapper(issue2));
11170
11443
  continue;
@@ -11196,8 +11469,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
11196
11469
  }
11197
11470
  function toDotPath(_path) {
11198
11471
  const segs = [];
11199
- const path27 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
11200
- for (const seg of path27) {
11472
+ const path28 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
11473
+ for (const seg of path28) {
11201
11474
  if (typeof seg === "number")
11202
11475
  segs.push(`[${seg}]`);
11203
11476
  else if (typeof seg === "symbol")
@@ -23961,13 +24234,13 @@ function resolveRef(ref, ctx) {
23961
24234
  if (!ref.startsWith("#")) {
23962
24235
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
23963
24236
  }
23964
- const path27 = ref.slice(1).split("/").filter(Boolean);
23965
- if (path27.length === 0) {
24237
+ const path28 = ref.slice(1).split("/").filter(Boolean);
24238
+ if (path28.length === 0) {
23966
24239
  return ctx.rootSchema;
23967
24240
  }
23968
24241
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
23969
- if (path27[0] === defsKey) {
23970
- const key = path27[1];
24242
+ if (path28[0] === defsKey) {
24243
+ const key = path28[1];
23971
24244
  if (!key || !ctx.defs[key]) {
23972
24245
  throw new Error(`Reference not found: ${ref}`);
23973
24246
  }
@@ -27835,8 +28108,8 @@ var init_cli_manager = __esm({
27835
28108
  const spawnCmd = provider.spawn?.command;
27836
28109
  if (spawnCmd) {
27837
28110
  try {
27838
- const { execSync: execSync7 } = require("child_process");
27839
- execSync7(`which ${spawnCmd}`, { stdio: "ignore" });
28111
+ const { execSync: execSync8 } = require("child_process");
28112
+ execSync8(`which ${spawnCmd}`, { stdio: "ignore" });
27840
28113
  } catch {
27841
28114
  const installInfo = provider.install || `Install: check ${provider.displayName || provider.name} documentation`;
27842
28115
  throw new Error(
@@ -28060,6 +28333,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
28060
28333
  if (!instanceManager) return 0;
28061
28334
  const sessions = records || await this.deps.listHostedCliRuntimes?.() || [];
28062
28335
  let restored = 0;
28336
+ const restoredBindings = /* @__PURE__ */ new Set();
28063
28337
  for (const record2 of sessions) {
28064
28338
  if (!record2?.runtimeId || !record2?.cliType || !record2?.workspace) continue;
28065
28339
  if (this.adapters.has(record2.runtimeId) || instanceManager.getInstance(record2.runtimeId)) continue;
@@ -28073,6 +28347,18 @@ Run 'adhdev doctor' for detailed diagnostics.`
28073
28347
  record2.cliArgs,
28074
28348
  record2.providerSessionId
28075
28349
  );
28350
+ const bindingKey = [
28351
+ normalizedType,
28352
+ record2.workspace,
28353
+ sessionBinding.providerSessionId || record2.runtimeId
28354
+ ].join("::");
28355
+ if (restoredBindings.has(bindingKey)) {
28356
+ LOG.info(
28357
+ "CLI",
28358
+ `\u21B7 Skipping duplicate hosted runtime restore: ${record2.runtimeKey || record2.runtimeId} (${normalizedType} @ ${record2.workspace}) binding=${sessionBinding.providerSessionId || "runtime"}`
28359
+ );
28360
+ continue;
28361
+ }
28076
28362
  try {
28077
28363
  await this.registerCliInstance(
28078
28364
  record2.runtimeId,
@@ -28088,6 +28374,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
28088
28374
  launchMode: "manual"
28089
28375
  }
28090
28376
  );
28377
+ restoredBindings.add(bindingKey);
28091
28378
  restored += 1;
28092
28379
  LOG.info("CLI", `\u267B Restored hosted runtime: ${record2.runtimeKey || record2.runtimeId} (${record2.displayName || record2.workspace})`);
28093
28380
  } catch (error48) {
@@ -28376,7 +28663,7 @@ var init_readdirp = __esm({
28376
28663
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
28377
28664
  const statMethod = opts.lstat ? import_promises.lstat : import_promises.stat;
28378
28665
  if (wantBigintFsStats) {
28379
- this._stat = (path27) => statMethod(path27, { bigint: true });
28666
+ this._stat = (path28) => statMethod(path28, { bigint: true });
28380
28667
  } else {
28381
28668
  this._stat = statMethod;
28382
28669
  }
@@ -28401,8 +28688,8 @@ var init_readdirp = __esm({
28401
28688
  const par = this.parent;
28402
28689
  const fil = par && par.files;
28403
28690
  if (fil && fil.length > 0) {
28404
- const { path: path27, depth } = par;
28405
- const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path27));
28691
+ const { path: path28, depth } = par;
28692
+ const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path28));
28406
28693
  const awaited = await Promise.all(slice);
28407
28694
  for (const entry of awaited) {
28408
28695
  if (!entry)
@@ -28442,20 +28729,20 @@ var init_readdirp = __esm({
28442
28729
  this.reading = false;
28443
28730
  }
28444
28731
  }
28445
- async _exploreDir(path27, depth) {
28732
+ async _exploreDir(path28, depth) {
28446
28733
  let files;
28447
28734
  try {
28448
- files = await (0, import_promises.readdir)(path27, this._rdOptions);
28735
+ files = await (0, import_promises.readdir)(path28, this._rdOptions);
28449
28736
  } catch (error48) {
28450
28737
  this._onError(error48);
28451
28738
  }
28452
- return { files, depth, path: path27 };
28739
+ return { files, depth, path: path28 };
28453
28740
  }
28454
- async _formatEntry(dirent, path27) {
28741
+ async _formatEntry(dirent, path28) {
28455
28742
  let entry;
28456
28743
  const basename8 = this._isDirent ? dirent.name : dirent;
28457
28744
  try {
28458
- const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path27, basename8));
28745
+ const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path28, basename8));
28459
28746
  entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename8 };
28460
28747
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
28461
28748
  } catch (err) {
@@ -28512,16 +28799,16 @@ var init_readdirp = __esm({
28512
28799
  });
28513
28800
 
28514
28801
  // ../../oss/packages/daemon-core/node_modules/chokidar/handler.js
28515
- function createFsWatchInstance(path27, options, listener, errHandler, emitRaw) {
28802
+ function createFsWatchInstance(path28, options, listener, errHandler, emitRaw) {
28516
28803
  const handleEvent = (rawEvent, evPath) => {
28517
- listener(path27);
28518
- emitRaw(rawEvent, evPath, { watchedPath: path27 });
28519
- if (evPath && path27 !== evPath) {
28520
- fsWatchBroadcast(sp.resolve(path27, evPath), KEY_LISTENERS, sp.join(path27, evPath));
28804
+ listener(path28);
28805
+ emitRaw(rawEvent, evPath, { watchedPath: path28 });
28806
+ if (evPath && path28 !== evPath) {
28807
+ fsWatchBroadcast(sp.resolve(path28, evPath), KEY_LISTENERS, sp.join(path28, evPath));
28521
28808
  }
28522
28809
  };
28523
28810
  try {
28524
- return (0, import_node_fs.watch)(path27, {
28811
+ return (0, import_node_fs.watch)(path28, {
28525
28812
  persistent: options.persistent
28526
28813
  }, handleEvent);
28527
28814
  } catch (error48) {
@@ -28870,12 +29157,12 @@ var init_handler2 = __esm({
28870
29157
  listener(val1, val2, val3);
28871
29158
  });
28872
29159
  };
28873
- setFsWatchListener = (path27, fullPath, options, handlers) => {
29160
+ setFsWatchListener = (path28, fullPath, options, handlers) => {
28874
29161
  const { listener, errHandler, rawEmitter } = handlers;
28875
29162
  let cont = FsWatchInstances.get(fullPath);
28876
29163
  let watcher;
28877
29164
  if (!options.persistent) {
28878
- watcher = createFsWatchInstance(path27, options, listener, errHandler, rawEmitter);
29165
+ watcher = createFsWatchInstance(path28, options, listener, errHandler, rawEmitter);
28879
29166
  if (!watcher)
28880
29167
  return;
28881
29168
  return watcher.close.bind(watcher);
@@ -28886,7 +29173,7 @@ var init_handler2 = __esm({
28886
29173
  addAndConvert(cont, KEY_RAW, rawEmitter);
28887
29174
  } else {
28888
29175
  watcher = createFsWatchInstance(
28889
- path27,
29176
+ path28,
28890
29177
  options,
28891
29178
  fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
28892
29179
  errHandler,
@@ -28901,7 +29188,7 @@ var init_handler2 = __esm({
28901
29188
  cont.watcherUnusable = true;
28902
29189
  if (isWindows && error48.code === "EPERM") {
28903
29190
  try {
28904
- const fd = await (0, import_promises2.open)(path27, "r");
29191
+ const fd = await (0, import_promises2.open)(path28, "r");
28905
29192
  await fd.close();
28906
29193
  broadcastErr(error48);
28907
29194
  } catch (err) {
@@ -28932,7 +29219,7 @@ var init_handler2 = __esm({
28932
29219
  };
28933
29220
  };
28934
29221
  FsWatchFileInstances = /* @__PURE__ */ new Map();
28935
- setFsWatchFileListener = (path27, fullPath, options, handlers) => {
29222
+ setFsWatchFileListener = (path28, fullPath, options, handlers) => {
28936
29223
  const { listener, rawEmitter } = handlers;
28937
29224
  let cont = FsWatchFileInstances.get(fullPath);
28938
29225
  const copts = cont && cont.options;
@@ -28954,7 +29241,7 @@ var init_handler2 = __esm({
28954
29241
  });
28955
29242
  const currmtime = curr.mtimeMs;
28956
29243
  if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
28957
- foreach(cont.listeners, (listener2) => listener2(path27, curr));
29244
+ foreach(cont.listeners, (listener2) => listener2(path28, curr));
28958
29245
  }
28959
29246
  })
28960
29247
  };
@@ -28984,13 +29271,13 @@ var init_handler2 = __esm({
28984
29271
  * @param listener on fs change
28985
29272
  * @returns closer for the watcher instance
28986
29273
  */
28987
- _watchWithNodeFs(path27, listener) {
29274
+ _watchWithNodeFs(path28, listener) {
28988
29275
  const opts = this.fsw.options;
28989
- const directory = sp.dirname(path27);
28990
- const basename8 = sp.basename(path27);
29276
+ const directory = sp.dirname(path28);
29277
+ const basename8 = sp.basename(path28);
28991
29278
  const parent = this.fsw._getWatchedDir(directory);
28992
29279
  parent.add(basename8);
28993
- const absolutePath = sp.resolve(path27);
29280
+ const absolutePath = sp.resolve(path28);
28994
29281
  const options = {
28995
29282
  persistent: opts.persistent
28996
29283
  };
@@ -29000,12 +29287,12 @@ var init_handler2 = __esm({
29000
29287
  if (opts.usePolling) {
29001
29288
  const enableBin = opts.interval !== opts.binaryInterval;
29002
29289
  options.interval = enableBin && isBinaryPath(basename8) ? opts.binaryInterval : opts.interval;
29003
- closer = setFsWatchFileListener(path27, absolutePath, options, {
29290
+ closer = setFsWatchFileListener(path28, absolutePath, options, {
29004
29291
  listener,
29005
29292
  rawEmitter: this.fsw._emitRaw
29006
29293
  });
29007
29294
  } else {
29008
- closer = setFsWatchListener(path27, absolutePath, options, {
29295
+ closer = setFsWatchListener(path28, absolutePath, options, {
29009
29296
  listener,
29010
29297
  errHandler: this._boundHandleError,
29011
29298
  rawEmitter: this.fsw._emitRaw
@@ -29027,7 +29314,7 @@ var init_handler2 = __esm({
29027
29314
  let prevStats = stats;
29028
29315
  if (parent.has(basename8))
29029
29316
  return;
29030
- const listener = async (path27, newStats) => {
29317
+ const listener = async (path28, newStats) => {
29031
29318
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file2, 5))
29032
29319
  return;
29033
29320
  if (!newStats || newStats.mtimeMs === 0) {
@@ -29041,11 +29328,11 @@ var init_handler2 = __esm({
29041
29328
  this.fsw._emit(EV.CHANGE, file2, newStats2);
29042
29329
  }
29043
29330
  if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
29044
- this.fsw._closeFile(path27);
29331
+ this.fsw._closeFile(path28);
29045
29332
  prevStats = newStats2;
29046
29333
  const closer2 = this._watchWithNodeFs(file2, listener);
29047
29334
  if (closer2)
29048
- this.fsw._addPathCloser(path27, closer2);
29335
+ this.fsw._addPathCloser(path28, closer2);
29049
29336
  } else {
29050
29337
  prevStats = newStats2;
29051
29338
  }
@@ -29077,7 +29364,7 @@ var init_handler2 = __esm({
29077
29364
  * @param item basename of this item
29078
29365
  * @returns true if no more processing is needed for this entry.
29079
29366
  */
29080
- async _handleSymlink(entry, directory, path27, item) {
29367
+ async _handleSymlink(entry, directory, path28, item) {
29081
29368
  if (this.fsw.closed) {
29082
29369
  return;
29083
29370
  }
@@ -29087,7 +29374,7 @@ var init_handler2 = __esm({
29087
29374
  this.fsw._incrReadyCount();
29088
29375
  let linkPath;
29089
29376
  try {
29090
- linkPath = await (0, import_promises2.realpath)(path27);
29377
+ linkPath = await (0, import_promises2.realpath)(path28);
29091
29378
  } catch (e) {
29092
29379
  this.fsw._emitReady();
29093
29380
  return true;
@@ -29097,12 +29384,12 @@ var init_handler2 = __esm({
29097
29384
  if (dir.has(item)) {
29098
29385
  if (this.fsw._symlinkPaths.get(full) !== linkPath) {
29099
29386
  this.fsw._symlinkPaths.set(full, linkPath);
29100
- this.fsw._emit(EV.CHANGE, path27, entry.stats);
29387
+ this.fsw._emit(EV.CHANGE, path28, entry.stats);
29101
29388
  }
29102
29389
  } else {
29103
29390
  dir.add(item);
29104
29391
  this.fsw._symlinkPaths.set(full, linkPath);
29105
- this.fsw._emit(EV.ADD, path27, entry.stats);
29392
+ this.fsw._emit(EV.ADD, path28, entry.stats);
29106
29393
  }
29107
29394
  this.fsw._emitReady();
29108
29395
  return true;
@@ -29132,9 +29419,9 @@ var init_handler2 = __esm({
29132
29419
  return;
29133
29420
  }
29134
29421
  const item = entry.path;
29135
- let path27 = sp.join(directory, item);
29422
+ let path28 = sp.join(directory, item);
29136
29423
  current.add(item);
29137
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path27, item)) {
29424
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path28, item)) {
29138
29425
  return;
29139
29426
  }
29140
29427
  if (this.fsw.closed) {
@@ -29143,8 +29430,8 @@ var init_handler2 = __esm({
29143
29430
  }
29144
29431
  if (item === target || !target && !previous.has(item)) {
29145
29432
  this.fsw._incrReadyCount();
29146
- path27 = sp.join(dir, sp.relative(dir, path27));
29147
- this._addToNodeFs(path27, initialAdd, wh, depth + 1);
29433
+ path28 = sp.join(dir, sp.relative(dir, path28));
29434
+ this._addToNodeFs(path28, initialAdd, wh, depth + 1);
29148
29435
  }
29149
29436
  }).on(EV.ERROR, this._boundHandleError);
29150
29437
  return new Promise((resolve17, reject) => {
@@ -29213,13 +29500,13 @@ var init_handler2 = __esm({
29213
29500
  * @param depth Child path actually targeted for watch
29214
29501
  * @param target Child path actually targeted for watch
29215
29502
  */
29216
- async _addToNodeFs(path27, initialAdd, priorWh, depth, target) {
29503
+ async _addToNodeFs(path28, initialAdd, priorWh, depth, target) {
29217
29504
  const ready = this.fsw._emitReady;
29218
- if (this.fsw._isIgnored(path27) || this.fsw.closed) {
29505
+ if (this.fsw._isIgnored(path28) || this.fsw.closed) {
29219
29506
  ready();
29220
29507
  return false;
29221
29508
  }
29222
- const wh = this.fsw._getWatchHelpers(path27);
29509
+ const wh = this.fsw._getWatchHelpers(path28);
29223
29510
  if (priorWh) {
29224
29511
  wh.filterPath = (entry) => priorWh.filterPath(entry);
29225
29512
  wh.filterDir = (entry) => priorWh.filterDir(entry);
@@ -29235,8 +29522,8 @@ var init_handler2 = __esm({
29235
29522
  const follow = this.fsw.options.followSymlinks;
29236
29523
  let closer;
29237
29524
  if (stats.isDirectory()) {
29238
- const absPath = sp.resolve(path27);
29239
- const targetPath = follow ? await (0, import_promises2.realpath)(path27) : path27;
29525
+ const absPath = sp.resolve(path28);
29526
+ const targetPath = follow ? await (0, import_promises2.realpath)(path28) : path28;
29240
29527
  if (this.fsw.closed)
29241
29528
  return;
29242
29529
  closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
@@ -29246,29 +29533,29 @@ var init_handler2 = __esm({
29246
29533
  this.fsw._symlinkPaths.set(absPath, targetPath);
29247
29534
  }
29248
29535
  } else if (stats.isSymbolicLink()) {
29249
- const targetPath = follow ? await (0, import_promises2.realpath)(path27) : path27;
29536
+ const targetPath = follow ? await (0, import_promises2.realpath)(path28) : path28;
29250
29537
  if (this.fsw.closed)
29251
29538
  return;
29252
29539
  const parent = sp.dirname(wh.watchPath);
29253
29540
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
29254
29541
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
29255
- closer = await this._handleDir(parent, stats, initialAdd, depth, path27, wh, targetPath);
29542
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path28, wh, targetPath);
29256
29543
  if (this.fsw.closed)
29257
29544
  return;
29258
29545
  if (targetPath !== void 0) {
29259
- this.fsw._symlinkPaths.set(sp.resolve(path27), targetPath);
29546
+ this.fsw._symlinkPaths.set(sp.resolve(path28), targetPath);
29260
29547
  }
29261
29548
  } else {
29262
29549
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
29263
29550
  }
29264
29551
  ready();
29265
29552
  if (closer)
29266
- this.fsw._addPathCloser(path27, closer);
29553
+ this.fsw._addPathCloser(path28, closer);
29267
29554
  return false;
29268
29555
  } catch (error48) {
29269
29556
  if (this.fsw._handleError(error48)) {
29270
29557
  ready();
29271
- return path27;
29558
+ return path28;
29272
29559
  }
29273
29560
  }
29274
29561
  }
@@ -29303,24 +29590,24 @@ function createPattern(matcher) {
29303
29590
  }
29304
29591
  return () => false;
29305
29592
  }
29306
- function normalizePath(path27) {
29307
- if (typeof path27 !== "string")
29593
+ function normalizePath(path28) {
29594
+ if (typeof path28 !== "string")
29308
29595
  throw new Error("string expected");
29309
- path27 = sp2.normalize(path27);
29310
- path27 = path27.replace(/\\/g, "/");
29596
+ path28 = sp2.normalize(path28);
29597
+ path28 = path28.replace(/\\/g, "/");
29311
29598
  let prepend = false;
29312
- if (path27.startsWith("//"))
29599
+ if (path28.startsWith("//"))
29313
29600
  prepend = true;
29314
- path27 = path27.replace(DOUBLE_SLASH_RE, "/");
29601
+ path28 = path28.replace(DOUBLE_SLASH_RE, "/");
29315
29602
  if (prepend)
29316
- path27 = "/" + path27;
29317
- return path27;
29603
+ path28 = "/" + path28;
29604
+ return path28;
29318
29605
  }
29319
29606
  function matchPatterns(patterns, testString, stats) {
29320
- const path27 = normalizePath(testString);
29607
+ const path28 = normalizePath(testString);
29321
29608
  for (let index = 0; index < patterns.length; index++) {
29322
29609
  const pattern = patterns[index];
29323
- if (pattern(path27, stats)) {
29610
+ if (pattern(path28, stats)) {
29324
29611
  return true;
29325
29612
  }
29326
29613
  }
@@ -29383,19 +29670,19 @@ var init_chokidar = __esm({
29383
29670
  }
29384
29671
  return str;
29385
29672
  };
29386
- normalizePathToUnix = (path27) => toUnix(sp2.normalize(toUnix(path27)));
29387
- normalizeIgnored = (cwd = "") => (path27) => {
29388
- if (typeof path27 === "string") {
29389
- return normalizePathToUnix(sp2.isAbsolute(path27) ? path27 : sp2.join(cwd, path27));
29673
+ normalizePathToUnix = (path28) => toUnix(sp2.normalize(toUnix(path28)));
29674
+ normalizeIgnored = (cwd = "") => (path28) => {
29675
+ if (typeof path28 === "string") {
29676
+ return normalizePathToUnix(sp2.isAbsolute(path28) ? path28 : sp2.join(cwd, path28));
29390
29677
  } else {
29391
- return path27;
29678
+ return path28;
29392
29679
  }
29393
29680
  };
29394
- getAbsolutePath = (path27, cwd) => {
29395
- if (sp2.isAbsolute(path27)) {
29396
- return path27;
29681
+ getAbsolutePath = (path28, cwd) => {
29682
+ if (sp2.isAbsolute(path28)) {
29683
+ return path28;
29397
29684
  }
29398
- return sp2.join(cwd, path27);
29685
+ return sp2.join(cwd, path28);
29399
29686
  };
29400
29687
  EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
29401
29688
  DirEntry = class {
@@ -29460,10 +29747,10 @@ var init_chokidar = __esm({
29460
29747
  dirParts;
29461
29748
  followSymlinks;
29462
29749
  statMethod;
29463
- constructor(path27, follow, fsw) {
29750
+ constructor(path28, follow, fsw) {
29464
29751
  this.fsw = fsw;
29465
- const watchPath = path27;
29466
- this.path = path27 = path27.replace(REPLACER_RE, "");
29752
+ const watchPath = path28;
29753
+ this.path = path28 = path28.replace(REPLACER_RE, "");
29467
29754
  this.watchPath = watchPath;
29468
29755
  this.fullWatchPath = sp2.resolve(watchPath);
29469
29756
  this.dirParts = [];
@@ -29603,20 +29890,20 @@ var init_chokidar = __esm({
29603
29890
  this._closePromise = void 0;
29604
29891
  let paths = unifyPaths(paths_);
29605
29892
  if (cwd) {
29606
- paths = paths.map((path27) => {
29607
- const absPath = getAbsolutePath(path27, cwd);
29893
+ paths = paths.map((path28) => {
29894
+ const absPath = getAbsolutePath(path28, cwd);
29608
29895
  return absPath;
29609
29896
  });
29610
29897
  }
29611
- paths.forEach((path27) => {
29612
- this._removeIgnoredPath(path27);
29898
+ paths.forEach((path28) => {
29899
+ this._removeIgnoredPath(path28);
29613
29900
  });
29614
29901
  this._userIgnored = void 0;
29615
29902
  if (!this._readyCount)
29616
29903
  this._readyCount = 0;
29617
29904
  this._readyCount += paths.length;
29618
- Promise.all(paths.map(async (path27) => {
29619
- const res = await this._nodeFsHandler._addToNodeFs(path27, !_internal, void 0, 0, _origAdd);
29905
+ Promise.all(paths.map(async (path28) => {
29906
+ const res = await this._nodeFsHandler._addToNodeFs(path28, !_internal, void 0, 0, _origAdd);
29620
29907
  if (res)
29621
29908
  this._emitReady();
29622
29909
  return res;
@@ -29638,17 +29925,17 @@ var init_chokidar = __esm({
29638
29925
  return this;
29639
29926
  const paths = unifyPaths(paths_);
29640
29927
  const { cwd } = this.options;
29641
- paths.forEach((path27) => {
29642
- if (!sp2.isAbsolute(path27) && !this._closers.has(path27)) {
29928
+ paths.forEach((path28) => {
29929
+ if (!sp2.isAbsolute(path28) && !this._closers.has(path28)) {
29643
29930
  if (cwd)
29644
- path27 = sp2.join(cwd, path27);
29645
- path27 = sp2.resolve(path27);
29931
+ path28 = sp2.join(cwd, path28);
29932
+ path28 = sp2.resolve(path28);
29646
29933
  }
29647
- this._closePath(path27);
29648
- this._addIgnoredPath(path27);
29649
- if (this._watched.has(path27)) {
29934
+ this._closePath(path28);
29935
+ this._addIgnoredPath(path28);
29936
+ if (this._watched.has(path28)) {
29650
29937
  this._addIgnoredPath({
29651
- path: path27,
29938
+ path: path28,
29652
29939
  recursive: true
29653
29940
  });
29654
29941
  }
@@ -29712,38 +29999,38 @@ var init_chokidar = __esm({
29712
29999
  * @param stats arguments to be passed with event
29713
30000
  * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
29714
30001
  */
29715
- async _emit(event, path27, stats) {
30002
+ async _emit(event, path28, stats) {
29716
30003
  if (this.closed)
29717
30004
  return;
29718
30005
  const opts = this.options;
29719
30006
  if (isWindows)
29720
- path27 = sp2.normalize(path27);
30007
+ path28 = sp2.normalize(path28);
29721
30008
  if (opts.cwd)
29722
- path27 = sp2.relative(opts.cwd, path27);
29723
- const args = [path27];
30009
+ path28 = sp2.relative(opts.cwd, path28);
30010
+ const args = [path28];
29724
30011
  if (stats != null)
29725
30012
  args.push(stats);
29726
30013
  const awf = opts.awaitWriteFinish;
29727
30014
  let pw;
29728
- if (awf && (pw = this._pendingWrites.get(path27))) {
30015
+ if (awf && (pw = this._pendingWrites.get(path28))) {
29729
30016
  pw.lastChange = /* @__PURE__ */ new Date();
29730
30017
  return this;
29731
30018
  }
29732
30019
  if (opts.atomic) {
29733
30020
  if (event === EVENTS.UNLINK) {
29734
- this._pendingUnlinks.set(path27, [event, ...args]);
30021
+ this._pendingUnlinks.set(path28, [event, ...args]);
29735
30022
  setTimeout(() => {
29736
- this._pendingUnlinks.forEach((entry, path28) => {
30023
+ this._pendingUnlinks.forEach((entry, path29) => {
29737
30024
  this.emit(...entry);
29738
30025
  this.emit(EVENTS.ALL, ...entry);
29739
- this._pendingUnlinks.delete(path28);
30026
+ this._pendingUnlinks.delete(path29);
29740
30027
  });
29741
30028
  }, typeof opts.atomic === "number" ? opts.atomic : 100);
29742
30029
  return this;
29743
30030
  }
29744
- if (event === EVENTS.ADD && this._pendingUnlinks.has(path27)) {
30031
+ if (event === EVENTS.ADD && this._pendingUnlinks.has(path28)) {
29745
30032
  event = EVENTS.CHANGE;
29746
- this._pendingUnlinks.delete(path27);
30033
+ this._pendingUnlinks.delete(path28);
29747
30034
  }
29748
30035
  }
29749
30036
  if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
@@ -29761,16 +30048,16 @@ var init_chokidar = __esm({
29761
30048
  this.emitWithAll(event, args);
29762
30049
  }
29763
30050
  };
29764
- this._awaitWriteFinish(path27, awf.stabilityThreshold, event, awfEmit);
30051
+ this._awaitWriteFinish(path28, awf.stabilityThreshold, event, awfEmit);
29765
30052
  return this;
29766
30053
  }
29767
30054
  if (event === EVENTS.CHANGE) {
29768
- const isThrottled = !this._throttle(EVENTS.CHANGE, path27, 50);
30055
+ const isThrottled = !this._throttle(EVENTS.CHANGE, path28, 50);
29769
30056
  if (isThrottled)
29770
30057
  return this;
29771
30058
  }
29772
30059
  if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
29773
- const fullPath = opts.cwd ? sp2.join(opts.cwd, path27) : path27;
30060
+ const fullPath = opts.cwd ? sp2.join(opts.cwd, path28) : path28;
29774
30061
  let stats2;
29775
30062
  try {
29776
30063
  stats2 = await (0, import_promises3.stat)(fullPath);
@@ -29801,23 +30088,23 @@ var init_chokidar = __esm({
29801
30088
  * @param timeout duration of time to suppress duplicate actions
29802
30089
  * @returns tracking object or false if action should be suppressed
29803
30090
  */
29804
- _throttle(actionType, path27, timeout) {
30091
+ _throttle(actionType, path28, timeout) {
29805
30092
  if (!this._throttled.has(actionType)) {
29806
30093
  this._throttled.set(actionType, /* @__PURE__ */ new Map());
29807
30094
  }
29808
30095
  const action = this._throttled.get(actionType);
29809
30096
  if (!action)
29810
30097
  throw new Error("invalid throttle");
29811
- const actionPath = action.get(path27);
30098
+ const actionPath = action.get(path28);
29812
30099
  if (actionPath) {
29813
30100
  actionPath.count++;
29814
30101
  return false;
29815
30102
  }
29816
30103
  let timeoutObject;
29817
30104
  const clear = () => {
29818
- const item = action.get(path27);
30105
+ const item = action.get(path28);
29819
30106
  const count = item ? item.count : 0;
29820
- action.delete(path27);
30107
+ action.delete(path28);
29821
30108
  clearTimeout(timeoutObject);
29822
30109
  if (item)
29823
30110
  clearTimeout(item.timeoutObject);
@@ -29825,7 +30112,7 @@ var init_chokidar = __esm({
29825
30112
  };
29826
30113
  timeoutObject = setTimeout(clear, timeout);
29827
30114
  const thr = { timeoutObject, clear, count: 0 };
29828
- action.set(path27, thr);
30115
+ action.set(path28, thr);
29829
30116
  return thr;
29830
30117
  }
29831
30118
  _incrReadyCount() {
@@ -29839,44 +30126,44 @@ var init_chokidar = __esm({
29839
30126
  * @param event
29840
30127
  * @param awfEmit Callback to be called when ready for event to be emitted.
29841
30128
  */
29842
- _awaitWriteFinish(path27, threshold, event, awfEmit) {
30129
+ _awaitWriteFinish(path28, threshold, event, awfEmit) {
29843
30130
  const awf = this.options.awaitWriteFinish;
29844
30131
  if (typeof awf !== "object")
29845
30132
  return;
29846
30133
  const pollInterval = awf.pollInterval;
29847
30134
  let timeoutHandler;
29848
- let fullPath = path27;
29849
- if (this.options.cwd && !sp2.isAbsolute(path27)) {
29850
- fullPath = sp2.join(this.options.cwd, path27);
30135
+ let fullPath = path28;
30136
+ if (this.options.cwd && !sp2.isAbsolute(path28)) {
30137
+ fullPath = sp2.join(this.options.cwd, path28);
29851
30138
  }
29852
30139
  const now = /* @__PURE__ */ new Date();
29853
30140
  const writes = this._pendingWrites;
29854
30141
  function awaitWriteFinishFn(prevStat) {
29855
30142
  (0, import_node_fs2.stat)(fullPath, (err, curStat) => {
29856
- if (err || !writes.has(path27)) {
30143
+ if (err || !writes.has(path28)) {
29857
30144
  if (err && err.code !== "ENOENT")
29858
30145
  awfEmit(err);
29859
30146
  return;
29860
30147
  }
29861
30148
  const now2 = Number(/* @__PURE__ */ new Date());
29862
30149
  if (prevStat && curStat.size !== prevStat.size) {
29863
- writes.get(path27).lastChange = now2;
30150
+ writes.get(path28).lastChange = now2;
29864
30151
  }
29865
- const pw = writes.get(path27);
30152
+ const pw = writes.get(path28);
29866
30153
  const df = now2 - pw.lastChange;
29867
30154
  if (df >= threshold) {
29868
- writes.delete(path27);
30155
+ writes.delete(path28);
29869
30156
  awfEmit(void 0, curStat);
29870
30157
  } else {
29871
30158
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
29872
30159
  }
29873
30160
  });
29874
30161
  }
29875
- if (!writes.has(path27)) {
29876
- writes.set(path27, {
30162
+ if (!writes.has(path28)) {
30163
+ writes.set(path28, {
29877
30164
  lastChange: now,
29878
30165
  cancelWait: () => {
29879
- writes.delete(path27);
30166
+ writes.delete(path28);
29880
30167
  clearTimeout(timeoutHandler);
29881
30168
  return event;
29882
30169
  }
@@ -29887,8 +30174,8 @@ var init_chokidar = __esm({
29887
30174
  /**
29888
30175
  * Determines whether user has asked to ignore this path.
29889
30176
  */
29890
- _isIgnored(path27, stats) {
29891
- if (this.options.atomic && DOT_RE.test(path27))
30177
+ _isIgnored(path28, stats) {
30178
+ if (this.options.atomic && DOT_RE.test(path28))
29892
30179
  return true;
29893
30180
  if (!this._userIgnored) {
29894
30181
  const { cwd } = this.options;
@@ -29898,17 +30185,17 @@ var init_chokidar = __esm({
29898
30185
  const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
29899
30186
  this._userIgnored = anymatch(list, void 0);
29900
30187
  }
29901
- return this._userIgnored(path27, stats);
30188
+ return this._userIgnored(path28, stats);
29902
30189
  }
29903
- _isntIgnored(path27, stat4) {
29904
- return !this._isIgnored(path27, stat4);
30190
+ _isntIgnored(path28, stat4) {
30191
+ return !this._isIgnored(path28, stat4);
29905
30192
  }
29906
30193
  /**
29907
30194
  * Provides a set of common helpers and properties relating to symlink handling.
29908
30195
  * @param path file or directory pattern being watched
29909
30196
  */
29910
- _getWatchHelpers(path27) {
29911
- return new WatchHelper(path27, this.options.followSymlinks, this);
30197
+ _getWatchHelpers(path28) {
30198
+ return new WatchHelper(path28, this.options.followSymlinks, this);
29912
30199
  }
29913
30200
  // Directory helpers
29914
30201
  // -----------------
@@ -29940,63 +30227,63 @@ var init_chokidar = __esm({
29940
30227
  * @param item base path of item/directory
29941
30228
  */
29942
30229
  _remove(directory, item, isDirectory) {
29943
- const path27 = sp2.join(directory, item);
29944
- const fullPath = sp2.resolve(path27);
29945
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path27) || this._watched.has(fullPath);
29946
- if (!this._throttle("remove", path27, 100))
30230
+ const path28 = sp2.join(directory, item);
30231
+ const fullPath = sp2.resolve(path28);
30232
+ isDirectory = isDirectory != null ? isDirectory : this._watched.has(path28) || this._watched.has(fullPath);
30233
+ if (!this._throttle("remove", path28, 100))
29947
30234
  return;
29948
30235
  if (!isDirectory && this._watched.size === 1) {
29949
30236
  this.add(directory, item, true);
29950
30237
  }
29951
- const wp = this._getWatchedDir(path27);
30238
+ const wp = this._getWatchedDir(path28);
29952
30239
  const nestedDirectoryChildren = wp.getChildren();
29953
- nestedDirectoryChildren.forEach((nested) => this._remove(path27, nested));
30240
+ nestedDirectoryChildren.forEach((nested) => this._remove(path28, nested));
29954
30241
  const parent = this._getWatchedDir(directory);
29955
30242
  const wasTracked = parent.has(item);
29956
30243
  parent.remove(item);
29957
30244
  if (this._symlinkPaths.has(fullPath)) {
29958
30245
  this._symlinkPaths.delete(fullPath);
29959
30246
  }
29960
- let relPath = path27;
30247
+ let relPath = path28;
29961
30248
  if (this.options.cwd)
29962
- relPath = sp2.relative(this.options.cwd, path27);
30249
+ relPath = sp2.relative(this.options.cwd, path28);
29963
30250
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
29964
30251
  const event = this._pendingWrites.get(relPath).cancelWait();
29965
30252
  if (event === EVENTS.ADD)
29966
30253
  return;
29967
30254
  }
29968
- this._watched.delete(path27);
30255
+ this._watched.delete(path28);
29969
30256
  this._watched.delete(fullPath);
29970
30257
  const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
29971
- if (wasTracked && !this._isIgnored(path27))
29972
- this._emit(eventName, path27);
29973
- this._closePath(path27);
30258
+ if (wasTracked && !this._isIgnored(path28))
30259
+ this._emit(eventName, path28);
30260
+ this._closePath(path28);
29974
30261
  }
29975
30262
  /**
29976
30263
  * Closes all watchers for a path
29977
30264
  */
29978
- _closePath(path27) {
29979
- this._closeFile(path27);
29980
- const dir = sp2.dirname(path27);
29981
- this._getWatchedDir(dir).remove(sp2.basename(path27));
30265
+ _closePath(path28) {
30266
+ this._closeFile(path28);
30267
+ const dir = sp2.dirname(path28);
30268
+ this._getWatchedDir(dir).remove(sp2.basename(path28));
29982
30269
  }
29983
30270
  /**
29984
30271
  * Closes only file-specific watchers
29985
30272
  */
29986
- _closeFile(path27) {
29987
- const closers = this._closers.get(path27);
30273
+ _closeFile(path28) {
30274
+ const closers = this._closers.get(path28);
29988
30275
  if (!closers)
29989
30276
  return;
29990
30277
  closers.forEach((closer) => closer());
29991
- this._closers.delete(path27);
30278
+ this._closers.delete(path28);
29992
30279
  }
29993
- _addPathCloser(path27, closer) {
30280
+ _addPathCloser(path28, closer) {
29994
30281
  if (!closer)
29995
30282
  return;
29996
- let list = this._closers.get(path27);
30283
+ let list = this._closers.get(path28);
29997
30284
  if (!list) {
29998
30285
  list = [];
29999
- this._closers.set(path27, list);
30286
+ this._closers.set(path28, list);
30000
30287
  }
30001
30288
  list.push(closer);
30002
30289
  }
@@ -30656,7 +30943,7 @@ var init_provider_loader = __esm({
30656
30943
  return { updated: false };
30657
30944
  }
30658
30945
  const https = require("https");
30659
- const { execSync: execSync7 } = require("child_process");
30946
+ const { execSync: execSync8 } = require("child_process");
30660
30947
  const metaPath = path13.join(this.upstreamDir, _ProviderLoader.META_FILE);
30661
30948
  let prevEtag = "";
30662
30949
  let prevTimestamp = 0;
@@ -30721,7 +31008,7 @@ var init_provider_loader = __esm({
30721
31008
  const tmpExtract = path13.join(os12.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
30722
31009
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
30723
31010
  fs6.mkdirSync(tmpExtract, { recursive: true });
30724
- execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
31011
+ execSync8(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
30725
31012
  const extracted = fs6.readdirSync(tmpExtract);
30726
31013
  const rootDir = extracted.find(
30727
31014
  (d) => fs6.statSync(path13.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
@@ -31369,7 +31656,7 @@ function detectCurrentWorkspace(ideId) {
31369
31656
  }
31370
31657
  } else if (plat === "win32") {
31371
31658
  try {
31372
- const fs19 = require("fs");
31659
+ const fs20 = require("fs");
31373
31660
  const appNameMap = getMacAppIdentifiers();
31374
31661
  const appName = appNameMap[ideId];
31375
31662
  if (appName) {
@@ -31378,8 +31665,8 @@ function detectCurrentWorkspace(ideId) {
31378
31665
  appName,
31379
31666
  "storage.json"
31380
31667
  );
31381
- if (fs19.existsSync(storagePath)) {
31382
- const data = JSON.parse(fs19.readFileSync(storagePath, "utf-8"));
31668
+ if (fs20.existsSync(storagePath)) {
31669
+ const data = JSON.parse(fs20.readFileSync(storagePath, "utf-8"));
31383
31670
  const workspaces = data?.openedPathsList?.workspaces3 || data?.openedPathsList?.entries || [];
31384
31671
  if (workspaces.length > 0) {
31385
31672
  const recent = workspaces[0];
@@ -32240,6 +32527,15 @@ var init_router = __esm({
32240
32527
  const record2 = await this.deps.sessionHostControl.forceDetachClient(sessionId, clientId);
32241
32528
  return { success: true, record: record2 };
32242
32529
  }
32530
+ case "session_host_prune_duplicate_sessions": {
32531
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
32532
+ const result = await this.deps.sessionHostControl.pruneDuplicateSessions({
32533
+ providerType: typeof args?.providerType === "string" ? args.providerType : void 0,
32534
+ workspace: typeof args?.workspace === "string" ? args.workspace : void 0,
32535
+ dryRun: args?.dryRun === true
32536
+ });
32537
+ return { success: true, result };
32538
+ }
32243
32539
  case "session_host_acquire_write": {
32244
32540
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
32245
32541
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
@@ -32450,14 +32746,14 @@ var init_router = __esm({
32450
32746
  case "daemon_upgrade": {
32451
32747
  LOG.info("Upgrade", "Remote upgrade requested from dashboard");
32452
32748
  try {
32453
- const { execSync: execSync7 } = await import("child_process");
32749
+ const { execSync: execSync8 } = await import("child_process");
32454
32750
  const isStandalone = this.deps.packageName === "@adhdev/daemon-standalone" || process.argv[1]?.includes("daemon-standalone");
32455
32751
  const pkgName = isStandalone ? "@adhdev/daemon-standalone" : "adhdev";
32456
- const latest = execSync7(`npm view ${pkgName} version`, { encoding: "utf-8", timeout: 1e4 }).trim();
32752
+ const latest = execSync8(`npm view ${pkgName} version`, { encoding: "utf-8", timeout: 1e4 }).trim();
32457
32753
  LOG.info("Upgrade", `Latest ${pkgName}: v${latest}`);
32458
32754
  let currentInstalled = null;
32459
32755
  try {
32460
- const currentJson = execSync7(`npm ls -g ${pkgName} --depth=0 --json`, {
32756
+ const currentJson = execSync8(`npm ls -g ${pkgName} --depth=0 --json`, {
32461
32757
  encoding: "utf-8",
32462
32758
  timeout: 1e4,
32463
32759
  stdio: ["pipe", "pipe", "pipe"]
@@ -32843,6 +33139,51 @@ var init_provider_adapter = __esm({
32843
33139
  isTransportError(reason) {
32844
33140
  return /Session with given id not found/i.test(reason) || /CDP not connected/i.test(reason) || /Target closed/i.test(reason) || /WebSocket not open/i.test(reason) || /not connected/i.test(reason) || /execution context/i.test(reason) || /Cannot find context with specified id/i.test(reason);
32845
33141
  }
33142
+ titlesMatch(actual, expected) {
33143
+ const lhs = actual.trim().toLowerCase();
33144
+ const rhs = expected.trim().toLowerCase();
33145
+ if (!lhs || !rhs) return false;
33146
+ return lhs === rhs || lhs.includes(rhs) || rhs.includes(lhs);
33147
+ }
33148
+ messageCount(state) {
33149
+ return Array.isArray(state?.messages) ? state.messages.length : 0;
33150
+ }
33151
+ lastMessageSignature(state) {
33152
+ const messages = Array.isArray(state?.messages) ? state.messages : [];
33153
+ const last = messages[messages.length - 1];
33154
+ if (!last) return "";
33155
+ return `${last.role || ""}:${String(last.content || "").replace(/\s+/g, " ").trim()}`;
33156
+ }
33157
+ async verifySendOutcome(evaluate, before) {
33158
+ const beforeCount = this.messageCount(before);
33159
+ const beforeSignature = this.lastMessageSignature(before);
33160
+ for (let attempt = 0; attempt < 12; attempt += 1) {
33161
+ await new Promise((resolve17) => setTimeout(resolve17, 250));
33162
+ let state;
33163
+ try {
33164
+ state = await this.readChat(evaluate);
33165
+ } catch {
33166
+ continue;
33167
+ }
33168
+ if (state.status === "waiting_approval") {
33169
+ return true;
33170
+ }
33171
+ const afterCount = this.messageCount(state);
33172
+ const afterSignature = this.lastMessageSignature(state);
33173
+ if (afterCount > beforeCount) return true;
33174
+ if (afterSignature && afterSignature !== beforeSignature) return true;
33175
+ }
33176
+ return false;
33177
+ }
33178
+ async readStableBaselineState(evaluate) {
33179
+ const first = await this.readChat(evaluate);
33180
+ if (this.messageCount(first) > 0 || this.lastMessageSignature(first)) {
33181
+ return first;
33182
+ }
33183
+ await new Promise((resolve17) => setTimeout(resolve17, 150));
33184
+ const second = await this.readChat(evaluate);
33185
+ return this.messageCount(second) >= this.messageCount(first) ? second : first;
33186
+ }
32846
33187
  async readChat(evaluate) {
32847
33188
  const script = this.callScript("readChat");
32848
33189
  if (!script) return this.errorState("readChat script not available");
@@ -32868,6 +33209,9 @@ var init_provider_adapter = __esm({
32868
33209
  mode: data.mode,
32869
33210
  activeModal: data.activeModal
32870
33211
  };
33212
+ if (typeof data.title === "string" && data.title.trim()) {
33213
+ state.title = data.title.trim();
33214
+ }
32871
33215
  const controlValues = extractProviderControlValues(this.provider.controls, data);
32872
33216
  if (controlValues) state.controlValues = controlValues;
32873
33217
  const effects = normalizeProviderEffects(data);
@@ -32891,6 +33235,12 @@ var init_provider_adapter = __esm({
32891
33235
  }
32892
33236
  }
32893
33237
  async sendMessage(evaluate, text) {
33238
+ let beforeState = null;
33239
+ try {
33240
+ beforeState = await this.readStableBaselineState(evaluate);
33241
+ } catch {
33242
+ beforeState = null;
33243
+ }
32894
33244
  const params = { message: text };
32895
33245
  const script = this.callScript("sendMessage", params) || this.callScript("sendMessage", text);
32896
33246
  if (!script) throw new Error(`[${this.agentName}] sendMessage script not available`);
@@ -32908,7 +33258,9 @@ var init_provider_adapter = __esm({
32908
33258
  }
32909
33259
  if (parsed && typeof parsed === "object") {
32910
33260
  if (parsed.sent === true || parsed.success === true || parsed.ok === true || parsed.submitted === true || parsed.dispatched === true) {
32911
- return;
33261
+ const verified = await this.verifySendOutcome(evaluate, beforeState);
33262
+ if (verified) return;
33263
+ throw new Error(`[${this.agentName}] sendMessage was not observed in chat state`);
32912
33264
  }
32913
33265
  if (typeof parsed.error === "string" && parsed.error.trim()) {
32914
33266
  throw new Error(`[${this.agentName}] sendMessage failed: ${parsed.error}`);
@@ -32919,7 +33271,15 @@ var init_provider_adapter = __esm({
32919
33271
  async resolveAction(evaluate, action, button) {
32920
33272
  const script = this.callScript("resolveAction", { action, button });
32921
33273
  if (!script) return false;
32922
- return await evaluate(script) === true;
33274
+ const result = await evaluate(script);
33275
+ const parsed = this.parseMaybeJson(result);
33276
+ if (parsed === true) return true;
33277
+ if (typeof parsed === "string") {
33278
+ const normalized = parsed.trim().toLowerCase();
33279
+ return normalized === "ok" || normalized === "success" || normalized === "true" || normalized === "resolved" || normalized === "approved" || normalized === "rejected";
33280
+ }
33281
+ if (!parsed || typeof parsed !== "object") return false;
33282
+ return parsed.resolved === true || parsed.success === true || parsed.ok === true || parsed.found === true;
32923
33283
  }
32924
33284
  async newSession(evaluate) {
32925
33285
  const script = this.callScript("newSession");
@@ -32956,7 +33316,14 @@ var init_provider_adapter = __esm({
32956
33316
  return normalized === "true" || normalized === "ok" || normalized === "switched" || normalized === "success";
32957
33317
  }
32958
33318
  if (data && typeof data === "object") {
32959
- return data.switched === true || data.success === true || data.ok === true;
33319
+ if (data.switched === true || data.success === true || data.ok === true) return true;
33320
+ if (typeof data.error === "string" && data.error.trim()) return false;
33321
+ }
33322
+ for (let attempt = 0; attempt < 6; attempt += 1) {
33323
+ await new Promise((resolve17) => setTimeout(resolve17, 250));
33324
+ const state = await this.readChat(evaluate);
33325
+ const title = typeof state.title === "string" ? state.title : "";
33326
+ if (this.titlesMatch(title, sessionId)) return true;
32960
33327
  }
32961
33328
  return false;
32962
33329
  }
@@ -33171,7 +33538,7 @@ var init_manager2 = __esm({
33171
33538
  return false;
33172
33539
  }
33173
33540
  }
33174
- async resolveSessionAction(cdp, sessionId, action) {
33541
+ async resolveSessionAction(cdp, sessionId, action, button) {
33175
33542
  await this.ensureSessionPanelOpen(sessionId);
33176
33543
  const target = this.getSessionTarget(sessionId);
33177
33544
  if (!target?.parentSessionId) return false;
@@ -33181,7 +33548,7 @@ var init_manager2 = __esm({
33181
33548
  if (!agent) return false;
33182
33549
  try {
33183
33550
  const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
33184
- return await agent.adapter.resolveAction(evaluate, action);
33551
+ return await agent.adapter.resolveAction(evaluate, action, button);
33185
33552
  } catch (e) {
33186
33553
  this.logFn(`[AgentStream] resolveAction(${sessionId}) error: ${e.message}`);
33187
33554
  return false;
@@ -37592,8 +37959,8 @@ var init_dev_server = __esm({
37592
37959
  }
37593
37960
  getEndpointList() {
37594
37961
  return this.routes.map((r) => {
37595
- const path27 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
37596
- return `${r.method.padEnd(5)} ${path27}`;
37962
+ const path28 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
37963
+ return `${r.method.padEnd(5)} ${path28}`;
37597
37964
  });
37598
37965
  }
37599
37966
  async start(port = DEV_SERVER_PORT) {
@@ -39484,8 +39851,8 @@ async function installExtension(ide, extension) {
39484
39851
  const res = await fetch(extension.vsixUrl);
39485
39852
  if (res.ok) {
39486
39853
  const buffer = Buffer.from(await res.arrayBuffer());
39487
- const fs19 = await import("fs");
39488
- fs19.writeFileSync(vsixPath, buffer);
39854
+ const fs20 = await import("fs");
39855
+ fs20.writeFileSync(vsixPath, buffer);
39489
39856
  return new Promise((resolve17) => {
39490
39857
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
39491
39858
  (0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error48, _stdout, stderr) => {
@@ -41348,27 +41715,27 @@ var require_process = __commonJS({
41348
41715
  var require_filesystem = __commonJS({
41349
41716
  "../../node_modules/detect-libc/lib/filesystem.js"(exports2, module2) {
41350
41717
  "use strict";
41351
- var fs19 = require("fs");
41718
+ var fs20 = require("fs");
41352
41719
  var LDD_PATH = "/usr/bin/ldd";
41353
41720
  var SELF_PATH = "/proc/self/exe";
41354
41721
  var MAX_LENGTH = 2048;
41355
- var readFileSync18 = (path27) => {
41356
- const fd = fs19.openSync(path27, "r");
41722
+ var readFileSync18 = (path28) => {
41723
+ const fd = fs20.openSync(path28, "r");
41357
41724
  const buffer = Buffer.alloc(MAX_LENGTH);
41358
- const bytesRead = fs19.readSync(fd, buffer, 0, MAX_LENGTH, 0);
41359
- fs19.close(fd, () => {
41725
+ const bytesRead = fs20.readSync(fd, buffer, 0, MAX_LENGTH, 0);
41726
+ fs20.close(fd, () => {
41360
41727
  });
41361
41728
  return buffer.subarray(0, bytesRead);
41362
41729
  };
41363
- var readFile = (path27) => new Promise((resolve17, reject) => {
41364
- fs19.open(path27, "r", (err, fd) => {
41730
+ var readFile = (path28) => new Promise((resolve17, reject) => {
41731
+ fs20.open(path28, "r", (err, fd) => {
41365
41732
  if (err) {
41366
41733
  reject(err);
41367
41734
  } else {
41368
41735
  const buffer = Buffer.alloc(MAX_LENGTH);
41369
- fs19.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
41736
+ fs20.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
41370
41737
  resolve17(buffer.subarray(0, bytesRead));
41371
- fs19.close(fd, () => {
41738
+ fs20.close(fd, () => {
41372
41739
  });
41373
41740
  });
41374
41741
  }
@@ -41480,11 +41847,11 @@ var require_detect_libc = __commonJS({
41480
41847
  }
41481
41848
  return null;
41482
41849
  };
41483
- var familyFromInterpreterPath = (path27) => {
41484
- if (path27) {
41485
- if (path27.includes("/ld-musl-")) {
41850
+ var familyFromInterpreterPath = (path28) => {
41851
+ if (path28) {
41852
+ if (path28.includes("/ld-musl-")) {
41486
41853
  return MUSL;
41487
- } else if (path27.includes("/ld-linux-")) {
41854
+ } else if (path28.includes("/ld-linux-")) {
41488
41855
  return GLIBC;
41489
41856
  }
41490
41857
  }
@@ -41531,8 +41898,8 @@ var require_detect_libc = __commonJS({
41531
41898
  cachedFamilyInterpreter = null;
41532
41899
  try {
41533
41900
  const selfContent = await readFile(SELF_PATH);
41534
- const path27 = interpreterPath(selfContent);
41535
- cachedFamilyInterpreter = familyFromInterpreterPath(path27);
41901
+ const path28 = interpreterPath(selfContent);
41902
+ cachedFamilyInterpreter = familyFromInterpreterPath(path28);
41536
41903
  } catch (e) {
41537
41904
  }
41538
41905
  return cachedFamilyInterpreter;
@@ -41544,8 +41911,8 @@ var require_detect_libc = __commonJS({
41544
41911
  cachedFamilyInterpreter = null;
41545
41912
  try {
41546
41913
  const selfContent = readFileSync18(SELF_PATH);
41547
- const path27 = interpreterPath(selfContent);
41548
- cachedFamilyInterpreter = familyFromInterpreterPath(path27);
41914
+ const path28 = interpreterPath(selfContent);
41915
+ cachedFamilyInterpreter = familyFromInterpreterPath(path28);
41549
41916
  } catch (e) {
41550
41917
  }
41551
41918
  return cachedFamilyInterpreter;
@@ -43264,18 +43631,18 @@ var require_sharp = __commonJS({
43264
43631
  `@img/sharp-${runtimePlatform}/sharp.node`,
43265
43632
  "@img/sharp-wasm32/sharp.node"
43266
43633
  ];
43267
- var path27;
43634
+ var path28;
43268
43635
  var sharp;
43269
43636
  var errors = [];
43270
- for (path27 of paths) {
43637
+ for (path28 of paths) {
43271
43638
  try {
43272
- sharp = require(path27);
43639
+ sharp = require(path28);
43273
43640
  break;
43274
43641
  } catch (err) {
43275
43642
  errors.push(err);
43276
43643
  }
43277
43644
  }
43278
- if (sharp && path27.startsWith("@img/sharp-linux-x64") && !sharp._isUsingX64V2()) {
43645
+ if (sharp && path28.startsWith("@img/sharp-linux-x64") && !sharp._isUsingX64V2()) {
43279
43646
  const err = new Error("Prebuilt binaries for linux-x64 require v2 microarchitecture");
43280
43647
  err.code = "Unsupported CPU";
43281
43648
  errors.push(err);
@@ -43284,7 +43651,7 @@ var require_sharp = __commonJS({
43284
43651
  if (sharp) {
43285
43652
  module2.exports = sharp;
43286
43653
  } else {
43287
- const [isLinux2, isMacOs, isWindows2] = ["linux", "darwin", "win32"].map((os24) => runtimePlatform.startsWith(os24));
43654
+ const [isLinux2, isMacOs, isWindows2] = ["linux", "darwin", "win32"].map((os25) => runtimePlatform.startsWith(os25));
43288
43655
  const help = [`Could not load the "sharp" module using the ${runtimePlatform} runtime`];
43289
43656
  errors.forEach((err) => {
43290
43657
  if (err.code !== "MODULE_NOT_FOUND") {
@@ -43301,15 +43668,15 @@ var require_sharp = __commonJS({
43301
43668
  ` Requires ${expected}`
43302
43669
  );
43303
43670
  } else if (prebuiltPlatforms.includes(runtimePlatform)) {
43304
- const [os24, cpu] = runtimePlatform.split("-");
43305
- const libc = os24.endsWith("musl") ? " --libc=musl" : "";
43671
+ const [os25, cpu] = runtimePlatform.split("-");
43672
+ const libc = os25.endsWith("musl") ? " --libc=musl" : "";
43306
43673
  help.push(
43307
43674
  "- Ensure optional dependencies can be installed:",
43308
43675
  " npm install --include=optional sharp",
43309
43676
  "- Ensure your package manager supports multi-platform installation:",
43310
43677
  " See https://sharp.pixelplumbing.com/install#cross-platform",
43311
43678
  "- Add platform-specific dependencies:",
43312
- ` npm install --os=${os24.replace("musl", "")}${libc} --cpu=${cpu} sharp`
43679
+ ` npm install --os=${os25.replace("musl", "")}${libc} --cpu=${cpu} sharp`
43313
43680
  );
43314
43681
  } else {
43315
43682
  help.push(
@@ -46184,15 +46551,15 @@ var require_color = __commonJS({
46184
46551
  };
46185
46552
  }
46186
46553
  function wrapConversion(toModel, graph) {
46187
- const path27 = [graph[toModel].parent, toModel];
46554
+ const path28 = [graph[toModel].parent, toModel];
46188
46555
  let fn = conversions_default[graph[toModel].parent][toModel];
46189
46556
  let cur = graph[toModel].parent;
46190
46557
  while (graph[cur].parent) {
46191
- path27.unshift(graph[cur].parent);
46558
+ path28.unshift(graph[cur].parent);
46192
46559
  fn = link(conversions_default[graph[cur].parent][cur], fn);
46193
46560
  cur = graph[cur].parent;
46194
46561
  }
46195
- fn.conversion = path27;
46562
+ fn.conversion = path28;
46196
46563
  return fn;
46197
46564
  }
46198
46565
  function route(fromModel) {
@@ -46809,7 +47176,7 @@ var require_channel = __commonJS({
46809
47176
  var require_output = __commonJS({
46810
47177
  "../../node_modules/sharp/lib/output.js"(exports2, module2) {
46811
47178
  "use strict";
46812
- var path27 = require("path");
47179
+ var path28 = require("path");
46813
47180
  var is = require_is();
46814
47181
  var sharp = require_sharp();
46815
47182
  var formats = /* @__PURE__ */ new Map([
@@ -46840,9 +47207,9 @@ var require_output = __commonJS({
46840
47207
  let err;
46841
47208
  if (!is.string(fileOut)) {
46842
47209
  err = new Error("Missing output file path");
46843
- } else if (is.string(this.options.input.file) && path27.resolve(this.options.input.file) === path27.resolve(fileOut)) {
47210
+ } else if (is.string(this.options.input.file) && path28.resolve(this.options.input.file) === path28.resolve(fileOut)) {
46844
47211
  err = new Error("Cannot use same file for input and output");
46845
- } else if (jp2Regex.test(path27.extname(fileOut)) && !this.constructor.format.jp2k.output.file) {
47212
+ } else if (jp2Regex.test(path28.extname(fileOut)) && !this.constructor.format.jp2k.output.file) {
46846
47213
  err = errJp2Save();
46847
47214
  }
46848
47215
  if (err) {
@@ -48340,6 +48707,12 @@ var init_session_host_controller = __esm({
48340
48707
  payload: { sessionId, clientId }
48341
48708
  });
48342
48709
  }
48710
+ async pruneDuplicateSessions(payload = {}) {
48711
+ return this.request({
48712
+ type: "prune_duplicate_sessions",
48713
+ payload
48714
+ });
48715
+ }
48343
48716
  async acquireWrite(payload) {
48344
48717
  return this.request({
48345
48718
  type: "acquire_write",
@@ -48506,7 +48879,7 @@ var init_adhdev_daemon = __esm({
48506
48879
  import_ws3 = require("ws");
48507
48880
  import_chalk2 = __toESM(require("chalk"));
48508
48881
  init_version();
48509
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.28" });
48882
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.29" });
48510
48883
  DANGEROUS_PATTERNS = [
48511
48884
  /\brm\s+(-[a-z]*f|-[a-z]*r|--force|--recursive)/i,
48512
48885
  /\bsudo\b/i,
@@ -49157,10 +49530,10 @@ async function runWizard(options = {}) {
49157
49530
  }
49158
49531
  async function checkForUpdate() {
49159
49532
  try {
49160
- const { execSync: execSync7 } = await import("child_process");
49533
+ const { execSync: execSync8 } = await import("child_process");
49161
49534
  let currentVersion = null;
49162
49535
  try {
49163
- currentVersion = execSync7("adhdev --version", {
49536
+ currentVersion = execSync8("adhdev --version", {
49164
49537
  encoding: "utf-8",
49165
49538
  timeout: 3e3,
49166
49539
  stdio: ["pipe", "pipe", "pipe"]
@@ -49170,7 +49543,7 @@ async function checkForUpdate() {
49170
49543
  }
49171
49544
  let latestVersion = null;
49172
49545
  try {
49173
- latestVersion = execSync7("npm show adhdev version", {
49546
+ latestVersion = execSync8("npm show adhdev version", {
49174
49547
  encoding: "utf-8",
49175
49548
  timeout: 5e3,
49176
49549
  stdio: ["pipe", "pipe", "pipe"]
@@ -49192,7 +49565,7 @@ async function checkForUpdate() {
49192
49565
  }
49193
49566
  const spinner = (await import("ora")).default("Updating adhdev CLI...").start();
49194
49567
  try {
49195
- execSync7("npm install -g adhdev@latest", {
49568
+ execSync8("npm install -g adhdev@latest", {
49196
49569
  encoding: "utf-8",
49197
49570
  timeout: 6e4,
49198
49571
  stdio: ["pipe", "pipe", "pipe"]
@@ -49276,16 +49649,16 @@ async function loginFlow() {
49276
49649
  let verificationUrl;
49277
49650
  try {
49278
49651
  const config2 = loadConfig();
49279
- const os24 = await import("os");
49652
+ const os25 = await import("os");
49280
49653
  const res = await fetch(`${SERVER_URL}/auth/cli/init`, {
49281
49654
  method: "POST",
49282
49655
  headers: { "Content-Type": "application/json" },
49283
49656
  body: JSON.stringify({
49284
49657
  clientMachineId: config2.machineId,
49285
49658
  registeredMachineId: config2.registeredMachineId,
49286
- hostname: os24.hostname(),
49287
- platform: os24.platform(),
49288
- arch: os24.arch()
49659
+ hostname: os25.hostname(),
49660
+ platform: os25.platform(),
49661
+ arch: os25.arch()
49289
49662
  })
49290
49663
  });
49291
49664
  if (!res.ok) {
@@ -49383,20 +49756,20 @@ async function startDaemonFlow() {
49383
49756
  try {
49384
49757
  const { AdhdevDaemon: AdhdevDaemon2 } = await Promise.resolve().then(() => (init_adhdev_daemon(), adhdev_daemon_exports));
49385
49758
  const daemon = new AdhdevDaemon2();
49386
- const { execSync: execSync7 } = await import("child_process");
49759
+ const { execSync: execSync8 } = await import("child_process");
49387
49760
  const { getCurrentDaemonLogPath: getCurrentDaemonLogPath2 } = await Promise.resolve().then(() => (init_src(), src_exports));
49388
49761
  const logPath = getCurrentDaemonLogPath2();
49389
- const os24 = await import("os");
49390
- const platform11 = os24.platform();
49762
+ const os25 = await import("os");
49763
+ const platform11 = os25.platform();
49391
49764
  try {
49392
49765
  if (platform11 === "win32") {
49393
- execSync7("start /B adhdev daemon >NUL 2>&1", {
49766
+ execSync8("start /B adhdev daemon >NUL 2>&1", {
49394
49767
  timeout: 3e3,
49395
49768
  stdio: "ignore",
49396
49769
  shell: "cmd.exe"
49397
49770
  });
49398
49771
  } else {
49399
- execSync7("nohup adhdev daemon >/dev/null 2>&1 &", {
49772
+ execSync8("nohup adhdev daemon >/dev/null 2>&1 &", {
49400
49773
  timeout: 3e3,
49401
49774
  stdio: "ignore"
49402
49775
  });
@@ -49825,7 +50198,7 @@ var init_supported = __esm({
49825
50198
  "source": "docs/site/data/provider-catalog.mjs"
49826
50199
  },
49827
50200
  "codex-cli": {
49828
- "status": "unverified",
50201
+ "status": "partial",
49829
50202
  "testedOn": [
49830
50203
  "macOS 26.4"
49831
50204
  ],
@@ -49837,11 +50210,12 @@ var init_supported = __esm({
49837
50210
  "send_chat",
49838
50211
  "read_chat",
49839
50212
  "resume",
50213
+ "reconnect",
49840
50214
  "stop"
49841
50215
  ],
49842
50216
  "lastValidated": "2026-04-09",
49843
- "notes": "Saved-session resume works locally, but reconnect after daemon or transport disruption is still unverified. Fresh launch still lands in an onboarding-style prompt state often enough that exact-answer send/read validation is not yet trustworthy.",
49844
- "evidence": "Manual local validation via standalone API on 2026-04-09",
50217
+ "notes": "Fresh launch, live send/read, saved-session resume, daemon-restart reconnect, and stop were validated locally after tightening onboarding-screen parsing, providerSessionId recovery, and history replay dedupe. Some older saved transcripts may still need one-time compaction if they were polluted before the fix.",
50218
+ "evidence": "Manual local validation via standalone API and session-host restart recovery on 2026-04-09",
49845
50219
  "owner": "core",
49846
50220
  "source": "docs/site/data/provider-catalog.mjs"
49847
50221
  },
@@ -49922,11 +50296,14 @@ var init_supported = __esm({
49922
50296
  "validatedFlows": [
49923
50297
  "read_chat",
49924
50298
  "new_session",
49925
- "send_chat"
50299
+ "send_chat",
50300
+ "list_sessions",
50301
+ "switch_session",
50302
+ "resolve_action"
49926
50303
  ],
49927
- "lastValidated": "2026-04-09",
49928
- "notes": "A fresh Codex extension chat could be created and answered correctly inside Antigravity. The current provider surface still does not expose dedicated list_sessions or switch_session scripts, and extension history listing remains empty in local validation.",
49929
- "evidence": "Manual local validation via standalone API on 2026-04-09",
50304
+ "lastValidated": "2026-04-10",
50305
+ "notes": "Cursor-hosted Codex on macOS now has locale-agnostic read/list/switch handling, approve-path resolve_action, and transcript cleanup for localized timestamps plus stale replay turns. It remains Partial because recent-task history can still collapse to the current chat and some send_chat attempts still fail to materialize as a real turn, even though false-success reporting is now blocked.",
50306
+ "evidence": "Manual local validation via standalone API on 2026-04-10 against Cursor-hosted Codex webview, including recent-task list/switch, approve-path resolve_action, and transcript cleanup verification",
49930
50307
  "owner": "core",
49931
50308
  "source": "docs/site/data/provider-catalog.mjs"
49932
50309
  },
@@ -50352,7 +50729,7 @@ var init_supported = __esm({
50352
50729
  "windsurf": "unverified",
50353
50730
  "aider-cli": "unverified",
50354
50731
  "claude-cli": "partial",
50355
- "codex-cli": "unverified",
50732
+ "codex-cli": "partial",
50356
50733
  "cursor-cli": "unverified",
50357
50734
  "gemini-cli": "unverified",
50358
50735
  "github-copilot-cli": "unverified",
@@ -50469,7 +50846,7 @@ var init_supported = __esm({
50469
50846
 
50470
50847
  // src/cli/index.ts
50471
50848
  var import_commander = require("commander");
50472
- var import_chalk8 = __toESM(require("chalk"));
50849
+ var import_chalk9 = __toESM(require("chalk"));
50473
50850
  init_src();
50474
50851
 
50475
50852
  // src/cli/setup-commands.ts
@@ -50859,7 +51236,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
50859
51236
  });
50860
51237
  });
50861
51238
  program2.command("standalone").description("\u{1F5A5}\uFE0F Start ADHDev Standalone Server (Local Dashboard & Embedded Daemon)").option("-p, --port <port>", "Local HTTP/WS server port", "3847").option("--host <host>", "Bind to specific host (use 0.0.0.0 for LAN access)").option("--no-open", "Prevent opening browser automatically").option("--token <token>", "Require token authentication").option("--dev", "Enable Dev Mode").action(async (options) => {
50862
- const { spawn: spawn5, execSync: execSync7 } = await import("child_process");
51239
+ const { spawn: spawn5, execSync: execSync8 } = await import("child_process");
50863
51240
  console.log(import_chalk5.default.cyan("\n Starting ADHDev Standalone Server..."));
50864
51241
  const args = [];
50865
51242
  if (options.port) args.push("--port", options.port);
@@ -50870,7 +51247,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
50870
51247
  let bin = "npx";
50871
51248
  const npxArgs = ["-y", "@adhdev/daemon-standalone@latest", ...args];
50872
51249
  try {
50873
- execSync7("adhdev-standalone --help", { stdio: "ignore" });
51250
+ execSync8("adhdev-standalone --help", { stdio: "ignore" });
50874
51251
  bin = "adhdev-standalone";
50875
51252
  } catch {
50876
51253
  console.log(import_chalk5.default.gray(" Standalone server package not found locally."));
@@ -50976,7 +51353,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
50976
51353
  `));
50977
51354
  }
50978
51355
  }));
50979
- hideCommand(program2.command("daemon:session-host").description("Inspect and control the session host").option("-p, --port <port>", "Local WS server port", "19222").option("--json", "Print raw JSON diagnostics/result").option("--limit <count>", "Number of diagnostics entries to include", "20").option("--session <sessionId>", "Target session ID").option("--restart", "Restart the target session").option("--resume", "Resume the target session").option("--stop", "Stop the target session").option("--signal <signal>", "Send a signal to the target session").option("--detach-client <clientId>", "Force-detach a client from the target session").option("--acquire-write <clientId>", "Force-acquire write ownership for a client").option("--release-write <clientId>", "Release write ownership for a client").option("--owner-type <type>", "ownerType for --acquire-write (user|agent)", "user").action(async (options) => {
51356
+ hideCommand(program2.command("daemon:session-host").description("Inspect and control the session host").option("-p, --port <port>", "Local WS server port", "19222").option("--json", "Print raw JSON diagnostics/result").option("--limit <count>", "Number of diagnostics entries to include", "20").option("--session <sessionId>", "Target session ID").option("--restart", "Restart the target session").option("--resume", "Resume the target session").option("--stop", "Stop the target session").option("--signal <signal>", "Send a signal to the target session").option("--detach-client <clientId>", "Force-detach a client from the target session").option("--prune-duplicates", "Stop and remove duplicate hosted runtimes that share the same provider session binding").option("--acquire-write <clientId>", "Force-acquire write ownership for a client").option("--release-write <clientId>", "Release write ownership for a client").option("--owner-type <type>", "ownerType for --acquire-write (user|agent)", "user").action(async (options) => {
50980
51357
  const sessionId = typeof options.session === "string" ? options.session.trim() : "";
50981
51358
  const limit = Math.max(1, Math.min(200, parseInt(options.limit, 10) || 20));
50982
51359
  const port = parseInt(options.port, 10) || 19222;
@@ -51023,6 +51400,10 @@ function registerDaemonCommands(program2, pkgVersion3) {
51023
51400
  daemonCommand = "session_host_force_detach_client";
51024
51401
  daemonArgs = { sessionId, clientId: String(options.detachClient) };
51025
51402
  directRequest = { type: "force_detach_client", payload: { sessionId, clientId: String(options.detachClient) } };
51403
+ } else if (options.pruneDuplicates) {
51404
+ daemonCommand = "session_host_prune_duplicate_sessions";
51405
+ daemonArgs = {};
51406
+ directRequest = { type: "prune_duplicate_sessions", payload: {} };
51026
51407
  } else if (options.acquireWrite) {
51027
51408
  requireSessionId();
51028
51409
  daemonCommand = "session_host_acquire_write";
@@ -51063,7 +51444,17 @@ function registerDaemonCommands(program2, pkgVersion3) {
51063
51444
  console.log(JSON.stringify(payload, null, 2));
51064
51445
  return;
51065
51446
  }
51066
- if (options.restart || options.resume || options.stop || options.signal || options.detachClient || options.acquireWrite || options.releaseWrite) {
51447
+ if (options.restart || options.resume || options.stop || options.signal || options.detachClient || options.pruneDuplicates || options.acquireWrite || options.releaseWrite) {
51448
+ if (options.pruneDuplicates) {
51449
+ const result = payload || {};
51450
+ console.log(import_chalk5.default.green("\n \u2713 Session host duplicate prune completed.\n"));
51451
+ console.log(import_chalk5.default.gray(` Source: ${source === "daemon" ? "daemon control plane" : "direct host fallback"}`));
51452
+ console.log(import_chalk5.default.gray(` Groups: ${result?.duplicateGroupCount || 0}`));
51453
+ console.log(import_chalk5.default.gray(` Kept: ${Array.isArray(result?.keptSessionIds) ? result.keptSessionIds.length : 0}`));
51454
+ console.log(import_chalk5.default.gray(` Pruned: ${Array.isArray(result?.prunedSessionIds) ? result.prunedSessionIds.length : 0}`));
51455
+ console.log();
51456
+ return;
51457
+ }
51067
51458
  const record2 = payload;
51068
51459
  console.log(import_chalk5.default.green("\n \u2713 Session host action completed.\n"));
51069
51460
  console.log(import_chalk5.default.gray(` Source: ${source === "daemon" ? "daemon control plane" : "direct host fallback"}`));
@@ -51153,7 +51544,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
51153
51544
  hideCommand(program2.command("daemon:upgrade").description("Upgrade ADHDev to latest version and restart daemon").option("--no-restart", "Upgrade only, skip daemon restart").action(async (options) => {
51154
51545
  const { isDaemonRunning: isDaemonRunning2, stopDaemon: stopDaemon2 } = await Promise.resolve().then(() => (init_adhdev_daemon(), adhdev_daemon_exports));
51155
51546
  const { stopSessionHost: stopSessionHost2 } = await Promise.resolve().then(() => (init_session_host(), session_host_exports));
51156
- const { execSync: execSync7, spawn: spawn5 } = await import("child_process");
51547
+ const { execSync: execSync8, spawn: spawn5 } = await import("child_process");
51157
51548
  const fsMod = await import("fs");
51158
51549
  const pathMod = await import("path");
51159
51550
  console.log(import_chalk5.default.bold("\n \u{1F504} ADHDev Upgrade\n"));
@@ -51173,10 +51564,10 @@ function registerDaemonCommands(program2, pkgVersion3) {
51173
51564
  while (!fsMod.existsSync(pathMod.join(gitRoot, ".git")) && gitRoot !== "/") {
51174
51565
  gitRoot = pathMod.dirname(gitRoot);
51175
51566
  }
51176
- execSync7("git pull --rebase", { cwd: gitRoot, stdio: "inherit" });
51567
+ execSync8("git pull --rebase", { cwd: gitRoot, stdio: "inherit" });
51177
51568
  console.log(import_chalk5.default.cyan("\n Building..."));
51178
- execSync7("npm run build", { cwd: launcherDir, stdio: "inherit" });
51179
- execSync7("npm link", { cwd: launcherDir, stdio: "inherit" });
51569
+ execSync8("npm run build", { cwd: launcherDir, stdio: "inherit" });
51570
+ execSync8("npm link", { cwd: launcherDir, stdio: "inherit" });
51180
51571
  console.log(import_chalk5.default.green("\n \u2713 Build complete"));
51181
51572
  } catch (e) {
51182
51573
  console.log(import_chalk5.default.red(`
@@ -51188,7 +51579,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
51188
51579
  console.log(import_chalk5.default.cyan("\n Checking for updates..."));
51189
51580
  let latest;
51190
51581
  try {
51191
- latest = execSync7("npm view adhdev version", { encoding: "utf-8" }).trim();
51582
+ latest = execSync8("npm view adhdev version", { encoding: "utf-8" }).trim();
51192
51583
  } catch (e) {
51193
51584
  console.log(import_chalk5.default.red(`
51194
51585
  \u2717 Failed to check latest version: ${e?.message}
@@ -51857,35 +52248,35 @@ function registerProviderCommands(program2) {
51857
52248
  let osPaths = {};
51858
52249
  let processNames = {};
51859
52250
  if (category === "ide") {
51860
- const fs19 = await import("fs");
51861
- const path27 = await import("path");
51862
- const os24 = await import("os");
51863
- if (os24.platform() === "darwin") {
52251
+ const fs20 = await import("fs");
52252
+ const path28 = await import("path");
52253
+ const os25 = await import("os");
52254
+ if (os25.platform() === "darwin") {
51864
52255
  while (true) {
51865
52256
  const p = (await rl.question(`macOS Application Path (e.g. /Applications/${defaultName}.app): `)).trim() || `/Applications/${defaultName}.app`;
51866
52257
  if (p === "skip") break;
51867
- if (!fs19.existsSync(p)) {
52258
+ if (!fs20.existsSync(p)) {
51868
52259
  console.log(import_chalk7.default.red(` \u2717 Path not found: ${p}`));
51869
52260
  console.log(import_chalk7.default.gray(` (Please provide the exact absolute path to the .app or binary, or type 'skip')`));
51870
52261
  continue;
51871
52262
  }
51872
52263
  console.log(import_chalk7.default.green(` \u2713 Path verified: ${p}`));
51873
52264
  osPaths["darwin"] = [p];
51874
- processNames["darwin"] = path27.basename(p, ".app");
52265
+ processNames["darwin"] = path28.basename(p, ".app");
51875
52266
  break;
51876
52267
  }
51877
- } else if (os24.platform() === "win32") {
52268
+ } else if (os25.platform() === "win32") {
51878
52269
  while (true) {
51879
52270
  const p = (await rl.question(`Windows Executable Path (e.g. C:\\Program Files\\${defaultName}\\${defaultName}.exe): `)).trim();
51880
52271
  if (!p || p === "skip") break;
51881
- if (!fs19.existsSync(p)) {
52272
+ if (!fs20.existsSync(p)) {
51882
52273
  console.log(import_chalk7.default.red(` \u2717 Path not found: ${p}`));
51883
52274
  console.log(import_chalk7.default.gray(` (Please provide the exact absolute path, or type 'skip')`));
51884
52275
  continue;
51885
52276
  }
51886
52277
  console.log(import_chalk7.default.green(` \u2713 Path verified: ${p}`));
51887
52278
  osPaths["win32"] = [p];
51888
- processNames["win32"] = path27.basename(p, ".exe");
52279
+ processNames["win32"] = path28.basename(p, ".exe");
51889
52280
  break;
51890
52281
  }
51891
52282
  }
@@ -52571,8 +52962,8 @@ function registerCdpCommands(program2) {
52571
52962
  }
52572
52963
  const output = typeof result === "string" ? result : JSON.stringify(result, null, 2);
52573
52964
  if (options.output) {
52574
- const fs19 = await import("fs");
52575
- fs19.writeFileSync(options.output, output, "utf-8");
52965
+ const fs20 = await import("fs");
52966
+ fs20.writeFileSync(options.output, output, "utf-8");
52576
52967
  console.log(import_chalk7.default.green(`
52577
52968
  \u2713 Saved to ${options.output} (${output.length} chars)
52578
52969
  `));
@@ -52675,8 +53066,8 @@ function registerCdpCommands(program2) {
52675
53066
  ws.on("message", async (data) => {
52676
53067
  const msg = JSON.parse(data.toString());
52677
53068
  if (msg.id === 1 && msg.result?.data) {
52678
- const fs19 = await import("fs");
52679
- fs19.writeFileSync(options.output, Buffer.from(msg.result.data, "base64"));
53069
+ const fs20 = await import("fs");
53070
+ fs20.writeFileSync(options.output, Buffer.from(msg.result.data, "base64"));
52680
53071
  console.log(import_chalk7.default.green(`
52681
53072
  \u2713 Screenshot saved to ${options.output}
52682
53073
  `));
@@ -52695,14 +53086,197 @@ function registerCdpCommands(program2) {
52695
53086
  });
52696
53087
  }
52697
53088
 
53089
+ // src/cli/service-commands.ts
53090
+ var import_node_fs3 = __toESM(require("fs"));
53091
+ var import_node_path2 = __toESM(require("path"));
53092
+ var import_node_os2 = __toESM(require("os"));
53093
+ var import_node_child_process = require("child_process");
53094
+ var import_chalk8 = __toESM(require("chalk"));
53095
+ var LAUNCHD_LABEL = "dev.adhf.daemon";
53096
+ var ADHDEV_DIR = import_node_path2.default.join(import_node_os2.default.homedir(), ".adhdev");
53097
+ function getDarwinPlistPath() {
53098
+ return import_node_path2.default.join(import_node_os2.default.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
53099
+ }
53100
+ function getWindowsStartupDir() {
53101
+ const appData = process.env.APPDATA || import_node_path2.default.join(import_node_os2.default.homedir(), "AppData", "Roaming");
53102
+ return import_node_path2.default.join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "Startup");
53103
+ }
53104
+ function getWindowsVbsPath() {
53105
+ return import_node_path2.default.join(getWindowsStartupDir(), "adhdev-daemon.vbs");
53106
+ }
53107
+ function resolveCliPath() {
53108
+ return import_node_fs3.default.realpathSync(process.argv[1]);
53109
+ }
53110
+ function ensureDir(dir) {
53111
+ if (!import_node_fs3.default.existsSync(dir)) import_node_fs3.default.mkdirSync(dir, { recursive: true });
53112
+ }
53113
+ function buildPlist(nodeExe, cliExe) {
53114
+ const outLog = import_node_path2.default.join(ADHDEV_DIR, "daemon-launchd.out");
53115
+ const errLog = import_node_path2.default.join(ADHDEV_DIR, "daemon-launchd.err");
53116
+ const brewPrefix = import_node_fs3.default.existsSync("/opt/homebrew/bin") ? "/opt/homebrew/bin" : "/usr/local/bin";
53117
+ return `<?xml version="1.0" encoding="UTF-8"?>
53118
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
53119
+ <plist version="1.0">
53120
+ <dict>
53121
+ <key>Label</key>
53122
+ <string>${LAUNCHD_LABEL}</string>
53123
+ <key>ProgramArguments</key>
53124
+ <array>
53125
+ <string>${nodeExe}</string>
53126
+ <string>${cliExe}</string>
53127
+ <string>daemon</string>
53128
+ </array>
53129
+ <key>RunAtLoad</key>
53130
+ <true/>
53131
+ <key>KeepAlive</key>
53132
+ <dict>
53133
+ <key>SuccessfulExit</key>
53134
+ <false/>
53135
+ </dict>
53136
+ <key>ThrottleInterval</key>
53137
+ <integer>10</integer>
53138
+ <key>StandardOutPath</key>
53139
+ <string>${outLog}</string>
53140
+ <key>StandardErrorPath</key>
53141
+ <string>${errLog}</string>
53142
+ <key>EnvironmentVariables</key>
53143
+ <dict>
53144
+ <key>PATH</key>
53145
+ <string>${brewPrefix}:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
53146
+ </dict>
53147
+ </dict>
53148
+ </plist>`;
53149
+ }
53150
+ function installDarwin(nodeExe, cliExe) {
53151
+ const plistPath = getDarwinPlistPath();
53152
+ ensureDir(ADHDEV_DIR);
53153
+ ensureDir(import_node_path2.default.dirname(plistPath));
53154
+ import_node_fs3.default.writeFileSync(plistPath, buildPlist(nodeExe, cliExe), "utf-8");
53155
+ console.log(import_chalk8.default.gray(` Plist: ${plistPath}`));
53156
+ try {
53157
+ (0, import_node_child_process.execSync)(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" });
53158
+ } catch {
53159
+ }
53160
+ try {
53161
+ (0, import_node_child_process.execSync)(`launchctl load -w "${plistPath}"`, { stdio: "ignore" });
53162
+ console.log(import_chalk8.default.green("\n \u2713 Registered as LaunchAgent \u2014 daemon will start on login."));
53163
+ console.log(import_chalk8.default.gray(` Logs: ~/.adhdev/daemon-launchd.{out,err}`));
53164
+ } catch (e) {
53165
+ console.log(import_chalk8.default.red(`
53166
+ \u2717 launchctl load failed: ${e.message}`));
53167
+ console.log(import_chalk8.default.gray(" Try: launchctl load -w ~/Library/LaunchAgents/dev.adhf.daemon.plist"));
53168
+ }
53169
+ }
53170
+ function uninstallDarwin() {
53171
+ const plistPath = getDarwinPlistPath();
53172
+ if (!import_node_fs3.default.existsSync(plistPath)) {
53173
+ console.log(import_chalk8.default.yellow("\n \u26A0 Service is not installed."));
53174
+ return;
53175
+ }
53176
+ try {
53177
+ (0, import_node_child_process.execSync)(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" });
53178
+ } catch {
53179
+ }
53180
+ import_node_fs3.default.unlinkSync(plistPath);
53181
+ console.log(import_chalk8.default.green("\n \u2713 Removed LaunchAgent. Daemon will no longer auto-start."));
53182
+ }
53183
+ function statusDarwin() {
53184
+ const plistPath = getDarwinPlistPath();
53185
+ if (!import_node_fs3.default.existsSync(plistPath)) return "not-installed";
53186
+ return "installed";
53187
+ }
53188
+ function buildVbs(cliExe) {
53189
+ return `' ADHDev Daemon Auto-Start (generated by adhdev service install)
53190
+ Set WshShell = CreateObject("WScript.Shell")
53191
+ WshShell.Run "cmd.exe /c ""node"" ""${cliExe.replace(/\\/g, "\\\\")}"" daemon", 0, False
53192
+ `;
53193
+ }
53194
+ function installWindows(cliExe) {
53195
+ const vbsPath = getWindowsVbsPath();
53196
+ ensureDir(ADHDEV_DIR);
53197
+ ensureDir(import_node_path2.default.dirname(vbsPath));
53198
+ import_node_fs3.default.writeFileSync(vbsPath, buildVbs(cliExe), "utf-8");
53199
+ console.log(import_chalk8.default.gray(` Startup script: ${vbsPath}`));
53200
+ console.log(import_chalk8.default.green("\n \u2713 Registered in Startup folder \u2014 daemon will start on login (hidden)."));
53201
+ console.log(import_chalk8.default.gray(" To start now without rebooting, run: adhdev daemon"));
53202
+ }
53203
+ function uninstallWindows() {
53204
+ const vbsPath = getWindowsVbsPath();
53205
+ if (!import_node_fs3.default.existsSync(vbsPath)) {
53206
+ console.log(import_chalk8.default.yellow("\n \u26A0 Service is not installed."));
53207
+ return;
53208
+ }
53209
+ import_node_fs3.default.unlinkSync(vbsPath);
53210
+ console.log(import_chalk8.default.green("\n \u2713 Removed Startup script. Daemon will no longer auto-start."));
53211
+ console.log(import_chalk8.default.gray(" Note: a currently running daemon is not affected. Stop with: adhdev daemon:stop"));
53212
+ }
53213
+ function statusWindows() {
53214
+ return import_node_fs3.default.existsSync(getWindowsVbsPath()) ? "installed" : "not-installed";
53215
+ }
53216
+ function registerServiceCommands(program2) {
53217
+ const svc = program2.command("service").description("\u{1F50C} Manage ADHDev as an OS background auto-start service");
53218
+ svc.command("install").description("Register ADHDev daemon to start automatically on login").action(async () => {
53219
+ console.log(import_chalk8.default.bold("\n \u{1F680} Installing ADHDev Background Service"));
53220
+ const platform11 = import_node_os2.default.platform();
53221
+ const nodeExe = process.execPath;
53222
+ const cliExe = resolveCliPath();
53223
+ console.log(import_chalk8.default.gray(` Node: ${nodeExe}`));
53224
+ console.log(import_chalk8.default.gray(` CLI: ${cliExe}`));
53225
+ console.log(import_chalk8.default.gray(` Platform: ${platform11}`));
53226
+ if (platform11 === "darwin") {
53227
+ installDarwin(nodeExe, cliExe);
53228
+ } else if (platform11 === "win32") {
53229
+ installWindows(cliExe);
53230
+ } else {
53231
+ console.log(import_chalk8.default.yellow("\n \u26A0 Auto-start service install is not supported on this platform."));
53232
+ console.log(import_chalk8.default.gray(" On Linux, create a systemd user unit manually:"));
53233
+ console.log(import_chalk8.default.gray(" ~/.config/systemd/user/adhdev-daemon.service"));
53234
+ }
53235
+ console.log();
53236
+ });
53237
+ svc.command("uninstall").description("Remove the OS background service").action(async () => {
53238
+ console.log(import_chalk8.default.bold("\n \u{1F5D1}\uFE0F Removing ADHDev Background Service"));
53239
+ const platform11 = import_node_os2.default.platform();
53240
+ if (platform11 === "darwin") {
53241
+ uninstallDarwin();
53242
+ } else if (platform11 === "win32") {
53243
+ uninstallWindows();
53244
+ } else {
53245
+ console.log(import_chalk8.default.yellow("\n \u26A0 Not supported on this platform."));
53246
+ }
53247
+ console.log();
53248
+ });
53249
+ svc.command("status").description("Check whether the OS background service is installed").action(async () => {
53250
+ const platform11 = import_node_os2.default.platform();
53251
+ let state = "not-installed";
53252
+ if (platform11 === "darwin") {
53253
+ state = statusDarwin();
53254
+ } else if (platform11 === "win32") {
53255
+ state = statusWindows();
53256
+ }
53257
+ if (state === "installed") {
53258
+ console.log(import_chalk8.default.green("\n \u2713 Service is installed. Daemon auto-starts on login."));
53259
+ if (platform11 === "darwin") {
53260
+ console.log(import_chalk8.default.gray(` Plist: ${getDarwinPlistPath()}`));
53261
+ } else {
53262
+ console.log(import_chalk8.default.gray(` Script: ${getWindowsVbsPath()}`));
53263
+ }
53264
+ } else {
53265
+ console.log(import_chalk8.default.gray("\n \u2717 Service is not installed."));
53266
+ console.log(import_chalk8.default.gray(" Run: adhdev service install"));
53267
+ }
53268
+ console.log();
53269
+ });
53270
+ }
53271
+
52698
53272
  // src/cli/index.ts
52699
53273
  init_version();
52700
53274
  var pkgVersion2 = resolvePackageVersion();
52701
53275
  if (process.platform === "win32") {
52702
53276
  const nodeMajor = Number.parseInt(process.versions.node.split(".")[0] || "0", 10);
52703
53277
  if (nodeMajor >= 24) {
52704
- console.error(import_chalk8.default.red("\n\u2717 Windows is currently unsupported on Node.js 24+ for ADHDev."));
52705
- console.error(import_chalk8.default.gray(" Install Node.js 22.x on Windows, then retry.\n"));
53278
+ console.error(import_chalk9.default.red("\n\u2717 Windows is currently unsupported on Node.js 24+ for ADHDev."));
53279
+ console.error(import_chalk9.default.gray(" Install Node.js 22.x on Windows, then retry.\n"));
52706
53280
  process.exit(1);
52707
53281
  }
52708
53282
  }
@@ -52717,6 +53291,7 @@ registerDaemonCommands(program, pkgVersion2);
52717
53291
  registerDoctorCommands(program, pkgVersion2);
52718
53292
  registerProviderCommands(program);
52719
53293
  registerCdpCommands(program);
53294
+ registerServiceCommands(program);
52720
53295
  void (async () => {
52721
53296
  const helperMode = await maybeRunDaemonUpgradeHelperFromEnv();
52722
53297
  if (helperMode) {
@@ -52725,25 +53300,26 @@ void (async () => {
52725
53300
  if (process.argv.length <= 2) {
52726
53301
  program.outputHelp();
52727
53302
  console.log();
52728
- console.log(import_chalk8.default.gray(" Quick start:"));
52729
- console.log(import_chalk8.default.gray(" adhdev setup \u2014 First-time setup & login"));
52730
- console.log(import_chalk8.default.gray(" adhdev daemon \u2014 Start unified daemon (Required)"));
52731
- console.log(import_chalk8.default.gray(" adhdev standalone \u2014 Start standalone local dashboard & daemon"));
52732
- console.log(import_chalk8.default.gray(" adhdev launch cursor \u2014 Launch IDE with CDP (e.g. cursor, windsurf)"));
52733
- console.log(import_chalk8.default.gray(" adhdev launch claude \u2014 Launch CLI agent via the running daemon"));
52734
- console.log(import_chalk8.default.gray(" adhdev status \u2014 Check current setup"));
52735
- console.log(import_chalk8.default.gray(" adhdev doctor \u2014 Diagnose install & native dependencies"));
52736
- console.log(import_chalk8.default.gray(" adhdev update \u2014 Upgrade to latest version"));
53303
+ console.log(import_chalk9.default.gray(" Quick start:"));
53304
+ console.log(import_chalk9.default.gray(" adhdev setup \u2014 First-time setup & login"));
53305
+ console.log(import_chalk9.default.gray(" adhdev daemon \u2014 Start unified daemon (Required)"));
53306
+ console.log(import_chalk9.default.gray(" adhdev standalone \u2014 Start standalone local dashboard & daemon"));
53307
+ console.log(import_chalk9.default.gray(" adhdev launch cursor \u2014 Launch IDE with CDP (e.g. cursor, windsurf)"));
53308
+ console.log(import_chalk9.default.gray(" adhdev launch claude \u2014 Launch CLI agent via the running daemon"));
53309
+ console.log(import_chalk9.default.gray(" adhdev status \u2014 Check current setup"));
53310
+ console.log(import_chalk9.default.gray(" adhdev doctor \u2014 Diagnose install & native dependencies"));
53311
+ console.log(import_chalk9.default.gray(" adhdev update \u2014 Upgrade to latest version"));
52737
53312
  console.log();
52738
- console.log(import_chalk8.default.gray(" Advanced tools:"));
52739
- console.log(import_chalk8.default.gray(" adhdev provider ... \u2014 Provider development commands"));
52740
- console.log(import_chalk8.default.gray(" adhdev cdp ... \u2014 CDP debugging tools"));
53313
+ console.log(import_chalk9.default.gray(" Advanced tools:"));
53314
+ console.log(import_chalk9.default.gray(" adhdev service \u2014 Manage OS background auto-start service"));
53315
+ console.log(import_chalk9.default.gray(" adhdev provider ... \u2014 Provider development commands"));
53316
+ console.log(import_chalk9.default.gray(" adhdev cdp ... \u2014 CDP debugging tools"));
52741
53317
  console.log();
52742
53318
  return;
52743
53319
  }
52744
53320
  await program.parseAsync(process.argv);
52745
53321
  })().catch((err) => {
52746
- console.error(import_chalk8.default.red(`
53322
+ console.error(import_chalk9.default.red(`
52747
53323
  \u2717 ${err.message}`));
52748
53324
  process.exit(1);
52749
53325
  });