@adhdev/daemon-core 0.8.93 → 0.8.94

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2507,7 +2507,7 @@ var init_provider_cli_adapter = __esm({
2507
2507
  `[${this.cliType}] Waiting for interactive prompt: hasPrompt=${hasPrompt} stableMs=${stableMs} recentOutputMs=${recentlyOutput} status=${status} startup=${startupLikelyActive} screen=${JSON.stringify(summarizeCliTraceText(screenText, 220)).slice(0, 260)}`
2508
2508
  );
2509
2509
  }
2510
- await new Promise((resolve11) => setTimeout(resolve11, 50));
2510
+ await new Promise((resolve12) => setTimeout(resolve12, 50));
2511
2511
  }
2512
2512
  const finalScreenText = this.terminalScreen.getText() || "";
2513
2513
  LOG.warn(
@@ -3095,7 +3095,7 @@ var init_provider_cli_adapter = __esm({
3095
3095
  }
3096
3096
  projectEffectiveStatus(startupModal = null) {
3097
3097
  if (this.parseErrorMessage) return "error";
3098
- if (startupModal) return "waiting_approval";
3098
+ if (startupModal || this.activeModal) return "waiting_approval";
3099
3099
  if (this.isWaitingForResponse && this.currentTurnScope && this.currentStatus === "idle") return "generating";
3100
3100
  return this.currentStatus;
3101
3101
  }
@@ -3103,12 +3103,24 @@ var init_provider_cli_adapter = __esm({
3103
3103
  getStatus() {
3104
3104
  const screenText = this.terminalScreen.getText() || "";
3105
3105
  const startupModal = this.startupParseGate ? this.getStartupConfirmationModal(screenText) : null;
3106
- const effectiveStatus = this.projectEffectiveStatus(startupModal);
3106
+ let effectiveStatus = this.projectEffectiveStatus(startupModal);
3107
+ let effectiveModal = startupModal || this.activeModal;
3108
+ if (!startupModal && !effectiveModal && typeof this.cliScripts?.parseOutput === "function") {
3109
+ try {
3110
+ const parsed = this.getScriptParsedStatus();
3111
+ const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
3112
+ if (parsed?.status === "waiting_approval" && parsedModal) {
3113
+ effectiveStatus = "waiting_approval";
3114
+ effectiveModal = parsedModal;
3115
+ }
3116
+ } catch {
3117
+ }
3118
+ }
3107
3119
  return {
3108
3120
  status: effectiveStatus,
3109
3121
  messages: [...this.committedMessages],
3110
3122
  workingDir: this.workingDir,
3111
- activeModal: startupModal || this.activeModal,
3123
+ activeModal: effectiveModal,
3112
3124
  errorMessage: this.parseErrorMessage || void 0,
3113
3125
  errorReason: this.parseErrorMessage ? "parse_error" : void 0
3114
3126
  };
@@ -3144,6 +3156,15 @@ var init_provider_cli_adapter = __esm({
3144
3156
  this.currentTurnScope,
3145
3157
  screenText
3146
3158
  );
3159
+ const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
3160
+ if (parsedModal && parsed?.status === "waiting_approval") {
3161
+ this.activeModal = parsedModal;
3162
+ this.isWaitingForResponse = true;
3163
+ if (this.currentStatus !== "waiting_approval") {
3164
+ this.setStatus("waiting_approval", "parsed_waiting_approval");
3165
+ this.onStatusChange?.();
3166
+ }
3167
+ }
3147
3168
  if (this.maybeCommitVisibleIdleTranscript(parsed)) {
3148
3169
  return this.getScriptParsedStatus();
3149
3170
  }
@@ -3348,7 +3369,7 @@ ${data.message || ""}`.trim();
3348
3369
  const deadline = Date.now() + 1e4;
3349
3370
  while (this.startupParseGate && Date.now() < deadline) {
3350
3371
  this.resolveStartupState("send_wait");
3351
- await new Promise((resolve11) => setTimeout(resolve11, 50));
3372
+ await new Promise((resolve12) => setTimeout(resolve12, 50));
3352
3373
  }
3353
3374
  }
3354
3375
  if (!allowInterventionPrompt) {
@@ -3440,12 +3461,12 @@ ${data.message || ""}`.trim();
3440
3461
  if (this.isWaitingForResponse) this.finishResponse();
3441
3462
  }, this.timeouts.maxResponse);
3442
3463
  };
3443
- await new Promise((resolve11) => {
3464
+ await new Promise((resolve12) => {
3444
3465
  let resolved = false;
3445
3466
  const resolveOnce = () => {
3446
3467
  if (resolved) return;
3447
3468
  resolved = true;
3448
- resolve11();
3469
+ resolve12();
3449
3470
  };
3450
3471
  const submit = () => {
3451
3472
  if (!this.ptyProcess) {
@@ -3619,17 +3640,17 @@ ${data.message || ""}`.trim();
3619
3640
  }
3620
3641
  }
3621
3642
  waitForStopped(timeoutMs) {
3622
- return new Promise((resolve11) => {
3643
+ return new Promise((resolve12) => {
3623
3644
  const startedAt = Date.now();
3624
3645
  const timer = setInterval(() => {
3625
3646
  if (!this.ptyProcess || this.currentStatus === "stopped") {
3626
3647
  clearInterval(timer);
3627
- resolve11(true);
3648
+ resolve12(true);
3628
3649
  return;
3629
3650
  }
3630
3651
  if (Date.now() - startedAt >= timeoutMs) {
3631
3652
  clearInterval(timer);
3632
- resolve11(false);
3653
+ resolve12(false);
3633
3654
  }
3634
3655
  }, 100);
3635
3656
  });
@@ -3794,7 +3815,22 @@ ${data.message || ""}`.trim();
3794
3815
  }
3795
3816
  resolveModal(buttonIndex) {
3796
3817
  const screenText = this.terminalScreen.getText() || "";
3797
- const modal = this.activeModal || this.getStartupConfirmationModal(screenText);
3818
+ let modal = this.activeModal || this.getStartupConfirmationModal(screenText);
3819
+ if (!modal && typeof this.cliScripts?.parseOutput === "function") {
3820
+ try {
3821
+ const parsed = this.getScriptParsedStatus();
3822
+ const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
3823
+ if (parsed?.status === "waiting_approval" && parsedModal) {
3824
+ modal = parsedModal;
3825
+ this.activeModal = parsedModal;
3826
+ if (this.currentStatus !== "waiting_approval") {
3827
+ this.setStatus("waiting_approval", "resolve_modal_parse");
3828
+ this.onStatusChange?.();
3829
+ }
3830
+ }
3831
+ } catch {
3832
+ }
3833
+ }
3798
3834
  if (!this.ptyProcess || this.currentStatus !== "waiting_approval" && !modal) return;
3799
3835
  this.clearIdleFinishCandidate("resolve_modal");
3800
3836
  this.recordTrace("resolve_modal", {
@@ -4756,15 +4792,15 @@ function resolveCommandPath(command) {
4756
4792
  return null;
4757
4793
  }
4758
4794
  function execAsync(cmd, timeoutMs = 5e3) {
4759
- return new Promise((resolve11) => {
4795
+ return new Promise((resolve12) => {
4760
4796
  const child = (0, import_child_process2.exec)(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
4761
4797
  if (err || !stdout?.trim()) {
4762
- resolve11(null);
4798
+ resolve12(null);
4763
4799
  } else {
4764
- resolve11(stdout.trim());
4800
+ resolve12(stdout.trim());
4765
4801
  }
4766
4802
  });
4767
- child.on("error", () => resolve11(null));
4803
+ child.on("error", () => resolve12(null));
4768
4804
  });
4769
4805
  }
4770
4806
  async function detectCLIs(providerLoader, options) {
@@ -5124,7 +5160,7 @@ var DaemonCdpManager = class {
5124
5160
  * Returns multiple entries if multiple IDE windows are open on same port
5125
5161
  */
5126
5162
  static listAllTargets(port) {
5127
- return new Promise((resolve11) => {
5163
+ return new Promise((resolve12) => {
5128
5164
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
5129
5165
  let data = "";
5130
5166
  res.on("data", (chunk) => data += chunk.toString());
@@ -5140,16 +5176,16 @@ var DaemonCdpManager = class {
5140
5176
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
5141
5177
  );
5142
5178
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
5143
- resolve11(mainPages.length > 0 ? mainPages : fallbackPages);
5179
+ resolve12(mainPages.length > 0 ? mainPages : fallbackPages);
5144
5180
  } catch {
5145
- resolve11([]);
5181
+ resolve12([]);
5146
5182
  }
5147
5183
  });
5148
5184
  });
5149
- req.on("error", () => resolve11([]));
5185
+ req.on("error", () => resolve12([]));
5150
5186
  req.setTimeout(2e3, () => {
5151
5187
  req.destroy();
5152
- resolve11([]);
5188
+ resolve12([]);
5153
5189
  });
5154
5190
  });
5155
5191
  }
@@ -5189,7 +5225,7 @@ var DaemonCdpManager = class {
5189
5225
  }
5190
5226
  }
5191
5227
  findTargetOnPort(port) {
5192
- return new Promise((resolve11) => {
5228
+ return new Promise((resolve12) => {
5193
5229
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
5194
5230
  let data = "";
5195
5231
  res.on("data", (chunk) => data += chunk.toString());
@@ -5200,7 +5236,7 @@ var DaemonCdpManager = class {
5200
5236
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
5201
5237
  );
5202
5238
  if (pages.length === 0) {
5203
- resolve11(targets.find((t) => t.webSocketDebuggerUrl) || null);
5239
+ resolve12(targets.find((t) => t.webSocketDebuggerUrl) || null);
5204
5240
  return;
5205
5241
  }
5206
5242
  const titleFilteredPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -5219,25 +5255,25 @@ var DaemonCdpManager = class {
5219
5255
  this._targetId = selected.target.id;
5220
5256
  }
5221
5257
  this._pageTitle = selected.target.title || "";
5222
- resolve11(selected.target);
5258
+ resolve12(selected.target);
5223
5259
  return;
5224
5260
  }
5225
5261
  if (previousTargetId) {
5226
5262
  this.log(`[CDP] Target ${previousTargetId} not found in page list`);
5227
- resolve11(null);
5263
+ resolve12(null);
5228
5264
  return;
5229
5265
  }
5230
5266
  this._pageTitle = list[0]?.title || "";
5231
- resolve11(list[0]);
5267
+ resolve12(list[0]);
5232
5268
  } catch {
5233
- resolve11(null);
5269
+ resolve12(null);
5234
5270
  }
5235
5271
  });
5236
5272
  });
5237
- req.on("error", () => resolve11(null));
5273
+ req.on("error", () => resolve12(null));
5238
5274
  req.setTimeout(2e3, () => {
5239
5275
  req.destroy();
5240
- resolve11(null);
5276
+ resolve12(null);
5241
5277
  });
5242
5278
  });
5243
5279
  }
@@ -5248,7 +5284,7 @@ var DaemonCdpManager = class {
5248
5284
  this.extensionProviders = providers;
5249
5285
  }
5250
5286
  connectToTarget(wsUrl) {
5251
- return new Promise((resolve11) => {
5287
+ return new Promise((resolve12) => {
5252
5288
  this.ws = new import_ws.default(wsUrl);
5253
5289
  this.ws.on("open", async () => {
5254
5290
  this._connected = true;
@@ -5258,17 +5294,17 @@ var DaemonCdpManager = class {
5258
5294
  }
5259
5295
  this.connectBrowserWs().catch(() => {
5260
5296
  });
5261
- resolve11(true);
5297
+ resolve12(true);
5262
5298
  });
5263
5299
  this.ws.on("message", (data) => {
5264
5300
  try {
5265
5301
  const msg = JSON.parse(data.toString());
5266
5302
  if (msg.id && this.pending.has(msg.id)) {
5267
- const { resolve: resolve12, reject } = this.pending.get(msg.id);
5303
+ const { resolve: resolve13, reject } = this.pending.get(msg.id);
5268
5304
  this.pending.delete(msg.id);
5269
5305
  this.failureCount = 0;
5270
5306
  if (msg.error) reject(new Error(msg.error.message));
5271
- else resolve12(msg.result);
5307
+ else resolve13(msg.result);
5272
5308
  } else if (msg.method === "Runtime.executionContextCreated") {
5273
5309
  this.contexts.add(msg.params.context.id);
5274
5310
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -5291,7 +5327,7 @@ var DaemonCdpManager = class {
5291
5327
  this.ws.on("error", (err) => {
5292
5328
  this.log(`[CDP] WebSocket error: ${err.message}`);
5293
5329
  this._connected = false;
5294
- resolve11(false);
5330
+ resolve12(false);
5295
5331
  });
5296
5332
  });
5297
5333
  }
@@ -5305,7 +5341,7 @@ var DaemonCdpManager = class {
5305
5341
  return;
5306
5342
  }
5307
5343
  this.log(`[CDP] Connecting browser WS for target discovery...`);
5308
- await new Promise((resolve11, reject) => {
5344
+ await new Promise((resolve12, reject) => {
5309
5345
  this.browserWs = new import_ws.default(browserWsUrl);
5310
5346
  this.browserWs.on("open", async () => {
5311
5347
  this._browserConnected = true;
@@ -5315,16 +5351,16 @@ var DaemonCdpManager = class {
5315
5351
  } catch (e) {
5316
5352
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
5317
5353
  }
5318
- resolve11();
5354
+ resolve12();
5319
5355
  });
5320
5356
  this.browserWs.on("message", (data) => {
5321
5357
  try {
5322
5358
  const msg = JSON.parse(data.toString());
5323
5359
  if (msg.id && this.browserPending.has(msg.id)) {
5324
- const { resolve: resolve12, reject: reject2 } = this.browserPending.get(msg.id);
5360
+ const { resolve: resolve13, reject: reject2 } = this.browserPending.get(msg.id);
5325
5361
  this.browserPending.delete(msg.id);
5326
5362
  if (msg.error) reject2(new Error(msg.error.message));
5327
- else resolve12(msg.result);
5363
+ else resolve13(msg.result);
5328
5364
  }
5329
5365
  } catch {
5330
5366
  }
@@ -5344,31 +5380,31 @@ var DaemonCdpManager = class {
5344
5380
  }
5345
5381
  }
5346
5382
  getBrowserWsUrl() {
5347
- return new Promise((resolve11) => {
5383
+ return new Promise((resolve12) => {
5348
5384
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
5349
5385
  let data = "";
5350
5386
  res.on("data", (chunk) => data += chunk.toString());
5351
5387
  res.on("end", () => {
5352
5388
  try {
5353
5389
  const info = JSON.parse(data);
5354
- resolve11(info.webSocketDebuggerUrl || null);
5390
+ resolve12(info.webSocketDebuggerUrl || null);
5355
5391
  } catch {
5356
- resolve11(null);
5392
+ resolve12(null);
5357
5393
  }
5358
5394
  });
5359
5395
  });
5360
- req.on("error", () => resolve11(null));
5396
+ req.on("error", () => resolve12(null));
5361
5397
  req.setTimeout(3e3, () => {
5362
5398
  req.destroy();
5363
- resolve11(null);
5399
+ resolve12(null);
5364
5400
  });
5365
5401
  });
5366
5402
  }
5367
5403
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
5368
- return new Promise((resolve11, reject) => {
5404
+ return new Promise((resolve12, reject) => {
5369
5405
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
5370
5406
  const id = this.browserMsgId++;
5371
- this.browserPending.set(id, { resolve: resolve11, reject });
5407
+ this.browserPending.set(id, { resolve: resolve12, reject });
5372
5408
  this.browserWs.send(JSON.stringify({ id, method, params }));
5373
5409
  setTimeout(() => {
5374
5410
  if (this.browserPending.has(id)) {
@@ -5408,11 +5444,11 @@ var DaemonCdpManager = class {
5408
5444
  }
5409
5445
  // ─── CDP Protocol ────────────────────────────────────────
5410
5446
  sendInternal(method, params = {}, timeoutMs = 15e3) {
5411
- return new Promise((resolve11, reject) => {
5447
+ return new Promise((resolve12, reject) => {
5412
5448
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
5413
5449
  if (this.ws.readyState !== import_ws.default.OPEN) return reject(new Error("WebSocket not open"));
5414
5450
  const id = this.msgId++;
5415
- this.pending.set(id, { resolve: resolve11, reject });
5451
+ this.pending.set(id, { resolve: resolve12, reject });
5416
5452
  this.ws.send(JSON.stringify({ id, method, params }));
5417
5453
  setTimeout(() => {
5418
5454
  if (this.pending.has(id)) {
@@ -5661,7 +5697,7 @@ var DaemonCdpManager = class {
5661
5697
  const browserWs = this.browserWs;
5662
5698
  let msgId = this.browserMsgId;
5663
5699
  const sendWs = (method, params = {}, sessionId) => {
5664
- return new Promise((resolve11, reject) => {
5700
+ return new Promise((resolve12, reject) => {
5665
5701
  const mid = msgId++;
5666
5702
  this.browserMsgId = msgId;
5667
5703
  const handler = (raw) => {
@@ -5670,7 +5706,7 @@ var DaemonCdpManager = class {
5670
5706
  if (msg.id === mid) {
5671
5707
  browserWs.removeListener("message", handler);
5672
5708
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
5673
- else resolve11(msg.result);
5709
+ else resolve12(msg.result);
5674
5710
  }
5675
5711
  } catch {
5676
5712
  }
@@ -5871,14 +5907,14 @@ var DaemonCdpManager = class {
5871
5907
  if (!ws || ws.readyState !== import_ws.default.OPEN) {
5872
5908
  throw new Error("CDP not connected");
5873
5909
  }
5874
- return new Promise((resolve11, reject) => {
5910
+ return new Promise((resolve12, reject) => {
5875
5911
  const id = getNextId();
5876
5912
  pendingMap.set(id, {
5877
5913
  resolve: (result) => {
5878
5914
  if (result?.result?.subtype === "error") {
5879
5915
  reject(new Error(result.result.description));
5880
5916
  } else {
5881
- resolve11(result?.result?.value);
5917
+ resolve12(result?.result?.value);
5882
5918
  }
5883
5919
  },
5884
5920
  reject
@@ -5910,10 +5946,10 @@ var DaemonCdpManager = class {
5910
5946
  throw new Error("CDP not connected");
5911
5947
  }
5912
5948
  const sendViaSession = (method, params = {}) => {
5913
- return new Promise((resolve11, reject) => {
5949
+ return new Promise((resolve12, reject) => {
5914
5950
  const pendingMap = this._browserConnected ? this.browserPending : this.pending;
5915
5951
  const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
5916
- pendingMap.set(id, { resolve: resolve11, reject });
5952
+ pendingMap.set(id, { resolve: resolve12, reject });
5917
5953
  ws.send(JSON.stringify({ id, sessionId, method, params }));
5918
5954
  setTimeout(() => {
5919
5955
  if (pendingMap.has(id)) {
@@ -9810,7 +9846,9 @@ function getTargetInstance(h, args) {
9810
9846
  const targetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
9811
9847
  const sessionId = targetSessionId || h.currentSession?.sessionId || "";
9812
9848
  if (!sessionId) return null;
9813
- return h.ctx.instanceManager?.getInstance(sessionId) || null;
9849
+ const session = h.ctx.sessionRegistry?.get(sessionId);
9850
+ const instanceKey = session?.adapterKey || session?.instanceKey || sessionId;
9851
+ return h.ctx.instanceManager?.getInstance(instanceKey) || null;
9814
9852
  }
9815
9853
  function getTargetTransport(h, provider) {
9816
9854
  if (h.currentSession?.transport) return h.currentSession.transport;
@@ -10107,7 +10145,7 @@ function getStateLastSignature(state) {
10107
10145
  async function getStableExtensionBaseline(h) {
10108
10146
  const first = await readExtensionChatState(h);
10109
10147
  if (getStateMessageCount(first) > 0 || getStateLastSignature(first)) return first;
10110
- await new Promise((resolve11) => setTimeout(resolve11, 150));
10148
+ await new Promise((resolve12) => setTimeout(resolve12, 150));
10111
10149
  const second = await readExtensionChatState(h);
10112
10150
  return getStateMessageCount(second) >= getStateMessageCount(first) ? second : first;
10113
10151
  }
@@ -10115,7 +10153,7 @@ async function verifyExtensionSendObserved(h, before) {
10115
10153
  const beforeCount = getStateMessageCount(before);
10116
10154
  const beforeSignature = getStateLastSignature(before);
10117
10155
  for (let attempt = 0; attempt < 12; attempt += 1) {
10118
- await new Promise((resolve11) => setTimeout(resolve11, 250));
10156
+ await new Promise((resolve12) => setTimeout(resolve12, 250));
10119
10157
  const state = await readExtensionChatState(h);
10120
10158
  if (state?.status === "waiting_approval") return true;
10121
10159
  const afterCount = getStateMessageCount(state);
@@ -10879,10 +10917,17 @@ async function handleResolveAction(h, args) {
10879
10917
  }
10880
10918
  }
10881
10919
  const status = adapter.getStatus();
10882
- if (status?.status !== "waiting_approval") {
10920
+ const targetInstance = getTargetInstance(h, args);
10921
+ const targetState = targetInstance?.getState?.();
10922
+ const surfacedModal = targetState?.activeChat?.activeModal && Array.isArray(targetState.activeChat.activeModal.buttons) && targetState.activeChat.activeModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim()) ? targetState.activeChat.activeModal : null;
10923
+ const statusModal = status?.activeModal && Array.isArray(status.activeModal.buttons) && status.activeModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim()) ? status.activeModal : null;
10924
+ const effectiveModal = statusModal || surfacedModal;
10925
+ const effectiveStatus = status?.status === "waiting_approval" || targetState?.activeChat?.status === "waiting_approval" ? "waiting_approval" : status?.status;
10926
+ LOG.info("Command", `[resolveAction] CLI PTY gate target=${String(args?.targetSessionId || "")} rawStatus=${String(status?.status || "")} effectiveStatus=${String(effectiveStatus || "")} statusModal=${statusModal ? "yes" : "no"} surfacedModal=${surfacedModal ? "yes" : "no"} instance=${targetInstance ? "yes" : "no"}`);
10927
+ if (effectiveStatus !== "waiting_approval" && !effectiveModal) {
10883
10928
  return { success: false, error: "Not in approval state" };
10884
10929
  }
10885
- const buttons = status.activeModal?.buttons || ["Allow once", "Always allow", "Deny"];
10930
+ const buttons = effectiveModal?.buttons || ["Allow once", "Always allow", "Deny"];
10886
10931
  let buttonIndex = typeof args?.buttonIndex === "number" ? args.buttonIndex : -1;
10887
10932
  if (buttonIndex < 0) {
10888
10933
  const btnLower = button.toLowerCase();
@@ -12335,7 +12380,7 @@ var DaemonCommandHandler = class {
12335
12380
  try {
12336
12381
  const http3 = await import("http");
12337
12382
  const postData = JSON.stringify(body);
12338
- const result = await new Promise((resolve11, reject) => {
12383
+ const result = await new Promise((resolve12, reject) => {
12339
12384
  const req = http3.request({
12340
12385
  hostname: "127.0.0.1",
12341
12386
  port: 19280,
@@ -12347,9 +12392,9 @@ var DaemonCommandHandler = class {
12347
12392
  res.on("data", (chunk) => data += chunk);
12348
12393
  res.on("end", () => {
12349
12394
  try {
12350
- resolve11(JSON.parse(data));
12395
+ resolve12(JSON.parse(data));
12351
12396
  } catch {
12352
- resolve11({ raw: data });
12397
+ resolve12({ raw: data });
12353
12398
  }
12354
12399
  });
12355
12400
  });
@@ -12367,15 +12412,15 @@ var DaemonCommandHandler = class {
12367
12412
  if (!providerType) return { success: false, error: "providerType required" };
12368
12413
  try {
12369
12414
  const http3 = await import("http");
12370
- const result = await new Promise((resolve11, reject) => {
12415
+ const result = await new Promise((resolve12, reject) => {
12371
12416
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
12372
12417
  let data = "";
12373
12418
  res.on("data", (chunk) => data += chunk);
12374
12419
  res.on("end", () => {
12375
12420
  try {
12376
- resolve11(JSON.parse(data));
12421
+ resolve12(JSON.parse(data));
12377
12422
  } catch {
12378
- resolve11({ raw: data });
12423
+ resolve12({ raw: data });
12379
12424
  }
12380
12425
  });
12381
12426
  }).on("error", reject);
@@ -12389,7 +12434,7 @@ var DaemonCommandHandler = class {
12389
12434
  try {
12390
12435
  const http3 = await import("http");
12391
12436
  const postData = JSON.stringify(args || {});
12392
- const result = await new Promise((resolve11, reject) => {
12437
+ const result = await new Promise((resolve12, reject) => {
12393
12438
  const req = http3.request({
12394
12439
  hostname: "127.0.0.1",
12395
12440
  port: 19280,
@@ -12401,9 +12446,9 @@ var DaemonCommandHandler = class {
12401
12446
  res.on("data", (chunk) => data += chunk);
12402
12447
  res.on("end", () => {
12403
12448
  try {
12404
- resolve11(JSON.parse(data));
12449
+ resolve12(JSON.parse(data));
12405
12450
  } catch {
12406
- resolve11({ raw: data });
12451
+ resolve12({ raw: data });
12407
12452
  }
12408
12453
  });
12409
12454
  });
@@ -12501,7 +12546,7 @@ async function waitForCliAdapterReady(adapter, options) {
12501
12546
  if (status === "stopped") {
12502
12547
  throw new Error("CLI runtime stopped before it became ready");
12503
12548
  }
12504
- await new Promise((resolve11) => setTimeout(resolve11, pollMs));
12549
+ await new Promise((resolve12) => setTimeout(resolve12, pollMs));
12505
12550
  }
12506
12551
  throw new Error(`CLI runtime did not become ready within ${timeoutMs}ms`);
12507
12552
  }
@@ -13805,13 +13850,13 @@ var AcpProviderInstance = class {
13805
13850
  }
13806
13851
  this.currentStatus = "waiting_approval";
13807
13852
  this.detectStatusTransition();
13808
- const approved = await new Promise((resolve11) => {
13809
- this.permissionResolvers.push(resolve11);
13853
+ const approved = await new Promise((resolve12) => {
13854
+ this.permissionResolvers.push(resolve12);
13810
13855
  setTimeout(() => {
13811
- const idx = this.permissionResolvers.indexOf(resolve11);
13856
+ const idx = this.permissionResolvers.indexOf(resolve12);
13812
13857
  if (idx >= 0) {
13813
13858
  this.permissionResolvers.splice(idx, 1);
13814
- resolve11(false);
13859
+ resolve12(false);
13815
13860
  }
13816
13861
  }, 3e5);
13817
13862
  });
@@ -15353,10 +15398,75 @@ var ProviderLoader = class _ProviderLoader {
15353
15398
  }
15354
15399
  static GITHUB_TARBALL_URL = "https://github.com/vilmire/adhdev-providers/archive/refs/heads/main.tar.gz";
15355
15400
  static META_FILE = ".meta.json";
15401
+ static REPO_PROVIDER_DIRNAME = "adhdev-providers";
15402
+ static SIBLING_MARKER_FILE = ".adhdev-provider-root";
15403
+ static SIBLING_ENV_VAR = "ADHDEV_USE_SIBLING_PROVIDERS";
15404
+ probeStarts = [];
15405
+ siblingLogged = false;
15406
+ userDirSource = "home-default";
15407
+ /** Process-level dedup for stderr sibling-adoption notices (shared across all ProviderLoader instances). */
15408
+ static siblingStderrLogged = /* @__PURE__ */ new Set();
15409
+ static looksLikeProviderRoot(candidate) {
15410
+ try {
15411
+ if (!fs6.existsSync(candidate) || !fs6.statSync(candidate).isDirectory()) return false;
15412
+ return ["ide", "extension", "cli", "acp"].some(
15413
+ (category) => fs6.existsSync(path13.join(candidate, category))
15414
+ );
15415
+ } catch {
15416
+ return false;
15417
+ }
15418
+ }
15419
+ static hasProviderRootMarker(candidate) {
15420
+ try {
15421
+ return fs6.existsSync(path13.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
15422
+ } catch {
15423
+ return false;
15424
+ }
15425
+ }
15426
+ detectDefaultUserDir() {
15427
+ const fallback = path13.join(os13.homedir(), ".adhdev", "providers");
15428
+ const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
15429
+ const visited = /* @__PURE__ */ new Set();
15430
+ for (const start of this.probeStarts) {
15431
+ let current = path13.resolve(start);
15432
+ while (!visited.has(current)) {
15433
+ visited.add(current);
15434
+ const siblingCandidate = path13.join(path13.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
15435
+ if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
15436
+ const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
15437
+ if (envOptIn || hasMarker) {
15438
+ const source = hasMarker ? "sibling-marker" : "sibling-env";
15439
+ if (!this.siblingLogged) {
15440
+ this.log(`Using sibling provider checkout (${source}): ${siblingCandidate}`);
15441
+ this.siblingLogged = true;
15442
+ }
15443
+ if (!_ProviderLoader.siblingStderrLogged.has(siblingCandidate)) {
15444
+ _ProviderLoader.siblingStderrLogged.add(siblingCandidate);
15445
+ try {
15446
+ process.stderr.write(
15447
+ `[adhdev] Using sibling adhdev-providers checkout (${source}): ${siblingCandidate}
15448
+ `
15449
+ );
15450
+ } catch {
15451
+ }
15452
+ }
15453
+ return { path: siblingCandidate, source };
15454
+ }
15455
+ }
15456
+ const parent = path13.dirname(current);
15457
+ if (parent === current) break;
15458
+ current = parent;
15459
+ }
15460
+ }
15461
+ return { path: fallback, source: "home-default" };
15462
+ }
15356
15463
  constructor(options) {
15357
15464
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
15465
+ this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
15358
15466
  this.defaultProvidersDir = path13.join(os13.homedir(), ".adhdev", "providers");
15359
- this.userDir = this.defaultProvidersDir;
15467
+ const detected = this.detectDefaultUserDir();
15468
+ this.userDir = detected.path;
15469
+ this.userDirSource = detected.source;
15360
15470
  this.upstreamDir = path13.join(this.defaultProvidersDir, ".upstream");
15361
15471
  this.disableUpstream = false;
15362
15472
  this.applySourceConfig({
@@ -15394,6 +15504,7 @@ var ProviderLoader = class _ProviderLoader {
15394
15504
  disableUpstream: this.disableUpstream,
15395
15505
  explicitProviderDir: this.explicitProviderDir,
15396
15506
  userDir: this.userDir,
15507
+ userDirSource: this.userDirSource,
15397
15508
  upstreamDir: this.upstreamDir,
15398
15509
  providerRoots: this.getProviderRoots()
15399
15510
  };
@@ -15404,7 +15515,14 @@ var ProviderLoader = class _ProviderLoader {
15404
15515
  this.explicitProviderDir = options.userDir?.trim() ? options.userDir : null;
15405
15516
  }
15406
15517
  this.sourceMode = nextSourceMode;
15407
- this.userDir = this.explicitProviderDir || this.defaultProvidersDir;
15518
+ if (this.explicitProviderDir) {
15519
+ this.userDir = this.explicitProviderDir;
15520
+ this.userDirSource = "explicit";
15521
+ } else {
15522
+ const detected = this.detectDefaultUserDir();
15523
+ this.userDir = detected.path;
15524
+ this.userDirSource = detected.source;
15525
+ }
15408
15526
  this.upstreamDir = path13.join(this.defaultProvidersDir, ".upstream");
15409
15527
  this.disableUpstream = this.sourceMode === "no-upstream";
15410
15528
  if (this.explicitProviderDir) {
@@ -15998,7 +16116,7 @@ var ProviderLoader = class _ProviderLoader {
15998
16116
  return { updated: false };
15999
16117
  }
16000
16118
  try {
16001
- const etag = await new Promise((resolve11, reject) => {
16119
+ const etag = await new Promise((resolve12, reject) => {
16002
16120
  const options = {
16003
16121
  method: "HEAD",
16004
16122
  hostname: "github.com",
@@ -16016,7 +16134,7 @@ var ProviderLoader = class _ProviderLoader {
16016
16134
  headers: { "User-Agent": "adhdev-launcher" },
16017
16135
  timeout: 1e4
16018
16136
  }, (res2) => {
16019
- resolve11(res2.headers.etag || res2.headers["last-modified"] || "");
16137
+ resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
16020
16138
  });
16021
16139
  req2.on("error", reject);
16022
16140
  req2.on("timeout", () => {
@@ -16025,7 +16143,7 @@ var ProviderLoader = class _ProviderLoader {
16025
16143
  });
16026
16144
  req2.end();
16027
16145
  } else {
16028
- resolve11(res.headers.etag || res.headers["last-modified"] || "");
16146
+ resolve12(res.headers.etag || res.headers["last-modified"] || "");
16029
16147
  }
16030
16148
  });
16031
16149
  req.on("error", reject);
@@ -16089,7 +16207,7 @@ var ProviderLoader = class _ProviderLoader {
16089
16207
  downloadFile(url, destPath) {
16090
16208
  const https = require("https");
16091
16209
  const http3 = require("http");
16092
- return new Promise((resolve11, reject) => {
16210
+ return new Promise((resolve12, reject) => {
16093
16211
  const doRequest = (reqUrl, redirectCount = 0) => {
16094
16212
  if (redirectCount > 5) {
16095
16213
  reject(new Error("Too many redirects"));
@@ -16109,7 +16227,7 @@ var ProviderLoader = class _ProviderLoader {
16109
16227
  res.pipe(ws);
16110
16228
  ws.on("finish", () => {
16111
16229
  ws.close();
16112
- resolve11();
16230
+ resolve12();
16113
16231
  });
16114
16232
  ws.on("error", reject);
16115
16233
  });
@@ -16584,17 +16702,17 @@ async function findFreePort(ports) {
16584
16702
  throw new Error("No free port found");
16585
16703
  }
16586
16704
  function checkPortFree(port) {
16587
- return new Promise((resolve11) => {
16705
+ return new Promise((resolve12) => {
16588
16706
  const server = net.createServer();
16589
16707
  server.unref();
16590
- server.on("error", () => resolve11(false));
16708
+ server.on("error", () => resolve12(false));
16591
16709
  server.listen(port, "127.0.0.1", () => {
16592
- server.close(() => resolve11(true));
16710
+ server.close(() => resolve12(true));
16593
16711
  });
16594
16712
  });
16595
16713
  }
16596
16714
  async function isCdpActive(port) {
16597
- return new Promise((resolve11) => {
16715
+ return new Promise((resolve12) => {
16598
16716
  const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
16599
16717
  timeout: 2e3
16600
16718
  }, (res) => {
@@ -16603,16 +16721,16 @@ async function isCdpActive(port) {
16603
16721
  res.on("end", () => {
16604
16722
  try {
16605
16723
  const info = JSON.parse(data);
16606
- resolve11(!!info["WebKit-Version"] || !!info["Browser"]);
16724
+ resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
16607
16725
  } catch {
16608
- resolve11(false);
16726
+ resolve12(false);
16609
16727
  }
16610
16728
  });
16611
16729
  });
16612
- req.on("error", () => resolve11(false));
16730
+ req.on("error", () => resolve12(false));
16613
16731
  req.on("timeout", () => {
16614
16732
  req.destroy();
16615
- resolve11(false);
16733
+ resolve12(false);
16616
16734
  });
16617
16735
  });
16618
16736
  }
@@ -17404,7 +17522,7 @@ async function waitForPidExit(pid, timeoutMs) {
17404
17522
  while (Date.now() - start < timeoutMs) {
17405
17523
  try {
17406
17524
  process.kill(pid, 0);
17407
- await new Promise((resolve11) => setTimeout(resolve11, 250));
17525
+ await new Promise((resolve12) => setTimeout(resolve12, 250));
17408
17526
  } catch {
17409
17527
  return;
17410
17528
  }
@@ -17519,7 +17637,7 @@ async function runDaemonUpgradeHelper(payload) {
17519
17637
  appendUpgradeLog(installOutput.trim());
17520
17638
  }
17521
17639
  if (process.platform === "win32") {
17522
- await new Promise((resolve11) => setTimeout(resolve11, 500));
17640
+ await new Promise((resolve12) => setTimeout(resolve12, 500));
17523
17641
  cleanupStaleGlobalInstallDirs(payload.packageName);
17524
17642
  appendUpgradeLog("Post-install staging cleanup complete");
17525
17643
  }
@@ -18861,7 +18979,7 @@ var ProviderStreamAdapter = class {
18861
18979
  const beforeCount = this.messageCount(before);
18862
18980
  const beforeSignature = this.lastMessageSignature(before);
18863
18981
  for (let attempt = 0; attempt < 12; attempt += 1) {
18864
- await new Promise((resolve11) => setTimeout(resolve11, 250));
18982
+ await new Promise((resolve12) => setTimeout(resolve12, 250));
18865
18983
  let state;
18866
18984
  try {
18867
18985
  state = await this.readChat(evaluate);
@@ -18883,7 +19001,7 @@ var ProviderStreamAdapter = class {
18883
19001
  if (this.messageCount(first) > 0 || this.lastMessageSignature(first)) {
18884
19002
  return first;
18885
19003
  }
18886
- await new Promise((resolve11) => setTimeout(resolve11, 150));
19004
+ await new Promise((resolve12) => setTimeout(resolve12, 150));
18887
19005
  const second = await this.readChat(evaluate);
18888
19006
  return this.messageCount(second) >= this.messageCount(first) ? second : first;
18889
19007
  }
@@ -19034,7 +19152,7 @@ var ProviderStreamAdapter = class {
19034
19152
  if (typeof data.error === "string" && data.error.trim()) return false;
19035
19153
  }
19036
19154
  for (let attempt = 0; attempt < 6; attempt += 1) {
19037
- await new Promise((resolve11) => setTimeout(resolve11, 250));
19155
+ await new Promise((resolve12) => setTimeout(resolve12, 250));
19038
19156
  const state = await this.readChat(evaluate);
19039
19157
  const title = this.getStateTitle(state);
19040
19158
  if (this.titlesMatch(title, sessionId)) return true;
@@ -21560,7 +21678,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
21560
21678
  return { target, instance, adapter };
21561
21679
  }
21562
21680
  function sleep(ms) {
21563
- return new Promise((resolve11) => setTimeout(resolve11, ms));
21681
+ return new Promise((resolve12) => setTimeout(resolve12, ms));
21564
21682
  }
21565
21683
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
21566
21684
  const startedAt = Date.now();
@@ -23818,15 +23936,15 @@ var DevServer = class _DevServer {
23818
23936
  this.json(res, 500, { error: e.message });
23819
23937
  }
23820
23938
  });
23821
- return new Promise((resolve11, reject) => {
23939
+ return new Promise((resolve12, reject) => {
23822
23940
  this.server.listen(port, "127.0.0.1", () => {
23823
23941
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
23824
- resolve11();
23942
+ resolve12();
23825
23943
  });
23826
23944
  this.server.on("error", (e) => {
23827
23945
  if (e.code === "EADDRINUSE") {
23828
23946
  this.log(`Port ${port} in use, skipping dev server`);
23829
- resolve11();
23947
+ resolve12();
23830
23948
  } else {
23831
23949
  reject(e);
23832
23950
  }
@@ -23908,20 +24026,20 @@ var DevServer = class _DevServer {
23908
24026
  child.stderr?.on("data", (d) => {
23909
24027
  stderr += d.toString().slice(0, 2e3);
23910
24028
  });
23911
- await new Promise((resolve11) => {
24029
+ await new Promise((resolve12) => {
23912
24030
  const timer = setTimeout(() => {
23913
24031
  child.kill();
23914
- resolve11();
24032
+ resolve12();
23915
24033
  }, 3e3);
23916
24034
  child.on("exit", () => {
23917
24035
  clearTimeout(timer);
23918
- resolve11();
24036
+ resolve12();
23919
24037
  });
23920
24038
  child.stdout?.once("data", () => {
23921
24039
  setTimeout(() => {
23922
24040
  child.kill();
23923
24041
  clearTimeout(timer);
23924
- resolve11();
24042
+ resolve12();
23925
24043
  }, 500);
23926
24044
  });
23927
24045
  });
@@ -24437,14 +24555,14 @@ var DevServer = class _DevServer {
24437
24555
  child.stderr?.on("data", (d) => {
24438
24556
  stderr += d.toString();
24439
24557
  });
24440
- await new Promise((resolve11) => {
24558
+ await new Promise((resolve12) => {
24441
24559
  const timer = setTimeout(() => {
24442
24560
  child.kill();
24443
- resolve11();
24561
+ resolve12();
24444
24562
  }, timeout);
24445
24563
  child.on("exit", () => {
24446
24564
  clearTimeout(timer);
24447
- resolve11();
24565
+ resolve12();
24448
24566
  });
24449
24567
  });
24450
24568
  const elapsed = Date.now() - start;
@@ -25114,14 +25232,14 @@ data: ${JSON.stringify(msg.data)}
25114
25232
  res.end(JSON.stringify(data, null, 2));
25115
25233
  }
25116
25234
  async readBody(req) {
25117
- return new Promise((resolve11) => {
25235
+ return new Promise((resolve12) => {
25118
25236
  let body = "";
25119
25237
  req.on("data", (chunk) => body += chunk);
25120
25238
  req.on("end", () => {
25121
25239
  try {
25122
- resolve11(JSON.parse(body));
25240
+ resolve12(JSON.parse(body));
25123
25241
  } catch {
25124
- resolve11({});
25242
+ resolve12({});
25125
25243
  }
25126
25244
  });
25127
25245
  });
@@ -25629,7 +25747,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
25629
25747
  const deadline = Date.now() + timeoutMs;
25630
25748
  while (Date.now() < deadline) {
25631
25749
  if (await canConnect(endpoint)) return;
25632
- await new Promise((resolve11) => setTimeout(resolve11, STARTUP_POLL_MS));
25750
+ await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
25633
25751
  }
25634
25752
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
25635
25753
  }
@@ -25807,10 +25925,10 @@ async function installExtension(ide, extension) {
25807
25925
  const buffer = Buffer.from(await res.arrayBuffer());
25808
25926
  const fs15 = await import("fs");
25809
25927
  fs15.writeFileSync(vsixPath, buffer);
25810
- return new Promise((resolve11) => {
25928
+ return new Promise((resolve12) => {
25811
25929
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
25812
25930
  (0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
25813
- resolve11({
25931
+ resolve12({
25814
25932
  extensionId: extension.id,
25815
25933
  marketplaceId: extension.marketplaceId,
25816
25934
  success: !error,
@@ -25823,11 +25941,11 @@ async function installExtension(ide, extension) {
25823
25941
  } catch (e) {
25824
25942
  }
25825
25943
  }
25826
- return new Promise((resolve11) => {
25944
+ return new Promise((resolve12) => {
25827
25945
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
25828
25946
  (0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
25829
25947
  if (error) {
25830
- resolve11({
25948
+ resolve12({
25831
25949
  extensionId: extension.id,
25832
25950
  marketplaceId: extension.marketplaceId,
25833
25951
  success: false,
@@ -25835,7 +25953,7 @@ async function installExtension(ide, extension) {
25835
25953
  error: stderr || error.message
25836
25954
  });
25837
25955
  } else {
25838
- resolve11({
25956
+ resolve12({
25839
25957
  extensionId: extension.id,
25840
25958
  marketplaceId: extension.marketplaceId,
25841
25959
  success: true,