@adhdev/daemon-core 0.8.57 → 0.8.58

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.
Files changed (35) hide show
  1. package/dist/boot/daemon-lifecycle.d.ts +1 -0
  2. package/dist/commands/handler.d.ts +1 -0
  3. package/dist/commands/stream-commands.d.ts +2 -0
  4. package/dist/config/chat-history.d.ts +3 -0
  5. package/dist/config/config.d.ts +3 -0
  6. package/dist/config/provider-source-config.d.ts +23 -0
  7. package/dist/daemon/dev-server-types.d.ts +1 -0
  8. package/dist/daemon/dev-server.d.ts +4 -0
  9. package/dist/index.d.ts +2 -0
  10. package/dist/index.js +316 -155
  11. package/dist/index.js.map +1 -1
  12. package/dist/index.mjs +315 -155
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/providers/cli-provider-instance.d.ts +9 -0
  15. package/dist/providers/contracts.d.ts +1 -0
  16. package/dist/providers/provider-loader.d.ts +14 -1
  17. package/node_modules/@adhdev/session-host-core/package.json +1 -1
  18. package/package.json +1 -1
  19. package/src/boot/daemon-lifecycle.ts +13 -3
  20. package/src/commands/handler.ts +3 -0
  21. package/src/commands/router.ts +5 -4
  22. package/src/commands/stream-commands.ts +41 -0
  23. package/src/config/chat-history.ts +39 -0
  24. package/src/config/config.d.ts +3 -0
  25. package/src/config/config.ts +19 -3
  26. package/src/config/provider-source-config.ts +42 -0
  27. package/src/daemon/dev-auto-implement.ts +0 -13
  28. package/src/daemon/dev-server-types.ts +1 -0
  29. package/src/daemon/dev-server.ts +45 -20
  30. package/src/index.ts +2 -0
  31. package/src/providers/cli-provider-instance.ts +25 -0
  32. package/src/providers/contracts.ts +1 -0
  33. package/src/providers/provider-loader.d.ts +4 -1
  34. package/src/providers/provider-loader.ts +61 -23
  35. package/src/providers/provider-schema.ts +3 -0
package/dist/index.mjs CHANGED
@@ -35,6 +35,7 @@ __export(config_exports, {
35
35
  loadConfig: () => loadConfig,
36
36
  markSetupComplete: () => markSetupComplete,
37
37
  resetConfig: () => resetConfig,
38
+ resolveProviderSourceMode: () => resolveProviderSourceMode,
38
39
  saveConfig: () => saveConfig,
39
40
  updateConfig: () => updateConfig
40
41
  });
@@ -42,6 +43,12 @@ import { homedir } from "os";
42
43
  import { join } from "path";
43
44
  import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync } from "fs";
44
45
  import { randomUUID } from "crypto";
46
+ function resolveProviderSourceMode(providerSourceMode, legacyDisableUpstream) {
47
+ if (providerSourceMode === "normal" || providerSourceMode === "no-upstream") {
48
+ return providerSourceMode;
49
+ }
50
+ return legacyDisableUpstream === true ? "no-upstream" : "normal";
51
+ }
45
52
  function isPlainObject(value) {
46
53
  return !!value && typeof value === "object" && !Array.isArray(value);
47
54
  }
@@ -79,7 +86,7 @@ function normalizeConfig(raw) {
79
86
  registeredMachineId: asOptionalString(parsed.registeredMachineId),
80
87
  providerSettings: isPlainObject(parsed.providerSettings) ? parsed.providerSettings : {},
81
88
  ideSettings: isPlainObject(parsed.ideSettings) ? parsed.ideSettings : {},
82
- disableUpstream: asBoolean(parsed.disableUpstream, DEFAULT_CONFIG.disableUpstream ?? false),
89
+ providerSourceMode: resolveProviderSourceMode(parsed.providerSourceMode, parsed.disableUpstream),
83
90
  providerDir: asOptionalString(parsed.providerDir),
84
91
  terminalSizingMode: parsed.terminalSizingMode === "fit" ? "fit" : "measured"
85
92
  };
@@ -224,7 +231,7 @@ var init_config = __esm({
224
231
  registeredMachineId: void 0,
225
232
  providerSettings: {},
226
233
  ideSettings: {},
227
- disableUpstream: false,
234
+ providerSourceMode: "normal",
228
235
  terminalSizingMode: "measured"
229
236
  };
230
237
  MACHINE_ID_PREFIX = "mach_";
@@ -1894,7 +1901,7 @@ var init_provider_cli_adapter = __esm({
1894
1901
  `[${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)}`
1895
1902
  );
1896
1903
  }
1897
- await new Promise((resolve12) => setTimeout(resolve12, 50));
1904
+ await new Promise((resolve11) => setTimeout(resolve11, 50));
1898
1905
  }
1899
1906
  const finalScreenText = this.terminalScreen.getText() || "";
1900
1907
  LOG.warn(
@@ -2467,7 +2474,7 @@ ${data.message || ""}`.trim();
2467
2474
  const deadline = Date.now() + 1e4;
2468
2475
  while (this.startupParseGate && Date.now() < deadline) {
2469
2476
  this.resolveStartupState("send_wait");
2470
- await new Promise((resolve12) => setTimeout(resolve12, 50));
2477
+ await new Promise((resolve11) => setTimeout(resolve11, 50));
2471
2478
  }
2472
2479
  }
2473
2480
  await this.waitForInteractivePrompt();
@@ -2537,12 +2544,12 @@ ${data.message || ""}`.trim();
2537
2544
  if (this.isWaitingForResponse) this.finishResponse();
2538
2545
  }, this.timeouts.maxResponse);
2539
2546
  };
