@adhdev/daemon-core 0.7.33 → 0.7.36

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 (36) hide show
  1. package/dist/index.d.mts +29 -3
  2. package/dist/index.d.ts +29 -3
  3. package/dist/index.js +637 -253
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +637 -255
  6. package/dist/index.mjs.map +1 -1
  7. package/dist/{normalize-auJAPmKy.d.mts → normalize-DVI4Lo5I.d.mts} +63 -1
  8. package/dist/{normalize-auJAPmKy.d.ts → normalize-DVI4Lo5I.d.ts} +63 -1
  9. package/dist/status/normalize.d.mts +1 -1
  10. package/dist/status/normalize.d.ts +1 -1
  11. package/node_modules/@adhdev/session-host-core/package.json +1 -1
  12. package/package.json +1 -1
  13. package/src/agent-stream/manager.ts +14 -1
  14. package/src/agent-stream/provider-adapter.ts +45 -3
  15. package/src/agent-stream/types.ts +4 -0
  16. package/src/cli-adapters/terminal-screen.ts +15 -0
  17. package/src/commands/cli-manager.ts +35 -0
  18. package/src/commands/router.ts +44 -1
  19. package/src/commands/workspace-commands.ts +2 -1
  20. package/src/config/config.d.ts +4 -0
  21. package/src/config/config.ts +9 -1
  22. package/src/config/recent-activity.ts +83 -0
  23. package/src/config/workspaces.d.ts +3 -1
  24. package/src/config/workspaces.ts +15 -1
  25. package/src/index.ts +16 -0
  26. package/src/providers/acp-provider-instance.ts +5 -0
  27. package/src/providers/cli-provider-instance.ts +2 -0
  28. package/src/providers/contracts.ts +94 -0
  29. package/src/providers/extension-provider-instance.ts +4 -0
  30. package/src/providers/ide-provider-instance.ts +2 -0
  31. package/src/providers/provider-instance.ts +5 -1
  32. package/src/shared-types.d.ts +35 -0
  33. package/src/shared-types.ts +70 -0
  34. package/src/status/builders.ts +90 -1
  35. package/src/status/reporter.ts +8 -0
  36. package/src/status/snapshot.ts +162 -0
package/dist/index.js CHANGED
@@ -163,8 +163,17 @@ function findWorkspaceByPath(config, rawPath) {
163
163
  if (!abs) return void 0;
164
164
  return (config.workspaces || []).find((w) => path.resolve(expandPath(w.path)) === abs);
165
165
  }