2540
- await new Promise((resolve12) => {
2547
+ await new Promise((resolve11) => {
2541
2548
  let resolved = false;
2542
2549
  const resolveOnce = () => {
2543
2550
  if (resolved) return;
2544
2551
  resolved = true;
2545
- resolve12();
2552
+ resolve11();
2546
2553
  };
2547
2554
  const submit = () => {
2548
2555
  if (!this.ptyProcess) {
@@ -2716,17 +2723,17 @@ ${data.message || ""}`.trim();
2716
2723
  }
2717
2724
  }
2718
2725
  waitForStopped(timeoutMs) {
2719
- return new Promise((resolve12) => {
2726
+ return new Promise((resolve11) => {
2720
2727
  const startedAt = Date.now();
2721
2728
  const timer = setInterval(() => {
2722
2729
  if (!this.ptyProcess || this.currentStatus === "stopped") {
2723
2730
  clearInterval(timer);
2724
- resolve12(true);
2731
+ resolve11(true);
2725
2732
  return;
2726
2733
  }
2727
2734
  if (Date.now() - startedAt >= timeoutMs) {
2728
2735
  clearInterval(timer);
2729
- resolve12(false);
2736
+ resolve11(false);
2730
2737
  }
2731
2738
  }, 100);
2732
2739
  });
@@ -3465,15 +3472,15 @@ function resolveCommandPath(command) {
3465
3472
  return null;
3466
3473
  }
3467
3474
  function execAsync(cmd, timeoutMs = 5e3) {
3468
- return new Promise((resolve12) => {
3475
+ return new Promise((resolve11) => {
3469
3476
  const child = exec(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
3470
3477
  if (err || !stdout?.trim()) {
3471
- resolve12(null);
3478
+ resolve11(null);
3472
3479
  } else {
3473
- resolve12(stdout.trim());
3480
+ resolve11(stdout.trim());
3474
3481
  }
3475
3482
  });
3476
- child.on("error", () => resolve12(null));
3483
+ child.on("error", () => resolve11(null));
3477
3484
  });
3478
3485
  }
3479
3486
  async function detectCLIs(providerLoader, options) {
@@ -3684,7 +3691,7 @@ var DaemonCdpManager = class {
3684
3691
  * Returns multiple entries if multiple IDE windows are open on same port
3685
3692
  */
3686
3693
  static listAllTargets(port) {
3687
- return new Promise((resolve12) => {
3694
+ return new Promise((resolve11) => {
3688
3695
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
3689
3696
  let data = "";
3690
3697
  res.on("data", (chunk) => data += chunk.toString());
@@ -3700,16 +3707,16 @@ var DaemonCdpManager = class {
3700
3707
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
3701
3708
  );
3702
3709
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
3703
- resolve12(mainPages.length > 0 ? mainPages : fallbackPages);
3710
+ resolve11(mainPages.length > 0 ? mainPages : fallbackPages);
3704
3711
  } catch {
3705
- resolve12([]);
3712
+ resolve11([]);
3706
3713
  }
3707
3714
  });
3708
3715
  });
3709
- req.on("error", () => resolve12([]));
3716
+ req.on("error", () => resolve11([]));
3710
3717
  req.setTimeout(2e3, () => {
3711
3718
  req.destroy();
3712
- resolve12([]);
3719
+ resolve11([]);
3713
3720
  });
3714
3721
  });
3715
3722
  }
@@ -3749,7 +3756,7 @@ var DaemonCdpManager = class {
3749
3756
  }
3750
3757
  }
3751
3758
  findTargetOnPort(port) {
3752
- return new Promise((resolve12) => {
3759
+ return new Promise((resolve11) => {
3753
3760
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
3754
3761
  let data = "";
3755
3762
  res.on("data", (chunk) => data += chunk.toString());
@@ -3760,7 +3767,7 @@ var DaemonCdpManager = class {
3760
3767
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
3761
3768
  );
3762
3769
  if (pages.length === 0) {
3763
- resolve12(targets.find((t) => t.webSocketDebuggerUrl) || null);
3770
+ resolve11(targets.find((t) => t.webSocketDebuggerUrl) || null);
3764
3771
  return;
3765
3772
  }
3766
3773
  const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -3770,24 +3777,24 @@ var DaemonCdpManager = class {
3770
3777
  const specific = list.find((t) => t.id === this._targetId);
3771
3778
  if (specific) {
3772
3779
  this._pageTitle = specific.title || "";
3773
- resolve12(specific);
3780
+ resolve11(specific);
3774
3781
  } else {
3775
3782
  this.log(`[CDP] Target ${this._targetId} not found in page list`);
3776
- resolve12(null);
3783
+ resolve11(null);
3777
3784
  }
3778
3785
  return;
3779
3786
  }
3780
3787
  this._pageTitle = list[0]?.title || "";
3781
- resolve12(list[0]);
3788
+ resolve11(list[0]);
3782
3789
  } catch {
3783
- resolve12(null);
3790
+ resolve11(null);
3784
3791
  }
3785
3792
  });
3786
3793
  });
3787
- req.on("error", () => resolve12(null));
3794
+ req.on("error", () => resolve11(null));
3788
3795
  req.setTimeout(2e3, () => {
3789
3796
  req.destroy();
3790
- resolve12(null);
3797
+ resolve11(null);
3791
3798
  });
3792
3799
  });
3793
3800
  }
@@ -3798,7 +3805,7 @@ var DaemonCdpManager = class {
3798
3805
  this.extensionProviders = providers;
3799
3806
  }
3800
3807
  connectToTarget(wsUrl) {
3801
- return new Promise((resolve12) => {
3808
+ return new Promise((resolve11) => {
3802
3809
  this.ws = new WebSocket(wsUrl);
3803
3810
  this.ws.on("open", async () => {
3804
3811
  this._connected = true;
@@ -3808,17 +3815,17 @@ var DaemonCdpManager = class {
3808
3815
  }
3809
3816
  this.connectBrowserWs().catch(() => {
3810
3817
  });
3811
- resolve12(true);
3818
+ resolve11(true);
3812
3819
  });
3813
3820
  this.ws.on("message", (data) => {
3814
3821
  try {
3815
3822
  const msg = JSON.parse(data.toString());
3816
3823
  if (msg.id && this.pending.has(msg.id)) {
3817
- const { resolve: resolve13, reject } = this.pending.get(msg.id);
3824
+ const { resolve: resolve12, reject } = this.pending.get(msg.id);
3818
3825
  this.pending.delete(msg.id);
3819
3826
  this.failureCount = 0;
3820
3827
  if (msg.error) reject(new Error(msg.error.message));
3821
- else resolve13(msg.result);
3828
+ else resolve12(msg.result);
3822
3829
  } else if (msg.method === "Runtime.executionContextCreated") {
3823
3830
  this.contexts.add(msg.params.context.id);
3824
3831
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -3841,7 +3848,7 @@ var DaemonCdpManager = class {
3841
3848
  this.ws.on("error", (err) => {
3842
3849
  this.log(`[CDP] WebSocket error: ${err.message}`);
3843
3850
  this._connected = false;
3844
- resolve12(false);
3851
+ resolve11(false);
3845
3852
  });
3846
3853
  });
3847
3854
  }
@@ -3855,7 +3862,7 @@ var DaemonCdpManager = class {
3855
3862
  return;
3856
3863
  }
3857
3864
  this.log(`[CDP] Connecting browser WS for target discovery...`);
3858
- await new Promise((resolve12, reject) => {
3865
+ await new Promise((resolve11, reject) => {
3859
3866
  this.browserWs = new WebSocket(browserWsUrl);
3860
3867
  this.browserWs.on("open", async () => {
3861
3868
  this._browserConnected = true;
@@ -3865,16 +3872,16 @@ var DaemonCdpManager = class {
3865
3872
  } catch (e) {
3866
3873
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
3867
3874
  }
3868
- resolve12();
3875
+ resolve11();
3869
3876
  });
3870
3877
  this.browserWs.on("message", (data) => {
3871
3878
  try {
3872
3879
  const msg = JSON.parse(data.toString());
3873
3880
  if (msg.id && this.browserPending.has(msg.id)) {
3874
- const { resolve: resolve13, reject: reject2 } = this.browserPending.get(msg.id);
3881
+ const { resolve: resolve12, reject: reject2 } = this.browserPending.get(msg.id);
3875
3882
  this.browserPending.delete(msg.id);
3876
3883
  if (msg.error) reject2(new Error(msg.error.message));
3877
- else resolve13(msg.result);
3884
+ else resolve12(msg.result);
3878
3885
  }
3879
3886
  } catch {
3880
3887
  }
@@ -3894,31 +3901,31 @@ var DaemonCdpManager = class {
3894
3901
  }
3895
3902
  }
3896
3903
  getBrowserWsUrl() {
3897
- return new Promise((resolve12) => {
3904
+ return new Promise((resolve11) => {
3898
3905
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
3899
3906
  let data = "";
3900
3907
  res.on("data", (chunk) => data += chunk.toString());
3901
3908
  res.on("end", () => {
3902
3909
  try {
3903
3910
  const info = JSON.parse(data);
3904
- resolve12(info.webSocketDebuggerUrl || null);
3911
+ resolve11(info.webSocketDebuggerUrl || null);
3905
3912
  } catch {
3906
- resolve12(null);
3913
+ resolve11(null);
3907
3914
  }
3908
3915
  });
3909
3916
  });
3910
- req.on("error", () => resolve12(null));
3917
+ req.on("error", () => resolve11(null));
3911
3918
  req.setTimeout(3e3, () => {
3912
3919
  req.destroy();
3913
- resolve12(null);
3920
+ resolve11(null);
3914
3921
  });
3915
3922
  });
3916
3923
  }
3917
3924
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
3918
- return new Promise((resolve12, reject) => {
3925
+ return new Promise((resolve11, reject) => {
3919
3926
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
3920
3927
  const id = this.browserMsgId++;
3921
- this.browserPending.set(id, { resolve: resolve12, reject });
3928
+ this.browserPending.set(id, { resolve: resolve11, reject });
3922
3929
  this.browserWs.send(JSON.stringify({ id, method, params }));
3923
3930
  setTimeout(() => {
3924
3931
  if (this.browserPending.has(id)) {
@@ -3958,11 +3965,11 @@ var DaemonCdpManager = class {
3958
3965
  }
3959
3966
  // ─── CDP Protocol ────────────────────────────────────────
3960
3967
  sendInternal(method, params = {}, timeoutMs = 15e3) {
3961
- return new Promise((resolve12, reject) => {
3968
+ return new Promise((resolve11, reject) => {
3962
3969
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
3963
3970
  if (this.ws.readyState !== WebSocket.OPEN) return reject(new Error("WebSocket not open"));
3964
3971
  const id = this.msgId++;
3965
- this.pending.set(id, { resolve: resolve12, reject });
3972
+ this.pending.set(id, { resolve: resolve11, reject });
3966
3973
  this.ws.send(JSON.stringify({ id, method, params }));
3967
3974
  setTimeout(() => {
3968
3975
  if (this.pending.has(id)) {
@@ -4211,7 +4218,7 @@ var DaemonCdpManager = class {
4211
4218
  const browserWs = this.browserWs;
4212
4219
  let msgId = this.browserMsgId;
4213
4220
  const sendWs = (method, params = {}, sessionId) => {
4214
- return new Promise((resolve12, reject) => {
4221
+ return new Promise((resolve11, reject) => {
4215
4222
  const mid = msgId++;
4216
4223
  this.browserMsgId = msgId;
4217
4224
  const handler = (raw) => {
@@ -4220,7 +4227,7 @@ var DaemonCdpManager = class {
4220
4227
  if (msg.id === mid) {
4221
4228
  browserWs.removeListener("message", handler);
4222
4229
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
4223
- else resolve12(msg.result);
4230
+ else resolve11(msg.result);
4224
4231
  }
4225
4232
  } catch {
4226
4233
  }
@@ -4421,14 +4428,14 @@ var DaemonCdpManager = class {
4421
4428
  if (!ws || ws.readyState !== WebSocket.OPEN) {
4422
4429
  throw new Error("CDP not connected");
4423
4430
  }
4424
- return new Promise((resolve12, reject) => {
4431
+ return new Promise((resolve11, reject) => {
4425
4432
  const id = getNextId();
4426
4433
  pendingMap.set(id, {
4427
4434
  resolve: (result) => {
4428
4435
  if (result?.result?.subtype === "error") {
4429
4436
  reject(new Error(result.result.description));
4430
4437
  } else {
4431
- resolve12(result?.result?.value);
4438
+ resolve11(result?.result?.value);
4432
4439
  }
4433
4440
  },
4434
4441
  reject
@@ -4460,10 +4467,10 @@ var DaemonCdpManager = class {
4460
4467
  throw new Error("CDP not connected");
4461
4468
  }
4462
4469
  const sendViaSession = (method, params = {}) => {
4463
- return new Promise((resolve12, reject) => {
4470
+ return new Promise((resolve11, reject) => {
4464
4471
  const pendingMap = this._browserConnected ? this.browserPending : this.pending;
4465
4472
  const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
4466
- pendingMap.set(id, { resolve: resolve12, reject });
4473
+ pendingMap.set(id, { resolve: resolve11, reject });
4467
4474
  ws.send(JSON.stringify({ id, sessionId, method, params }));
4468
4475
  setTimeout(() => {
4469
4476
  if (pendingMap.has(id)) {
@@ -5373,6 +5380,30 @@ var ChatHistoryWriter = class {
5373
5380
  options.historySessionId
5374
5381
  );
5375
5382
  }
5383
+ writeSessionStart(agentType, historySessionId, workspace, instanceId) {
5384
+ const id = String(historySessionId || "").trim();
5385
+ const ws = String(workspace || "").trim();
5386
+ if (!id || !ws) return;
5387
+ try {
5388
+ const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
5389
+ fs3.mkdirSync(dir, { recursive: true });
5390
+ const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
5391
+ const filePath = path7.join(dir, `${this.sanitize(id)}_${date}.jsonl`);
5392
+ const record = {
5393
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
5394
+ receivedAt: Date.now(),
5395
+ role: "system",
5396
+ kind: "session_start",
5397
+ content: ws,
5398
+ agent: agentType,
5399
+ instanceId,
5400
+ historySessionId: id,
5401
+ workspace: ws
5402
+ };
5403
+ fs3.appendFileSync(filePath, JSON.stringify(record) + "\n", "utf-8");
5404
+ } catch {
5405
+ }
5406
+ }
5376
5407
  promoteHistorySession(agentType, previousHistorySessionId, nextHistorySessionId) {
5377
5408
  const fromId = String(previousHistorySessionId || "").trim();
5378
5409
  const toId = String(nextHistorySessionId || "").trim();
@@ -5592,6 +5623,7 @@ function listSavedHistorySessions(agentType, options = {}) {
5592
5623
  let lastMessageAt = 0;
5593
5624
  let sessionTitle = "";
5594
5625
  let preview = "";
5626
+ let workspace = "";
5595
5627
  for (const file of files.sort()) {
5596
5628
  const filePath = path7.join(dir, file);
5597
5629
  const content = fs3.readFileSync(filePath, "utf-8");
@@ -5604,6 +5636,10 @@ function listSavedHistorySessions(agentType, options = {}) {
5604
5636
  parsed = null;
5605
5637
  }
5606
5638
  if (!parsed || parsed.historySessionId !== historySessionId) continue;
5639
+ if (parsed.kind === "session_start") {
5640
+ if (!workspace && parsed.workspace) workspace = parsed.workspace;
5641
+ continue;
5642
+ }
5607
5643
  messageCount += 1;
5608
5644
  if (!firstMessageAt || parsed.receivedAt < firstMessageAt) firstMessageAt = parsed.receivedAt;
5609
5645
  if (!lastMessageAt || parsed.receivedAt > lastMessageAt) lastMessageAt = parsed.receivedAt;
@@ -5618,7 +5654,8 @@ function listSavedHistorySessions(agentType, options = {}) {
5618
5654
  messageCount,
5619
5655
  firstMessageAt,
5620
5656
  lastMessageAt,
5621
- preview: preview || void 0
5657
+ preview: preview || void 0,
5658
+ workspace: workspace || void 0
5622
5659
  });
5623
5660
  }
5624
5661
  summaries.sort((a, b) => b.lastMessageAt - a.lastMessageAt);
@@ -7993,7 +8030,7 @@ function getStateLastSignature(state) {
7993
8030
  async function getStableExtensionBaseline(h) {
7994
8031
  const first = await readExtensionChatState(h);
7995
8032
  if (getStateMessageCount(first) > 0 || getStateLastSignature(first)) return first;
7996
- await new Promise((resolve12) => setTimeout(resolve12, 150));
8033
+ await new Promise((resolve11) => setTimeout(resolve11, 150));
7997
8034
  const second = await readExtensionChatState(h);
7998
8035
  return getStateMessageCount(second) >= getStateMessageCount(first) ? second : first;
7999
8036
  }
@@ -8001,7 +8038,7 @@ async function verifyExtensionSendObserved(h, before) {
8001
8038
  const beforeCount = getStateMessageCount(before);
8002
8039
  const beforeSignature = getStateLastSignature(before);
8003
8040
  for (let attempt = 0; attempt < 12; attempt += 1) {
8004
- await new Promise((resolve12) => setTimeout(resolve12, 250));
8041
+ await new Promise((resolve11) => setTimeout(resolve11, 250));
8005
8042
  const state = await readExtensionChatState(h);
8006
8043
  if (state?.status === "waiting_approval") return true;
8007
8044
  const afterCount = getStateMessageCount(state);
@@ -9193,6 +9230,30 @@ async function handleFileListBrowse(h, args) {
9193
9230
  }
9194
9231
  }
9195
9232
 
9233
+ // src/commands/stream-commands.ts
9234
+ init_config();
9235
+
9236
+ // src/config/provider-source-config.ts
9237
+ function normalizeProviderDir(value) {
9238
+ if (typeof value !== "string") return void 0;
9239
+ const trimmed = value.trim();
9240
+ return trimmed ? trimmed : void 0;
9241
+ }
9242
+ function parseProviderSourceConfigUpdate(input) {
9243
+ const updates = {};
9244
+ if (Object.prototype.hasOwnProperty.call(input, "providerSourceMode")) {
9245
+ const { providerSourceMode } = input;
9246
+ if (providerSourceMode !== "normal" && providerSourceMode !== "no-upstream") {
9247
+ return { ok: false, error: "providerSourceMode must be 'normal' or 'no-upstream'" };
9248
+ }
9249
+ updates.providerSourceMode = providerSourceMode;
9250
+ }
9251
+ if (Object.prototype.hasOwnProperty.call(input, "providerDir")) {
9252
+ updates.providerDir = normalizeProviderDir(input.providerDir);
9253
+ }
9254
+ return { ok: true, updates };
9255
+ }
9256
+
9196
9257
  // src/providers/cli-script-results.ts
9197
9258
  function parseCliScriptResult(result) {
9198
9259
  if (typeof result === "string") {
@@ -9305,6 +9366,38 @@ async function handleSetProviderSetting(h, args) {
9305
9366
  }
9306
9367
  return { success: false, error: `Failed to set ${providerType}.${key} \u2014 invalid key, value, or not a public setting` };
9307
9368
  }
9369
+ function handleGetProviderSourceConfig(h, _args) {
9370
+ const loader = h.ctx.providerLoader;
9371
+ if (!loader) return { success: false, error: "providerLoader not available" };
9372
+ return { success: true, ...loader.getSourceConfig() };
9373
+ }
9374
+ async function handleSetProviderSourceConfig(h, args) {
9375
+ const loader = h.ctx.providerLoader;
9376
+ if (!loader) return { success: false, error: "providerLoader not available" };
9377
+ const parsed = parseProviderSourceConfigUpdate(args || {});
9378
+ if ("error" in parsed) {
9379
+ return { success: false, error: parsed.error };
9380
+ }
9381
+ const currentConfig2 = loadConfig();
9382
+ const nextConfig = {
9383
+ ...currentConfig2,
9384
+ ...parsed.updates.providerSourceMode ? { providerSourceMode: parsed.updates.providerSourceMode } : {},
9385
+ ...Object.prototype.hasOwnProperty.call(parsed.updates, "providerDir") ? { providerDir: parsed.updates.providerDir } : {}
9386
+ };
9387
+ saveConfig(nextConfig);
9388
+ const sourceConfig = loader.applySourceConfig({
9389
+ sourceMode: nextConfig.providerSourceMode,
9390
+ userDir: Object.prototype.hasOwnProperty.call(parsed.updates, "providerDir") ? parsed.updates.providerDir : loader.getSourceConfig().explicitProviderDir || void 0
9391
+ });
9392
+ loader.reload();
9393
+ loader.registerToDetector();
9394
+ await h.ctx.onProviderSourceConfigChanged?.();
9395
+ LOG.info(
9396
+ "Command",
9397
+ `[set_provider_source_config] mode=${sourceConfig.sourceMode} explicitProviderDir=${sourceConfig.explicitProviderDir || "-"} userDir=${sourceConfig.userDir}`
9398
+ );
9399
+ return { success: true, reloaded: true, ...sourceConfig };
9400
+ }
9308
9401
  function normalizeProviderScriptArgs(args) {
9309
9402
  const normalizedArgs = { ...args || {} };
9310
9403
  for (const key of ["mode", "model", "message", "action", "button", "text", "sessionId", "value"]) {
@@ -9998,6 +10091,10 @@ var DaemonCommandHandler = class {
9998
10091
  return handleGetProviderSettings(this, args);
9999
10092
  case "set_provider_setting":
10000
10093
  return handleSetProviderSetting(this, args);
10094
+ case "get_provider_source_config":
10095
+ return handleGetProviderSourceConfig(this, args);
10096
+ case "set_provider_source_config":
10097
+ return handleSetProviderSourceConfig(this, args);
10001
10098
  // ─── IDE Extension Settings (stream-commands.ts) ──────────
10002
10099
  case "get_ide_extensions":
10003
10100
  return handleGetIdeExtensions(this, args);
@@ -10037,7 +10134,7 @@ var DaemonCommandHandler = class {
10037
10134
  try {
10038
10135
  const http3 = await import("http");
10039
10136
  const postData = JSON.stringify(body);
10040
- const result = await new Promise((resolve12, reject) => {
10137
+ const result = await new Promise((resolve11, reject) => {
10041
10138
  const req = http3.request({
10042
10139
  hostname: "127.0.0.1",
10043
10140
  port: 19280,
@@ -10049,9 +10146,9 @@ var DaemonCommandHandler = class {
10049
10146
  res.on("data", (chunk) => data += chunk);
10050
10147
  res.on("end", () => {
10051
10148
  try {
10052
- resolve12(JSON.parse(data));
10149
+ resolve11(JSON.parse(data));
10053
10150
  } catch {
10054
- resolve12({ raw: data });
10151
+ resolve11({ raw: data });
10055
10152
  }
10056
10153
  });
10057
10154
  });
@@ -10069,15 +10166,15 @@ var DaemonCommandHandler = class {
10069
10166
  if (!providerType) return { success: false, error: "providerType required" };
10070
10167
  try {
10071
10168
  const http3 = await import("http");
10072
- const result = await new Promise((resolve12, reject) => {
10169
+ const result = await new Promise((resolve11, reject) => {
10073
10170
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
10074
10171
  let data = "";
10075
10172
  res.on("data", (chunk) => data += chunk);
10076
10173
  res.on("end", () => {
10077
10174
  try {
10078
- resolve12(JSON.parse(data));
10175
+ resolve11(JSON.parse(data));
10079
10176
  } catch {
10080
- resolve12({ raw: data });
10177
+ resolve11({ raw: data });
10081
10178
  }
10082
10179
  });
10083
10180
  }).on("error", reject);
@@ -10091,7 +10188,7 @@ var DaemonCommandHandler = class {
10091
10188
  try {
10092
10189
  const http3 = await import("http");
10093
10190
  const postData = JSON.stringify(args || {});
10094
- const result = await new Promise((resolve12, reject) => {
10191
+ const result = await new Promise((resolve11, reject) => {
10095
10192
  const req = http3.request({
10096
10193
  hostname: "127.0.0.1",
10097
10194
  port: 19280,
@@ -10103,9 +10200,9 @@ var DaemonCommandHandler = class {
10103
10200
  res.on("data", (chunk) => data += chunk);
10104
10201
  res.on("end", () => {
10105
10202
  try {
10106
- resolve12(JSON.parse(data));
10203
+ resolve11(JSON.parse(data));
10107
10204
  } catch {
10108
- resolve12({ raw: data });
10205
+ resolve11({ raw: data });
10109
10206
  }
10110
10207
  });
10111
10208
  });
@@ -10155,6 +10252,9 @@ function getForcedNewSessionScriptName(provider, launchMode) {
10155
10252
  const controls = Array.isArray(provider.controls) ? provider.controls : [];
10156
10253
  for (const control of controls) {
10157
10254
  if (control?.type !== "action") continue;
10255
+ if (typeof control?.confirmTitle === "string" && control.confirmTitle.trim()) continue;
10256
+ if (typeof control?.confirmMessage === "string" && control.confirmMessage.trim()) continue;
10257
+ if (typeof control?.confirmLabel === "string" && control.confirmLabel.trim()) continue;
10158
10258
  const invokeScript = typeof control?.invokeScript === "string" ? control.invokeScript.trim() : "";
10159
10259
  if (!invokeScript) continue;
10160
10260
  const controlId = typeof control?.id === "string" ? control.id.trim() : "";
@@ -10164,6 +10264,20 @@ function getForcedNewSessionScriptName(provider, launchMode) {
10164
10264
  }
10165
10265
  return null;
10166
10266
  }
10267
+ async function waitForCliAdapterReady(adapter, options) {
10268
+ const timeoutMs = Math.max(100, options?.timeoutMs ?? 15e3);
10269
+ const pollMs = Math.max(10, options?.pollMs ?? 50);
10270
+ const deadline = Date.now() + timeoutMs;
10271
+ while (Date.now() < deadline) {
10272
+ if (adapter?.isReady?.()) return;
10273
+ const status = adapter?.getStatus?.()?.status;
10274
+ if (status === "stopped") {
10275
+ throw new Error("CLI runtime stopped before it became ready");
10276
+ }
10277
+ await new Promise((resolve11) => setTimeout(resolve11, pollMs));
10278
+ }
10279
+ throw new Error(`CLI runtime did not become ready within ${timeoutMs}ms`);
10280
+ }
10167
10281
  var CliProviderInstance = class {
10168
10282
  constructor(provider, workingDir, cliArgs = [], instanceId, transportFactory, options) {
10169
10283
  this.provider = provider;
@@ -10442,6 +10556,7 @@ var CliProviderInstance = class {
10442
10556
  const scriptName = getForcedNewSessionScriptName(this.provider, this.launchMode);
10443
10557
  if (!scriptName) return;
10444
10558
  LOG.info("CLI", `[${this.type}] forcing fresh session launch via script: ${scriptName}`);
10559
+ await waitForCliAdapterReady(this.adapter);
10445
10560
  const raw = await this.adapter.invokeScript(scriptName, {});
10446
10561
  const parsed = parseCliScriptResult(raw);
10447
10562
  if (!parsed.success) {
@@ -10791,6 +10906,7 @@ ${effect.notification.body || ""}`.trim();
10791
10906
  const previousProviderSessionId = this.providerSessionId;
10792
10907
  this.providerSessionId = nextSessionId;
10793
10908
  this.historyWriter.promoteHistorySession(this.type, previousHistorySessionId, nextSessionId);
10909
+ this.historyWriter.writeSessionStart(this.type, nextSessionId, this.workingDir, this.instanceId);
10794
10910
  this.adapter.updateRuntimeMeta({ providerSessionId: nextSessionId });
10795
10911
  this.onProviderSessionResolved?.({
10796
10912
  instanceId: this.instanceId,
@@ -11377,13 +11493,13 @@ var AcpProviderInstance = class {
11377
11493
  }
11378
11494
  this.currentStatus = "waiting_approval";
11379
11495
  this.detectStatusTransition();
11380
- const approved = await new Promise((resolve12) => {
11381
- this.permissionResolvers.push(resolve12);
11496
+ const approved = await new Promise((resolve11) => {
11497
+ this.permissionResolvers.push(resolve11);
11382
11498
  setTimeout(() => {
11383
- const idx = this.permissionResolvers.indexOf(resolve12);
11499
+ const idx = this.permissionResolvers.indexOf(resolve11);
11384
11500
  if (idx >= 0) {
11385
11501
  this.permissionResolvers.splice(idx, 1);
11386
- resolve12(false);
11502
+ resolve11(false);
11387
11503
  }
11388
11504
  }, 3e5);
11389
11505
  });
@@ -12699,6 +12815,9 @@ function validateProviderDefinition(raw) {
12699
12815
  warnings.push(`Unknown provider field: ${key}`);
12700
12816
  }
12701
12817
  }
12818
+ if (provider.disableUpstream !== void 0) {
12819
+ warnings.push("disableUpstream is deprecated in provider definitions; use machine-level provider source policy instead");
12820
+ }
12702
12821
  const category = provider.category;
12703
12822
  if (category === "cli" || category === "acp") {
12704
12823
  const spawn4 = provider.spawn;
@@ -12758,8 +12877,11 @@ function validateControl(control, errors) {
12758
12877
  var ProviderLoader = class _ProviderLoader {
12759
12878
  providers = /* @__PURE__ */ new Map();
12760
12879
  providerAvailability = /* @__PURE__ */ new Map();
12880
+ defaultProvidersDir;
12881
+ explicitProviderDir = null;
12761
12882
  userDir;
12762
12883
  upstreamDir;
12884
+ sourceMode = "normal";
12763
12885
  disableUpstream;
12764
12886
  watchers = [];
12765
12887
  logFn;
@@ -12773,22 +12895,15 @@ var ProviderLoader = class _ProviderLoader {
12773
12895
  static META_FILE = ".meta.json";
12774
12896
  constructor(options) {
12775
12897
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
12776
- const defaultProvidersDir = path14.join(os13.homedir(), ".adhdev", "providers");
12777
- if (options?.userDir) {
12778
- this.userDir = options.userDir;
12779
- this.log(`Config 'providerDir' applied: ${this.userDir}`);
12780
- } else {
12781
- const localRepoPath = path14.resolve(__dirname, "../../../../../adhdev-providers");
12782
- if (fs6.existsSync(localRepoPath)) {
12783
- this.userDir = localRepoPath;
12784
- this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
12785
- } else {
12786
- this.userDir = defaultProvidersDir;
12787
- this.log(`Using default user providers directory: ${this.userDir}`);
12788
- }
12789
- }
12790
- this.upstreamDir = path14.join(defaultProvidersDir, ".upstream");
12791
- this.disableUpstream = options?.disableUpstream ?? false;
12898
+ this.defaultProvidersDir = path14.join(os13.homedir(), ".adhdev", "providers");
12899
+ this.userDir = this.defaultProvidersDir;
12900
+ this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
12901
+ this.disableUpstream = false;
12902
+ this.applySourceConfig({
12903
+ userDir: options?.userDir,
12904
+ sourceMode: options?.sourceMode,
12905
+ disableUpstream: options?.disableUpstream
12906
+ });
12792
12907
  }
12793
12908
  log(msg) {
12794
12909
  this.logFn(`[ProviderLoader] ${msg}`);
@@ -12813,6 +12928,33 @@ var ProviderLoader = class _ProviderLoader {
12813
12928
  getProviderRoots() {
12814
12929
  return [this.userDir, this.upstreamDir];
12815
12930
  }
12931
+ getSourceConfig() {
12932
+ return {
12933
+ sourceMode: this.sourceMode,
12934
+ disableUpstream: this.disableUpstream,
12935
+ explicitProviderDir: this.explicitProviderDir,
12936
+ userDir: this.userDir,
12937
+ upstreamDir: this.upstreamDir,
12938
+ providerRoots: this.getProviderRoots()
12939
+ };
12940
+ }
12941
+ applySourceConfig(options) {
12942
+ const nextSourceMode = options?.sourceMode === "no-upstream" ? "no-upstream" : options?.sourceMode === "normal" ? "normal" : options?.disableUpstream ? "no-upstream" : this.sourceMode || "normal";
12943
+ if (options && Object.prototype.hasOwnProperty.call(options, "userDir")) {
12944
+ this.explicitProviderDir = options.userDir?.trim() ? options.userDir : null;
12945
+ }
12946
+ this.sourceMode = nextSourceMode;
12947
+ this.userDir = this.explicitProviderDir || this.defaultProvidersDir;
12948
+ this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
12949
+ this.disableUpstream = this.sourceMode === "no-upstream";
12950
+ if (this.explicitProviderDir) {
12951
+ this.log(`Config 'providerDir' applied: ${this.userDir}`);
12952
+ } else {
12953
+ this.log(`Using default user providers directory: ${this.userDir}`);
12954
+ }
12955
+ this.log(`Provider source config: mode=${this.sourceMode} explicitProviderDir=${this.explicitProviderDir || "-"} userDir=${this.userDir} upstreamDir=${this.upstreamDir}`);
12956
+ return this.getSourceConfig();
12957
+ }
12816
12958
  /**
12817
12959
  * Canonical provider directory shape for a given root.
12818
12960
  */
@@ -12863,7 +13005,7 @@ var ProviderLoader = class _ProviderLoader {
12863
13005
  this.log(`Loaded ${upstreamCount} upstream providers (auto-updated)`);
12864
13006
  }
12865
13007
  } else if (this.disableUpstream) {
12866
- this.log("Upstream loading disabled (disableUpstream=true)");
13008
+ this.log("Upstream loading disabled (sourceMode=no-upstream)");
12867
13009
  }
12868
13010
  if (fs6.existsSync(this.userDir)) {
12869
13011
  const userCount = this.loadDir(this.userDir, [".upstream"]);
@@ -13374,7 +13516,7 @@ var ProviderLoader = class _ProviderLoader {
13374
13516
  */
13375
13517
  async fetchLatest() {
13376
13518
  if (this.disableUpstream) {
13377
- this.log("Upstream fetch skipped (disableUpstream=true)");
13519
+ this.log("Upstream fetch skipped (sourceMode=no-upstream)");
13378
13520
  return { updated: false };
13379
13521
  }
13380
13522
  const https = __require("https");
@@ -13396,7 +13538,7 @@ var ProviderLoader = class _ProviderLoader {
13396
13538
  return { updated: false };
13397
13539
  }
13398
13540
  try {
13399
- const etag = await new Promise((resolve12, reject) => {
13541
+ const etag = await new Promise((resolve11, reject) => {
13400
13542
  const options = {
13401
13543
  method: "HEAD",
13402
13544
  hostname: "github.com",
@@ -13414,7 +13556,7 @@ var ProviderLoader = class _ProviderLoader {
13414
13556
  headers: { "User-Agent": "adhdev-launcher" },
13415
13557
  timeout: 1e4
13416
13558
  }, (res2) => {
13417
- resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
13559
+ resolve11(res2.headers.etag || res2.headers["last-modified"] || "");
13418
13560
  });
13419
13561
  req2.on("error", reject);
13420
13562
  req2.on("timeout", () => {
@@ -13423,7 +13565,7 @@ var ProviderLoader = class _ProviderLoader {
13423
13565
  });
13424
13566
  req2.end();
13425
13567
  } else {
13426
- resolve12(res.headers.etag || res.headers["last-modified"] || "");
13568
+ resolve11(res.headers.etag || res.headers["last-modified"] || "");
13427
13569
  }
13428
13570
  });
13429
13571
  req.on("error", reject);
@@ -13487,7 +13629,7 @@ var ProviderLoader = class _ProviderLoader {
13487
13629
  downloadFile(url, destPath) {
13488
13630
  const https = __require("https");
13489
13631
  const http3 = __require("http");
13490
- return new Promise((resolve12, reject) => {
13632
+ return new Promise((resolve11, reject) => {
13491
13633
  const doRequest = (reqUrl, redirectCount = 0) => {
13492
13634
  if (redirectCount > 5) {
13493
13635
  reject(new Error("Too many redirects"));
@@ -13507,7 +13649,7 @@ var ProviderLoader = class _ProviderLoader {
13507
13649
  res.pipe(ws);
13508
13650
  ws.on("finish", () => {
13509
13651
  ws.close();
13510
- resolve12();
13652
+ resolve11();
13511
13653
  });
13512
13654
  ws.on("error", reject);
13513
13655
  });
@@ -13982,17 +14124,17 @@ async function findFreePort(ports) {
13982
14124
  throw new Error("No free port found");
13983
14125
  }
13984
14126
  function checkPortFree(port) {
13985
- return new Promise((resolve12) => {
14127
+ return new Promise((resolve11) => {
13986
14128
  const server = net.createServer();
13987
14129
  server.unref();
13988
- server.on("error", () => resolve12(false));
14130
+ server.on("error", () => resolve11(false));
13989
14131
  server.listen(port, "127.0.0.1", () => {
13990
- server.close(() => resolve12(true));
14132
+ server.close(() => resolve11(true));
13991
14133
  });
13992
14134
  });
13993
14135
  }
13994
14136
  async function isCdpActive(port) {
13995
- return new Promise((resolve12) => {
14137
+ return new Promise((resolve11) => {
13996
14138
  const req = __require("http").get(`http://127.0.0.1:${port}/json/version`, {
13997
14139
  timeout: 2e3
13998
14140
  }, (res) => {
@@ -14001,16 +14143,16 @@ async function isCdpActive(port) {
14001
14143
  res.on("end", () => {
14002
14144
  try {
14003
14145
  const info = JSON.parse(data);
14004
- resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
14146
+ resolve11(!!info["WebKit-Version"] || !!info["Browser"]);
14005
14147
  } catch {
14006
- resolve12(false);
14148
+ resolve11(false);
14007
14149
  }
14008
14150
  });
14009
14151
  });
14010
- req.on("error", () => resolve12(false));
14152
+ req.on("error", () => resolve11(false));
14011
14153
  req.on("timeout", () => {
14012
14154
  req.destroy();
14013
- resolve12(false);
14155
+ resolve11(false);
14014
14156
  });
14015
14157
  });
14016
14158
  }
@@ -14739,7 +14881,7 @@ async function waitForPidExit(pid, timeoutMs) {
14739
14881
  while (Date.now() - start < timeoutMs) {
14740
14882
  try {
14741
14883
  process.kill(pid, 0);
14742
- await new Promise((resolve12) => setTimeout(resolve12, 250));
14884
+ await new Promise((resolve11) => setTimeout(resolve11, 250));
14743
14885
  } catch {
14744
14886
  return;
14745
14887
  }
@@ -14854,7 +14996,7 @@ async function runDaemonUpgradeHelper(payload) {
14854
14996
  appendUpgradeLog(installOutput.trim());
14855
14997
  }
14856
14998
  if (process.platform === "win32") {
14857
- await new Promise((resolve12) => setTimeout(resolve12, 500));
14999
+ await new Promise((resolve11) => setTimeout(resolve11, 500));
14858
15000
  cleanupStaleGlobalInstallDirs(payload.packageName);
14859
15001
  appendUpgradeLog("Post-install staging cleanup complete");
14860
15002
  }
@@ -15147,8 +15289,9 @@ var DaemonCommandRouter = class {
15147
15289
  if (!providerType) {
15148
15290
  return { success: false, error: "providerType required" };
15149
15291
  }
15150
- const offset = Math.max(0, Number(args?.offset) || 0);
15151
- const limit = Math.max(1, Math.min(100, Number(args?.limit) || 30));
15292
+ const wantsAll = args?.all === true;
15293
+ const offset = wantsAll ? 0 : Math.max(0, Number(args?.offset) || 0);
15294
+ const limit = wantsAll ? Number.MAX_SAFE_INTEGER : Math.max(1, Math.min(100, Number(args?.limit) || 30));
15152
15295
  const { sessions: historySessions, hasMore } = listSavedHistorySessions(providerType, { offset, limit });
15153
15296
  const state = loadState();
15154
15297
  const savedSessions = getSavedProviderSessions(state, { providerType, kind });
@@ -15169,13 +15312,13 @@ var DaemonCommandRouter = class {
15169
15312
  providerName: saved?.providerName || recent?.providerName || providerType,
15170
15313
  kind: saved?.kind || recent?.kind || kind,
15171
15314
  title: saved?.title || recent?.title || session.sessionTitle || session.preview || providerType,
15172
- workspace: saved?.workspace || recent?.workspace,
15315
+ workspace: saved?.workspace || recent?.workspace || session.workspace,
15173
15316
  currentModel: saved?.currentModel || recent?.currentModel,
15174
15317
  preview: session.preview,
15175
15318
  messageCount: session.messageCount,
15176
15319
  firstMessageAt: session.firstMessageAt,
15177
15320
  lastMessageAt: session.lastMessageAt,
15178
- canResume: !!(saved?.workspace || recent?.workspace) && canResumeById
15321
+ canResume: !!(saved?.workspace || recent?.workspace || session.workspace) && canResumeById
15179
15322
  };
15180
15323
  }),
15181
15324
  hasMore
@@ -15792,7 +15935,7 @@ var ProviderStreamAdapter = class {
15792
15935
  const beforeCount = this.messageCount(before);
15793
15936
  const beforeSignature = this.lastMessageSignature(before);
15794
15937
  for (let attempt = 0; attempt < 12; attempt += 1) {
15795
- await new Promise((resolve12) => setTimeout(resolve12, 250));
15938
+ await new Promise((resolve11) => setTimeout(resolve11, 250));
15796
15939
  let state;
15797
15940
  try {
15798
15941
  state = await this.readChat(evaluate);
@@ -15814,7 +15957,7 @@ var ProviderStreamAdapter = class {
15814
15957
  if (this.messageCount(first) > 0 || this.lastMessageSignature(first)) {
15815
15958
  return first;
15816
15959
  }
15817
- await new Promise((resolve12) => setTimeout(resolve12, 150));
15960
+ await new Promise((resolve11) => setTimeout(resolve11, 150));
15818
15961
  const second = await this.readChat(evaluate);
15819
15962
  return this.messageCount(second) >= this.messageCount(first) ? second : first;
15820
15963
  }
@@ -15954,7 +16097,7 @@ var ProviderStreamAdapter = class {
15954
16097
  if (typeof data.error === "string" && data.error.trim()) return false;
15955
16098
  }
15956
16099
  for (let attempt = 0; attempt < 6; attempt += 1) {
15957
- await new Promise((resolve12) => setTimeout(resolve12, 250));
16100
+ await new Promise((resolve11) => setTimeout(resolve11, 250));
15958
16101
  const state = await this.readChat(evaluate);
15959
16102
  const title = this.getStateTitle(state);
15960
16103
  if (this.titlesMatch(title, sessionId)) return true;
@@ -16876,6 +17019,7 @@ async function detectAllVersions(loader, archive) {
16876
17019
  import * as http2 from "http";
16877
17020
  import * as fs14 from "fs";
16878
17021
  import * as path22 from "path";
17022
+ init_config();
16879
17023
 
16880
17024
  // src/daemon/scaffold-template.ts
16881
17025
  function generateFiles(type, name, category, opts = {}) {
@@ -18412,7 +18556,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
18412
18556
  return { target, instance, adapter };
18413
18557
  }
18414
18558
  function sleep(ms) {
18415
- return new Promise((resolve12) => setTimeout(resolve12, ms));
18559
+ return new Promise((resolve11) => setTimeout(resolve11, ms));
18416
18560
  }
18417
18561
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
18418
18562
  const startedAt = Date.now();
@@ -19259,18 +19403,6 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
19259
19403
  if (!fs13.existsSync(providerJson)) {
19260
19404
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
19261
19405
  }
19262
- try {
19263
- const providerData = JSON.parse(fs13.readFileSync(providerJson, "utf-8"));
19264
- if (providerData.disableUpstream !== true) {
19265
- providerData.disableUpstream = true;
19266
- fs13.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
19267
- }
19268
- } catch (error) {
19269
- return {
19270
- dir: null,
19271
- reason: `Failed to update provider.json in writable provider directory: ${error.message}`
19272
- };
19273
- }
19274
19406
  return { dir: desiredDir };
19275
19407
  }
19276
19408
  function loadAutoImplReferenceScripts(ctx, referenceType) {
@@ -20557,6 +20689,7 @@ var DevServer = class _DevServer {
20557
20689
  cdpManagers;
20558
20690
  instanceManager;
20559
20691
  cliManager;
20692
+ onProviderSourceConfigChanged;
20560
20693
  logFn;
20561
20694
  sseClients = [];
20562
20695
  watchScriptPath = null;
@@ -20573,6 +20706,7 @@ var DevServer = class _DevServer {
20573
20706
  this.cdpManagers = options.cdpManagers;
20574
20707
  this.instanceManager = options.instanceManager || null;
20575
20708
  this.cliManager = options.cliManager || null;
20709
+ this.onProviderSourceConfigChanged = options.onProviderSourceConfigChanged || null;
20576
20710
  this.logFn = options.logFn || LOG.forComponent("DevServer").asLogFn();
20577
20711
  }
20578
20712
  log(msg) {
@@ -20582,6 +20716,8 @@ var DevServer = class _DevServer {
20582
20716
  routes = [
20583
20717
  // Static routes
20584
20718
  { method: "GET", pattern: "/api/providers", handler: (q, s) => this.handleListProviders(q, s) },
20719
+ { method: "GET", pattern: "/api/providers/source-config", handler: (q, s) => this.handleGetProviderSourceConfig(q, s) },
20720
+ { method: "POST", pattern: "/api/providers/source-config", handler: (q, s) => this.handleSetProviderSourceConfig(q, s) },
20585
20721
  { method: "GET", pattern: "/api/providers/versions", handler: (q, s) => this.handleDetectVersions(q, s) },
20586
20722
  { method: "POST", pattern: "/api/providers/reload", handler: (q, s) => this.handleReload(q, s) },
20587
20723
  { method: "POST", pattern: "/api/cdp/evaluate", handler: (q, s) => this.handleCdpEvaluate(q, s) },
@@ -20679,15 +20815,15 @@ var DevServer = class _DevServer {
20679
20815
  this.json(res, 500, { error: e.message });
20680
20816
  }
20681
20817
  });
20682
- return new Promise((resolve12, reject) => {
20818
+ return new Promise((resolve11, reject) => {
20683
20819
  this.server.listen(port, "127.0.0.1", () => {
20684
20820
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
20685
- resolve12();
20821
+ resolve11();
20686
20822
  });
20687
20823
  this.server.on("error", (e) => {
20688
20824
  if (e.code === "EADDRINUSE") {
20689
20825
  this.log(`Port ${port} in use, skipping dev server`);
20690
- resolve12();
20826
+ resolve11();
20691
20827
  } else {
20692
20828
  reject(e);
20693
20829
  }
@@ -20701,7 +20837,33 @@ var DevServer = class _DevServer {
20701
20837
  // ─── Handlers ───
20702
20838
  async handleListProviders(_req, res) {
20703
20839
  const providers = this.providerLoader.getAll().map(toProviderListEntry);
20704
- this.json(res, 200, { providers, count: providers.length });
20840
+ this.json(res, 200, { providers, count: providers.length, sourceConfig: this.providerLoader.getSourceConfig() });
20841
+ }
20842
+ async handleGetProviderSourceConfig(_req, res) {
20843
+ this.json(res, 200, { success: true, sourceConfig: this.providerLoader.getSourceConfig() });
20844
+ }
20845
+ async handleSetProviderSourceConfig(req, res) {
20846
+ const body = await this.readBody(req);
20847
+ const parsed = parseProviderSourceConfigUpdate(body || {});
20848
+ if (!parsed.ok) {
20849
+ this.json(res, 400, { success: false, error: parsed.error });
20850
+ return;
20851
+ }
20852
+ const currentConfig2 = loadConfig();
20853
+ const nextConfig = {
20854
+ ...currentConfig2,
20855
+ ...parsed.updates.providerSourceMode ? { providerSourceMode: parsed.updates.providerSourceMode } : {},
20856
+ ...Object.prototype.hasOwnProperty.call(parsed.updates, "providerDir") ? { providerDir: parsed.updates.providerDir } : {}
20857
+ };
20858
+ saveConfig(nextConfig);
20859
+ const sourceConfig = this.providerLoader.applySourceConfig({
20860
+ sourceMode: nextConfig.providerSourceMode,
20861
+ userDir: Object.prototype.hasOwnProperty.call(parsed.updates, "providerDir") ? parsed.updates.providerDir : this.providerLoader.getSourceConfig().explicitProviderDir || void 0
20862
+ });
20863
+ this.providerLoader.reload();
20864
+ this.providerLoader.registerToDetector();
20865
+ await this.onProviderSourceConfigChanged?.();
20866
+ this.json(res, 200, { success: true, reloaded: true, sourceConfig });
20705
20867
  }
20706
20868
  async handleProviderConfig(type, _req, res) {
20707
20869
  const provider = this.providerLoader.resolve(type);
@@ -20743,20 +20905,20 @@ var DevServer = class _DevServer {
20743
20905
  child.stderr?.on("data", (d) => {
20744
20906
  stderr += d.toString().slice(0, 2e3);
20745
20907
  });
20746
- await new Promise((resolve12) => {
20908
+ await new Promise((resolve11) => {
20747
20909
  const timer = setTimeout(() => {
20748
20910
  child.kill();
20749
- resolve12();
20911
+ resolve11();
20750
20912
  }, 3e3);
20751
20913
  child.on("exit", () => {
20752
20914
  clearTimeout(timer);
20753
- resolve12();
20915
+ resolve11();
20754
20916
  });
20755
20917
  child.stdout?.once("data", () => {
20756
20918
  setTimeout(() => {
20757
20919
  child.kill();
20758
20920
  clearTimeout(timer);
20759
- resolve12();
20921
+ resolve11();
20760
20922
  }, 500);
20761
20923
  });
20762
20924
  });
@@ -21252,14 +21414,14 @@ var DevServer = class _DevServer {
21252
21414
  child.stderr?.on("data", (d) => {
21253
21415
  stderr += d.toString();
21254
21416
  });
21255
- await new Promise((resolve12) => {
21417
+ await new Promise((resolve11) => {
21256
21418
  const timer = setTimeout(() => {
21257
21419
  child.kill();
21258
- resolve12();
21420
+ resolve11();
21259
21421
  }, timeout);
21260
21422
  child.on("exit", () => {
21261
21423
  clearTimeout(timer);
21262
- resolve12();
21424
+ resolve11();
21263
21425
  });
21264
21426
  });
21265
21427
  const elapsed = Date.now() - start;
@@ -21404,18 +21566,6 @@ var DevServer = class _DevServer {
21404
21566
  if (!fs14.existsSync(providerJson)) {
21405
21567
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
21406
21568
  }
21407
- try {
21408
- const providerData = JSON.parse(fs14.readFileSync(providerJson, "utf-8"));
21409
- if (providerData.disableUpstream !== true) {
21410
- providerData.disableUpstream = true;
21411
- fs14.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
21412
- }
21413
- } catch (error) {
21414
- return {
21415
- dir: null,
21416
- reason: `Failed to update provider.json in writable provider directory: ${error.message}`
21417
- };
21418
- }
21419
21569
  return { dir: desiredDir };
21420
21570
  }
21421
21571
  async handleAutoImplement(type, req, res) {
@@ -21941,14 +22091,14 @@ data: ${JSON.stringify(msg.data)}
21941
22091
  res.end(JSON.stringify(data, null, 2));
21942
22092
  }
21943
22093
  async readBody(req) {
21944
- return new Promise((resolve12) => {
22094
+ return new Promise((resolve11) => {
21945
22095
  let body = "";
21946
22096
  req.on("data", (chunk) => body += chunk);
21947
22097
  req.on("end", () => {
21948
22098
  try {
21949
- resolve12(JSON.parse(body));
22099
+ resolve11(JSON.parse(body));
21950
22100
  } catch {
21951
- resolve12({});
22101
+ resolve11({});
21952
22102
  }
21953
22103
  });
21954
22104
  });
@@ -22431,7 +22581,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
22431
22581
  const deadline = Date.now() + timeoutMs;
22432
22582
  while (Date.now() < deadline) {
22433
22583
  if (await canConnect(endpoint)) return;
22434
- await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
22584
+ await new Promise((resolve11) => setTimeout(resolve11, STARTUP_POLL_MS));
22435
22585
  }
22436
22586
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
22437
22587
  }
@@ -22662,10 +22812,10 @@ async function installExtension(ide, extension) {
22662
22812
  const buffer = Buffer.from(await res.arrayBuffer());
22663
22813
  const fs15 = await import("fs");
22664
22814
  fs15.writeFileSync(vsixPath, buffer);
22665
- return new Promise((resolve12) => {
22815
+ return new Promise((resolve11) => {
22666
22816
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
22667
22817
  exec2(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
22668
- resolve12({
22818
+ resolve11({
22669
22819
  extensionId: extension.id,
22670
22820
  marketplaceId: extension.marketplaceId,
22671
22821
  success: !error,
@@ -22678,11 +22828,11 @@ async function installExtension(ide, extension) {
22678
22828
  } catch (e) {
22679
22829
  }
22680
22830
  }
22681
- return new Promise((resolve12) => {
22831
+ return new Promise((resolve11) => {
22682
22832
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
22683
22833
  exec2(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
22684
22834
  if (error) {
22685
- resolve12({
22835
+ resolve11({
22686
22836
  extensionId: extension.id,
22687
22837
  marketplaceId: extension.marketplaceId,
22688
22838
  success: false,
@@ -22690,7 +22840,7 @@ async function installExtension(ide, extension) {
22690
22840
  error: stderr || error.message
22691
22841
  });
22692
22842
  } else {
22693
- resolve12({
22843
+ resolve11({
22694
22844
  extensionId: extension.id,
22695
22845
  marketplaceId: extension.marketplaceId,
22696
22846
  success: true,
@@ -22787,10 +22937,11 @@ init_config();
22787
22937
  async function initDaemonComponents(config) {
22788
22938
  installGlobalInterceptor();
22789
22939
  const appConfig = loadConfig();
22790
- const disableUpstream = appConfig.disableUpstream ?? false;
22940
+ const providerSourceMode = appConfig.providerSourceMode || "normal";
22941
+ const disableUpstream = providerSourceMode === "no-upstream";
22791
22942
  const providerLoader = new ProviderLoader({
22792
22943
  logFn: config.providerLogFn,
22793
- disableUpstream,
22944
+ sourceMode: providerSourceMode,
22794
22945
  userDir: appConfig.providerDir
22795
22946
  });
22796
22947
  if (!disableUpstream && !providerLoader.hasUpstream()) {
@@ -22895,6 +23046,10 @@ async function initDaemonComponents(config) {
22895
23046
  onProviderSettingChanged: async (providerType) => {
22896
23047
  await refreshProviderAvailability(providerType);
22897
23048
  config.onStatusChange?.();
23049
+ },
23050
+ onProviderSourceConfigChanged: async () => {
23051
+ await refreshProviderAvailability();
23052
+ config.onStatusChange?.();
22898
23053
  }
22899
23054
  });
22900
23055
  agentStreamManager = new DaemonAgentStreamManager(
@@ -22944,7 +23099,8 @@ async function initDaemonComponents(config) {
22944
23099
  cdpInitializer,
22945
23100
  cdpManagers,
22946
23101
  sessionRegistry,
22947
- detectedIdes: detectedIdesRef
23102
+ detectedIdes: detectedIdesRef,
23103
+ refreshProviderAvailability
22948
23104
  };
22949
23105
  }
22950
23106
  async function startDaemonDevSupport(options) {
@@ -22953,7 +23109,10 @@ async function startDaemonDevSupport(options) {
22953
23109
  cdpManagers: options.components.cdpManagers,
22954
23110
  instanceManager: options.components.instanceManager,
22955
23111
  cliManager: options.components.cliManager,
22956
- logFn: options.logFn
23112
+ logFn: options.logFn,
23113
+ onProviderSourceConfigChanged: async () => {
23114
+ await options.components.refreshProviderAvailability();
23115
+ }
22957
23116
  });
22958
23117
  await devServer.start();
22959
23118
  options.components.providerLoader.watch();
@@ -23079,6 +23238,7 @@ export {
23079
23238
  normalizeInputEnvelope,
23080
23239
  normalizeManagedStatus,
23081
23240
  normalizeMessageParts,
23241
+ parseProviderSourceConfigUpdate,
23082
23242
  partitionSessionHostDiagnosticsSessions,
23083
23243
  partitionSessionHostRecords,
23084
23244
  probeCdpPort,