166
- function addWorkspaceEntry(config, rawPath, label) {
166
+ function addWorkspaceEntry(config, rawPath, label, options) {
167
167
  const abs = expandPath(rawPath);
168
+ const createIfMissing = options?.createIfMissing === true;
169
+ if (!abs) return { error: "Path required" };
170
+ if (!fs.existsSync(abs) && createIfMissing) {
171
+ try {
172
+ fs.mkdirSync(abs, { recursive: true });
173
+ } catch (e) {
174
+ return { error: e?.message || "Could not create directory" };
175
+ }
176
+ }
168
177
  const v = validateWorkspacePath(abs);
169
178
  if (!v.ok) return { error: v.error };
170
179
  const list = [...config.workspaces || []];
@@ -394,6 +403,8 @@ var init_config = __esm({
394
403
  workspaces: [],
395
404
  defaultWorkspaceId: null,
396
405
  recentWorkspaceActivity: [],
406
+ recentActivity: [],
407
+ recentSessionReads: {},
397
408
  machineNickname: null,
398
409
  machineId: void 0,
399
410
  machineSecret: null,
@@ -422,7 +433,7 @@ function checkDateRotation() {
422
433
  const today = getDateStr();
423
434
  if (today !== currentDate) {
424
435
  currentDate = today;
425
- currentLogFile = path3.join(LOG_DIR, `daemon-${currentDate}.log`);
436
+ currentLogFile = path4.join(LOG_DIR, `daemon-${currentDate}.log`);
426
437
  cleanOldLogs();
427
438
  }
428
439
  }
@@ -436,7 +447,7 @@ function cleanOldLogs() {
436
447
  const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
437
448
  if (dateMatch && dateMatch[1] < cutoffStr) {
438
449
  try {
439
- fs2.unlinkSync(path3.join(LOG_DIR, file));
450
+ fs2.unlinkSync(path4.join(LOG_DIR, file));
440
451
  } catch {
441
452
  }
442
453
  }
@@ -553,17 +564,17 @@ function installGlobalInterceptor() {
553
564
  writeToFile(`Log file: ${currentLogFile}`);
554
565
  writeToFile(`Log level: ${currentLevel}`);
555
566
  }
556
- var fs2, path3, os4, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH;
567
+ var fs2, path4, os4, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH;
557
568
  var init_logger = __esm({
558
569
  "src/logging/logger.ts"() {
559
570
  "use strict";
560
571
  fs2 = __toESM(require("fs"));
561
- path3 = __toESM(require("path"));
572
+ path4 = __toESM(require("path"));
562
573
  os4 = __toESM(require("os"));
563
574
  LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
564
575
  LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
565
576
  currentLevel = "info";
566
- LOG_DIR = process.platform === "win32" ? path3.join(process.env.LOCALAPPDATA || process.env.APPDATA || path3.join(os4.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path3.join(os4.homedir(), "Library", "Logs", "adhdev") : path3.join(os4.homedir(), ".local", "share", "adhdev", "logs");
577
+ LOG_DIR = process.platform === "win32" ? path4.join(process.env.LOCALAPPDATA || process.env.APPDATA || path4.join(os4.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path4.join(os4.homedir(), "Library", "Logs", "adhdev") : path4.join(os4.homedir(), ".local", "share", "adhdev", "logs");
567
578
  MAX_LOG_SIZE = 5 * 1024 * 1024;
568
579
  MAX_LOG_DAYS = 7;
569
580
  try {
@@ -571,16 +582,16 @@ var init_logger = __esm({
571
582
  } catch {
572
583
  }
573
584
  currentDate = getDateStr();
574
- currentLogFile = path3.join(LOG_DIR, `daemon-${currentDate}.log`);
585
+ currentLogFile = path4.join(LOG_DIR, `daemon-${currentDate}.log`);
575
586
  cleanOldLogs();
576
587
  try {
577
- const oldLog = path3.join(LOG_DIR, "daemon.log");
588
+ const oldLog = path4.join(LOG_DIR, "daemon.log");
578
589
  if (fs2.existsSync(oldLog)) {
579
590
  const stat = fs2.statSync(oldLog);
580
591
  const oldDate = stat.mtime.toISOString().slice(0, 10);
581
- fs2.renameSync(oldLog, path3.join(LOG_DIR, `daemon-${oldDate}.log`));
592
+ fs2.renameSync(oldLog, path4.join(LOG_DIR, `daemon-${oldDate}.log`));
582
593
  }
583
- const oldLogBackup = path3.join(LOG_DIR, "daemon.log.old");
594
+ const oldLogBackup = path4.join(LOG_DIR, "daemon.log.old");
584
595
  if (fs2.existsSync(oldLogBackup)) {
585
596
  fs2.unlinkSync(oldLogBackup);
586
597
  }
@@ -612,7 +623,7 @@ var init_logger = __esm({
612
623
  }
613
624
  };
614
625
  interceptorInstalled = false;
615
- LOG_PATH = path3.join(LOG_DIR, `daemon-${getDateStr()}.log`);
626
+ LOG_PATH = path4.join(LOG_DIR, `daemon-${getDateStr()}.log`);
616
627
  }
617
628
  });
618
629
 
@@ -777,6 +788,12 @@ var init_xterm_backend = __esm({
777
788
  });
778
789
 
779
790
  // src/cli-adapters/terminal-screen.ts
791
+ function getTerminalBackendRuntimeStatus() {
792
+ const preference = resolveTerminalBackendPreference();
793
+ const ghosttyAvailable = isGhosttyVtBackendAvailable();
794
+ const backend = preference === "ghostty-vt" || preference === "auto" && ghosttyAvailable ? "ghostty-vt" : "xterm";
795
+ return { backend, preference, ghosttyAvailable };
796
+ }
780
797
  function createTerminalBackend(options, preference) {
781
798
  const ghosttyAvailable = isGhosttyVtBackendAvailable();
782
799
  if (preference === "ghostty-vt") {
@@ -934,7 +951,7 @@ function findBinary(name) {
934
951
  }
935
952
  }
936
953
  function isScriptBinary(binaryPath) {
937
- if (!path9.isAbsolute(binaryPath)) return false;
954
+ if (!path10.isAbsolute(binaryPath)) return false;
938
955
  try {
939
956
  const fs12 = require("fs");
940
957
  const resolved = fs12.realpathSync(binaryPath);
@@ -950,7 +967,7 @@ function isScriptBinary(binaryPath) {
950
967
  }
951
968
  }
952
969
  function looksLikeMachOOrElf(filePath) {
953
- if (!path9.isAbsolute(filePath)) return false;
970
+ if (!path10.isAbsolute(filePath)) return false;
954
971
  try {
955
972
  const fs12 = require("fs");
956
973
  const resolved = fs12.realpathSync(filePath);
@@ -1064,12 +1081,12 @@ function normalizeCliProviderForRuntime(raw) {
1064
1081
  }
1065
1082
  };
1066
1083
  }
1067
- var os12, path9, import_child_process5, pty2, ProviderCliAdapter;
1084
+ var os12, path10, import_child_process5, pty2, ProviderCliAdapter;
1068
1085
  var init_provider_cli_adapter = __esm({
1069
1086
  "src/cli-adapters/provider-cli-adapter.ts"() {
1070
1087
  "use strict";
1071
1088
  os12 = __toESM(require("os"));
1072
- path9 = __toESM(require("path"));
1089
+ path10 = __toESM(require("path"));
1073
1090
  import_child_process5 = require("child_process");
1074
1091
  init_logger();
1075
1092
  init_terminal_screen();
@@ -1079,9 +1096,9 @@ var init_provider_cli_adapter = __esm({
1079
1096
  if (os12.platform() !== "win32") {
1080
1097
  try {
1081
1098
  const fs12 = require("fs");
1082
- const ptyDir = path9.resolve(path9.dirname(require.resolve("node-pty")), "..");
1099
+ const ptyDir = path10.resolve(path10.dirname(require.resolve("node-pty")), "..");
1083
1100
  const platformArch = `${os12.platform()}-${os12.arch()}`;
1084
- const helper = path9.join(ptyDir, "prebuilds", platformArch, "spawn-helper");
1101
+ const helper = path10.join(ptyDir, "prebuilds", platformArch, "spawn-helper");
1085
1102
  if (fs12.existsSync(helper)) {
1086
1103
  const stat = fs12.statSync(helper);
1087
1104
  if (!(stat.mode & 73)) {
@@ -1270,7 +1287,7 @@ var init_provider_cli_adapter = __esm({
1270
1287
  LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
1271
1288
  let shellCmd;
1272
1289
  let shellArgs;
1273
- const useShellUnix = !isWin && (!!spawnConfig.shell || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1290
+ const useShellUnix = !isWin && (!!spawnConfig.shell || !path10.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1274
1291
  const useShell = isWin ? !!spawnConfig.shell : useShellUnix;
1275
1292
  if (useShell) {
1276
1293
  if (!spawnConfig.shell && !isWin) {
@@ -1695,7 +1712,7 @@ ${data.message || ""}`.trim();
1695
1712
  if (this.startupParseGate) {
1696
1713
  const deadline = Date.now() + 1e4;
1697
1714
  while (this.startupParseGate && Date.now() < deadline) {
1698
- await new Promise((resolve9) => setTimeout(resolve9, 50));
1715
+ await new Promise((resolve10) => setTimeout(resolve10, 50));
1699
1716
  }
1700
1717
  }
1701
1718
  if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
@@ -1863,17 +1880,17 @@ ${data.message || ""}`.trim();
1863
1880
  }
1864
1881
  }
1865
1882
  waitForStopped(timeoutMs) {
1866
- return new Promise((resolve9) => {
1883
+ return new Promise((resolve10) => {
1867
1884
  const startedAt = Date.now();
1868
1885
  const timer = setInterval(() => {
1869
1886
  if (!this.ptyProcess || this.currentStatus === "stopped") {
1870
1887
  clearInterval(timer);
1871
- resolve9(true);
1888
+ resolve10(true);
1872
1889
  return;
1873
1890
  }
1874
1891
  if (Date.now() - startedAt >= timeoutMs) {
1875
1892
  clearInterval(timer);
1876
- resolve9(false);
1893
+ resolve10(false);
1877
1894
  }
1878
1895
  }, 100);
1879
1896
  });
@@ -2090,6 +2107,7 @@ __export(index_exports, {
2090
2107
  SessionHostPtyTransportFactory: () => SessionHostPtyTransportFactory,
2091
2108
  VersionArchive: () => VersionArchive,
2092
2109
  addCliHistory: () => addCliHistory,
2110
+ appendRecentActivity: () => appendRecentActivity,
2093
2111
  buildSessionEntries: () => buildSessionEntries,
2094
2112
  buildStatusSnapshot: () => buildStatusSnapshot,
2095
2113
  connectCdpManager: () => connectCdpManager,
@@ -2103,6 +2121,7 @@ __export(index_exports, {
2103
2121
  getAvailableIdeIds: () => getAvailableIdeIds,
2104
2122
  getHostMemorySnapshot: () => getHostMemorySnapshot,
2105
2123
  getLogLevel: () => getLogLevel,
2124
+ getRecentActivity: () => getRecentActivity,
2106
2125
  getRecentCommands: () => getRecentCommands,
2107
2126
  getRecentLogs: () => getRecentLogs,
2108
2127
  getWorkspaceActivity: () => getWorkspaceActivity,
@@ -2181,6 +2200,52 @@ function removeActivityForPath(config, rawPath) {
2181
2200
  };
2182
2201
  }
2183
2202
 
2203
+ // src/config/recent-activity.ts
2204
+ var path3 = __toESM(require("path"));
2205
+ init_workspaces();
2206
+ var MAX_ACTIVITY2 = 30;
2207
+ function normalizeWorkspace(workspace) {
2208
+ if (!workspace) return "";
2209
+ try {
2210
+ return path3.resolve(expandPath(workspace));
2211
+ } catch {
2212
+ return path3.resolve(workspace);
2213
+ }
2214
+ }
2215
+ function buildRecentActivityKey(entry) {
2216
+ return `${entry.kind}:${entry.providerType}:${normalizeWorkspace(entry.workspace)}`;
2217
+ }
2218
+ function appendRecentActivity(config, entry) {
2219
+ const nextEntry = {
2220
+ ...entry,
2221
+ workspace: entry.workspace ? normalizeWorkspace(entry.workspace) : void 0,
2222
+ id: buildRecentActivityKey(entry),
2223
+ lastUsedAt: entry.lastUsedAt || Date.now()
2224
+ };
2225
+ const filtered = (config.recentActivity || []).filter((item) => item.id !== nextEntry.id);
2226
+ return {
2227
+ ...config,
2228
+ recentActivity: [nextEntry, ...filtered].slice(0, MAX_ACTIVITY2)
2229
+ };
2230
+ }
2231
+ function getRecentActivity(config, limit = 20) {
2232
+ return [...config.recentActivity || []].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, limit);
2233
+ }
2234
+ function getRecentSessionSeenAt(config, recentKey) {
2235
+ return config.recentSessionReads?.[recentKey] || 0;
2236
+ }
2237
+ function markRecentSessionSeen(config, recentKey, seenAt = Date.now()) {
2238
+ const prev = config.recentSessionReads || {};
2239
+ const nextSeenAt = Math.max(prev[recentKey] || 0, seenAt);
2240
+ return {
2241
+ ...config,
2242
+ recentSessionReads: {
2243
+ ...prev,
2244
+ [recentKey]: nextSeenAt
2245
+ }
2246
+ };
2247
+ }
2248
+
2184
2249
  // src/detection/ide-detector.ts
2185
2250
  var import_child_process = require("child_process");
2186
2251
  var import_fs2 = require("fs");
@@ -2288,15 +2353,15 @@ function parseVersion(raw) {
2288
2353
  return match ? match[1] : raw.split("\n")[0].slice(0, 100);
2289
2354
  }
2290
2355
  function execAsync(cmd, timeoutMs = 5e3) {
2291
- return new Promise((resolve9) => {
2356
+ return new Promise((resolve10) => {
2292
2357
  const child = (0, import_child_process2.exec)(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
2293
2358
  if (err || !stdout?.trim()) {
2294
- resolve9(null);
2359
+ resolve10(null);
2295
2360
  } else {
2296
- resolve9(stdout.trim());
2361
+ resolve10(stdout.trim());
2297
2362
  }
2298
2363
  });
2299
- child.on("error", () => resolve9(null));
2364
+ child.on("error", () => resolve10(null));
2300
2365
  });
2301
2366
  }
2302
2367
  async function detectCLIs(providerLoader) {
@@ -2463,7 +2528,7 @@ var DaemonCdpManager = class {
2463
2528
  * Returns multiple entries if multiple IDE windows are open on same port
2464
2529
  */
2465
2530
  static listAllTargets(port) {
2466
- return new Promise((resolve9) => {
2531
+ return new Promise((resolve10) => {
2467
2532
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
2468
2533
  let data = "";
2469
2534
  res.on("data", (chunk) => data += chunk.toString());
@@ -2479,16 +2544,16 @@ var DaemonCdpManager = class {
2479
2544
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
2480
2545
  );
2481
2546
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
2482
- resolve9(mainPages.length > 0 ? mainPages : fallbackPages);
2547
+ resolve10(mainPages.length > 0 ? mainPages : fallbackPages);
2483
2548
  } catch {
2484
- resolve9([]);
2549
+ resolve10([]);
2485
2550
  }
2486
2551
  });
2487
2552
  });
2488
- req.on("error", () => resolve9([]));
2553
+ req.on("error", () => resolve10([]));
2489
2554
  req.setTimeout(2e3, () => {
2490
2555
  req.destroy();
2491
- resolve9([]);
2556
+ resolve10([]);
2492
2557
  });
2493
2558
  });
2494
2559
  }
@@ -2528,7 +2593,7 @@ var DaemonCdpManager = class {
2528
2593
  }
2529
2594
  }
2530
2595
  findTargetOnPort(port) {
2531
- return new Promise((resolve9) => {
2596
+ return new Promise((resolve10) => {
2532
2597
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
2533
2598
  let data = "";
2534
2599
  res.on("data", (chunk) => data += chunk.toString());
@@ -2539,7 +2604,7 @@ var DaemonCdpManager = class {
2539
2604
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
2540
2605
  );
2541
2606
  if (pages.length === 0) {
2542
- resolve9(targets.find((t) => t.webSocketDebuggerUrl) || null);
2607
+ resolve10(targets.find((t) => t.webSocketDebuggerUrl) || null);
2543
2608
  return;
2544
2609
  }
2545
2610
  const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -2549,24 +2614,24 @@ var DaemonCdpManager = class {
2549
2614
  const specific = list.find((t) => t.id === this._targetId);
2550
2615
  if (specific) {
2551
2616
  this._pageTitle = specific.title || "";
2552
- resolve9(specific);
2617
+ resolve10(specific);
2553
2618
  } else {
2554
2619
  this.log(`[CDP] Target ${this._targetId} not found in page list`);
2555
- resolve9(null);
2620
+ resolve10(null);
2556
2621
  }
2557
2622
  return;
2558
2623
  }
2559
2624
  this._pageTitle = list[0]?.title || "";
2560
- resolve9(list[0]);
2625
+ resolve10(list[0]);
2561
2626
  } catch {
2562
- resolve9(null);
2627
+ resolve10(null);
2563
2628
  }
2564
2629
  });
2565
2630
  });
2566
- req.on("error", () => resolve9(null));
2631
+ req.on("error", () => resolve10(null));
2567
2632
  req.setTimeout(2e3, () => {
2568
2633
  req.destroy();
2569
- resolve9(null);
2634
+ resolve10(null);
2570
2635
  });
2571
2636
  });
2572
2637
  }
@@ -2577,7 +2642,7 @@ var DaemonCdpManager = class {
2577
2642
  this.extensionProviders = providers;
2578
2643
  }
2579
2644
  connectToTarget(wsUrl) {
2580
- return new Promise((resolve9) => {
2645
+ return new Promise((resolve10) => {
2581
2646
  this.ws = new import_ws.default(wsUrl);
2582
2647
  this.ws.on("open", async () => {
2583
2648
  this._connected = true;
@@ -2587,17 +2652,17 @@ var DaemonCdpManager = class {
2587
2652
  }
2588
2653
  this.connectBrowserWs().catch(() => {
2589
2654
  });
2590
- resolve9(true);
2655
+ resolve10(true);
2591
2656
  });
2592
2657
  this.ws.on("message", (data) => {
2593
2658
  try {
2594
2659
  const msg = JSON.parse(data.toString());
2595
2660
  if (msg.id && this.pending.has(msg.id)) {
2596
- const { resolve: resolve10, reject } = this.pending.get(msg.id);
2661
+ const { resolve: resolve11, reject } = this.pending.get(msg.id);
2597
2662
  this.pending.delete(msg.id);
2598
2663
  this.failureCount = 0;
2599
2664
  if (msg.error) reject(new Error(msg.error.message));
2600
- else resolve10(msg.result);
2665
+ else resolve11(msg.result);
2601
2666
  } else if (msg.method === "Runtime.executionContextCreated") {
2602
2667
  this.contexts.add(msg.params.context.id);
2603
2668
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -2620,7 +2685,7 @@ var DaemonCdpManager = class {
2620
2685
  this.ws.on("error", (err) => {
2621
2686
  this.log(`[CDP] WebSocket error: ${err.message}`);
2622
2687
  this._connected = false;
2623
- resolve9(false);
2688
+ resolve10(false);
2624
2689
  });
2625
2690
  });
2626
2691
  }
@@ -2634,7 +2699,7 @@ var DaemonCdpManager = class {
2634
2699
  return;
2635
2700
  }
2636
2701
  this.log(`[CDP] Connecting browser WS for target discovery...`);
2637
- await new Promise((resolve9, reject) => {
2702
+ await new Promise((resolve10, reject) => {
2638
2703
  this.browserWs = new import_ws.default(browserWsUrl);
2639
2704
  this.browserWs.on("open", async () => {
2640
2705
  this._browserConnected = true;
@@ -2644,16 +2709,16 @@ var DaemonCdpManager = class {
2644
2709
  } catch (e) {
2645
2710
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
2646
2711
  }
2647
- resolve9();
2712
+ resolve10();
2648
2713
  });
2649
2714
  this.browserWs.on("message", (data) => {
2650
2715
  try {
2651
2716
  const msg = JSON.parse(data.toString());
2652
2717
  if (msg.id && this.browserPending.has(msg.id)) {
2653
- const { resolve: resolve10, reject: reject2 } = this.browserPending.get(msg.id);
2718
+ const { resolve: resolve11, reject: reject2 } = this.browserPending.get(msg.id);
2654
2719
  this.browserPending.delete(msg.id);
2655
2720
  if (msg.error) reject2(new Error(msg.error.message));
2656
- else resolve10(msg.result);
2721
+ else resolve11(msg.result);
2657
2722
  }
2658
2723
  } catch {
2659
2724
  }
@@ -2673,31 +2738,31 @@ var DaemonCdpManager = class {
2673
2738
  }
2674
2739
  }
2675
2740
  getBrowserWsUrl() {
2676
- return new Promise((resolve9) => {
2741
+ return new Promise((resolve10) => {
2677
2742
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
2678
2743
  let data = "";
2679
2744
  res.on("data", (chunk) => data += chunk.toString());
2680
2745
  res.on("end", () => {
2681
2746
  try {
2682
2747
  const info = JSON.parse(data);
2683
- resolve9(info.webSocketDebuggerUrl || null);
2748
+ resolve10(info.webSocketDebuggerUrl || null);
2684
2749
  } catch {
2685
- resolve9(null);
2750
+ resolve10(null);
2686
2751
  }
2687
2752
  });
2688
2753
  });
2689
- req.on("error", () => resolve9(null));
2754
+ req.on("error", () => resolve10(null));
2690
2755
  req.setTimeout(3e3, () => {
2691
2756
  req.destroy();
2692
- resolve9(null);
2757
+ resolve10(null);
2693
2758
  });
2694
2759
  });
2695
2760
  }
2696
2761
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
2697
- return new Promise((resolve9, reject) => {
2762
+ return new Promise((resolve10, reject) => {
2698
2763
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
2699
2764
  const id = this.browserMsgId++;
2700
- this.browserPending.set(id, { resolve: resolve9, reject });
2765
+ this.browserPending.set(id, { resolve: resolve10, reject });
2701
2766
  this.browserWs.send(JSON.stringify({ id, method, params }));
2702
2767
  setTimeout(() => {
2703
2768
  if (this.browserPending.has(id)) {
@@ -2737,11 +2802,11 @@ var DaemonCdpManager = class {
2737
2802
  }
2738
2803
  // ─── CDP Protocol ────────────────────────────────────────
2739
2804
  sendInternal(method, params = {}, timeoutMs = 15e3) {
2740
- return new Promise((resolve9, reject) => {
2805
+ return new Promise((resolve10, reject) => {
2741
2806
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
2742
2807
  if (this.ws.readyState !== import_ws.default.OPEN) return reject(new Error("WebSocket not open"));
2743
2808
  const id = this.msgId++;
2744
- this.pending.set(id, { resolve: resolve9, reject });
2809
+ this.pending.set(id, { resolve: resolve10, reject });
2745
2810
  this.ws.send(JSON.stringify({ id, method, params }));
2746
2811
  setTimeout(() => {
2747
2812
  if (this.pending.has(id)) {
@@ -2990,7 +3055,7 @@ var DaemonCdpManager = class {
2990
3055
  const browserWs = this.browserWs;
2991
3056
  let msgId = this.browserMsgId;
2992
3057
  const sendWs = (method, params = {}, sessionId) => {
2993
- return new Promise((resolve9, reject) => {
3058
+ return new Promise((resolve10, reject) => {
2994
3059
  const mid = msgId++;
2995
3060
  this.browserMsgId = msgId;
2996
3061
  const handler = (raw) => {
@@ -2999,7 +3064,7 @@ var DaemonCdpManager = class {
2999
3064
  if (msg.id === mid) {
3000
3065
  browserWs.removeListener("message", handler);
3001
3066
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
3002
- else resolve9(msg.result);
3067
+ else resolve10(msg.result);
3003
3068
  }
3004
3069
  } catch {
3005
3070
  }
@@ -3190,14 +3255,14 @@ var DaemonCdpManager = class {
3190
3255
  if (!ws || ws.readyState !== import_ws.default.OPEN) {
3191
3256
  throw new Error("CDP not connected");
3192
3257
  }
3193
- return new Promise((resolve9, reject) => {
3258
+ return new Promise((resolve10, reject) => {
3194
3259
  const id = getNextId();
3195
3260
  pendingMap.set(id, {
3196
3261
  resolve: (result) => {
3197
3262
  if (result?.result?.subtype === "error") {
3198
3263
  reject(new Error(result.result.description));
3199
3264
  } else {
3200
- resolve9(result?.result?.value);
3265
+ resolve10(result?.result?.value);
3201
3266
  }
3202
3267
  },
3203
3268
  reject
@@ -3229,10 +3294,10 @@ var DaemonCdpManager = class {
3229
3294
  throw new Error("CDP not connected");
3230
3295
  }
3231
3296
  const sendViaSession = (method, params = {}) => {
3232
- return new Promise((resolve9, reject) => {
3297
+ return new Promise((resolve10, reject) => {
3233
3298
  const pendingMap = this._browserConnected ? this.browserPending : this.pending;
3234
3299
  const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
3235
- pendingMap.set(id, { resolve: resolve9, reject });
3300
+ pendingMap.set(id, { resolve: resolve10, reject });
3236
3301
  ws.send(JSON.stringify({ id, sessionId, method, params }));
3237
3302
  setTimeout(() => {
3238
3303
  if (pendingMap.has(id)) {
@@ -3784,6 +3849,7 @@ var ExtensionProviderInstance = class {
3784
3849
  activeModal = null;
3785
3850
  currentModel = "";
3786
3851
  currentMode = "";
3852
+ controlValues = {};
3787
3853
  lastAgentStatus = "idle";
3788
3854
  generatingStartedAt = 0;
3789
3855
  monitor;
@@ -3829,6 +3895,8 @@ var ExtensionProviderInstance = class {
3829
3895
  } : null,
3830
3896
  currentModel: this.currentModel || void 0,
3831
3897
  currentPlan: this.currentMode || void 0,
3898
+ controlValues: this.controlValues,
3899
+ providerControls: this.provider.controls,
3832
3900
  agentStreams: this.agentStreams,
3833
3901
  instanceId: this.instanceId,
3834
3902
  lastUpdated: Date.now(),
@@ -3843,6 +3911,7 @@ var ExtensionProviderInstance = class {
3843
3911
  if (data?.activeModal !== void 0) this.activeModal = data.activeModal;
3844
3912
  if (data?.model) this.currentModel = data.model;
3845
3913
  if (data?.mode) this.currentMode = data.mode;
3914
+ if (data?.controlValues) this.controlValues = data.controlValues;
3846
3915
  if (typeof data?.sessionId === "string" && data.sessionId.trim()) this.chatId = data.sessionId;
3847
3916
  if (typeof data?.title === "string" && data.title.trim()) this.chatTitle = data.title;
3848
3917
  if (typeof data?.agentName === "string" && data.agentName.trim()) this.agentName = data.agentName;
@@ -3935,9 +4004,9 @@ var ExtensionProviderInstance = class {
3935
4004
 
3936
4005
  // src/config/chat-history.ts
3937
4006
  var fs3 = __toESM(require("fs"));
3938
- var path4 = __toESM(require("path"));
4007
+ var path5 = __toESM(require("path"));
3939
4008
  var os5 = __toESM(require("os"));
3940
- var HISTORY_DIR = path4.join(os5.homedir(), ".adhdev", "history");
4009
+ var HISTORY_DIR = path5.join(os5.homedir(), ".adhdev", "history");
3941
4010
  var RETAIN_DAYS = 30;
3942
4011
  var ChatHistoryWriter = class {
3943
4012
  /** Last seen message count per agent (deduplication) */
@@ -3980,11 +4049,11 @@ var ChatHistoryWriter = class {
3980
4049
  });
3981
4050
  }
3982
4051
  if (newMessages.length === 0) return;
3983
- const dir = path4.join(HISTORY_DIR, this.sanitize(agentType));
4052
+ const dir = path5.join(HISTORY_DIR, this.sanitize(agentType));
3984
4053
  fs3.mkdirSync(dir, { recursive: true });
3985
4054
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3986
4055
  const filePrefix = instanceId ? `${this.sanitize(instanceId)}_` : "";
3987
- const filePath = path4.join(dir, `${filePrefix}${date}.jsonl`);
4056
+ const filePath = path5.join(dir, `${filePrefix}${date}.jsonl`);
3988
4057
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
3989
4058
  fs3.appendFileSync(filePath, lines, "utf-8");
3990
4059
  const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
@@ -4028,11 +4097,11 @@ ${next}`;
4028
4097
  this.lastSeenTerminal.set(dedupKey, next);
4029
4098
  return;
4030
4099
  }
4031
- const dir = path4.join(HISTORY_DIR, this.sanitize(agentType));
4100
+ const dir = path5.join(HISTORY_DIR, this.sanitize(agentType));
4032
4101
  fs3.mkdirSync(dir, { recursive: true });
4033
4102
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4034
4103
  const filePrefix = instanceId ? `${this.sanitize(instanceId)}_` : "";
4035
- const filePath = path4.join(dir, `${filePrefix}${date}.terminal.log`);
4104
+ const filePath = path5.join(dir, `${filePrefix}${date}.terminal.log`);
4036
4105
  fs3.appendFileSync(filePath, delta, "utf-8");
4037
4106
  this.lastSeenTerminal.set(dedupKey, next);
4038
4107
  if (!this.rotated) {
@@ -4056,10 +4125,10 @@ ${next}`;
4056
4125
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
4057
4126
  const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
4058
4127
  for (const dir of agentDirs) {
4059
- const dirPath = path4.join(HISTORY_DIR, dir.name);
4128
+ const dirPath = path5.join(HISTORY_DIR, dir.name);
4060
4129
  const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
4061
4130
  for (const file of files) {
4062
- const filePath = path4.join(dirPath, file);
4131
+ const filePath = path5.join(dirPath, file);
4063
4132
  const stat = fs3.statSync(filePath);
4064
4133
  if (stat.mtimeMs < cutoff) {
4065
4134
  fs3.unlinkSync(filePath);
@@ -4077,7 +4146,7 @@ ${next}`;
4077
4146
  function readChatHistory(agentType, offset = 0, limit = 30, instanceId) {
4078
4147
  try {
4079
4148
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
4080
- const dir = path4.join(HISTORY_DIR, sanitized);
4149
+ const dir = path5.join(HISTORY_DIR, sanitized);
4081
4150
  if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
4082
4151
  const sanitizedInstance = instanceId?.replace(/[^a-zA-Z0-9_-]/g, "_");
4083
4152
  const files = fs3.readdirSync(dir).filter((f) => {
@@ -4091,7 +4160,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, instanceId) {
4091
4160
  const needed = offset + limit + 1;
4092
4161
  for (const file of files) {
4093
4162
  if (allMessages.length >= needed) break;
4094
- const filePath = path4.join(dir, file);
4163
+ const filePath = path5.join(dir, file);
4095
4164
  const content = fs3.readFileSync(filePath, "utf-8");
4096
4165
  const lines = content.trim().split("\n").filter(Boolean);
4097
4166
  for (let i = lines.length - 1; i >= 0; i--) {
@@ -4200,6 +4269,8 @@ var IdeProviderInstance = class {
4200
4269
  currentModel: this.cachedChat?.model || void 0,
4201
4270
  currentPlan: this.cachedChat?.mode || void 0,
4202
4271
  currentAutoApprove: this.cachedChat?.autoApprove || void 0,
4272
+ controlValues: this.cachedChat?.controlValues || void 0,
4273
+ providerControls: this.provider.controls,
4203
4274
  instanceId: this.instanceId,
4204
4275
  lastUpdated: Date.now(),
4205
4276
  settings: this.settings,
@@ -4934,6 +5005,50 @@ function isCdpConnected(cdpManagers, key) {
4934
5005
  const m = findCdpManager(cdpManagers, key);
4935
5006
  return m?.isConnected ?? false;
4936
5007
  }
5008
+ function buildFallbackControls(providerControls, serverModel, serverMode, acpConfigOptions, acpModes) {
5009
+ if (providerControls && providerControls.length > 0) return providerControls;
5010
+ const controls = [];
5011
+ const isAcp = !!(acpConfigOptions || acpModes);
5012
+ const modelFromAcp = acpConfigOptions?.find((c) => c.category === "model");
5013
+ if (!isAcp || modelFromAcp) {
5014
+ controls.push({
5015
+ id: "model",
5016
+ type: "select",
5017
+ label: "Model",
5018
+ icon: "\u{1F916}",
5019
+ placement: "bar",
5020
+ dynamic: !modelFromAcp,
5021
+ listScript: "listModels",
5022
+ setScript: "setModel",
5023
+ readFrom: "model",
5024
+ ...modelFromAcp && {
5025
+ options: modelFromAcp.options.map((o) => ({ value: o.value, label: o.name || o.value }))
5026
+ }
5027
+ });
5028
+ }
5029
+ const modeFromAcp = acpModes && acpModes.length > 0;
5030
+ const thoughtFromAcp = !modeFromAcp && acpConfigOptions?.find((c) => c.category !== "model");
5031
+ if (!isAcp || modeFromAcp || thoughtFromAcp) {
5032
+ controls.push({
5033
+ id: "mode",
5034
+ type: thoughtFromAcp ? "cycle" : "select",
5035
+ label: thoughtFromAcp ? "Thinking" : "Mode",
5036
+ icon: thoughtFromAcp ? "\u{1F9E0}" : "\u26A1",
5037
+ placement: "bar",
5038
+ dynamic: !modeFromAcp && !thoughtFromAcp,
5039
+ listScript: "listModes",
5040
+ setScript: thoughtFromAcp ? "setThinkingLevel" : "setMode",
5041
+ readFrom: "mode",
5042
+ ...modeFromAcp && {
5043
+ options: acpModes.map((m) => ({ value: m.id, label: m.name || m.id }))
5044
+ },
5045
+ ...thoughtFromAcp && {
5046
+ options: thoughtFromAcp.options.map((o) => ({ value: o.value, label: o.name || o.value }))
5047
+ }
5048
+ });
5049
+ }
5050
+ return controls;
5051
+ }
4937
5052
  var IDE_SESSION_CAPABILITIES = [
4938
5053
  "read_chat",
4939
5054
  "send_message",
@@ -4992,8 +5107,15 @@ function buildIdeWorkspaceSession(state, cdpManagers) {
4992
5107
  currentModel: state.currentModel,
4993
5108
  currentPlan: state.currentPlan,
4994
5109
  currentAutoApprove: state.currentAutoApprove,
5110
+ controlValues: state.controlValues,
5111
+ providerControls: buildFallbackControls(
5112
+ state.providerControls,
5113
+ state.currentModel,
5114
+ state.currentPlan
5115
+ ),
4995
5116
  errorMessage: state.errorMessage,
4996
- errorReason: state.errorReason
5117
+ errorReason: state.errorReason,
5118
+ lastUpdated: state.lastUpdated
4997
5119
  };
4998
5120
  }
4999
5121
  function buildExtensionAgentSession(parent, ext) {
@@ -5014,8 +5136,15 @@ function buildExtensionAgentSession(parent, ext) {
5014
5136
  capabilities: EXTENSION_SESSION_CAPABILITIES,
5015
5137
  currentModel: ext.currentModel,
5016
5138
  currentPlan: ext.currentPlan,
5139
+ controlValues: ext.controlValues,
5140
+ providerControls: buildFallbackControls(
5141
+ ext.providerControls,
5142
+ ext.currentModel,
5143
+ ext.currentPlan
5144
+ ),
5017
5145
  errorMessage: ext.errorMessage,
5018
- errorReason: ext.errorReason
5146
+ errorReason: ext.errorReason,
5147
+ lastUpdated: ext.lastUpdated
5019
5148
  };
5020
5149
  }
5021
5150
  function buildCliSession(state) {
@@ -5040,8 +5169,13 @@ function buildCliSession(state) {
5040
5169
  resume: state.resume,
5041
5170
  activeChat,
5042
5171
  capabilities: PTY_SESSION_CAPABILITIES,
5172
+ controlValues: state.controlValues,
5173
+ providerControls: buildFallbackControls(
5174
+ state.providerControls
5175
+ ),
5043
5176
  errorMessage: state.errorMessage,
5044
- errorReason: state.errorReason
5177
+ errorReason: state.errorReason,
5178
+ lastUpdated: state.lastUpdated
5045
5179
  };
5046
5180
  }
5047
5181
  function buildAcpSession(state) {
@@ -5064,8 +5198,17 @@ function buildAcpSession(state) {
5064
5198
  currentPlan: state.currentPlan,
5065
5199
  acpConfigOptions: state.acpConfigOptions,
5066
5200
  acpModes: state.acpModes,
5201
+ controlValues: state.controlValues,
5202
+ providerControls: buildFallbackControls(
5203
+ state.providerControls,
5204
+ state.currentModel,
5205
+ state.currentPlan,
5206
+ state.acpConfigOptions,
5207
+ state.acpModes
5208
+ ),
5067
5209
  errorMessage: state.errorMessage,
5068
- errorReason: state.errorReason
5210
+ errorReason: state.errorReason,
5211
+ lastUpdated: state.lastUpdated
5069
5212
  };
5070
5213
  }
5071
5214
  function buildSessionEntries(allStates, cdpManagers) {
@@ -5914,7 +6057,7 @@ async function handleResolveAction(h, args) {
5914
6057
 
5915
6058
  // src/commands/cdp-commands.ts
5916
6059
  var fs4 = __toESM(require("fs"));
5917
- var path5 = __toESM(require("path"));
6060
+ var path6 = __toESM(require("path"));
5918
6061
  var os6 = __toESM(require("os"));
5919
6062
  var KEY_TO_VK = {
5920
6063
  Backspace: 8,
@@ -6145,11 +6288,11 @@ function resolveSafePath(requestedPath) {
6145
6288
  const home = os6.homedir();
6146
6289
  let resolved;
6147
6290
  if (requestedPath.startsWith("~")) {
6148
- resolved = path5.join(home, requestedPath.slice(1));
6149
- } else if (path5.isAbsolute(requestedPath)) {
6291
+ resolved = path6.join(home, requestedPath.slice(1));
6292
+ } else if (path6.isAbsolute(requestedPath)) {
6150
6293
  resolved = requestedPath;
6151
6294
  } else {
6152
- resolved = path5.resolve(requestedPath);
6295
+ resolved = path6.resolve(requestedPath);
6153
6296
  }
6154
6297
  return resolved;
6155
6298
  }
@@ -6165,7 +6308,7 @@ async function handleFileRead(h, args) {
6165
6308
  async function handleFileWrite(h, args) {
6166
6309
  try {
6167
6310
  const filePath = resolveSafePath(args?.path);
6168
- fs4.mkdirSync(path5.dirname(filePath), { recursive: true });
6311
+ fs4.mkdirSync(path6.dirname(filePath), { recursive: true });
6169
6312
  fs4.writeFileSync(filePath, args?.content || "", "utf-8");
6170
6313
  return { success: true, path: filePath };
6171
6314
  } catch (e) {
@@ -6179,7 +6322,7 @@ async function handleFileList(h, args) {
6179
6322
  const files = entries.map((e) => ({
6180
6323
  name: e.name,
6181
6324
  type: e.isDirectory() ? "directory" : "file",
6182
- size: e.isFile() ? fs4.statSync(path5.join(dirPath, e.name)).size : void 0
6325
+ size: e.isFile() ? fs4.statSync(path6.join(dirPath, e.name)).size : void 0
6183
6326
  }));
6184
6327
  return { success: true, files, path: dirPath };
6185
6328
  } catch (e) {
@@ -6401,9 +6544,10 @@ function handleWorkspaceList() {
6401
6544
  function handleWorkspaceAdd(args) {
6402
6545
  const rawPath = (args?.path || args?.dir || "").trim();
6403
6546
  const label = (args?.label || "").trim() || void 0;
6547
+ const createIfMissing = args?.createIfMissing === true;
6404
6548
  if (!rawPath) return { success: false, error: "path required" };
6405
6549
  const config = loadConfig();
6406
- const result = addWorkspaceEntry(config, rawPath, label);
6550
+ const result = addWorkspaceEntry(config, rawPath, label, { createIfMissing });
6407
6551
  if ("error" in result) return { success: false, error: result.error };
6408
6552
  let cfg = appendWorkspaceActivity(result.config, result.entry.path, {});
6409
6553
  saveConfig(cfg);
@@ -6897,7 +7041,7 @@ var DaemonCommandHandler = class {
6897
7041
  try {
6898
7042
  const http3 = await import("http");
6899
7043
  const postData = JSON.stringify(body);
6900
- const result = await new Promise((resolve9, reject) => {
7044
+ const result = await new Promise((resolve10, reject) => {
6901
7045
  const req = http3.request({
6902
7046
  hostname: "127.0.0.1",
6903
7047
  port: 19280,
@@ -6909,9 +7053,9 @@ var DaemonCommandHandler = class {
6909
7053
  res.on("data", (chunk) => data += chunk);
6910
7054
  res.on("end", () => {
6911
7055
  try {
6912
- resolve9(JSON.parse(data));
7056
+ resolve10(JSON.parse(data));
6913
7057
  } catch {
6914
- resolve9({ raw: data });
7058
+ resolve10({ raw: data });
6915
7059
  }
6916
7060
  });
6917
7061
  });
@@ -6929,15 +7073,15 @@ var DaemonCommandHandler = class {
6929
7073
  if (!providerType) return { success: false, error: "providerType required" };
6930
7074
  try {
6931
7075
  const http3 = await import("http");
6932
- const result = await new Promise((resolve9, reject) => {
7076
+ const result = await new Promise((resolve10, reject) => {
6933
7077
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
6934
7078
  let data = "";
6935
7079
  res.on("data", (chunk) => data += chunk);
6936
7080
  res.on("end", () => {
6937
7081
  try {
6938
- resolve9(JSON.parse(data));
7082
+ resolve10(JSON.parse(data));
6939
7083
  } catch {
6940
- resolve9({ raw: data });
7084
+ resolve10({ raw: data });
6941
7085
  }
6942
7086
  });
6943
7087
  }).on("error", reject);
@@ -6951,7 +7095,7 @@ var DaemonCommandHandler = class {
6951
7095
  try {
6952
7096
  const http3 = await import("http");
6953
7097
  const postData = JSON.stringify(args || {});
6954
- const result = await new Promise((resolve9, reject) => {
7098
+ const result = await new Promise((resolve10, reject) => {
6955
7099
  const req = http3.request({
6956
7100
  hostname: "127.0.0.1",
6957
7101
  port: 19280,
@@ -6963,9 +7107,9 @@ var DaemonCommandHandler = class {
6963
7107
  res.on("data", (chunk) => data += chunk);
6964
7108
  res.on("end", () => {
6965
7109
  try {
6966
- resolve9(JSON.parse(data));
7110
+ resolve10(JSON.parse(data));
6967
7111
  } catch {
6968
- resolve9({ raw: data });
7112
+ resolve10({ raw: data });
6969
7113
  }
6970
7114
  });
6971
7115
  });
@@ -6984,11 +7128,11 @@ var DaemonCommandHandler = class {
6984
7128
  var import_child_process4 = require("child_process");
6985
7129
  var net = __toESM(require("net"));
6986
7130
  var os8 = __toESM(require("os"));
6987
- var path7 = __toESM(require("path"));
7131
+ var path8 = __toESM(require("path"));
6988
7132
 
6989
7133
  // src/providers/provider-loader.ts
6990
7134
  var fs5 = __toESM(require("fs"));
6991
- var path6 = __toESM(require("path"));
7135
+ var path7 = __toESM(require("path"));
6992
7136
  var os7 = __toESM(require("os"));
6993
7137
  var chokidar = __toESM(require("chokidar"));
6994
7138
  init_logger();
@@ -7009,12 +7153,12 @@ var ProviderLoader = class _ProviderLoader {
7009
7153
  static META_FILE = ".meta.json";
7010
7154
  constructor(options) {
7011
7155
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
7012
- const defaultProvidersDir = path6.join(os7.homedir(), ".adhdev", "providers");
7156
+ const defaultProvidersDir = path7.join(os7.homedir(), ".adhdev", "providers");
7013
7157
  if (options?.userDir) {
7014
7158
  this.userDir = options.userDir;
7015
7159
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
7016
7160
  } else {
7017
- const localRepoPath = path6.resolve(__dirname, "../../../../../adhdev-providers");
7161
+ const localRepoPath = path7.resolve(__dirname, "../../../../../adhdev-providers");
7018
7162
  if (fs5.existsSync(localRepoPath)) {
7019
7163
  this.userDir = localRepoPath;
7020
7164
  this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
@@ -7023,7 +7167,7 @@ var ProviderLoader = class _ProviderLoader {
7023
7167
  this.log(`Using default user providers directory: ${this.userDir}`);
7024
7168
  }
7025
7169
  }
7026
- this.upstreamDir = path6.join(defaultProvidersDir, ".upstream");
7170
+ this.upstreamDir = path7.join(defaultProvidersDir, ".upstream");
7027
7171
  this.disableUpstream = options?.disableUpstream ?? false;
7028
7172
  }
7029
7173
  log(msg) {
@@ -7053,7 +7197,7 @@ var ProviderLoader = class _ProviderLoader {
7053
7197
  * Canonical provider directory shape for a given root.
7054
7198
  */
7055
7199
  getProviderDir(root, category, type) {
7056
- return path6.join(root, category, type);
7200
+ return path7.join(root, category, type);
7057
7201
  }
7058
7202
  /**
7059
7203
  * Canonical user override directory for a provider.
@@ -7080,7 +7224,7 @@ var ProviderLoader = class _ProviderLoader {
7080
7224
  resolveProviderFile(type, ...segments) {
7081
7225
  const dir = this.findProviderDirInternal(type);
7082
7226
  if (!dir) return null;
7083
- return path6.join(dir, ...segments);
7227
+ return path7.join(dir, ...segments);
7084
7228
  }
7085
7229
  /**
7086
7230
  * Load all providers (3-tier priority)
@@ -7118,7 +7262,7 @@ var ProviderLoader = class _ProviderLoader {
7118
7262
  if (!fs5.existsSync(this.upstreamDir)) return false;
7119
7263
  try {
7120
7264
  return fs5.readdirSync(this.upstreamDir).some(
7121
- (d) => fs5.statSync(path6.join(this.upstreamDir, d)).isDirectory()
7265
+ (d) => fs5.statSync(path7.join(this.upstreamDir, d)).isDirectory()
7122
7266
  );
7123
7267
  } catch {
7124
7268
  return false;
@@ -7410,14 +7554,14 @@ var ProviderLoader = class _ProviderLoader {
7410
7554
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
7411
7555
  return null;
7412
7556
  }
7413
- const dir = path6.join(providerDir, scriptDir);
7557
+ const dir = path7.join(providerDir, scriptDir);
7414
7558
  if (!fs5.existsSync(dir)) {
7415
7559
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
7416
7560
  return null;
7417
7561
  }
7418
7562
  const cached = this.scriptsCache.get(dir);
7419
7563
  if (cached) return cached;
7420
- const scriptsJs = path6.join(dir, "scripts.js");
7564
+ const scriptsJs = path7.join(dir, "scripts.js");
7421
7565
  if (fs5.existsSync(scriptsJs)) {
7422
7566
  try {
7423
7567
  delete require.cache[require.resolve(scriptsJs)];
@@ -7456,7 +7600,7 @@ var ProviderLoader = class _ProviderLoader {
7456
7600
  });
7457
7601
  const handleChange = (filePath) => {
7458
7602
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
7459
- this.log(`File changed: ${path6.basename(filePath)}, reloading...`);
7603
+ this.log(`File changed: ${path7.basename(filePath)}, reloading...`);
7460
7604
  this.reload();
7461
7605
  }
7462
7606
  };
@@ -7511,7 +7655,7 @@ var ProviderLoader = class _ProviderLoader {
7511
7655
  }
7512
7656
  const https = require("https");
7513
7657
  const { execSync: execSync7 } = require("child_process");
7514
- const metaPath = path6.join(this.upstreamDir, _ProviderLoader.META_FILE);
7658
+ const metaPath = path7.join(this.upstreamDir, _ProviderLoader.META_FILE);
7515
7659
  let prevEtag = "";
7516
7660
  let prevTimestamp = 0;
7517
7661
  try {
@@ -7528,7 +7672,7 @@ var ProviderLoader = class _ProviderLoader {
7528
7672
  return { updated: false };
7529
7673
  }
7530
7674
  try {
7531
- const etag = await new Promise((resolve9, reject) => {
7675
+ const etag = await new Promise((resolve10, reject) => {
7532
7676
  const options = {
7533
7677
  method: "HEAD",
7534
7678
  hostname: "github.com",
@@ -7546,7 +7690,7 @@ var ProviderLoader = class _ProviderLoader {
7546
7690
  headers: { "User-Agent": "adhdev-launcher" },
7547
7691
  timeout: 1e4
7548
7692
  }, (res2) => {
7549
- resolve9(res2.headers.etag || res2.headers["last-modified"] || "");
7693
+ resolve10(res2.headers.etag || res2.headers["last-modified"] || "");
7550
7694
  });
7551
7695
  req2.on("error", reject);
7552
7696
  req2.on("timeout", () => {
@@ -7555,7 +7699,7 @@ var ProviderLoader = class _ProviderLoader {
7555
7699
  });
7556
7700
  req2.end();
7557
7701
  } else {
7558
- resolve9(res.headers.etag || res.headers["last-modified"] || "");
7702
+ resolve10(res.headers.etag || res.headers["last-modified"] || "");
7559
7703
  }
7560
7704
  });
7561
7705
  req.on("error", reject);
@@ -7571,17 +7715,17 @@ var ProviderLoader = class _ProviderLoader {
7571
7715
  return { updated: false };
7572
7716
  }
7573
7717
  this.log("Downloading latest providers from GitHub...");
7574
- const tmpTar = path6.join(os7.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
7575
- const tmpExtract = path6.join(os7.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
7718
+ const tmpTar = path7.join(os7.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
7719
+ const tmpExtract = path7.join(os7.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
7576
7720
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
7577
7721
  fs5.mkdirSync(tmpExtract, { recursive: true });
7578
7722
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
7579
7723
  const extracted = fs5.readdirSync(tmpExtract);
7580
7724
  const rootDir = extracted.find(
7581
- (d) => fs5.statSync(path6.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
7725
+ (d) => fs5.statSync(path7.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
7582
7726
  );
7583
7727
  if (!rootDir) throw new Error("Unexpected tarball structure");
7584
- const sourceDir = path6.join(tmpExtract, rootDir);
7728
+ const sourceDir = path7.join(tmpExtract, rootDir);
7585
7729
  const backupDir = this.upstreamDir + ".bak";
7586
7730
  if (fs5.existsSync(this.upstreamDir)) {
7587
7731
  if (fs5.existsSync(backupDir)) fs5.rmSync(backupDir, { recursive: true, force: true });
@@ -7619,7 +7763,7 @@ var ProviderLoader = class _ProviderLoader {
7619
7763
  downloadFile(url, destPath) {
7620
7764
  const https = require("https");
7621
7765
  const http3 = require("http");
7622
- return new Promise((resolve9, reject) => {
7766
+ return new Promise((resolve10, reject) => {
7623
7767
  const doRequest = (reqUrl, redirectCount = 0) => {
7624
7768
  if (redirectCount > 5) {
7625
7769
  reject(new Error("Too many redirects"));
@@ -7639,7 +7783,7 @@ var ProviderLoader = class _ProviderLoader {
7639
7783
  res.pipe(ws);
7640
7784
  ws.on("finish", () => {
7641
7785
  ws.close();
7642
- resolve9();
7786
+ resolve10();
7643
7787
  });
7644
7788
  ws.on("error", reject);
7645
7789
  });
@@ -7656,8 +7800,8 @@ var ProviderLoader = class _ProviderLoader {
7656
7800
  copyDirRecursive(src, dest) {
7657
7801
  fs5.mkdirSync(dest, { recursive: true });
7658
7802
  for (const entry of fs5.readdirSync(src, { withFileTypes: true })) {
7659
- const srcPath = path6.join(src, entry.name);
7660
- const destPath = path6.join(dest, entry.name);
7803
+ const srcPath = path7.join(src, entry.name);
7804
+ const destPath = path7.join(dest, entry.name);
7661
7805
  if (entry.isDirectory()) {
7662
7806
  this.copyDirRecursive(srcPath, destPath);
7663
7807
  } else {
@@ -7668,7 +7812,7 @@ var ProviderLoader = class _ProviderLoader {
7668
7812
  /** .meta.json save */
7669
7813
  writeMeta(metaPath, etag, timestamp) {
7670
7814
  try {
7671
- fs5.mkdirSync(path6.dirname(metaPath), { recursive: true });
7815
+ fs5.mkdirSync(path7.dirname(metaPath), { recursive: true });
7672
7816
  fs5.writeFileSync(metaPath, JSON.stringify({
7673
7817
  etag,
7674
7818
  timestamp,
@@ -7685,7 +7829,7 @@ var ProviderLoader = class _ProviderLoader {
7685
7829
  const scan = (d) => {
7686
7830
  try {
7687
7831
  for (const entry of fs5.readdirSync(d, { withFileTypes: true })) {
7688
- if (entry.isDirectory()) scan(path6.join(d, entry.name));
7832
+ if (entry.isDirectory()) scan(path7.join(d, entry.name));
7689
7833
  else if (entry.name === "provider.json") count++;
7690
7834
  }
7691
7835
  } catch {
@@ -7784,17 +7928,17 @@ var ProviderLoader = class _ProviderLoader {
7784
7928
  for (const root of searchRoots) {
7785
7929
  if (!fs5.existsSync(root)) continue;
7786
7930
  const candidate = this.getProviderDir(root, cat, type);
7787
- if (fs5.existsSync(path6.join(candidate, "provider.json"))) return candidate;
7788
- const catDir = path6.join(root, cat);
7931
+ if (fs5.existsSync(path7.join(candidate, "provider.json"))) return candidate;
7932
+ const catDir = path7.join(root, cat);
7789
7933
  if (fs5.existsSync(catDir)) {
7790
7934
  try {
7791
7935
  for (const entry of fs5.readdirSync(catDir, { withFileTypes: true })) {
7792
7936
  if (!entry.isDirectory()) continue;
7793
- const jsonPath = path6.join(catDir, entry.name, "provider.json");
7937
+ const jsonPath = path7.join(catDir, entry.name, "provider.json");
7794
7938
  if (fs5.existsSync(jsonPath)) {
7795
7939
  try {
7796
7940
  const data = JSON.parse(fs5.readFileSync(jsonPath, "utf-8"));
7797
- if (data.type === type) return path6.join(catDir, entry.name);
7941
+ if (data.type === type) return path7.join(catDir, entry.name);
7798
7942
  } catch {
7799
7943
  }
7800
7944
  }
@@ -7811,7 +7955,7 @@ var ProviderLoader = class _ProviderLoader {
7811
7955
  * (template substitution is NOT applied here — scripts.js handles that)
7812
7956
  */
7813
7957
  buildScriptWrappersFromDir(dir) {
7814
- const scriptsJs = path6.join(dir, "scripts.js");
7958
+ const scriptsJs = path7.join(dir, "scripts.js");
7815
7959
  if (fs5.existsSync(scriptsJs)) {
7816
7960
  try {
7817
7961
  delete require.cache[require.resolve(scriptsJs)];
@@ -7825,7 +7969,7 @@ var ProviderLoader = class _ProviderLoader {
7825
7969
  for (const file of fs5.readdirSync(dir)) {
7826
7970
  if (!file.endsWith(".js")) continue;
7827
7971
  const scriptName = toCamel(file.replace(".js", ""));
7828
- const filePath = path6.join(dir, file);
7972
+ const filePath = path7.join(dir, file);
7829
7973
  result[scriptName] = (...args) => {
7830
7974
  try {
7831
7975
  let content = fs5.readFileSync(filePath, "utf-8");
@@ -7885,7 +8029,7 @@ var ProviderLoader = class _ProviderLoader {
7885
8029
  }
7886
8030
  const hasJson = entries.some((e) => e.name === "provider.json");
7887
8031
  if (hasJson) {
7888
- const jsonPath = path6.join(d, "provider.json");
8032
+ const jsonPath = path7.join(d, "provider.json");
7889
8033
  try {
7890
8034
  const raw = fs5.readFileSync(jsonPath, "utf-8");
7891
8035
  const mod = JSON.parse(raw);
@@ -7898,7 +8042,7 @@ var ProviderLoader = class _ProviderLoader {
7898
8042
  delete mod.extensionIdPattern_flags;
7899
8043
  }
7900
8044
  const hasCompatibility = Array.isArray(mod.compatibility);
7901
- const scriptsPath = path6.join(d, "scripts.js");
8045
+ const scriptsPath = path7.join(d, "scripts.js");
7902
8046
  if (!hasCompatibility && fs5.existsSync(scriptsPath)) {
7903
8047
  try {
7904
8048
  delete require.cache[require.resolve(scriptsPath)];
@@ -7924,7 +8068,7 @@ var ProviderLoader = class _ProviderLoader {
7924
8068
  if (!entry.isDirectory()) continue;
7925
8069
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
7926
8070
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
7927
- scan(path6.join(d, entry.name));
8071
+ scan(path7.join(d, entry.name));
7928
8072
  }
7929
8073
  }
7930
8074
  };
@@ -8004,17 +8148,17 @@ async function findFreePort(ports) {
8004
8148
  throw new Error("No free port found");
8005
8149
  }
8006
8150
  function checkPortFree(port) {
8007
- return new Promise((resolve9) => {
8151
+ return new Promise((resolve10) => {
8008
8152
  const server = net.createServer();
8009
8153
  server.unref();
8010
- server.on("error", () => resolve9(false));
8154
+ server.on("error", () => resolve10(false));
8011
8155
  server.listen(port, "127.0.0.1", () => {
8012
- server.close(() => resolve9(true));
8156
+ server.close(() => resolve10(true));
8013
8157
  });
8014
8158
  });
8015
8159
  }
8016
8160
  async function isCdpActive(port) {
8017
- return new Promise((resolve9) => {
8161
+ return new Promise((resolve10) => {
8018
8162
  const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
8019
8163
  timeout: 2e3
8020
8164
  }, (res) => {
@@ -8023,16 +8167,16 @@ async function isCdpActive(port) {
8023
8167
  res.on("end", () => {
8024
8168
  try {
8025
8169
  const info = JSON.parse(data);
8026
- resolve9(!!info["WebKit-Version"] || !!info["Browser"]);
8170
+ resolve10(!!info["WebKit-Version"] || !!info["Browser"]);
8027
8171
  } catch {
8028
- resolve9(false);
8172
+ resolve10(false);
8029
8173
  }
8030
8174
  });
8031
8175
  });
8032
- req.on("error", () => resolve9(false));
8176
+ req.on("error", () => resolve10(false));
8033
8177
  req.on("timeout", () => {
8034
8178
  req.destroy();
8035
- resolve9(false);
8179
+ resolve10(false);
8036
8180
  });
8037
8181
  });
8038
8182
  }
@@ -8151,8 +8295,8 @@ function detectCurrentWorkspace(ideId) {
8151
8295
  const appNameMap = getMacAppIdentifiers();
8152
8296
  const appName = appNameMap[ideId];
8153
8297
  if (appName) {
8154
- const storagePath = path7.join(
8155
- process.env.APPDATA || path7.join(os8.homedir(), "AppData", "Roaming"),
8298
+ const storagePath = path8.join(
8299
+ process.env.APPDATA || path8.join(os8.homedir(), "AppData", "Roaming"),
8156
8300
  appName,
8157
8301
  "storage.json"
8158
8302
  );
@@ -8327,9 +8471,9 @@ init_logger();
8327
8471
 
8328
8472
  // src/logging/command-log.ts
8329
8473
  var fs6 = __toESM(require("fs"));
8330
- var path8 = __toESM(require("path"));
8474
+ var path9 = __toESM(require("path"));
8331
8475
  var os9 = __toESM(require("os"));
8332
- var LOG_DIR2 = process.platform === "win32" ? path8.join(process.env.LOCALAPPDATA || process.env.APPDATA || path8.join(os9.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path8.join(os9.homedir(), "Library", "Logs", "adhdev") : path8.join(os9.homedir(), ".local", "share", "adhdev", "logs");
8476
+ var LOG_DIR2 = process.platform === "win32" ? path9.join(process.env.LOCALAPPDATA || process.env.APPDATA || path9.join(os9.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path9.join(os9.homedir(), "Library", "Logs", "adhdev") : path9.join(os9.homedir(), ".local", "share", "adhdev", "logs");
8333
8477
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
8334
8478
  var MAX_DAYS = 7;
8335
8479
  try {
@@ -8367,13 +8511,13 @@ function getDateStr2() {
8367
8511
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8368
8512
  }
8369
8513
  var currentDate2 = getDateStr2();
8370
- var currentFile = path8.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
8514
+ var currentFile = path9.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
8371
8515
  var writeCount2 = 0;
8372
8516
  function checkRotation() {
8373
8517
  const today = getDateStr2();
8374
8518
  if (today !== currentDate2) {
8375
8519
  currentDate2 = today;
8376
- currentFile = path8.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
8520
+ currentFile = path9.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
8377
8521
  cleanOldFiles();
8378
8522
  }
8379
8523
  }
@@ -8387,7 +8531,7 @@ function cleanOldFiles() {
8387
8531
  const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
8388
8532
  if (dateMatch && dateMatch[1] < cutoffStr) {
8389
8533
  try {
8390
- fs6.unlinkSync(path8.join(LOG_DIR2, file));
8534
+ fs6.unlinkSync(path9.join(LOG_DIR2, file));
8391
8535
  } catch {
8392
8536
  }
8393
8537
  }
@@ -8616,9 +8760,27 @@ var DaemonCommandRouter = class {
8616
8760
  this.deps.onIdeConnected?.();
8617
8761
  if (result.success && resolvedWorkspace) {
8618
8762
  try {
8619
- saveConfig(appendWorkspaceActivity(loadConfig(), resolvedWorkspace, {
8763
+ let next = appendWorkspaceActivity(loadConfig(), resolvedWorkspace, {
8620
8764
  kind: "ide",
8621
8765
  agentType: result.ideId
8766
+ });
8767
+ next = appendRecentActivity(next, {
8768
+ kind: "ide",
8769
+ providerType: result.ideId || ideKey,
8770
+ providerName: result.ideId || ideKey,
8771
+ workspace: resolvedWorkspace,
8772
+ title: result.ideId || ideKey
8773
+ });
8774
+ saveConfig(next);
8775
+ } catch {
8776
+ }
8777
+ } else if (result.success && (result.ideId || ideKey)) {
8778
+ try {
8779
+ saveConfig(appendRecentActivity(loadConfig(), {
8780
+ kind: "ide",
8781
+ providerType: result.ideId || ideKey,
8782
+ providerName: result.ideId || ideKey,
8783
+ title: result.ideId || ideKey
8622
8784
  }));
8623
8785
  } catch {
8624
8786
  }
@@ -8638,6 +8800,30 @@ var DaemonCommandRouter = class {
8638
8800
  updateConfig({ userName: name });
8639
8801
  return { success: true, userName: name };
8640
8802
  }
8803
+ case "mark_recent_seen": {
8804
+ const kind = args?.kind;
8805
+ const providerType = args?.providerType;
8806
+ if (!kind || !providerType) {
8807
+ return { success: false, error: "kind and providerType are required" };
8808
+ }
8809
+ const recentKey = args?.recentKey || buildRecentActivityKey({
8810
+ kind,
8811
+ providerType,
8812
+ workspace: args?.workspace || null
8813
+ });
8814
+ const next = markRecentSessionSeen(
8815
+ loadConfig(),
8816
+ recentKey,
8817
+ typeof args?.seenAt === "number" ? args.seenAt : Date.now()
8818
+ );
8819
+ saveConfig(next);
8820
+ this.deps.onStatusChange?.();
8821
+ return {
8822
+ success: true,
8823
+ recentKey,
8824
+ seenAt: next.recentSessionReads?.[recentKey] || Date.now()
8825
+ };
8826
+ }
8641
8827
  // ─── Daemon Self-Upgrade ───
8642
8828
  case "daemon_upgrade": {
8643
8829
  LOG.info("Upgrade", "Remote upgrade requested from dashboard");
@@ -8656,9 +8842,9 @@ var DaemonCommandRouter = class {
8656
8842
  setTimeout(() => {
8657
8843
  LOG.info("Upgrade", "Restarting daemon with new version...");
8658
8844
  try {
8659
- const path15 = require("path");
8845
+ const path16 = require("path");
8660
8846
  const fs12 = require("fs");
8661
- const pidFile = path15.join(process.env.HOME || process.env.USERPROFILE || "", ".adhdev", "daemon.pid");
8847
+ const pidFile = path16.join(process.env.HOME || process.env.USERPROFILE || "", ".adhdev", "daemon.pid");
8662
8848
  if (fs12.existsSync(pidFile)) fs12.unlinkSync(pidFile);
8663
8849
  } catch {
8664
8850
  }
@@ -8757,6 +8943,7 @@ init_logger();
8757
8943
  var os10 = __toESM(require("os"));
8758
8944
  init_config();
8759
8945
  init_workspaces();
8946
+ init_terminal_screen();
8760
8947
  function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
8761
8948
  return detectedIdes.filter((ide) => ide.installed !== false).map((ide) => ({
8762
8949
  id: ide.id,
@@ -8775,14 +8962,127 @@ function buildAvailableProviders(providerLoader) {
8775
8962
  category: provider.category
8776
8963
  }));
8777
8964
  }
8965
+ function parseMessageTime(value) {
8966
+ if (typeof value === "number" && Number.isFinite(value)) return value;
8967
+ if (typeof value === "string") {
8968
+ const parsed = Date.parse(value);
8969
+ if (Number.isFinite(parsed)) return parsed;
8970
+ }
8971
+ return 0;
8972
+ }
8973
+ function getSessionMessageUpdatedAt(session) {
8974
+ const lastMessage = session.activeChat?.messages?.at?.(-1);
8975
+ if (!lastMessage) return 0;
8976
+ return parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt) || 0;
8977
+ }
8978
+ function getSessionLastUsedAt(session) {
8979
+ return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
8980
+ }
8981
+ function getSessionKind(session) {
8982
+ return session.transport === "cdp-page" || session.transport === "cdp-webview" ? "ide" : session.transport === "acp" ? "acp" : "cli";
8983
+ }
8984
+ function getLastMessageRole(session) {
8985
+ const role = session.activeChat?.messages?.at?.(-1)?.role;
8986
+ return typeof role === "string" ? role : "";
8987
+ }
8988
+ function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole) {
8989
+ if (status === "waiting_approval") {
8990
+ return { unread: false, inboxBucket: "needs_attention" };
8991
+ }
8992
+ if (status === "generating" || status === "starting") {
8993
+ return { unread: false, inboxBucket: "working" };
8994
+ }
8995
+ const unread = hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
8996
+ return { unread, inboxBucket: unread ? "task_complete" : "idle" };
8997
+ }
8998
+ function buildRecentSessions(sessions, recentActivity, readState) {
8999
+ const live = sessions.filter((session) => !session.parentId && session.status !== "stopped").map((session) => {
9000
+ const kind = getSessionKind(session);
9001
+ const recentKey = buildRecentActivityKey({
9002
+ kind,
9003
+ providerType: session.providerType,
9004
+ workspace: session.workspace
9005
+ });
9006
+ const lastSeenAt = readState[recentKey] || 0;
9007
+ const lastUsedAt = getSessionLastUsedAt(session);
9008
+ const { unread, inboxBucket } = getUnreadState(
9009
+ getSessionMessageUpdatedAt(session) > 0,
9010
+ session.status,
9011
+ lastUsedAt,
9012
+ lastSeenAt,
9013
+ getLastMessageRole(session)
9014
+ );
9015
+ return {
9016
+ id: session.id,
9017
+ recentKey,
9018
+ sessionId: session.id,
9019
+ providerType: session.providerType,
9020
+ providerName: session.providerName,
9021
+ kind,
9022
+ title: session.activeChat?.title || session.title || session.providerName,
9023
+ workspace: session.workspace,
9024
+ currentModel: session.currentModel,
9025
+ status: session.status,
9026
+ lastUsedAt,
9027
+ unread,
9028
+ lastSeenAt,
9029
+ inboxBucket
9030
+ };
9031
+ });
9032
+ const seen = new Set(live.map((item) => `${item.kind}:${item.providerType}:${item.workspace || ""}`));
9033
+ const persisted = recentActivity.filter((item) => !seen.has(`${item.kind}:${item.providerType}:${item.workspace || ""}`)).map((item) => {
9034
+ const lastSeenAt = readState[item.id] || 0;
9035
+ const unread = item.lastUsedAt > lastSeenAt;
9036
+ return {
9037
+ id: item.id,
9038
+ recentKey: item.id,
9039
+ sessionId: item.sessionId || null,
9040
+ providerType: item.providerType,
9041
+ providerName: item.providerName,
9042
+ kind: item.kind,
9043
+ title: item.title || item.providerName,
9044
+ workspace: item.workspace,
9045
+ currentModel: item.currentModel,
9046
+ lastUsedAt: item.lastUsedAt,
9047
+ unread,
9048
+ lastSeenAt,
9049
+ inboxBucket: unread ? "task_complete" : "idle"
9050
+ };
9051
+ });
9052
+ return [...live, ...persisted].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, 12);
9053
+ }
8778
9054
  function buildStatusSnapshot(options) {
8779
9055
  const cfg = loadConfig();
8780
9056
  const wsState = getWorkspaceState(cfg);
8781
9057
  const memSnap = getHostMemorySnapshot();
9058
+ const recentActivity = getRecentActivity(cfg, 20);
8782
9059
  const sessions = buildSessionEntries(
8783
9060
  options.allStates,
8784
9061
  options.cdpManagers
8785
9062
  );
9063
+ const readState = cfg.recentSessionReads || {};
9064
+ for (const session of sessions) {
9065
+ const kind = getSessionKind(session);
9066
+ const recentKey = buildRecentActivityKey({
9067
+ kind,
9068
+ providerType: session.providerType,
9069
+ workspace: session.workspace
9070
+ });
9071
+ const lastSeenAt = getRecentSessionSeenAt(cfg, recentKey);
9072
+ const lastUsedAt = getSessionLastUsedAt(session);
9073
+ const { unread, inboxBucket } = getUnreadState(
9074
+ getSessionMessageUpdatedAt(session) > 0,
9075
+ session.status,
9076
+ lastUsedAt,
9077
+ lastSeenAt,
9078
+ getLastMessageRole(session)
9079
+ );
9080
+ session.recentKey = recentKey;
9081
+ session.lastSeenAt = lastSeenAt;
9082
+ session.unread = unread;
9083
+ session.inboxBucket = inboxBucket;
9084
+ }
9085
+ const terminalBackend = getTerminalBackendRuntimeStatus();
8786
9086
  return {
8787
9087
  instanceId: options.instanceId,
8788
9088
  version: options.version,
@@ -8808,6 +9108,8 @@ function buildStatusSnapshot(options) {
8808
9108
  defaultWorkspaceId: wsState.defaultWorkspaceId,
8809
9109
  defaultWorkspacePath: wsState.defaultWorkspacePath,
8810
9110
  workspaceActivity: getWorkspaceActivity(cfg, 15),
9111
+ recentSessions: buildRecentSessions(sessions, recentActivity, readState),
9112
+ terminalBackend,
8811
9113
  availableProviders: buildAvailableProviders(options.providerLoader)
8812
9114
  };
8813
9115
  }
@@ -8959,7 +9261,15 @@ var DaemonStatusReporter = class {
8959
9261
  cdpConnected: session.cdpConnected,
8960
9262
  currentModel: session.currentModel,
8961
9263
  currentPlan: session.currentPlan,
8962
- currentAutoApprove: session.currentAutoApprove
9264
+ currentAutoApprove: session.currentAutoApprove,
9265
+ recentKey: session.recentKey,
9266
+ unread: session.unread,
9267
+ lastSeenAt: session.lastSeenAt,
9268
+ inboxBucket: session.inboxBucket,
9269
+ controlValues: session.controlValues,
9270
+ providerControls: session.providerControls,
9271
+ acpConfigOptions: session.acpConfigOptions,
9272
+ acpModes: session.acpModes
8963
9273
  })),
8964
9274
  p2p: payload.p2p,
8965
9275
  timestamp: now
@@ -8997,7 +9307,7 @@ init_logger();
8997
9307
 
8998
9308
  // src/commands/cli-manager.ts
8999
9309
  var os13 = __toESM(require("os"));
9000
- var path10 = __toESM(require("path"));
9310
+ var path11 = __toESM(require("path"));
9001
9311
  var crypto4 = __toESM(require("crypto"));
9002
9312
  var import_chalk = __toESM(require("chalk"));
9003
9313
  init_provider_cli_adapter();
@@ -9095,7 +9405,10 @@ var CliProviderInstance = class {
9095
9405
  writeOwner: runtime.writeOwner || null,
9096
9406
  attachedClients: runtime.attachedClients || []
9097
9407
  } : void 0,
9098
- resume: this.provider.resume
9408
+ resume: this.provider.resume,
9409
+ controlValues: void 0,
9410
+ // CLI controls not yet wired from stream
9411
+ providerControls: this.provider.controls
9099
9412
  };
9100
9413
  }
9101
9414
  onEvent(event, data) {
@@ -9371,7 +9684,12 @@ var AcpProviderInstance = class {
9371
9684
  acpModes: this.availableModes,
9372
9685
  // Error details for dashboard display
9373
9686
  errorMessage: this.errorMessage || void 0,
9374
- errorReason: this.errorReason || void 0
9687
+ errorReason: this.errorReason || void 0,
9688
+ controlValues: {
9689
+ ...this.currentModel ? { model: this.currentModel } : {},
9690
+ ...this.currentMode ? { mode: this.currentMode } : {}
9691
+ },
9692
+ providerControls: this.provider.controls
9375
9693
  };
9376
9694
  }
9377
9695
  onEvent(event, data) {
@@ -9670,13 +9988,13 @@ var AcpProviderInstance = class {
9670
9988
  }
9671
9989
  this.currentStatus = "waiting_approval";
9672
9990
  this.detectStatusTransition();
9673
- const approved = await new Promise((resolve9) => {
9674
- this.permissionResolvers.push(resolve9);
9991
+ const approved = await new Promise((resolve10) => {
9992
+ this.permissionResolvers.push(resolve10);
9675
9993
  setTimeout(() => {
9676
- const idx = this.permissionResolvers.indexOf(resolve9);
9994
+ const idx = this.permissionResolvers.indexOf(resolve10);
9677
9995
  if (idx >= 0) {
9678
9996
  this.permissionResolvers.splice(idx, 1);
9679
- resolve9(false);
9997
+ resolve10(false);
9680
9998
  }
9681
9999
  }, 3e5);
9682
10000
  });
@@ -10169,6 +10487,13 @@ var DaemonCliManager = class {
10169
10487
  console.error(colorize("red", ` \u2717 Failed to save recent workspace: ${e}`));
10170
10488
  }
10171
10489
  }
10490
+ persistRecentActivity(entry) {
10491
+ try {
10492
+ saveConfig(appendRecentActivity(loadConfig(), entry));
10493
+ } catch (e) {
10494
+ console.error(colorize("red", ` \u2717 Failed to save recent activity: ${e}`));
10495
+ }
10496
+ }
10172
10497
  getTransportFactory(runtimeId, providerType, workspace, cliArgs, attachExisting = false) {
10173
10498
  return this.deps.createPtyTransportFactory?.({
10174
10499
  runtimeId,
@@ -10251,7 +10576,7 @@ var DaemonCliManager = class {
10251
10576
  async startSession(cliType, workingDir, cliArgs, initialModel) {
10252
10577
  const trimmed = (workingDir || "").trim();
10253
10578
  if (!trimmed) throw new Error("working directory required");
10254
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path10.resolve(trimmed);
10579
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path11.resolve(trimmed);
10255
10580
  const normalizedType = this.providerLoader.resolveAlias(cliType);
10256
10581
  const provider = this.providerLoader.getByAlias(cliType);
10257
10582
  const key = crypto4.randomUUID();
@@ -10327,6 +10652,15 @@ ${installInfo}`
10327
10652
  } catch (e) {
10328
10653
  LOG.warn("CLI", `ACP history save failed: ${e?.message}`);
10329
10654
  }
10655
+ this.persistRecentActivity({
10656
+ kind: "acp",
10657
+ providerType: normalizedType,
10658
+ providerName: provider.displayName || provider.name || normalizedType,
10659
+ workspace: resolvedDir,
10660
+ currentModel: initialModel,
10661
+ sessionId,
10662
+ title: provider.displayName || provider.name || normalizedType
10663
+ });
10330
10664
  this.deps.onStatusChange();
10331
10665
  return;
10332
10666
  }
@@ -10389,6 +10723,15 @@ ${installInfo}`
10389
10723
  } catch (e) {
10390
10724
  LOG.warn("CLI", `CLI history save failed: ${e?.message}`);
10391
10725
  }
10726
+ this.persistRecentActivity({
10727
+ kind: "cli",
10728
+ providerType: normalizedType,
10729
+ providerName: provider?.displayName || provider?.name || normalizedType,
10730
+ workspace: resolvedDir,
10731
+ currentModel: initialModel,
10732
+ sessionId: key,
10733
+ title: provider?.displayName || provider?.name || normalizedType
10734
+ });
10392
10735
  this.deps.onStatusChange();
10393
10736
  }
10394
10737
  async stopSession(key) {
@@ -10634,11 +10977,24 @@ var ProviderStreamAdapter = class {
10634
10977
  hasScript(name) {
10635
10978
  return typeof this.provider.scripts?.[name] === "function";
10636
10979
  }
10980
+ summarizeRaw(raw) {
10981
+ try {
10982
+ if (typeof raw === "string") return raw.replace(/\s+/g, " ").trim().slice(0, 240);
10983
+ if (raw == null) return String(raw);
10984
+ return JSON.stringify(raw).replace(/\s+/g, " ").trim().slice(0, 240);
10985
+ } catch {
10986
+ return Object.prototype.toString.call(raw);
10987
+ }
10988
+ }
10989
+ isTransportError(reason) {
10990
+ return /Session with given id not found/i.test(reason) || /CDP not connected/i.test(reason) || /Target closed/i.test(reason) || /WebSocket not open/i.test(reason) || /not connected/i.test(reason) || /execution context/i.test(reason) || /Cannot find context with specified id/i.test(reason);
10991
+ }
10637
10992
  async readChat(evaluate) {
10638
10993
  const script = this.callScript("readChat");
10639
10994
  if (!script) return this.errorState("readChat script not available");
10995
+ let raw = null;
10640
10996
  try {
10641
- const raw = await evaluate(script);
10997
+ raw = await evaluate(script);
10642
10998
  const data = typeof raw === "string" ? JSON.parse(raw) : raw;
10643
10999
  if (data?.error) {
10644
11000
  const state2 = this.errorState(data.error);
@@ -10658,12 +11014,31 @@ var ProviderStreamAdapter = class {
10658
11014
  mode: data.mode,
10659
11015
  activeModal: data.activeModal
10660
11016
  };
11017
+ if (this.provider.controls?.length) {
11018
+ const cv = {};
11019
+ for (const ctrl of this.provider.controls) {
11020
+ if (!ctrl.readFrom) continue;
11021
+ const val = data[ctrl.readFrom];
11022
+ if (val !== void 0 && val !== null) {
11023
+ cv[ctrl.id] = typeof val === "object" ? val.name || val.id || String(val) : val;
11024
+ }
11025
+ }
11026
+ if (data.model && !cv["model"]) cv["model"] = data.model;
11027
+ if (data.mode && !cv["mode"]) cv["mode"] = data.mode;
11028
+ if (Object.keys(cv).length > 0) state.controlValues = cv;
11029
+ }
10661
11030
  if (state.messages.length > 0) {
10662
11031
  this.lastSuccessState = state;
10663
11032
  }
10664
11033
  return state;
10665
- } catch {
10666
- const state = this.errorState(`Failed to parse ${this.agentName} state`);
11034
+ } catch (error) {
11035
+ const reason = error instanceof Error ? error.message : String(error);
11036
+ if (this.isTransportError(reason)) {
11037
+ throw error instanceof Error ? error : new Error(reason);
11038
+ }
11039
+ const preview = this.summarizeRaw(raw);
11040
+ const detail = preview ? ` (reason=${reason}; raw=${preview})` : ` (reason=${reason})`;
11041
+ const state = this.errorState(`Failed to parse ${this.agentName} state${detail}`);
10667
11042
  if (this.lastSuccessState?.messages?.length) {
10668
11043
  state.messages = this.lastSuccessState.messages;
10669
11044
  }
@@ -10760,6 +11135,9 @@ var DaemonAgentStreamManager = class {
10760
11135
  getActiveSessionId(parentSessionId) {
10761
11136
  return this.activeSessionIdByParent.get(parentSessionId) || null;
10762
11137
  }
11138
+ isRecoverableSessionError(message) {
11139
+ return message.includes("timeout") || message.includes("not connected") || message.includes("Session") || message.includes("Target closed") || message.includes("execution context") || message.includes("context with specified id");
11140
+ }
10763
11141
  getSessionTarget(sessionId) {
10764
11142
  return this.sessionRegistry?.get(sessionId);
10765
11143
  }
@@ -10861,6 +11239,10 @@ var DaemonAgentStreamManager = class {
10861
11239
  const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
10862
11240
  const state = await agent.adapter.readChat(evaluate);
10863
11241
  LOG.debug("AgentStream", `[AgentStream] readChat(${type}) result: status=${state.status} msgs=${state.messages?.length || 0} model=${state.model || ""}${state.status === "error" ? " error=" + JSON.stringify(state.error || state._error || "unknown") : ""}`);
11242
+ const stateError = String(state.error || state._error || "");
11243
+ if (state.status === "error" && this.isRecoverableSessionError(stateError)) {
11244
+ throw new Error(stateError);
11245
+ }
10864
11246
  agent.lastState = state;
10865
11247
  agent.lastError = null;
10866
11248
  if (state.status === "panel_hidden") {
@@ -10871,7 +11253,7 @@ var DaemonAgentStreamManager = class {
10871
11253
  const errorMsg = e?.message || String(e);
10872
11254
  this.logFn(`[AgentStream] readChat(${type}) error: ${errorMsg.slice(0, 200)}`);
10873
11255
  agent.lastError = errorMsg;
10874
- if (errorMsg.includes("timeout") || errorMsg.includes("not connected") || errorMsg.includes("Session")) {
11256
+ if (this.isRecoverableSessionError(errorMsg)) {
10875
11257
  try {
10876
11258
  await cdp.detachAgent(agent.cdpSessionId);
10877
11259
  } catch {
@@ -11359,11 +11741,11 @@ var ProviderInstanceManager = class {
11359
11741
 
11360
11742
  // src/providers/version-archive.ts
11361
11743
  var fs8 = __toESM(require("fs"));
11362
- var path11 = __toESM(require("path"));
11744
+ var path12 = __toESM(require("path"));
11363
11745
  var os14 = __toESM(require("os"));
11364
11746
  var import_child_process7 = require("child_process");
11365
11747
  var import_os3 = require("os");
11366
- var ARCHIVE_PATH = path11.join(os14.homedir(), ".adhdev", "version-history.json");
11748
+ var ARCHIVE_PATH = path12.join(os14.homedir(), ".adhdev", "version-history.json");
11367
11749
  var MAX_ENTRIES_PER_PROVIDER = 20;
11368
11750
  var VersionArchive = class {
11369
11751
  history = {};
@@ -11410,7 +11792,7 @@ var VersionArchive = class {
11410
11792
  }
11411
11793
  save() {
11412
11794
  try {
11413
- fs8.mkdirSync(path11.dirname(ARCHIVE_PATH), { recursive: true });
11795
+ fs8.mkdirSync(path12.dirname(ARCHIVE_PATH), { recursive: true });
11414
11796
  fs8.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
11415
11797
  } catch {
11416
11798
  }
@@ -11451,7 +11833,7 @@ function checkPathExists2(paths) {
11451
11833
  for (const p of paths) {
11452
11834
  if (p.includes("*")) {
11453
11835
  const home = os14.homedir();
11454
- const resolved = p.replace(/\*/g, home.split(path11.sep).pop() || "");
11836
+ const resolved = p.replace(/\*/g, home.split(path12.sep).pop() || "");
11455
11837
  if (fs8.existsSync(resolved)) return resolved;
11456
11838
  } else {
11457
11839
  if (fs8.existsSync(p)) return p;
@@ -11461,7 +11843,7 @@ function checkPathExists2(paths) {
11461
11843
  }
11462
11844
  function getMacAppVersion(appPath) {
11463
11845
  if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
11464
- const plistPath = path11.join(appPath, "Contents", "Info.plist");
11846
+ const plistPath = path12.join(appPath, "Contents", "Info.plist");
11465
11847
  if (!fs8.existsSync(plistPath)) return null;
11466
11848
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
11467
11849
  return raw || null;
@@ -11488,7 +11870,7 @@ async function detectAllVersions(loader, archive) {
11488
11870
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
11489
11871
  let resolvedBin = cliBin;
11490
11872
  if (!resolvedBin && appPath && currentOs === "darwin") {
11491
- const bundled = path11.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
11873
+ const bundled = path12.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
11492
11874
  if (provider.cli && fs8.existsSync(bundled)) resolvedBin = bundled;
11493
11875
  }
11494
11876
  info.installed = !!(appPath || resolvedBin);
@@ -11529,7 +11911,7 @@ async function detectAllVersions(loader, archive) {
11529
11911
  // src/daemon/dev-server.ts
11530
11912
  var http2 = __toESM(require("http"));
11531
11913
  var fs11 = __toESM(require("fs"));
11532
- var path14 = __toESM(require("path"));
11914
+ var path15 = __toESM(require("path"));
11533
11915
 
11534
11916
  // src/daemon/scaffold-template.ts
11535
11917
  function generateFiles(type, name, category, opts = {}) {
@@ -11865,7 +12247,7 @@ init_logger();
11865
12247
 
11866
12248
  // src/daemon/dev-cdp-handlers.ts
11867
12249
  var fs9 = __toESM(require("fs"));
11868
- var path12 = __toESM(require("path"));
12250
+ var path13 = __toESM(require("path"));
11869
12251
  init_logger();
11870
12252
  async function handleCdpEvaluate(ctx, req, res) {
11871
12253
  const body = await ctx.readBody(req);
@@ -12044,17 +12426,17 @@ async function handleScriptHints(ctx, type, _req, res) {
12044
12426
  return;
12045
12427
  }
12046
12428
  let scriptsPath = "";
12047
- const directScripts = path12.join(dir, "scripts.js");
12429
+ const directScripts = path13.join(dir, "scripts.js");
12048
12430
  if (fs9.existsSync(directScripts)) {
12049
12431
  scriptsPath = directScripts;
12050
12432
  } else {
12051
- const scriptsDir = path12.join(dir, "scripts");
12433
+ const scriptsDir = path13.join(dir, "scripts");
12052
12434
  if (fs9.existsSync(scriptsDir)) {
12053
12435
  const versions = fs9.readdirSync(scriptsDir).filter((d) => {
12054
- return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
12436
+ return fs9.statSync(path13.join(scriptsDir, d)).isDirectory();
12055
12437
  }).sort().reverse();
12056
12438
  for (const ver of versions) {
12057
- const p = path12.join(scriptsDir, ver, "scripts.js");
12439
+ const p = path13.join(scriptsDir, ver, "scripts.js");
12058
12440
  if (fs9.existsSync(p)) {
12059
12441
  scriptsPath = p;
12060
12442
  break;
@@ -13109,7 +13491,7 @@ async function handleCliRaw(ctx, req, res) {
13109
13491
 
13110
13492
  // src/daemon/dev-auto-implement.ts
13111
13493
  var fs10 = __toESM(require("fs"));
13112
- var path13 = __toESM(require("path"));
13494
+ var path14 = __toESM(require("path"));
13113
13495
  var os15 = __toESM(require("os"));
13114
13496
  function getDefaultAutoImplReference(ctx, category, type) {
13115
13497
  if (category === "cli") {
@@ -13129,22 +13511,22 @@ function getLatestScriptVersionDir(scriptsDir) {
13129
13511
  if (!fs10.existsSync(scriptsDir)) return null;
13130
13512
  const versions = fs10.readdirSync(scriptsDir).filter((d) => {
13131
13513
  try {
13132
- return fs10.statSync(path13.join(scriptsDir, d)).isDirectory();
13514
+ return fs10.statSync(path14.join(scriptsDir, d)).isDirectory();
13133
13515
  } catch {
13134
13516
  return false;
13135
13517
  }
13136
13518
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
13137
13519
  if (versions.length === 0) return null;
13138
- return path13.join(scriptsDir, versions[0]);
13520
+ return path14.join(scriptsDir, versions[0]);
13139
13521
  }
13140
13522
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
13141
- const canonicalUserDir = path13.resolve(ctx.providerLoader.getUserProviderDir(category, type));
13142
- const desiredDir = requestedDir ? path13.resolve(requestedDir) : canonicalUserDir;
13143
- const upstreamRoot = path13.resolve(ctx.providerLoader.getUpstreamDir());
13144
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path13.sep}`)) {
13523
+ const canonicalUserDir = path14.resolve(ctx.providerLoader.getUserProviderDir(category, type));
13524
+ const desiredDir = requestedDir ? path14.resolve(requestedDir) : canonicalUserDir;
13525
+ const upstreamRoot = path14.resolve(ctx.providerLoader.getUpstreamDir());
13526
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path14.sep}`)) {
13145
13527
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
13146
13528
  }
13147
- if (path13.basename(desiredDir) !== type) {
13529
+ if (path14.basename(desiredDir) !== type) {
13148
13530
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
13149
13531
  }
13150
13532
  const sourceDir = ctx.findProviderDir(type);
@@ -13152,11 +13534,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
13152
13534
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
13153
13535
  }
13154
13536
  if (!fs10.existsSync(desiredDir)) {
13155
- fs10.mkdirSync(path13.dirname(desiredDir), { recursive: true });
13537
+ fs10.mkdirSync(path14.dirname(desiredDir), { recursive: true });
13156
13538
  fs10.cpSync(sourceDir, desiredDir, { recursive: true });
13157
13539
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
13158
13540
  }
13159
- const providerJson = path13.join(desiredDir, "provider.json");
13541
+ const providerJson = path14.join(desiredDir, "provider.json");
13160
13542
  if (!fs10.existsSync(providerJson)) {
13161
13543
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
13162
13544
  }
@@ -13179,13 +13561,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
13179
13561
  const refDir = ctx.findProviderDir(referenceType);
13180
13562
  if (!refDir || !fs10.existsSync(refDir)) return {};
13181
13563
  const referenceScripts = {};
13182
- const scriptsDir = path13.join(refDir, "scripts");
13564
+ const scriptsDir = path14.join(refDir, "scripts");
13183
13565
  const latestDir = getLatestScriptVersionDir(scriptsDir);
13184
13566
  if (!latestDir) return referenceScripts;
13185
13567
  for (const file of fs10.readdirSync(latestDir)) {
13186
13568
  if (!file.endsWith(".js")) continue;
13187
13569
  try {
13188
- referenceScripts[file] = fs10.readFileSync(path13.join(latestDir, file), "utf-8");
13570
+ referenceScripts[file] = fs10.readFileSync(path14.join(latestDir, file), "utf-8");
13189
13571
  } catch {
13190
13572
  }
13191
13573
  }
@@ -13236,9 +13618,9 @@ async function handleAutoImplement(ctx, type, req, res) {
13236
13618
  });
13237
13619
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
13238
13620
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference);
13239
- const tmpDir = path13.join(os15.tmpdir(), "adhdev-autoimpl");
13621
+ const tmpDir = path14.join(os15.tmpdir(), "adhdev-autoimpl");
13240
13622
  if (!fs10.existsSync(tmpDir)) fs10.mkdirSync(tmpDir, { recursive: true });
13241
- const promptFile = path13.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
13623
+ const promptFile = path14.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
13242
13624
  fs10.writeFileSync(promptFile, prompt, "utf-8");
13243
13625
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
13244
13626
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -13609,7 +13991,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
13609
13991
  setMode: "set_mode.js"
13610
13992
  };
13611
13993
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
13612
- const scriptsDir = path13.join(providerDir, "scripts");
13994
+ const scriptsDir = path14.join(providerDir, "scripts");
13613
13995
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
13614
13996
  if (latestScriptsDir) {
13615
13997
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -13620,7 +14002,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
13620
14002
  for (const file of fs10.readdirSync(latestScriptsDir)) {
13621
14003
  if (file.endsWith(".js") && targetFileNames.has(file)) {
13622
14004
  try {
13623
- const content = fs10.readFileSync(path13.join(latestScriptsDir, file), "utf-8");
14005
+ const content = fs10.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
13624
14006
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
13625
14007
  lines.push("```javascript");
13626
14008
  lines.push(content);
@@ -13637,7 +14019,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
13637
14019
  lines.push("");
13638
14020
  for (const file of refFiles) {
13639
14021
  try {
13640
- const content = fs10.readFileSync(path13.join(latestScriptsDir, file), "utf-8");
14022
+ const content = fs10.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
13641
14023
  lines.push(`### \`${file}\` \u{1F512}`);
13642
14024
  lines.push("```javascript");
13643
14025
  lines.push(content);
@@ -13678,10 +14060,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
13678
14060
  lines.push("");
13679
14061
  }
13680
14062
  }
13681
- const docsDir = path13.join(providerDir, "../../docs");
14063
+ const docsDir = path14.join(providerDir, "../../docs");
13682
14064
  const loadGuide = (name) => {
13683
14065
  try {
13684
- const p = path13.join(docsDir, name);
14066
+ const p = path14.join(docsDir, name);
13685
14067
  if (fs10.existsSync(p)) return fs10.readFileSync(p, "utf-8");
13686
14068
  } catch {
13687
14069
  }
@@ -13855,7 +14237,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
13855
14237
  parseApproval: "parse_approval.js"
13856
14238
  };
13857
14239
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
13858
- const scriptsDir = path13.join(providerDir, "scripts");
14240
+ const scriptsDir = path14.join(providerDir, "scripts");
13859
14241
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
13860
14242
  if (latestScriptsDir) {
13861
14243
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -13867,7 +14249,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
13867
14249
  if (!file.endsWith(".js")) continue;
13868
14250
  if (!targetFileNames.has(file)) continue;
13869
14251
  try {
13870
- const content = fs10.readFileSync(path13.join(latestScriptsDir, file), "utf-8");
14252
+ const content = fs10.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
13871
14253
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
13872
14254
  lines.push("```javascript");
13873
14255
  lines.push(content);
@@ -13883,7 +14265,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
13883
14265
  lines.push("");
13884
14266
  for (const file of refFiles) {
13885
14267
  try {
13886
- const content = fs10.readFileSync(path13.join(latestScriptsDir, file), "utf-8");
14268
+ const content = fs10.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
13887
14269
  lines.push(`### \`${file}\` \u{1F512}`);
13888
14270
  lines.push("```javascript");
13889
14271
  lines.push(content);
@@ -13916,10 +14298,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
13916
14298
  lines.push("");
13917
14299
  }
13918
14300
  }
13919
- const docsDir = path13.join(providerDir, "../../docs");
14301
+ const docsDir = path14.join(providerDir, "../../docs");
13920
14302
  const loadGuide = (name) => {
13921
14303
  try {
13922
- const p = path13.join(docsDir, name);
14304
+ const p = path14.join(docsDir, name);
13923
14305
  if (fs10.existsSync(p)) return fs10.readFileSync(p, "utf-8");
13924
14306
  } catch {
13925
14307
  }
@@ -14177,8 +14559,8 @@ var DevServer = class _DevServer {
14177
14559
  }
14178
14560
  getEndpointList() {
14179
14561
  return this.routes.map((r) => {
14180
- const path15 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
14181
- return `${r.method.padEnd(5)} ${path15}`;
14562
+ const path16 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
14563
+ return `${r.method.padEnd(5)} ${path16}`;
14182
14564
  });
14183
14565
  }
14184
14566
  async start(port = DEV_SERVER_PORT) {
@@ -14209,15 +14591,15 @@ var DevServer = class _DevServer {
14209
14591
  this.json(res, 500, { error: e.message });
14210
14592
  }
14211
14593
  });
14212
- return new Promise((resolve9, reject) => {
14594
+ return new Promise((resolve10, reject) => {
14213
14595
  this.server.listen(port, "127.0.0.1", () => {
14214
14596
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
14215
- resolve9();
14597
+ resolve10();
14216
14598
  });
14217
14599
  this.server.on("error", (e) => {
14218
14600
  if (e.code === "EADDRINUSE") {
14219
14601
  this.log(`Port ${port} in use, skipping dev server`);
14220
- resolve9();
14602
+ resolve10();
14221
14603
  } else {
14222
14604
  reject(e);
14223
14605
  }
@@ -14300,20 +14682,20 @@ var DevServer = class _DevServer {
14300
14682
  child.stderr?.on("data", (d) => {
14301
14683
  stderr += d.toString().slice(0, 2e3);
14302
14684
  });
14303
- await new Promise((resolve9) => {
14685
+ await new Promise((resolve10) => {
14304
14686
  const timer = setTimeout(() => {
14305
14687
  child.kill();
14306
- resolve9();
14688
+ resolve10();
14307
14689
  }, 3e3);
14308
14690
  child.on("exit", () => {
14309
14691
  clearTimeout(timer);
14310
- resolve9();
14692
+ resolve10();
14311
14693
  });
14312
14694
  child.stdout?.once("data", () => {
14313
14695
  setTimeout(() => {
14314
14696
  child.kill();
14315
14697
  clearTimeout(timer);
14316
- resolve9();
14698
+ resolve10();
14317
14699
  }, 500);
14318
14700
  });
14319
14701
  });
@@ -14460,12 +14842,12 @@ var DevServer = class _DevServer {
14460
14842
  // ─── DevConsole SPA ───
14461
14843
  getConsoleDistDir() {
14462
14844
  const candidates = [
14463
- path14.resolve(__dirname, "../../web-devconsole/dist"),
14464
- path14.resolve(__dirname, "../../../web-devconsole/dist"),
14465
- path14.join(process.cwd(), "packages/web-devconsole/dist")
14845
+ path15.resolve(__dirname, "../../web-devconsole/dist"),
14846
+ path15.resolve(__dirname, "../../../web-devconsole/dist"),
14847
+ path15.join(process.cwd(), "packages/web-devconsole/dist")
14466
14848
  ];
14467
14849
  for (const dir of candidates) {
14468
- if (fs11.existsSync(path14.join(dir, "index.html"))) return dir;
14850
+ if (fs11.existsSync(path15.join(dir, "index.html"))) return dir;
14469
14851
  }
14470
14852
  return null;
14471
14853
  }
@@ -14475,7 +14857,7 @@ var DevServer = class _DevServer {
14475
14857
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
14476
14858
  return;
14477
14859
  }
14478
- const htmlPath = path14.join(distDir, "index.html");
14860
+ const htmlPath = path15.join(distDir, "index.html");
14479
14861
  try {
14480
14862
  const html = fs11.readFileSync(htmlPath, "utf-8");
14481
14863
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -14500,15 +14882,15 @@ var DevServer = class _DevServer {
14500
14882
  this.json(res, 404, { error: "Not found" });
14501
14883
  return;
14502
14884
  }
14503
- const safePath = path14.normalize(pathname).replace(/^\.\.\//, "");
14504
- const filePath = path14.join(distDir, safePath);
14885
+ const safePath = path15.normalize(pathname).replace(/^\.\.\//, "");
14886
+ const filePath = path15.join(distDir, safePath);
14505
14887
  if (!filePath.startsWith(distDir)) {
14506
14888
  this.json(res, 403, { error: "Forbidden" });
14507
14889
  return;
14508
14890
  }
14509
14891
  try {
14510
14892
  const content = fs11.readFileSync(filePath);
14511
- const ext = path14.extname(filePath);
14893
+ const ext = path15.extname(filePath);
14512
14894
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
14513
14895
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
14514
14896
  res.end(content);
@@ -14621,9 +15003,9 @@ var DevServer = class _DevServer {
14621
15003
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
14622
15004
  if (entry.isDirectory()) {
14623
15005
  files.push({ path: rel, size: 0, type: "dir" });
14624
- scan(path14.join(d, entry.name), rel);
15006
+ scan(path15.join(d, entry.name), rel);
14625
15007
  } else {
14626
- const stat = fs11.statSync(path14.join(d, entry.name));
15008
+ const stat = fs11.statSync(path15.join(d, entry.name));
14627
15009
  files.push({ path: rel, size: stat.size, type: "file" });
14628
15010
  }
14629
15011
  }
@@ -14646,7 +15028,7 @@ var DevServer = class _DevServer {
14646
15028
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
14647
15029
  return;
14648
15030
  }
14649
- const fullPath = path14.resolve(dir, path14.normalize(filePath));
15031
+ const fullPath = path15.resolve(dir, path15.normalize(filePath));
14650
15032
  if (!fullPath.startsWith(dir)) {
14651
15033
  this.json(res, 403, { error: "Forbidden" });
14652
15034
  return;
@@ -14671,14 +15053,14 @@ var DevServer = class _DevServer {
14671
15053
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
14672
15054
  return;
14673
15055
  }
14674
- const fullPath = path14.resolve(dir, path14.normalize(filePath));
15056
+ const fullPath = path15.resolve(dir, path15.normalize(filePath));
14675
15057
  if (!fullPath.startsWith(dir)) {
14676
15058
  this.json(res, 403, { error: "Forbidden" });
14677
15059
  return;
14678
15060
  }
14679
15061
  try {
14680
15062
  if (fs11.existsSync(fullPath)) fs11.copyFileSync(fullPath, fullPath + ".bak");
14681
- fs11.mkdirSync(path14.dirname(fullPath), { recursive: true });
15063
+ fs11.mkdirSync(path15.dirname(fullPath), { recursive: true });
14682
15064
  fs11.writeFileSync(fullPath, content, "utf-8");
14683
15065
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
14684
15066
  this.providerLoader.reload();
@@ -14695,7 +15077,7 @@ var DevServer = class _DevServer {
14695
15077
  return;
14696
15078
  }
14697
15079
  for (const name of ["scripts.js", "provider.json"]) {
14698
- const p = path14.join(dir, name);
15080
+ const p = path15.join(dir, name);
14699
15081
  if (fs11.existsSync(p)) {
14700
15082
  const source = fs11.readFileSync(p, "utf-8");
14701
15083
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -14716,8 +15098,8 @@ var DevServer = class _DevServer {
14716
15098
  this.json(res, 404, { error: `Provider not found: ${type}` });
14717
15099
  return;
14718
15100
  }
14719
- const target = fs11.existsSync(path14.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
14720
- const targetPath = path14.join(dir, target);
15101
+ const target = fs11.existsSync(path15.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
15102
+ const targetPath = path15.join(dir, target);
14721
15103
  try {
14722
15104
  if (fs11.existsSync(targetPath)) fs11.copyFileSync(targetPath, targetPath + ".bak");
14723
15105
  fs11.writeFileSync(targetPath, source, "utf-8");
@@ -14822,14 +15204,14 @@ var DevServer = class _DevServer {
14822
15204
  child.stderr?.on("data", (d) => {
14823
15205
  stderr += d.toString();
14824
15206
  });
14825
- await new Promise((resolve9) => {
15207
+ await new Promise((resolve10) => {
14826
15208
  const timer = setTimeout(() => {
14827
15209
  child.kill();
14828
- resolve9();
15210
+ resolve10();
14829
15211
  }, timeout);
14830
15212
  child.on("exit", () => {
14831
15213
  clearTimeout(timer);
14832
- resolve9();
15214
+ resolve10();
14833
15215
  });
14834
15216
  });
14835
15217
  const elapsed = Date.now() - start;
@@ -14877,7 +15259,7 @@ var DevServer = class _DevServer {
14877
15259
  }
14878
15260
  let targetDir;
14879
15261
  targetDir = this.providerLoader.getUserProviderDir(category, type);
14880
- const jsonPath = path14.join(targetDir, "provider.json");
15262
+ const jsonPath = path15.join(targetDir, "provider.json");
14881
15263
  if (fs11.existsSync(jsonPath)) {
14882
15264
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
14883
15265
  return;
@@ -14889,8 +15271,8 @@ var DevServer = class _DevServer {
14889
15271
  const createdFiles = ["provider.json"];
14890
15272
  if (result.files) {
14891
15273
  for (const [relPath, content] of Object.entries(result.files)) {
14892
- const fullPath = path14.join(targetDir, relPath);
14893
- fs11.mkdirSync(path14.dirname(fullPath), { recursive: true });
15274
+ const fullPath = path15.join(targetDir, relPath);
15275
+ fs11.mkdirSync(path15.dirname(fullPath), { recursive: true });
14894
15276
  fs11.writeFileSync(fullPath, content, "utf-8");
14895
15277
  createdFiles.push(relPath);
14896
15278
  }
@@ -14943,22 +15325,22 @@ var DevServer = class _DevServer {
14943
15325
  if (!fs11.existsSync(scriptsDir)) return null;
14944
15326
  const versions = fs11.readdirSync(scriptsDir).filter((d) => {
14945
15327
  try {
14946
- return fs11.statSync(path14.join(scriptsDir, d)).isDirectory();
15328
+ return fs11.statSync(path15.join(scriptsDir, d)).isDirectory();
14947
15329
  } catch {
14948
15330
  return false;
14949
15331
  }
14950
15332
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
14951
15333
  if (versions.length === 0) return null;
14952
- return path14.join(scriptsDir, versions[0]);
15334
+ return path15.join(scriptsDir, versions[0]);
14953
15335
  }
14954
15336
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
14955
- const canonicalUserDir = path14.resolve(this.providerLoader.getUserProviderDir(category, type));
14956
- const desiredDir = requestedDir ? path14.resolve(requestedDir) : canonicalUserDir;
14957
- const upstreamRoot = path14.resolve(this.providerLoader.getUpstreamDir());
14958
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path14.sep}`)) {
15337
+ const canonicalUserDir = path15.resolve(this.providerLoader.getUserProviderDir(category, type));
15338
+ const desiredDir = requestedDir ? path15.resolve(requestedDir) : canonicalUserDir;
15339
+ const upstreamRoot = path15.resolve(this.providerLoader.getUpstreamDir());
15340
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path15.sep}`)) {
14959
15341
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
14960
15342
  }
14961
- if (path14.basename(desiredDir) !== type) {
15343
+ if (path15.basename(desiredDir) !== type) {
14962
15344
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
14963
15345
  }
14964
15346
  const sourceDir = this.findProviderDir(type);
@@ -14966,11 +15348,11 @@ var DevServer = class _DevServer {
14966
15348
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
14967
15349
  }
14968
15350
  if (!fs11.existsSync(desiredDir)) {
14969
- fs11.mkdirSync(path14.dirname(desiredDir), { recursive: true });
15351
+ fs11.mkdirSync(path15.dirname(desiredDir), { recursive: true });
14970
15352
  fs11.cpSync(sourceDir, desiredDir, { recursive: true });
14971
15353
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
14972
15354
  }
14973
- const providerJson = path14.join(desiredDir, "provider.json");
15355
+ const providerJson = path15.join(desiredDir, "provider.json");
14974
15356
  if (!fs11.existsSync(providerJson)) {
14975
15357
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
14976
15358
  }
@@ -15018,7 +15400,7 @@ var DevServer = class _DevServer {
15018
15400
  setMode: "set_mode.js"
15019
15401
  };
15020
15402
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
15021
- const scriptsDir = path14.join(providerDir, "scripts");
15403
+ const scriptsDir = path15.join(providerDir, "scripts");
15022
15404
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
15023
15405
  if (latestScriptsDir) {
15024
15406
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -15029,7 +15411,7 @@ var DevServer = class _DevServer {
15029
15411
  for (const file of fs11.readdirSync(latestScriptsDir)) {
15030
15412
  if (file.endsWith(".js") && targetFileNames.has(file)) {
15031
15413
  try {
15032
- const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
15414
+ const content = fs11.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
15033
15415
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
15034
15416
  lines.push("```javascript");
15035
15417
  lines.push(content);
@@ -15046,7 +15428,7 @@ var DevServer = class _DevServer {
15046
15428
  lines.push("");
15047
15429
  for (const file of refFiles) {
15048
15430
  try {
15049
- const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
15431
+ const content = fs11.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
15050
15432
  lines.push(`### \`${file}\` \u{1F512}`);
15051
15433
  lines.push("```javascript");
15052
15434
  lines.push(content);
@@ -15087,10 +15469,10 @@ var DevServer = class _DevServer {
15087
15469
  lines.push("");
15088
15470
  }
15089
15471
  }
15090
- const docsDir = path14.join(providerDir, "../../docs");
15472
+ const docsDir = path15.join(providerDir, "../../docs");
15091
15473
  const loadGuide = (name) => {
15092
15474
  try {
15093
- const p = path14.join(docsDir, name);
15475
+ const p = path15.join(docsDir, name);
15094
15476
  if (fs11.existsSync(p)) return fs11.readFileSync(p, "utf-8");
15095
15477
  } catch {
15096
15478
  }
@@ -15264,7 +15646,7 @@ var DevServer = class _DevServer {
15264
15646
  parseApproval: "parse_approval.js"
15265
15647
  };
15266
15648
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
15267
- const scriptsDir = path14.join(providerDir, "scripts");
15649
+ const scriptsDir = path15.join(providerDir, "scripts");
15268
15650
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
15269
15651
  if (latestScriptsDir) {
15270
15652
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -15276,7 +15658,7 @@ var DevServer = class _DevServer {
15276
15658
  if (!file.endsWith(".js")) continue;
15277
15659
  if (!targetFileNames.has(file)) continue;
15278
15660
  try {
15279
- const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
15661
+ const content = fs11.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
15280
15662
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
15281
15663
  lines.push("```javascript");
15282
15664
  lines.push(content);
@@ -15292,7 +15674,7 @@ var DevServer = class _DevServer {
15292
15674
  lines.push("");
15293
15675
  for (const file of refFiles) {
15294
15676
  try {
15295
- const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
15677
+ const content = fs11.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
15296
15678
  lines.push(`### \`${file}\` \u{1F512}`);
15297
15679
  lines.push("```javascript");
15298
15680
  lines.push(content);
@@ -15325,10 +15707,10 @@ var DevServer = class _DevServer {
15325
15707
  lines.push("");
15326
15708
  }
15327
15709
  }
15328
- const docsDir = path14.join(providerDir, "../../docs");
15710
+ const docsDir = path15.join(providerDir, "../../docs");
15329
15711
  const loadGuide = (name) => {
15330
15712
  try {
15331
- const p = path14.join(docsDir, name);
15713
+ const p = path15.join(docsDir, name);
15332
15714
  if (fs11.existsSync(p)) return fs11.readFileSync(p, "utf-8");
15333
15715
  } catch {
15334
15716
  }
@@ -15485,14 +15867,14 @@ data: ${JSON.stringify(msg.data)}
15485
15867
  res.end(JSON.stringify(data, null, 2));
15486
15868
  }
15487
15869
  async readBody(req) {
15488
- return new Promise((resolve9) => {
15870
+ return new Promise((resolve10) => {
15489
15871
  let body = "";
15490
15872
  req.on("data", (chunk) => body += chunk);
15491
15873
  req.on("end", () => {
15492
15874
  try {
15493
- resolve9(JSON.parse(body));
15875
+ resolve10(JSON.parse(body));
15494
15876
  } catch {
15495
- resolve9({});
15877
+ resolve10({});
15496
15878
  }
15497
15879
  });
15498
15880
  });
@@ -15909,7 +16291,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
15909
16291
  const deadline = Date.now() + timeoutMs;
15910
16292
  while (Date.now() < deadline) {
15911
16293
  if (await canConnect(endpoint)) return;
15912
- await new Promise((resolve9) => setTimeout(resolve9, STARTUP_POLL_MS));
16294
+ await new Promise((resolve10) => setTimeout(resolve10, STARTUP_POLL_MS));
15913
16295
  }
15914
16296
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
15915
16297
  }
@@ -16064,10 +16446,10 @@ async function installExtension(ide, extension) {
16064
16446
  const buffer = Buffer.from(await res.arrayBuffer());
16065
16447
  const fs12 = await import("fs");
16066
16448
  fs12.writeFileSync(vsixPath, buffer);
16067
- return new Promise((resolve9) => {
16449
+ return new Promise((resolve10) => {
16068
16450
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
16069
16451
  (0, import_child_process8.exec)(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
16070
- resolve9({
16452
+ resolve10({
16071
16453
  extensionId: extension.id,
16072
16454
  marketplaceId: extension.marketplaceId,
16073
16455
  success: !error,
@@ -16080,11 +16462,11 @@ async function installExtension(ide, extension) {
16080
16462
  } catch (e) {
16081
16463
  }
16082
16464
  }
16083
- return new Promise((resolve9) => {
16465
+ return new Promise((resolve10) => {
16084
16466
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
16085
16467
  (0, import_child_process8.exec)(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
16086
16468
  if (error) {
16087
- resolve9({
16469
+ resolve10({
16088
16470
  extensionId: extension.id,
16089
16471
  marketplaceId: extension.marketplaceId,
16090
16472
  success: false,
@@ -16092,7 +16474,7 @@ async function installExtension(ide, extension) {
16092
16474
  error: stderr || error.message
16093
16475
  });
16094
16476
  } else {
16095
- resolve9({
16477
+ resolve10({
16096
16478
  extensionId: extension.id,
16097
16479
  marketplaceId: extension.marketplaceId,
16098
16480
  success: true,
@@ -16397,6 +16779,7 @@ async function shutdownDaemonComponents(components) {
16397
16779
  SessionHostPtyTransportFactory,
16398
16780
  VersionArchive,
16399
16781
  addCliHistory,
16782
+ appendRecentActivity,
16400
16783
  buildSessionEntries,
16401
16784
  buildStatusSnapshot,
16402
16785
  connectCdpManager,
@@ -16410,6 +16793,7 @@ async function shutdownDaemonComponents(components) {
16410
16793
  getAvailableIdeIds,
16411
16794
  getHostMemorySnapshot,
16412
16795
  getLogLevel,
16796
+ getRecentActivity,
16413
16797
  getRecentCommands,
16414
16798
  getRecentLogs,
16415
16799
  getWorkspaceActivity,