@adhdev/daemon-core 0.7.35 → 0.7.37

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.mjs CHANGED
@@ -162,8 +162,17 @@ function findWorkspaceByPath(config, rawPath) {
162
162
  if (!abs) return void 0;
163
163
  return (config.workspaces || []).find((w) => path.resolve(expandPath(w.path)) === abs);
164
164
  }
165
- function addWorkspaceEntry(config, rawPath, label) {
165
+ function addWorkspaceEntry(config, rawPath, label, options) {
166
166
  const abs = expandPath(rawPath);
167
+ const createIfMissing = options?.createIfMissing === true;
168
+ if (!abs) return { error: "Path required" };
169
+ if (!fs.existsSync(abs) && createIfMissing) {
170
+ try {
171
+ fs.mkdirSync(abs, { recursive: true });
172
+ } catch (e) {
173
+ return { error: e?.message || "Could not create directory" };
174
+ }
175
+ }
167
176
  const v = validateWorkspacePath(abs);
168
177
  if (!v.ok) return { error: v.error };
169
178
  const list = [...config.workspaces || []];
@@ -224,7 +233,7 @@ __export(config_exports, {
224
233
  });
225
234
  import { homedir as homedir2 } from "os";
226
235
  import { join as join2 } from "path";
227
- import { existsSync as existsSync2, mkdirSync, readFileSync, writeFileSync, chmodSync } from "fs";
236
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync, writeFileSync, chmodSync } from "fs";
228
237
  import { randomUUID as randomUUID2 } from "crypto";
229
238
  function generateMachineId() {
230
239
  return `${MACHINE_ID_PREFIX}${randomUUID2().replace(/-/g, "")}`;
@@ -249,7 +258,7 @@ function ensureMachineId(config) {
249
258
  function getConfigDir() {
250
259
  const dir = join2(homedir2(), ".adhdev");
251
260
  if (!existsSync2(dir)) {
252
- mkdirSync(dir, { recursive: true });
261
+ mkdirSync2(dir, { recursive: true });
253
262
  }
254
263
  return dir;
255
264
  }
@@ -298,7 +307,7 @@ function saveConfig(config) {
298
307
  const configPath = getConfigPath();
299
308
  const dir = getConfigDir();
300
309
  if (!existsSync2(dir)) {
301
- mkdirSync(dir, { recursive: true, mode: 448 });
310
+ mkdirSync2(dir, { recursive: true, mode: 448 });
302
311
  }
303
312
  writeFileSync(configPath, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
304
313
  try {
@@ -389,6 +398,8 @@ var init_config = __esm({
389
398
  workspaces: [],
390
399
  defaultWorkspaceId: null,
391
400
  recentWorkspaceActivity: [],
401
+ recentActivity: [],
402
+ recentSessionReads: {},
392
403
  machineNickname: null,
393
404
  machineId: void 0,
394
405
  machineSecret: null,
@@ -404,7 +415,7 @@ var init_config = __esm({
404
415
 
405
416
  // src/logging/logger.ts
406
417
  import * as fs2 from "fs";
407
- import * as path3 from "path";
418
+ import * as path4 from "path";
408
419
  import * as os4 from "os";
409
420
  function setLogLevel(level) {
410
421
  currentLevel = level;
@@ -420,7 +431,7 @@ function checkDateRotation() {
420
431
  const today = getDateStr();
421
432
  if (today !== currentDate) {
422
433
  currentDate = today;
423
- currentLogFile = path3.join(LOG_DIR, `daemon-${currentDate}.log`);
434
+ currentLogFile = path4.join(LOG_DIR, `daemon-${currentDate}.log`);
424
435
  cleanOldLogs();
425
436
  }
426
437
  }
@@ -434,7 +445,7 @@ function cleanOldLogs() {
434
445
  const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
435
446
  if (dateMatch && dateMatch[1] < cutoffStr) {
436
447
  try {
437
- fs2.unlinkSync(path3.join(LOG_DIR, file));
448
+ fs2.unlinkSync(path4.join(LOG_DIR, file));
438
449
  } catch {
439
450
  }
440
451
  }
@@ -558,7 +569,7 @@ var init_logger = __esm({
558
569
  LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
559
570
  LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
560
571
  currentLevel = "info";
561
- 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");
572
+ 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");
562
573
  MAX_LOG_SIZE = 5 * 1024 * 1024;
563
574
  MAX_LOG_DAYS = 7;
564
575
  try {
@@ -566,16 +577,16 @@ var init_logger = __esm({
566
577
  } catch {
567
578
  }
568
579
  currentDate = getDateStr();
569
- currentLogFile = path3.join(LOG_DIR, `daemon-${currentDate}.log`);
580
+ currentLogFile = path4.join(LOG_DIR, `daemon-${currentDate}.log`);
570
581
  cleanOldLogs();
571
582
  try {
572
- const oldLog = path3.join(LOG_DIR, "daemon.log");
583
+ const oldLog = path4.join(LOG_DIR, "daemon.log");
573
584
  if (fs2.existsSync(oldLog)) {
574
585
  const stat = fs2.statSync(oldLog);
575
586
  const oldDate = stat.mtime.toISOString().slice(0, 10);
576
- fs2.renameSync(oldLog, path3.join(LOG_DIR, `daemon-${oldDate}.log`));
587
+ fs2.renameSync(oldLog, path4.join(LOG_DIR, `daemon-${oldDate}.log`));
577
588
  }
578
- const oldLogBackup = path3.join(LOG_DIR, "daemon.log.old");
589
+ const oldLogBackup = path4.join(LOG_DIR, "daemon.log.old");
579
590
  if (fs2.existsSync(oldLogBackup)) {
580
591
  fs2.unlinkSync(oldLogBackup);
581
592
  }
@@ -607,7 +618,7 @@ var init_logger = __esm({
607
618
  }
608
619
  };
609
620
  interceptorInstalled = false;
610
- LOG_PATH = path3.join(LOG_DIR, `daemon-${getDateStr()}.log`);
621
+ LOG_PATH = path4.join(LOG_DIR, `daemon-${getDateStr()}.log`);
611
622
  }
612
623
  });
613
624
 
@@ -772,6 +783,12 @@ var init_xterm_backend = __esm({
772
783
  });
773
784
 
774
785
  // src/cli-adapters/terminal-screen.ts
786
+ function getTerminalBackendRuntimeStatus() {
787
+ const preference = resolveTerminalBackendPreference();
788
+ const ghosttyAvailable = isGhosttyVtBackendAvailable();
789
+ const backend = preference === "ghostty-vt" || preference === "auto" && ghosttyAvailable ? "ghostty-vt" : "xterm";
790
+ return { backend, preference, ghosttyAvailable };
791
+ }
775
792
  function createTerminalBackend(options, preference) {
776
793
  const ghosttyAvailable = isGhosttyVtBackendAvailable();
777
794
  if (preference === "ghostty-vt") {
@@ -911,7 +928,7 @@ __export(provider_cli_adapter_exports, {
911
928
  normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
912
929
  });
913
930
  import * as os12 from "os";
914
- import * as path9 from "path";
931
+ import * as path10 from "path";
915
932
  import { execSync as execSync4 } from "child_process";
916
933
  function stripAnsi(str) {
917
934
  return str.replace(/\x1B\[\d*[A-HJKSTfG]/g, " ").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][^\x1B]*\x1B\\/g, "").replace(/ +/g, " ");
@@ -932,7 +949,7 @@ function findBinary(name) {
932
949
  }
933
950
  }
934
951
  function isScriptBinary(binaryPath) {
935
- if (!path9.isAbsolute(binaryPath)) return false;
952
+ if (!path10.isAbsolute(binaryPath)) return false;
936
953
  try {
937
954
  const fs12 = __require("fs");
938
955
  const resolved = fs12.realpathSync(binaryPath);
@@ -948,7 +965,7 @@ function isScriptBinary(binaryPath) {
948
965
  }
949
966
  }
950
967
  function looksLikeMachOOrElf(filePath) {
951
- if (!path9.isAbsolute(filePath)) return false;
968
+ if (!path10.isAbsolute(filePath)) return false;
952
969
  try {
953
970
  const fs12 = __require("fs");
954
971
  const resolved = fs12.realpathSync(filePath);
@@ -1074,9 +1091,9 @@ var init_provider_cli_adapter = __esm({
1074
1091
  if (os12.platform() !== "win32") {
1075
1092
  try {
1076
1093
  const fs12 = __require("fs");
1077
- const ptyDir = path9.resolve(path9.dirname(__require.resolve("node-pty")), "..");
1094
+ const ptyDir = path10.resolve(path10.dirname(__require.resolve("node-pty")), "..");
1078
1095
  const platformArch = `${os12.platform()}-${os12.arch()}`;
1079
- const helper = path9.join(ptyDir, "prebuilds", platformArch, "spawn-helper");
1096
+ const helper = path10.join(ptyDir, "prebuilds", platformArch, "spawn-helper");
1080
1097
  if (fs12.existsSync(helper)) {
1081
1098
  const stat = fs12.statSync(helper);
1082
1099
  if (!(stat.mode & 73)) {
@@ -1265,7 +1282,7 @@ var init_provider_cli_adapter = __esm({
1265
1282
  LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
1266
1283
  let shellCmd;
1267
1284
  let shellArgs;
1268
- const useShellUnix = !isWin && (!!spawnConfig.shell || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1285
+ const useShellUnix = !isWin && (!!spawnConfig.shell || !path10.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1269
1286
  const useShell = isWin ? !!spawnConfig.shell : useShellUnix;
1270
1287
  if (useShell) {
1271
1288
  if (!spawnConfig.shell && !isWin) {
@@ -1690,7 +1707,7 @@ ${data.message || ""}`.trim();
1690
1707
  if (this.startupParseGate) {
1691
1708
  const deadline = Date.now() + 1e4;
1692
1709
  while (this.startupParseGate && Date.now() < deadline) {
1693
- await new Promise((resolve9) => setTimeout(resolve9, 50));
1710
+ await new Promise((resolve10) => setTimeout(resolve10, 50));
1694
1711
  }
1695
1712
  }
1696
1713
  if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
@@ -1858,17 +1875,17 @@ ${data.message || ""}`.trim();
1858
1875
  }
1859
1876
  }
1860
1877
  waitForStopped(timeoutMs) {
1861
- return new Promise((resolve9) => {
1878
+ return new Promise((resolve10) => {
1862
1879
  const startedAt = Date.now();
1863
1880
  const timer = setInterval(() => {
1864
1881
  if (!this.ptyProcess || this.currentStatus === "stopped") {
1865
1882
  clearInterval(timer);
1866
- resolve9(true);
1883
+ resolve10(true);
1867
1884
  return;
1868
1885
  }
1869
1886
  if (Date.now() - startedAt >= timeoutMs) {
1870
1887
  clearInterval(timer);
1871
- resolve9(false);
1888
+ resolve10(false);
1872
1889
  }
1873
1890
  }, 100);
1874
1891
  });
@@ -2102,6 +2119,52 @@ function removeActivityForPath(config, rawPath) {
2102
2119
  };
2103
2120
  }
2104
2121
 
2122
+ // src/config/recent-activity.ts
2123
+ init_workspaces();
2124
+ import * as path3 from "path";
2125
+ var MAX_ACTIVITY2 = 30;
2126
+ function normalizeWorkspace(workspace) {
2127
+ if (!workspace) return "";
2128
+ try {
2129
+ return path3.resolve(expandPath(workspace));
2130
+ } catch {
2131
+ return path3.resolve(workspace);
2132
+ }
2133
+ }
2134
+ function buildRecentActivityKey(entry) {
2135
+ return `${entry.kind}:${entry.providerType}:${normalizeWorkspace(entry.workspace)}`;
2136
+ }
2137
+ function appendRecentActivity(config, entry) {
2138
+ const nextEntry = {
2139
+ ...entry,
2140
+ workspace: entry.workspace ? normalizeWorkspace(entry.workspace) : void 0,
2141
+ id: buildRecentActivityKey(entry),
2142
+ lastUsedAt: entry.lastUsedAt || Date.now()
2143
+ };
2144
+ const filtered = (config.recentActivity || []).filter((item) => item.id !== nextEntry.id);
2145
+ return {
2146
+ ...config,
2147
+ recentActivity: [nextEntry, ...filtered].slice(0, MAX_ACTIVITY2)
2148
+ };
2149
+ }
2150
+ function getRecentActivity(config, limit = 20) {
2151
+ return [...config.recentActivity || []].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, limit);
2152
+ }
2153
+ function getRecentSessionSeenAt(config, recentKey) {
2154
+ return config.recentSessionReads?.[recentKey] || 0;
2155
+ }
2156
+ function markRecentSessionSeen(config, recentKey, seenAt = Date.now()) {
2157
+ const prev = config.recentSessionReads || {};
2158
+ const nextSeenAt = Math.max(prev[recentKey] || 0, seenAt);
2159
+ return {
2160
+ ...config,
2161
+ recentSessionReads: {
2162
+ ...prev,
2163
+ [recentKey]: nextSeenAt
2164
+ }
2165
+ };
2166
+ }
2167
+
2105
2168
  // src/detection/ide-detector.ts
2106
2169
  import { execSync } from "child_process";
2107
2170
  import { existsSync as existsSync3 } from "fs";
@@ -2209,15 +2272,15 @@ function parseVersion(raw) {
2209
2272
  return match ? match[1] : raw.split("\n")[0].slice(0, 100);
2210
2273
  }
2211
2274
  function execAsync(cmd, timeoutMs = 5e3) {
2212
- return new Promise((resolve9) => {
2275
+ return new Promise((resolve10) => {
2213
2276
  const child = exec(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
2214
2277
  if (err || !stdout?.trim()) {
2215
- resolve9(null);
2278
+ resolve10(null);
2216
2279
  } else {
2217
- resolve9(stdout.trim());
2280
+ resolve10(stdout.trim());
2218
2281
  }
2219
2282
  });
2220
- child.on("error", () => resolve9(null));
2283
+ child.on("error", () => resolve10(null));
2221
2284
  });
2222
2285
  }
2223
2286
  async function detectCLIs(providerLoader) {
@@ -2384,7 +2447,7 @@ var DaemonCdpManager = class {
2384
2447
  * Returns multiple entries if multiple IDE windows are open on same port
2385
2448
  */
2386
2449
  static listAllTargets(port) {
2387
- return new Promise((resolve9) => {
2450
+ return new Promise((resolve10) => {
2388
2451
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
2389
2452
  let data = "";
2390
2453
  res.on("data", (chunk) => data += chunk.toString());
@@ -2400,16 +2463,16 @@ var DaemonCdpManager = class {
2400
2463
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
2401
2464
  );
2402
2465
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
2403
- resolve9(mainPages.length > 0 ? mainPages : fallbackPages);
2466
+ resolve10(mainPages.length > 0 ? mainPages : fallbackPages);
2404
2467
  } catch {
2405
- resolve9([]);
2468
+ resolve10([]);
2406
2469
  }
2407
2470
  });
2408
2471
  });
2409
- req.on("error", () => resolve9([]));
2472
+ req.on("error", () => resolve10([]));
2410
2473
  req.setTimeout(2e3, () => {
2411
2474
  req.destroy();
2412
- resolve9([]);
2475
+ resolve10([]);
2413
2476
  });
2414
2477
  });
2415
2478
  }
@@ -2449,7 +2512,7 @@ var DaemonCdpManager = class {
2449
2512
  }
2450
2513
  }
2451
2514
  findTargetOnPort(port) {
2452
- return new Promise((resolve9) => {
2515
+ return new Promise((resolve10) => {
2453
2516
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
2454
2517
  let data = "";
2455
2518
  res.on("data", (chunk) => data += chunk.toString());
@@ -2460,7 +2523,7 @@ var DaemonCdpManager = class {
2460
2523
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
2461
2524
  );
2462
2525
  if (pages.length === 0) {
2463
- resolve9(targets.find((t) => t.webSocketDebuggerUrl) || null);
2526
+ resolve10(targets.find((t) => t.webSocketDebuggerUrl) || null);
2464
2527
  return;
2465
2528
  }
2466
2529
  const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -2470,24 +2533,24 @@ var DaemonCdpManager = class {
2470
2533
  const specific = list.find((t) => t.id === this._targetId);
2471
2534
  if (specific) {
2472
2535
  this._pageTitle = specific.title || "";
2473
- resolve9(specific);
2536
+ resolve10(specific);
2474
2537
  } else {
2475
2538
  this.log(`[CDP] Target ${this._targetId} not found in page list`);
2476
- resolve9(null);
2539
+ resolve10(null);
2477
2540
  }
2478
2541
  return;
2479
2542
  }
2480
2543
  this._pageTitle = list[0]?.title || "";
2481
- resolve9(list[0]);
2544
+ resolve10(list[0]);
2482
2545
  } catch {
2483
- resolve9(null);
2546
+ resolve10(null);
2484
2547
  }
2485
2548
  });
2486
2549
  });
2487
- req.on("error", () => resolve9(null));
2550
+ req.on("error", () => resolve10(null));
2488
2551
  req.setTimeout(2e3, () => {
2489
2552
  req.destroy();
2490
- resolve9(null);
2553
+ resolve10(null);
2491
2554
  });
2492
2555
  });
2493
2556
  }
@@ -2498,7 +2561,7 @@ var DaemonCdpManager = class {
2498
2561
  this.extensionProviders = providers;
2499
2562
  }
2500
2563
  connectToTarget(wsUrl) {
2501
- return new Promise((resolve9) => {
2564
+ return new Promise((resolve10) => {
2502
2565
  this.ws = new WebSocket(wsUrl);
2503
2566
  this.ws.on("open", async () => {
2504
2567
  this._connected = true;
@@ -2508,17 +2571,17 @@ var DaemonCdpManager = class {
2508
2571
  }
2509
2572
  this.connectBrowserWs().catch(() => {
2510
2573
  });
2511
- resolve9(true);
2574
+ resolve10(true);
2512
2575
  });
2513
2576
  this.ws.on("message", (data) => {
2514
2577
  try {
2515
2578
  const msg = JSON.parse(data.toString());
2516
2579
  if (msg.id && this.pending.has(msg.id)) {
2517
- const { resolve: resolve10, reject } = this.pending.get(msg.id);
2580
+ const { resolve: resolve11, reject } = this.pending.get(msg.id);
2518
2581
  this.pending.delete(msg.id);
2519
2582
  this.failureCount = 0;
2520
2583
  if (msg.error) reject(new Error(msg.error.message));
2521
- else resolve10(msg.result);
2584
+ else resolve11(msg.result);
2522
2585
  } else if (msg.method === "Runtime.executionContextCreated") {
2523
2586
  this.contexts.add(msg.params.context.id);
2524
2587
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -2541,7 +2604,7 @@ var DaemonCdpManager = class {
2541
2604
  this.ws.on("error", (err) => {
2542
2605
  this.log(`[CDP] WebSocket error: ${err.message}`);
2543
2606
  this._connected = false;
2544
- resolve9(false);
2607
+ resolve10(false);
2545
2608
  });
2546
2609
  });
2547
2610
  }
@@ -2555,7 +2618,7 @@ var DaemonCdpManager = class {
2555
2618
  return;
2556
2619
  }
2557
2620
  this.log(`[CDP] Connecting browser WS for target discovery...`);
2558
- await new Promise((resolve9, reject) => {
2621
+ await new Promise((resolve10, reject) => {
2559
2622
  this.browserWs = new WebSocket(browserWsUrl);
2560
2623
  this.browserWs.on("open", async () => {
2561
2624
  this._browserConnected = true;
@@ -2565,16 +2628,16 @@ var DaemonCdpManager = class {
2565
2628
  } catch (e) {
2566
2629
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
2567
2630
  }
2568
- resolve9();
2631
+ resolve10();
2569
2632
  });
2570
2633
  this.browserWs.on("message", (data) => {
2571
2634
  try {
2572
2635
  const msg = JSON.parse(data.toString());
2573
2636
  if (msg.id && this.browserPending.has(msg.id)) {
2574
- const { resolve: resolve10, reject: reject2 } = this.browserPending.get(msg.id);
2637
+ const { resolve: resolve11, reject: reject2 } = this.browserPending.get(msg.id);
2575
2638
  this.browserPending.delete(msg.id);
2576
2639
  if (msg.error) reject2(new Error(msg.error.message));
2577
- else resolve10(msg.result);
2640
+ else resolve11(msg.result);
2578
2641
  }
2579
2642
  } catch {
2580
2643
  }
@@ -2594,31 +2657,31 @@ var DaemonCdpManager = class {
2594
2657
  }
2595
2658
  }
2596
2659
  getBrowserWsUrl() {
2597
- return new Promise((resolve9) => {
2660
+ return new Promise((resolve10) => {
2598
2661
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
2599
2662
  let data = "";
2600
2663
  res.on("data", (chunk) => data += chunk.toString());
2601
2664
  res.on("end", () => {
2602
2665
  try {
2603
2666
  const info = JSON.parse(data);
2604
- resolve9(info.webSocketDebuggerUrl || null);
2667
+ resolve10(info.webSocketDebuggerUrl || null);
2605
2668
  } catch {
2606
- resolve9(null);
2669
+ resolve10(null);
2607
2670
  }
2608
2671
  });
2609
2672
  });
2610
- req.on("error", () => resolve9(null));
2673
+ req.on("error", () => resolve10(null));
2611
2674
  req.setTimeout(3e3, () => {
2612
2675
  req.destroy();
2613
- resolve9(null);
2676
+ resolve10(null);
2614
2677
  });
2615
2678
  });
2616
2679
  }
2617
2680
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
2618
- return new Promise((resolve9, reject) => {
2681
+ return new Promise((resolve10, reject) => {
2619
2682
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
2620
2683
  const id = this.browserMsgId++;
2621
- this.browserPending.set(id, { resolve: resolve9, reject });
2684
+ this.browserPending.set(id, { resolve: resolve10, reject });
2622
2685
  this.browserWs.send(JSON.stringify({ id, method, params }));
2623
2686
  setTimeout(() => {
2624
2687
  if (this.browserPending.has(id)) {
@@ -2658,11 +2721,11 @@ var DaemonCdpManager = class {
2658
2721
  }
2659
2722
  // ─── CDP Protocol ────────────────────────────────────────
2660
2723
  sendInternal(method, params = {}, timeoutMs = 15e3) {
2661
- return new Promise((resolve9, reject) => {
2724
+ return new Promise((resolve10, reject) => {
2662
2725
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
2663
2726
  if (this.ws.readyState !== WebSocket.OPEN) return reject(new Error("WebSocket not open"));
2664
2727
  const id = this.msgId++;
2665
- this.pending.set(id, { resolve: resolve9, reject });
2728
+ this.pending.set(id, { resolve: resolve10, reject });
2666
2729
  this.ws.send(JSON.stringify({ id, method, params }));
2667
2730
  setTimeout(() => {
2668
2731
  if (this.pending.has(id)) {
@@ -2911,7 +2974,7 @@ var DaemonCdpManager = class {
2911
2974
  const browserWs = this.browserWs;
2912
2975
  let msgId = this.browserMsgId;
2913
2976
  const sendWs = (method, params = {}, sessionId) => {
2914
- return new Promise((resolve9, reject) => {
2977
+ return new Promise((resolve10, reject) => {
2915
2978
  const mid = msgId++;
2916
2979
  this.browserMsgId = msgId;
2917
2980
  const handler = (raw) => {
@@ -2920,7 +2983,7 @@ var DaemonCdpManager = class {
2920
2983
  if (msg.id === mid) {
2921
2984
  browserWs.removeListener("message", handler);
2922
2985
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
2923
- else resolve9(msg.result);
2986
+ else resolve10(msg.result);
2924
2987
  }
2925
2988
  } catch {
2926
2989
  }
@@ -3111,14 +3174,14 @@ var DaemonCdpManager = class {
3111
3174
  if (!ws || ws.readyState !== WebSocket.OPEN) {
3112
3175
  throw new Error("CDP not connected");
3113
3176
  }
3114
- return new Promise((resolve9, reject) => {
3177
+ return new Promise((resolve10, reject) => {
3115
3178
  const id = getNextId();
3116
3179
  pendingMap.set(id, {
3117
3180
  resolve: (result) => {
3118
3181
  if (result?.result?.subtype === "error") {
3119
3182
  reject(new Error(result.result.description));
3120
3183
  } else {
3121
- resolve9(result?.result?.value);
3184
+ resolve10(result?.result?.value);
3122
3185
  }
3123
3186
  },
3124
3187
  reject
@@ -3150,10 +3213,10 @@ var DaemonCdpManager = class {
3150
3213
  throw new Error("CDP not connected");
3151
3214
  }
3152
3215
  const sendViaSession = (method, params = {}) => {
3153
- return new Promise((resolve9, reject) => {
3216
+ return new Promise((resolve10, reject) => {
3154
3217
  const pendingMap = this._browserConnected ? this.browserPending : this.pending;
3155
3218
  const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
3156
- pendingMap.set(id, { resolve: resolve9, reject });
3219
+ pendingMap.set(id, { resolve: resolve10, reject });
3157
3220
  ws.send(JSON.stringify({ id, sessionId, method, params }));
3158
3221
  setTimeout(() => {
3159
3222
  if (pendingMap.has(id)) {
@@ -3705,6 +3768,7 @@ var ExtensionProviderInstance = class {
3705
3768
  activeModal = null;
3706
3769
  currentModel = "";
3707
3770
  currentMode = "";
3771
+ controlValues = {};
3708
3772
  lastAgentStatus = "idle";
3709
3773
  generatingStartedAt = 0;
3710
3774
  monitor;
@@ -3750,6 +3814,8 @@ var ExtensionProviderInstance = class {
3750
3814
  } : null,
3751
3815
  currentModel: this.currentModel || void 0,
3752
3816
  currentPlan: this.currentMode || void 0,
3817
+ controlValues: this.controlValues,
3818
+ providerControls: this.provider.controls,
3753
3819
  agentStreams: this.agentStreams,
3754
3820
  instanceId: this.instanceId,
3755
3821
  lastUpdated: Date.now(),
@@ -3764,6 +3830,7 @@ var ExtensionProviderInstance = class {
3764
3830
  if (data?.activeModal !== void 0) this.activeModal = data.activeModal;
3765
3831
  if (data?.model) this.currentModel = data.model;
3766
3832
  if (data?.mode) this.currentMode = data.mode;
3833
+ if (data?.controlValues) this.controlValues = data.controlValues;
3767
3834
  if (typeof data?.sessionId === "string" && data.sessionId.trim()) this.chatId = data.sessionId;
3768
3835
  if (typeof data?.title === "string" && data.title.trim()) this.chatTitle = data.title;
3769
3836
  if (typeof data?.agentName === "string" && data.agentName.trim()) this.agentName = data.agentName;
@@ -3856,9 +3923,9 @@ var ExtensionProviderInstance = class {
3856
3923
 
3857
3924
  // src/config/chat-history.ts
3858
3925
  import * as fs3 from "fs";
3859
- import * as path4 from "path";
3926
+ import * as path5 from "path";
3860
3927
  import * as os5 from "os";
3861
- var HISTORY_DIR = path4.join(os5.homedir(), ".adhdev", "history");
3928
+ var HISTORY_DIR = path5.join(os5.homedir(), ".adhdev", "history");
3862
3929
  var RETAIN_DAYS = 30;
3863
3930
  var ChatHistoryWriter = class {
3864
3931
  /** Last seen message count per agent (deduplication) */
@@ -3901,11 +3968,11 @@ var ChatHistoryWriter = class {
3901
3968
  });
3902
3969
  }
3903
3970
  if (newMessages.length === 0) return;
3904
- const dir = path4.join(HISTORY_DIR, this.sanitize(agentType));
3971
+ const dir = path5.join(HISTORY_DIR, this.sanitize(agentType));
3905
3972
  fs3.mkdirSync(dir, { recursive: true });
3906
3973
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3907
3974
  const filePrefix = instanceId ? `${this.sanitize(instanceId)}_` : "";
3908
- const filePath = path4.join(dir, `${filePrefix}${date}.jsonl`);
3975
+ const filePath = path5.join(dir, `${filePrefix}${date}.jsonl`);
3909
3976
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
3910
3977
  fs3.appendFileSync(filePath, lines, "utf-8");
3911
3978
  const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
@@ -3949,11 +4016,11 @@ ${next}`;
3949
4016
  this.lastSeenTerminal.set(dedupKey, next);
3950
4017
  return;
3951
4018
  }
3952
- const dir = path4.join(HISTORY_DIR, this.sanitize(agentType));
4019
+ const dir = path5.join(HISTORY_DIR, this.sanitize(agentType));
3953
4020
  fs3.mkdirSync(dir, { recursive: true });
3954
4021
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3955
4022
  const filePrefix = instanceId ? `${this.sanitize(instanceId)}_` : "";
3956
- const filePath = path4.join(dir, `${filePrefix}${date}.terminal.log`);
4023
+ const filePath = path5.join(dir, `${filePrefix}${date}.terminal.log`);
3957
4024
  fs3.appendFileSync(filePath, delta, "utf-8");
3958
4025
  this.lastSeenTerminal.set(dedupKey, next);
3959
4026
  if (!this.rotated) {
@@ -3977,10 +4044,10 @@ ${next}`;
3977
4044
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
3978
4045
  const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
3979
4046
  for (const dir of agentDirs) {
3980
- const dirPath = path4.join(HISTORY_DIR, dir.name);
4047
+ const dirPath = path5.join(HISTORY_DIR, dir.name);
3981
4048
  const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
3982
4049
  for (const file of files) {
3983
- const filePath = path4.join(dirPath, file);
4050
+ const filePath = path5.join(dirPath, file);
3984
4051
  const stat = fs3.statSync(filePath);
3985
4052
  if (stat.mtimeMs < cutoff) {
3986
4053
  fs3.unlinkSync(filePath);
@@ -3998,7 +4065,7 @@ ${next}`;
3998
4065
  function readChatHistory(agentType, offset = 0, limit = 30, instanceId) {
3999
4066
  try {
4000
4067
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
4001
- const dir = path4.join(HISTORY_DIR, sanitized);
4068
+ const dir = path5.join(HISTORY_DIR, sanitized);
4002
4069
  if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
4003
4070
  const sanitizedInstance = instanceId?.replace(/[^a-zA-Z0-9_-]/g, "_");
4004
4071
  const files = fs3.readdirSync(dir).filter((f) => {
@@ -4012,7 +4079,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, instanceId) {
4012
4079
  const needed = offset + limit + 1;
4013
4080
  for (const file of files) {
4014
4081
  if (allMessages.length >= needed) break;
4015
- const filePath = path4.join(dir, file);
4082
+ const filePath = path5.join(dir, file);
4016
4083
  const content = fs3.readFileSync(filePath, "utf-8");
4017
4084
  const lines = content.trim().split("\n").filter(Boolean);
4018
4085
  for (let i = lines.length - 1; i >= 0; i--) {
@@ -4121,6 +4188,8 @@ var IdeProviderInstance = class {
4121
4188
  currentModel: this.cachedChat?.model || void 0,
4122
4189
  currentPlan: this.cachedChat?.mode || void 0,
4123
4190
  currentAutoApprove: this.cachedChat?.autoApprove || void 0,
4191
+ controlValues: this.cachedChat?.controlValues || void 0,
4192
+ providerControls: this.provider.controls,
4124
4193
  instanceId: this.instanceId,
4125
4194
  lastUpdated: Date.now(),
4126
4195
  settings: this.settings,
@@ -4855,6 +4924,50 @@ function isCdpConnected(cdpManagers, key) {
4855
4924
  const m = findCdpManager(cdpManagers, key);
4856
4925
  return m?.isConnected ?? false;
4857
4926
  }
4927
+ function buildFallbackControls(providerControls, serverModel, serverMode, acpConfigOptions, acpModes) {
4928
+ if (providerControls && providerControls.length > 0) return providerControls;
4929
+ const controls = [];
4930
+ const isAcp = !!(acpConfigOptions || acpModes);
4931
+ const modelFromAcp = acpConfigOptions?.find((c) => c.category === "model");
4932
+ if (!isAcp || modelFromAcp) {
4933
+ controls.push({
4934
+ id: "model",
4935
+ type: "select",
4936
+ label: "Model",
4937
+ icon: "\u{1F916}",
4938
+ placement: "bar",
4939
+ dynamic: !modelFromAcp,
4940
+ listScript: "listModels",
4941
+ setScript: "setModel",
4942
+ readFrom: "model",
4943
+ ...modelFromAcp && {
4944
+ options: modelFromAcp.options.map((o) => ({ value: o.value, label: o.name || o.value }))
4945
+ }
4946
+ });
4947
+ }
4948
+ const modeFromAcp = acpModes && acpModes.length > 0;
4949
+ const thoughtFromAcp = !modeFromAcp && acpConfigOptions?.find((c) => c.category !== "model");
4950
+ if (!isAcp || modeFromAcp || thoughtFromAcp) {
4951
+ controls.push({
4952
+ id: "mode",
4953
+ type: thoughtFromAcp ? "cycle" : "select",
4954
+ label: thoughtFromAcp ? "Thinking" : "Mode",
4955
+ icon: thoughtFromAcp ? "\u{1F9E0}" : "\u26A1",
4956
+ placement: "bar",
4957
+ dynamic: !modeFromAcp && !thoughtFromAcp,
4958
+ listScript: "listModes",
4959
+ setScript: thoughtFromAcp ? "setThinkingLevel" : "setMode",
4960
+ readFrom: "mode",
4961
+ ...modeFromAcp && {
4962
+ options: acpModes.map((m) => ({ value: m.id, label: m.name || m.id }))
4963
+ },
4964
+ ...thoughtFromAcp && {
4965
+ options: thoughtFromAcp.options.map((o) => ({ value: o.value, label: o.name || o.value }))
4966
+ }
4967
+ });
4968
+ }
4969
+ return controls;
4970
+ }
4858
4971
  var IDE_SESSION_CAPABILITIES = [
4859
4972
  "read_chat",
4860
4973
  "send_message",
@@ -4913,8 +5026,15 @@ function buildIdeWorkspaceSession(state, cdpManagers) {
4913
5026
  currentModel: state.currentModel,
4914
5027
  currentPlan: state.currentPlan,
4915
5028
  currentAutoApprove: state.currentAutoApprove,
5029
+ controlValues: state.controlValues,
5030
+ providerControls: buildFallbackControls(
5031
+ state.providerControls,
5032
+ state.currentModel,
5033
+ state.currentPlan
5034
+ ),
4916
5035
  errorMessage: state.errorMessage,
4917
- errorReason: state.errorReason
5036
+ errorReason: state.errorReason,
5037
+ lastUpdated: state.lastUpdated
4918
5038
  };
4919
5039
  }
4920
5040
  function buildExtensionAgentSession(parent, ext) {
@@ -4935,8 +5055,15 @@ function buildExtensionAgentSession(parent, ext) {
4935
5055
  capabilities: EXTENSION_SESSION_CAPABILITIES,
4936
5056
  currentModel: ext.currentModel,
4937
5057
  currentPlan: ext.currentPlan,
5058
+ controlValues: ext.controlValues,
5059
+ providerControls: buildFallbackControls(
5060
+ ext.providerControls,
5061
+ ext.currentModel,
5062
+ ext.currentPlan
5063
+ ),
4938
5064
  errorMessage: ext.errorMessage,
4939
- errorReason: ext.errorReason
5065
+ errorReason: ext.errorReason,
5066
+ lastUpdated: ext.lastUpdated
4940
5067
  };
4941
5068
  }
4942
5069
  function buildCliSession(state) {
@@ -4961,8 +5088,13 @@ function buildCliSession(state) {
4961
5088
  resume: state.resume,
4962
5089
  activeChat,
4963
5090
  capabilities: PTY_SESSION_CAPABILITIES,
5091
+ controlValues: state.controlValues,
5092
+ providerControls: buildFallbackControls(
5093
+ state.providerControls
5094
+ ),
4964
5095
  errorMessage: state.errorMessage,
4965
- errorReason: state.errorReason
5096
+ errorReason: state.errorReason,
5097
+ lastUpdated: state.lastUpdated
4966
5098
  };
4967
5099
  }
4968
5100
  function buildAcpSession(state) {
@@ -4985,8 +5117,17 @@ function buildAcpSession(state) {
4985
5117
  currentPlan: state.currentPlan,
4986
5118
  acpConfigOptions: state.acpConfigOptions,
4987
5119
  acpModes: state.acpModes,
5120
+ controlValues: state.controlValues,
5121
+ providerControls: buildFallbackControls(
5122
+ state.providerControls,
5123
+ state.currentModel,
5124
+ state.currentPlan,
5125
+ state.acpConfigOptions,
5126
+ state.acpModes
5127
+ ),
4988
5128
  errorMessage: state.errorMessage,
4989
- errorReason: state.errorReason
5129
+ errorReason: state.errorReason,
5130
+ lastUpdated: state.lastUpdated
4990
5131
  };
4991
5132
  }
4992
5133
  function buildSessionEntries(allStates, cdpManagers) {
@@ -5835,7 +5976,7 @@ async function handleResolveAction(h, args) {
5835
5976
 
5836
5977
  // src/commands/cdp-commands.ts
5837
5978
  import * as fs4 from "fs";
5838
- import * as path5 from "path";
5979
+ import * as path6 from "path";
5839
5980
  import * as os6 from "os";
5840
5981
  var KEY_TO_VK = {
5841
5982
  Backspace: 8,
@@ -6066,11 +6207,11 @@ function resolveSafePath(requestedPath) {
6066
6207
  const home = os6.homedir();
6067
6208
  let resolved;
6068
6209
  if (requestedPath.startsWith("~")) {
6069
- resolved = path5.join(home, requestedPath.slice(1));
6070
- } else if (path5.isAbsolute(requestedPath)) {
6210
+ resolved = path6.join(home, requestedPath.slice(1));
6211
+ } else if (path6.isAbsolute(requestedPath)) {
6071
6212
  resolved = requestedPath;
6072
6213
  } else {
6073
- resolved = path5.resolve(requestedPath);
6214
+ resolved = path6.resolve(requestedPath);
6074
6215
  }
6075
6216
  return resolved;
6076
6217
  }
@@ -6086,7 +6227,7 @@ async function handleFileRead(h, args) {
6086
6227
  async function handleFileWrite(h, args) {
6087
6228
  try {
6088
6229
  const filePath = resolveSafePath(args?.path);
6089
- fs4.mkdirSync(path5.dirname(filePath), { recursive: true });
6230
+ fs4.mkdirSync(path6.dirname(filePath), { recursive: true });
6090
6231
  fs4.writeFileSync(filePath, args?.content || "", "utf-8");
6091
6232
  return { success: true, path: filePath };
6092
6233
  } catch (e) {
@@ -6100,7 +6241,7 @@ async function handleFileList(h, args) {
6100
6241
  const files = entries.map((e) => ({
6101
6242
  name: e.name,
6102
6243
  type: e.isDirectory() ? "directory" : "file",
6103
- size: e.isFile() ? fs4.statSync(path5.join(dirPath, e.name)).size : void 0
6244
+ size: e.isFile() ? fs4.statSync(path6.join(dirPath, e.name)).size : void 0
6104
6245
  }));
6105
6246
  return { success: true, files, path: dirPath };
6106
6247
  } catch (e) {
@@ -6322,9 +6463,10 @@ function handleWorkspaceList() {
6322
6463
  function handleWorkspaceAdd(args) {
6323
6464
  const rawPath = (args?.path || args?.dir || "").trim();
6324
6465
  const label = (args?.label || "").trim() || void 0;
6466
+ const createIfMissing = args?.createIfMissing === true;
6325
6467
  if (!rawPath) return { success: false, error: "path required" };
6326
6468
  const config = loadConfig();
6327
- const result = addWorkspaceEntry(config, rawPath, label);
6469
+ const result = addWorkspaceEntry(config, rawPath, label, { createIfMissing });
6328
6470
  if ("error" in result) return { success: false, error: result.error };
6329
6471
  let cfg = appendWorkspaceActivity(result.config, result.entry.path, {});
6330
6472
  saveConfig(cfg);
@@ -6818,7 +6960,7 @@ var DaemonCommandHandler = class {
6818
6960
  try {
6819
6961
  const http3 = await import("http");
6820
6962
  const postData = JSON.stringify(body);
6821
- const result = await new Promise((resolve9, reject) => {
6963
+ const result = await new Promise((resolve10, reject) => {
6822
6964
  const req = http3.request({
6823
6965
  hostname: "127.0.0.1",
6824
6966
  port: 19280,
@@ -6830,9 +6972,9 @@ var DaemonCommandHandler = class {
6830
6972
  res.on("data", (chunk) => data += chunk);
6831
6973
  res.on("end", () => {
6832
6974
  try {
6833
- resolve9(JSON.parse(data));
6975
+ resolve10(JSON.parse(data));
6834
6976
  } catch {
6835
- resolve9({ raw: data });
6977
+ resolve10({ raw: data });
6836
6978
  }
6837
6979
  });
6838
6980
  });
@@ -6850,15 +6992,15 @@ var DaemonCommandHandler = class {
6850
6992
  if (!providerType) return { success: false, error: "providerType required" };
6851
6993
  try {
6852
6994
  const http3 = await import("http");
6853
- const result = await new Promise((resolve9, reject) => {
6995
+ const result = await new Promise((resolve10, reject) => {
6854
6996
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
6855
6997
  let data = "";
6856
6998
  res.on("data", (chunk) => data += chunk);
6857
6999
  res.on("end", () => {
6858
7000
  try {
6859
- resolve9(JSON.parse(data));
7001
+ resolve10(JSON.parse(data));
6860
7002
  } catch {
6861
- resolve9({ raw: data });
7003
+ resolve10({ raw: data });
6862
7004
  }
6863
7005
  });
6864
7006
  }).on("error", reject);
@@ -6872,7 +7014,7 @@ var DaemonCommandHandler = class {
6872
7014
  try {
6873
7015
  const http3 = await import("http");
6874
7016
  const postData = JSON.stringify(args || {});
6875
- const result = await new Promise((resolve9, reject) => {
7017
+ const result = await new Promise((resolve10, reject) => {
6876
7018
  const req = http3.request({
6877
7019
  hostname: "127.0.0.1",
6878
7020
  port: 19280,
@@ -6884,9 +7026,9 @@ var DaemonCommandHandler = class {
6884
7026
  res.on("data", (chunk) => data += chunk);
6885
7027
  res.on("end", () => {
6886
7028
  try {
6887
- resolve9(JSON.parse(data));
7029
+ resolve10(JSON.parse(data));
6888
7030
  } catch {
6889
- resolve9({ raw: data });
7031
+ resolve10({ raw: data });
6890
7032
  }
6891
7033
  });
6892
7034
  });
@@ -6905,11 +7047,11 @@ var DaemonCommandHandler = class {
6905
7047
  import { execSync as execSync3, spawn } from "child_process";
6906
7048
  import * as net from "net";
6907
7049
  import * as os8 from "os";
6908
- import * as path7 from "path";
7050
+ import * as path8 from "path";
6909
7051
 
6910
7052
  // src/providers/provider-loader.ts
6911
7053
  import * as fs5 from "fs";
6912
- import * as path6 from "path";
7054
+ import * as path7 from "path";
6913
7055
  import * as os7 from "os";
6914
7056
  import * as chokidar from "chokidar";
6915
7057
  init_logger();
@@ -6930,12 +7072,12 @@ var ProviderLoader = class _ProviderLoader {
6930
7072
  static META_FILE = ".meta.json";
6931
7073
  constructor(options) {
6932
7074
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
6933
- const defaultProvidersDir = path6.join(os7.homedir(), ".adhdev", "providers");
7075
+ const defaultProvidersDir = path7.join(os7.homedir(), ".adhdev", "providers");
6934
7076
  if (options?.userDir) {
6935
7077
  this.userDir = options.userDir;
6936
7078
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
6937
7079
  } else {
6938
- const localRepoPath = path6.resolve(__dirname, "../../../../../adhdev-providers");
7080
+ const localRepoPath = path7.resolve(__dirname, "../../../../../adhdev-providers");
6939
7081
  if (fs5.existsSync(localRepoPath)) {
6940
7082
  this.userDir = localRepoPath;
6941
7083
  this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
@@ -6944,7 +7086,7 @@ var ProviderLoader = class _ProviderLoader {
6944
7086
  this.log(`Using default user providers directory: ${this.userDir}`);
6945
7087
  }
6946
7088
  }
6947
- this.upstreamDir = path6.join(defaultProvidersDir, ".upstream");
7089
+ this.upstreamDir = path7.join(defaultProvidersDir, ".upstream");
6948
7090
  this.disableUpstream = options?.disableUpstream ?? false;
6949
7091
  }
6950
7092
  log(msg) {
@@ -6974,7 +7116,7 @@ var ProviderLoader = class _ProviderLoader {
6974
7116
  * Canonical provider directory shape for a given root.
6975
7117
  */
6976
7118
  getProviderDir(root, category, type) {
6977
- return path6.join(root, category, type);
7119
+ return path7.join(root, category, type);
6978
7120
  }
6979
7121
  /**
6980
7122
  * Canonical user override directory for a provider.
@@ -7001,7 +7143,7 @@ var ProviderLoader = class _ProviderLoader {
7001
7143
  resolveProviderFile(type, ...segments) {
7002
7144
  const dir = this.findProviderDirInternal(type);
7003
7145
  if (!dir) return null;
7004
- return path6.join(dir, ...segments);
7146
+ return path7.join(dir, ...segments);
7005
7147
  }
7006
7148
  /**
7007
7149
  * Load all providers (3-tier priority)
@@ -7039,7 +7181,7 @@ var ProviderLoader = class _ProviderLoader {
7039
7181
  if (!fs5.existsSync(this.upstreamDir)) return false;
7040
7182
  try {
7041
7183
  return fs5.readdirSync(this.upstreamDir).some(
7042
- (d) => fs5.statSync(path6.join(this.upstreamDir, d)).isDirectory()
7184
+ (d) => fs5.statSync(path7.join(this.upstreamDir, d)).isDirectory()
7043
7185
  );
7044
7186
  } catch {
7045
7187
  return false;
@@ -7331,14 +7473,14 @@ var ProviderLoader = class _ProviderLoader {
7331
7473
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
7332
7474
  return null;
7333
7475
  }
7334
- const dir = path6.join(providerDir, scriptDir);
7476
+ const dir = path7.join(providerDir, scriptDir);
7335
7477
  if (!fs5.existsSync(dir)) {
7336
7478
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
7337
7479
  return null;
7338
7480
  }
7339
7481
  const cached = this.scriptsCache.get(dir);
7340
7482
  if (cached) return cached;
7341
- const scriptsJs = path6.join(dir, "scripts.js");
7483
+ const scriptsJs = path7.join(dir, "scripts.js");
7342
7484
  if (fs5.existsSync(scriptsJs)) {
7343
7485
  try {
7344
7486
  delete __require.cache[__require.resolve(scriptsJs)];
@@ -7377,7 +7519,7 @@ var ProviderLoader = class _ProviderLoader {
7377
7519
  });
7378
7520
  const handleChange = (filePath) => {
7379
7521
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
7380
- this.log(`File changed: ${path6.basename(filePath)}, reloading...`);
7522
+ this.log(`File changed: ${path7.basename(filePath)}, reloading...`);
7381
7523
  this.reload();
7382
7524
  }
7383
7525
  };
@@ -7432,7 +7574,7 @@ var ProviderLoader = class _ProviderLoader {
7432
7574
  }
7433
7575
  const https = __require("https");
7434
7576
  const { execSync: execSync7 } = __require("child_process");
7435
- const metaPath = path6.join(this.upstreamDir, _ProviderLoader.META_FILE);
7577
+ const metaPath = path7.join(this.upstreamDir, _ProviderLoader.META_FILE);
7436
7578
  let prevEtag = "";
7437
7579
  let prevTimestamp = 0;
7438
7580
  try {
@@ -7449,7 +7591,7 @@ var ProviderLoader = class _ProviderLoader {
7449
7591
  return { updated: false };
7450
7592
  }
7451
7593
  try {
7452
- const etag = await new Promise((resolve9, reject) => {
7594
+ const etag = await new Promise((resolve10, reject) => {
7453
7595
  const options = {
7454
7596
  method: "HEAD",
7455
7597
  hostname: "github.com",
@@ -7467,7 +7609,7 @@ var ProviderLoader = class _ProviderLoader {
7467
7609
  headers: { "User-Agent": "adhdev-launcher" },
7468
7610
  timeout: 1e4
7469
7611
  }, (res2) => {
7470
- resolve9(res2.headers.etag || res2.headers["last-modified"] || "");
7612
+ resolve10(res2.headers.etag || res2.headers["last-modified"] || "");
7471
7613
  });
7472
7614
  req2.on("error", reject);
7473
7615
  req2.on("timeout", () => {
@@ -7476,7 +7618,7 @@ var ProviderLoader = class _ProviderLoader {
7476
7618
  });
7477
7619
  req2.end();
7478
7620
  } else {
7479
- resolve9(res.headers.etag || res.headers["last-modified"] || "");
7621
+ resolve10(res.headers.etag || res.headers["last-modified"] || "");
7480
7622
  }
7481
7623
  });
7482
7624
  req.on("error", reject);
@@ -7492,17 +7634,17 @@ var ProviderLoader = class _ProviderLoader {
7492
7634
  return { updated: false };
7493
7635
  }
7494
7636
  this.log("Downloading latest providers from GitHub...");
7495
- const tmpTar = path6.join(os7.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
7496
- const tmpExtract = path6.join(os7.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
7637
+ const tmpTar = path7.join(os7.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
7638
+ const tmpExtract = path7.join(os7.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
7497
7639
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
7498
7640
  fs5.mkdirSync(tmpExtract, { recursive: true });
7499
7641
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
7500
7642
  const extracted = fs5.readdirSync(tmpExtract);
7501
7643
  const rootDir = extracted.find(
7502
- (d) => fs5.statSync(path6.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
7644
+ (d) => fs5.statSync(path7.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
7503
7645
  );
7504
7646
  if (!rootDir) throw new Error("Unexpected tarball structure");
7505
- const sourceDir = path6.join(tmpExtract, rootDir);
7647
+ const sourceDir = path7.join(tmpExtract, rootDir);
7506
7648
  const backupDir = this.upstreamDir + ".bak";
7507
7649
  if (fs5.existsSync(this.upstreamDir)) {
7508
7650
  if (fs5.existsSync(backupDir)) fs5.rmSync(backupDir, { recursive: true, force: true });
@@ -7540,7 +7682,7 @@ var ProviderLoader = class _ProviderLoader {
7540
7682
  downloadFile(url, destPath) {
7541
7683
  const https = __require("https");
7542
7684
  const http3 = __require("http");
7543
- return new Promise((resolve9, reject) => {
7685
+ return new Promise((resolve10, reject) => {
7544
7686
  const doRequest = (reqUrl, redirectCount = 0) => {
7545
7687
  if (redirectCount > 5) {
7546
7688
  reject(new Error("Too many redirects"));
@@ -7560,7 +7702,7 @@ var ProviderLoader = class _ProviderLoader {
7560
7702
  res.pipe(ws);
7561
7703
  ws.on("finish", () => {
7562
7704
  ws.close();
7563
- resolve9();
7705
+ resolve10();
7564
7706
  });
7565
7707
  ws.on("error", reject);
7566
7708
  });
@@ -7577,8 +7719,8 @@ var ProviderLoader = class _ProviderLoader {
7577
7719
  copyDirRecursive(src, dest) {
7578
7720
  fs5.mkdirSync(dest, { recursive: true });
7579
7721
  for (const entry of fs5.readdirSync(src, { withFileTypes: true })) {
7580
- const srcPath = path6.join(src, entry.name);
7581
- const destPath = path6.join(dest, entry.name);
7722
+ const srcPath = path7.join(src, entry.name);
7723
+ const destPath = path7.join(dest, entry.name);
7582
7724
  if (entry.isDirectory()) {
7583
7725
  this.copyDirRecursive(srcPath, destPath);
7584
7726
  } else {
@@ -7589,7 +7731,7 @@ var ProviderLoader = class _ProviderLoader {
7589
7731
  /** .meta.json save */
7590
7732
  writeMeta(metaPath, etag, timestamp) {
7591
7733
  try {
7592
- fs5.mkdirSync(path6.dirname(metaPath), { recursive: true });
7734
+ fs5.mkdirSync(path7.dirname(metaPath), { recursive: true });
7593
7735
  fs5.writeFileSync(metaPath, JSON.stringify({
7594
7736
  etag,
7595
7737
  timestamp,
@@ -7606,7 +7748,7 @@ var ProviderLoader = class _ProviderLoader {
7606
7748
  const scan = (d) => {
7607
7749
  try {
7608
7750
  for (const entry of fs5.readdirSync(d, { withFileTypes: true })) {
7609
- if (entry.isDirectory()) scan(path6.join(d, entry.name));
7751
+ if (entry.isDirectory()) scan(path7.join(d, entry.name));
7610
7752
  else if (entry.name === "provider.json") count++;
7611
7753
  }
7612
7754
  } catch {
@@ -7705,17 +7847,17 @@ var ProviderLoader = class _ProviderLoader {
7705
7847
  for (const root of searchRoots) {
7706
7848
  if (!fs5.existsSync(root)) continue;
7707
7849
  const candidate = this.getProviderDir(root, cat, type);
7708
- if (fs5.existsSync(path6.join(candidate, "provider.json"))) return candidate;
7709
- const catDir = path6.join(root, cat);
7850
+ if (fs5.existsSync(path7.join(candidate, "provider.json"))) return candidate;
7851
+ const catDir = path7.join(root, cat);
7710
7852
  if (fs5.existsSync(catDir)) {
7711
7853
  try {
7712
7854
  for (const entry of fs5.readdirSync(catDir, { withFileTypes: true })) {
7713
7855
  if (!entry.isDirectory()) continue;
7714
- const jsonPath = path6.join(catDir, entry.name, "provider.json");
7856
+ const jsonPath = path7.join(catDir, entry.name, "provider.json");
7715
7857
  if (fs5.existsSync(jsonPath)) {
7716
7858
  try {
7717
7859
  const data = JSON.parse(fs5.readFileSync(jsonPath, "utf-8"));
7718
- if (data.type === type) return path6.join(catDir, entry.name);
7860
+ if (data.type === type) return path7.join(catDir, entry.name);
7719
7861
  } catch {
7720
7862
  }
7721
7863
  }
@@ -7732,7 +7874,7 @@ var ProviderLoader = class _ProviderLoader {
7732
7874
  * (template substitution is NOT applied here — scripts.js handles that)
7733
7875
  */
7734
7876
  buildScriptWrappersFromDir(dir) {
7735
- const scriptsJs = path6.join(dir, "scripts.js");
7877
+ const scriptsJs = path7.join(dir, "scripts.js");
7736
7878
  if (fs5.existsSync(scriptsJs)) {
7737
7879
  try {
7738
7880
  delete __require.cache[__require.resolve(scriptsJs)];
@@ -7746,7 +7888,7 @@ var ProviderLoader = class _ProviderLoader {
7746
7888
  for (const file of fs5.readdirSync(dir)) {
7747
7889
  if (!file.endsWith(".js")) continue;
7748
7890
  const scriptName = toCamel(file.replace(".js", ""));
7749
- const filePath = path6.join(dir, file);
7891
+ const filePath = path7.join(dir, file);
7750
7892
  result[scriptName] = (...args) => {
7751
7893
  try {
7752
7894
  let content = fs5.readFileSync(filePath, "utf-8");
@@ -7806,7 +7948,7 @@ var ProviderLoader = class _ProviderLoader {
7806
7948
  }
7807
7949
  const hasJson = entries.some((e) => e.name === "provider.json");
7808
7950
  if (hasJson) {
7809
- const jsonPath = path6.join(d, "provider.json");
7951
+ const jsonPath = path7.join(d, "provider.json");
7810
7952
  try {
7811
7953
  const raw = fs5.readFileSync(jsonPath, "utf-8");
7812
7954
  const mod = JSON.parse(raw);
@@ -7819,7 +7961,7 @@ var ProviderLoader = class _ProviderLoader {
7819
7961
  delete mod.extensionIdPattern_flags;
7820
7962
  }
7821
7963
  const hasCompatibility = Array.isArray(mod.compatibility);
7822
- const scriptsPath = path6.join(d, "scripts.js");
7964
+ const scriptsPath = path7.join(d, "scripts.js");
7823
7965
  if (!hasCompatibility && fs5.existsSync(scriptsPath)) {
7824
7966
  try {
7825
7967
  delete __require.cache[__require.resolve(scriptsPath)];
@@ -7845,7 +7987,7 @@ var ProviderLoader = class _ProviderLoader {
7845
7987
  if (!entry.isDirectory()) continue;
7846
7988
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
7847
7989
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
7848
- scan(path6.join(d, entry.name));
7990
+ scan(path7.join(d, entry.name));
7849
7991
  }
7850
7992
  }
7851
7993
  };
@@ -7925,17 +8067,17 @@ async function findFreePort(ports) {
7925
8067
  throw new Error("No free port found");
7926
8068
  }
7927
8069
  function checkPortFree(port) {
7928
- return new Promise((resolve9) => {
8070
+ return new Promise((resolve10) => {
7929
8071
  const server = net.createServer();
7930
8072
  server.unref();
7931
- server.on("error", () => resolve9(false));
8073
+ server.on("error", () => resolve10(false));
7932
8074
  server.listen(port, "127.0.0.1", () => {
7933
- server.close(() => resolve9(true));
8075
+ server.close(() => resolve10(true));
7934
8076
  });
7935
8077
  });
7936
8078
  }
7937
8079
  async function isCdpActive(port) {
7938
- return new Promise((resolve9) => {
8080
+ return new Promise((resolve10) => {
7939
8081
  const req = __require("http").get(`http://127.0.0.1:${port}/json/version`, {
7940
8082
  timeout: 2e3
7941
8083
  }, (res) => {
@@ -7944,16 +8086,16 @@ async function isCdpActive(port) {
7944
8086
  res.on("end", () => {
7945
8087
  try {
7946
8088
  const info = JSON.parse(data);
7947
- resolve9(!!info["WebKit-Version"] || !!info["Browser"]);
8089
+ resolve10(!!info["WebKit-Version"] || !!info["Browser"]);
7948
8090
  } catch {
7949
- resolve9(false);
8091
+ resolve10(false);
7950
8092
  }
7951
8093
  });
7952
8094
  });
7953
- req.on("error", () => resolve9(false));
8095
+ req.on("error", () => resolve10(false));
7954
8096
  req.on("timeout", () => {
7955
8097
  req.destroy();
7956
- resolve9(false);
8098
+ resolve10(false);
7957
8099
  });
7958
8100
  });
7959
8101
  }
@@ -8072,8 +8214,8 @@ function detectCurrentWorkspace(ideId) {
8072
8214
  const appNameMap = getMacAppIdentifiers();
8073
8215
  const appName = appNameMap[ideId];
8074
8216
  if (appName) {
8075
- const storagePath = path7.join(
8076
- process.env.APPDATA || path7.join(os8.homedir(), "AppData", "Roaming"),
8217
+ const storagePath = path8.join(
8218
+ process.env.APPDATA || path8.join(os8.homedir(), "AppData", "Roaming"),
8077
8219
  appName,
8078
8220
  "storage.json"
8079
8221
  );
@@ -8248,9 +8390,9 @@ init_logger();
8248
8390
 
8249
8391
  // src/logging/command-log.ts
8250
8392
  import * as fs6 from "fs";
8251
- import * as path8 from "path";
8393
+ import * as path9 from "path";
8252
8394
  import * as os9 from "os";
8253
- 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");
8395
+ 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");
8254
8396
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
8255
8397
  var MAX_DAYS = 7;
8256
8398
  try {
@@ -8288,13 +8430,13 @@ function getDateStr2() {
8288
8430
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8289
8431
  }
8290
8432
  var currentDate2 = getDateStr2();
8291
- var currentFile = path8.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
8433
+ var currentFile = path9.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
8292
8434
  var writeCount2 = 0;
8293
8435
  function checkRotation() {
8294
8436
  const today = getDateStr2();
8295
8437
  if (today !== currentDate2) {
8296
8438
  currentDate2 = today;
8297
- currentFile = path8.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
8439
+ currentFile = path9.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
8298
8440
  cleanOldFiles();
8299
8441
  }
8300
8442
  }
@@ -8308,7 +8450,7 @@ function cleanOldFiles() {
8308
8450
  const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
8309
8451
  if (dateMatch && dateMatch[1] < cutoffStr) {
8310
8452
  try {
8311
- fs6.unlinkSync(path8.join(LOG_DIR2, file));
8453
+ fs6.unlinkSync(path9.join(LOG_DIR2, file));
8312
8454
  } catch {
8313
8455
  }
8314
8456
  }
@@ -8537,9 +8679,27 @@ var DaemonCommandRouter = class {
8537
8679
  this.deps.onIdeConnected?.();
8538
8680
  if (result.success && resolvedWorkspace) {
8539
8681
  try {
8540
- saveConfig(appendWorkspaceActivity(loadConfig(), resolvedWorkspace, {
8682
+ let next = appendWorkspaceActivity(loadConfig(), resolvedWorkspace, {
8541
8683
  kind: "ide",
8542
8684
  agentType: result.ideId
8685
+ });
8686
+ next = appendRecentActivity(next, {
8687
+ kind: "ide",
8688
+ providerType: result.ideId || ideKey,
8689
+ providerName: result.ideId || ideKey,
8690
+ workspace: resolvedWorkspace,
8691
+ title: result.ideId || ideKey
8692
+ });
8693
+ saveConfig(next);
8694
+ } catch {
8695
+ }
8696
+ } else if (result.success && (result.ideId || ideKey)) {
8697
+ try {
8698
+ saveConfig(appendRecentActivity(loadConfig(), {
8699
+ kind: "ide",
8700
+ providerType: result.ideId || ideKey,
8701
+ providerName: result.ideId || ideKey,
8702
+ title: result.ideId || ideKey
8543
8703
  }));
8544
8704
  } catch {
8545
8705
  }
@@ -8559,6 +8719,30 @@ var DaemonCommandRouter = class {
8559
8719
  updateConfig({ userName: name });
8560
8720
  return { success: true, userName: name };
8561
8721
  }
8722
+ case "mark_recent_seen": {
8723
+ const kind = args?.kind;
8724
+ const providerType = args?.providerType;
8725
+ if (!kind || !providerType) {
8726
+ return { success: false, error: "kind and providerType are required" };
8727
+ }
8728
+ const recentKey = args?.recentKey || buildRecentActivityKey({
8729
+ kind,
8730
+ providerType,
8731
+ workspace: args?.workspace || null
8732
+ });
8733
+ const next = markRecentSessionSeen(
8734
+ loadConfig(),
8735
+ recentKey,
8736
+ typeof args?.seenAt === "number" ? args.seenAt : Date.now()
8737
+ );
8738
+ saveConfig(next);
8739
+ this.deps.onStatusChange?.();
8740
+ return {
8741
+ success: true,
8742
+ recentKey,
8743
+ seenAt: next.recentSessionReads?.[recentKey] || Date.now()
8744
+ };
8745
+ }
8562
8746
  // ─── Daemon Self-Upgrade ───
8563
8747
  case "daemon_upgrade": {
8564
8748
  LOG.info("Upgrade", "Remote upgrade requested from dashboard");
@@ -8577,9 +8761,9 @@ var DaemonCommandRouter = class {
8577
8761
  setTimeout(() => {
8578
8762
  LOG.info("Upgrade", "Restarting daemon with new version...");
8579
8763
  try {
8580
- const path15 = __require("path");
8764
+ const path16 = __require("path");
8581
8765
  const fs12 = __require("fs");
8582
- const pidFile = path15.join(process.env.HOME || process.env.USERPROFILE || "", ".adhdev", "daemon.pid");
8766
+ const pidFile = path16.join(process.env.HOME || process.env.USERPROFILE || "", ".adhdev", "daemon.pid");
8583
8767
  if (fs12.existsSync(pidFile)) fs12.unlinkSync(pidFile);
8584
8768
  } catch {
8585
8769
  }
@@ -8676,8 +8860,9 @@ init_logger();
8676
8860
 
8677
8861
  // src/status/snapshot.ts
8678
8862
  init_config();
8679
- init_workspaces();
8680
8863
  import * as os10 from "os";
8864
+ init_workspaces();
8865
+ init_terminal_screen();
8681
8866
  function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
8682
8867
  return detectedIdes.filter((ide) => ide.installed !== false).map((ide) => ({
8683
8868
  id: ide.id,
@@ -8696,14 +8881,127 @@ function buildAvailableProviders(providerLoader) {
8696
8881
  category: provider.category
8697
8882
  }));
8698
8883
  }
8884
+ function parseMessageTime(value) {
8885
+ if (typeof value === "number" && Number.isFinite(value)) return value;
8886
+ if (typeof value === "string") {
8887
+ const parsed = Date.parse(value);
8888
+ if (Number.isFinite(parsed)) return parsed;
8889
+ }
8890
+ return 0;
8891
+ }
8892
+ function getSessionMessageUpdatedAt(session) {
8893
+ const lastMessage = session.activeChat?.messages?.at?.(-1);
8894
+ if (!lastMessage) return 0;
8895
+ return parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt) || 0;
8896
+ }
8897
+ function getSessionLastUsedAt(session) {
8898
+ return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
8899
+ }
8900
+ function getSessionKind(session) {
8901
+ return session.transport === "cdp-page" || session.transport === "cdp-webview" ? "ide" : session.transport === "acp" ? "acp" : "cli";
8902
+ }
8903
+ function getLastMessageRole(session) {
8904
+ const role = session.activeChat?.messages?.at?.(-1)?.role;
8905
+ return typeof role === "string" ? role : "";
8906
+ }
8907
+ function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole) {
8908
+ if (status === "waiting_approval") {
8909
+ return { unread: false, inboxBucket: "needs_attention" };
8910
+ }
8911
+ if (status === "generating" || status === "starting") {
8912
+ return { unread: false, inboxBucket: "working" };
8913
+ }
8914
+ const unread = hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
8915
+ return { unread, inboxBucket: unread ? "task_complete" : "idle" };
8916
+ }
8917
+ function buildRecentSessions(sessions, recentActivity, readState) {
8918
+ const live = sessions.filter((session) => !session.parentId && session.status !== "stopped").map((session) => {
8919
+ const kind = getSessionKind(session);
8920
+ const recentKey = buildRecentActivityKey({
8921
+ kind,
8922
+ providerType: session.providerType,
8923
+ workspace: session.workspace
8924
+ });
8925
+ const lastSeenAt = readState[recentKey] || 0;
8926
+ const lastUsedAt = getSessionLastUsedAt(session);
8927
+ const { unread, inboxBucket } = getUnreadState(
8928
+ getSessionMessageUpdatedAt(session) > 0,
8929
+ session.status,
8930
+ lastUsedAt,
8931
+ lastSeenAt,
8932
+ getLastMessageRole(session)
8933
+ );
8934
+ return {
8935
+ id: session.id,
8936
+ recentKey,
8937
+ sessionId: session.id,
8938
+ providerType: session.providerType,
8939
+ providerName: session.providerName,
8940
+ kind,
8941
+ title: session.activeChat?.title || session.title || session.providerName,
8942
+ workspace: session.workspace,
8943
+ currentModel: session.currentModel,
8944
+ status: session.status,
8945
+ lastUsedAt,
8946
+ unread,
8947
+ lastSeenAt,
8948
+ inboxBucket
8949
+ };
8950
+ });
8951
+ const seen = new Set(live.map((item) => `${item.kind}:${item.providerType}:${item.workspace || ""}`));
8952
+ const persisted = recentActivity.filter((item) => !seen.has(`${item.kind}:${item.providerType}:${item.workspace || ""}`)).map((item) => {
8953
+ const lastSeenAt = readState[item.id] || 0;
8954
+ const unread = item.lastUsedAt > lastSeenAt;
8955
+ return {
8956
+ id: item.id,
8957
+ recentKey: item.id,
8958
+ sessionId: item.sessionId || null,
8959
+ providerType: item.providerType,
8960
+ providerName: item.providerName,
8961
+ kind: item.kind,
8962
+ title: item.title || item.providerName,
8963
+ workspace: item.workspace,
8964
+ currentModel: item.currentModel,
8965
+ lastUsedAt: item.lastUsedAt,
8966
+ unread,
8967
+ lastSeenAt,
8968
+ inboxBucket: unread ? "task_complete" : "idle"
8969
+ };
8970
+ });
8971
+ return [...live, ...persisted].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, 12);
8972
+ }
8699
8973
  function buildStatusSnapshot(options) {
8700
8974
  const cfg = loadConfig();
8701
8975
  const wsState = getWorkspaceState(cfg);
8702
8976
  const memSnap = getHostMemorySnapshot();
8977
+ const recentActivity = getRecentActivity(cfg, 20);
8703
8978
  const sessions = buildSessionEntries(
8704
8979
  options.allStates,
8705
8980
  options.cdpManagers
8706
8981
  );
8982
+ const readState = cfg.recentSessionReads || {};
8983
+ for (const session of sessions) {
8984
+ const kind = getSessionKind(session);
8985
+ const recentKey = buildRecentActivityKey({
8986
+ kind,
8987
+ providerType: session.providerType,
8988
+ workspace: session.workspace
8989
+ });
8990
+ const lastSeenAt = getRecentSessionSeenAt(cfg, recentKey);
8991
+ const lastUsedAt = getSessionLastUsedAt(session);
8992
+ const { unread, inboxBucket } = getUnreadState(
8993
+ getSessionMessageUpdatedAt(session) > 0,
8994
+ session.status,
8995
+ lastUsedAt,
8996
+ lastSeenAt,
8997
+ getLastMessageRole(session)
8998
+ );
8999
+ session.recentKey = recentKey;
9000
+ session.lastSeenAt = lastSeenAt;
9001
+ session.unread = unread;
9002
+ session.inboxBucket = inboxBucket;
9003
+ }
9004
+ const terminalBackend = getTerminalBackendRuntimeStatus();
8707
9005
  return {
8708
9006
  instanceId: options.instanceId,
8709
9007
  version: options.version,
@@ -8729,6 +9027,8 @@ function buildStatusSnapshot(options) {
8729
9027
  defaultWorkspaceId: wsState.defaultWorkspaceId,
8730
9028
  defaultWorkspacePath: wsState.defaultWorkspacePath,
8731
9029
  workspaceActivity: getWorkspaceActivity(cfg, 15),
9030
+ recentSessions: buildRecentSessions(sessions, recentActivity, readState),
9031
+ terminalBackend,
8732
9032
  availableProviders: buildAvailableProviders(options.providerLoader)
8733
9033
  };
8734
9034
  }
@@ -8880,7 +9180,15 @@ var DaemonStatusReporter = class {
8880
9180
  cdpConnected: session.cdpConnected,
8881
9181
  currentModel: session.currentModel,
8882
9182
  currentPlan: session.currentPlan,
8883
- currentAutoApprove: session.currentAutoApprove
9183
+ currentAutoApprove: session.currentAutoApprove,
9184
+ recentKey: session.recentKey,
9185
+ unread: session.unread,
9186
+ lastSeenAt: session.lastSeenAt,
9187
+ inboxBucket: session.inboxBucket,
9188
+ controlValues: session.controlValues,
9189
+ providerControls: session.providerControls,
9190
+ acpConfigOptions: session.acpConfigOptions,
9191
+ acpModes: session.acpModes
8884
9192
  })),
8885
9193
  p2p: payload.p2p,
8886
9194
  timestamp: now
@@ -8919,7 +9227,7 @@ init_logger();
8919
9227
  // src/commands/cli-manager.ts
8920
9228
  init_provider_cli_adapter();
8921
9229
  import * as os13 from "os";
8922
- import * as path10 from "path";
9230
+ import * as path11 from "path";
8923
9231
  import * as crypto4 from "crypto";
8924
9232
  import chalk from "chalk";
8925
9233
  init_config();
@@ -9016,7 +9324,10 @@ var CliProviderInstance = class {
9016
9324
  writeOwner: runtime.writeOwner || null,
9017
9325
  attachedClients: runtime.attachedClients || []
9018
9326
  } : void 0,
9019
- resume: this.provider.resume
9327
+ resume: this.provider.resume,
9328
+ controlValues: void 0,
9329
+ // CLI controls not yet wired from stream
9330
+ providerControls: this.provider.controls
9020
9331
  };
9021
9332
  }
9022
9333
  onEvent(event, data) {
@@ -9297,7 +9608,12 @@ var AcpProviderInstance = class {
9297
9608
  acpModes: this.availableModes,
9298
9609
  // Error details for dashboard display
9299
9610
  errorMessage: this.errorMessage || void 0,
9300
- errorReason: this.errorReason || void 0
9611
+ errorReason: this.errorReason || void 0,
9612
+ controlValues: {
9613
+ ...this.currentModel ? { model: this.currentModel } : {},
9614
+ ...this.currentMode ? { mode: this.currentMode } : {}
9615
+ },
9616
+ providerControls: this.provider.controls
9301
9617
  };
9302
9618
  }
9303
9619
  onEvent(event, data) {
@@ -9596,13 +9912,13 @@ var AcpProviderInstance = class {
9596
9912
  }
9597
9913
  this.currentStatus = "waiting_approval";
9598
9914
  this.detectStatusTransition();
9599
- const approved = await new Promise((resolve9) => {
9600
- this.permissionResolvers.push(resolve9);
9915
+ const approved = await new Promise((resolve10) => {
9916
+ this.permissionResolvers.push(resolve10);
9601
9917
  setTimeout(() => {
9602
- const idx = this.permissionResolvers.indexOf(resolve9);
9918
+ const idx = this.permissionResolvers.indexOf(resolve10);
9603
9919
  if (idx >= 0) {
9604
9920
  this.permissionResolvers.splice(idx, 1);
9605
- resolve9(false);
9921
+ resolve10(false);
9606
9922
  }
9607
9923
  }, 3e5);
9608
9924
  });
@@ -10095,6 +10411,13 @@ var DaemonCliManager = class {
10095
10411
  console.error(colorize("red", ` \u2717 Failed to save recent workspace: ${e}`));
10096
10412
  }
10097
10413
  }
10414
+ persistRecentActivity(entry) {
10415
+ try {
10416
+ saveConfig(appendRecentActivity(loadConfig(), entry));
10417
+ } catch (e) {
10418
+ console.error(colorize("red", ` \u2717 Failed to save recent activity: ${e}`));
10419
+ }
10420
+ }
10098
10421
  getTransportFactory(runtimeId, providerType, workspace, cliArgs, attachExisting = false) {
10099
10422
  return this.deps.createPtyTransportFactory?.({
10100
10423
  runtimeId,
@@ -10177,7 +10500,7 @@ var DaemonCliManager = class {
10177
10500
  async startSession(cliType, workingDir, cliArgs, initialModel) {
10178
10501
  const trimmed = (workingDir || "").trim();
10179
10502
  if (!trimmed) throw new Error("working directory required");
10180
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path10.resolve(trimmed);
10503
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path11.resolve(trimmed);
10181
10504
  const normalizedType = this.providerLoader.resolveAlias(cliType);
10182
10505
  const provider = this.providerLoader.getByAlias(cliType);
10183
10506
  const key = crypto4.randomUUID();
@@ -10253,6 +10576,15 @@ ${installInfo}`
10253
10576
  } catch (e) {
10254
10577
  LOG.warn("CLI", `ACP history save failed: ${e?.message}`);
10255
10578
  }
10579
+ this.persistRecentActivity({
10580
+ kind: "acp",
10581
+ providerType: normalizedType,
10582
+ providerName: provider.displayName || provider.name || normalizedType,
10583
+ workspace: resolvedDir,
10584
+ currentModel: initialModel,
10585
+ sessionId,
10586
+ title: provider.displayName || provider.name || normalizedType
10587
+ });
10256
10588
  this.deps.onStatusChange();
10257
10589
  return;
10258
10590
  }
@@ -10315,6 +10647,15 @@ ${installInfo}`
10315
10647
  } catch (e) {
10316
10648
  LOG.warn("CLI", `CLI history save failed: ${e?.message}`);
10317
10649
  }
10650
+ this.persistRecentActivity({
10651
+ kind: "cli",
10652
+ providerType: normalizedType,
10653
+ providerName: provider?.displayName || provider?.name || normalizedType,
10654
+ workspace: resolvedDir,
10655
+ currentModel: initialModel,
10656
+ sessionId: key,
10657
+ title: provider?.displayName || provider?.name || normalizedType
10658
+ });
10318
10659
  this.deps.onStatusChange();
10319
10660
  }
10320
10661
  async stopSession(key) {
@@ -10560,11 +10901,24 @@ var ProviderStreamAdapter = class {
10560
10901
  hasScript(name) {
10561
10902
  return typeof this.provider.scripts?.[name] === "function";
10562
10903
  }
10904
+ summarizeRaw(raw) {
10905
+ try {
10906
+ if (typeof raw === "string") return raw.replace(/\s+/g, " ").trim().slice(0, 240);
10907
+ if (raw == null) return String(raw);
10908
+ return JSON.stringify(raw).replace(/\s+/g, " ").trim().slice(0, 240);
10909
+ } catch {
10910
+ return Object.prototype.toString.call(raw);
10911
+ }
10912
+ }
10913
+ isTransportError(reason) {
10914
+ 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);
10915
+ }
10563
10916
  async readChat(evaluate) {
10564
10917
  const script = this.callScript("readChat");
10565
10918
  if (!script) return this.errorState("readChat script not available");
10919
+ let raw = null;
10566
10920
  try {
10567
- const raw = await evaluate(script);
10921
+ raw = await evaluate(script);
10568
10922
  const data = typeof raw === "string" ? JSON.parse(raw) : raw;
10569
10923
  if (data?.error) {
10570
10924
  const state2 = this.errorState(data.error);
@@ -10584,12 +10938,31 @@ var ProviderStreamAdapter = class {
10584
10938
  mode: data.mode,
10585
10939
  activeModal: data.activeModal
10586
10940
  };
10941
+ if (this.provider.controls?.length) {
10942
+ const cv = {};
10943
+ for (const ctrl of this.provider.controls) {
10944
+ if (!ctrl.readFrom) continue;
10945
+ const val = data[ctrl.readFrom];
10946
+ if (val !== void 0 && val !== null) {
10947
+ cv[ctrl.id] = typeof val === "object" ? val.name || val.id || String(val) : val;
10948
+ }
10949
+ }
10950
+ if (data.model && !cv["model"]) cv["model"] = data.model;
10951
+ if (data.mode && !cv["mode"]) cv["mode"] = data.mode;
10952
+ if (Object.keys(cv).length > 0) state.controlValues = cv;
10953
+ }
10587
10954
  if (state.messages.length > 0) {
10588
10955
  this.lastSuccessState = state;
10589
10956
  }
10590
10957
  return state;
10591
- } catch {
10592
- const state = this.errorState(`Failed to parse ${this.agentName} state`);
10958
+ } catch (error) {
10959
+ const reason = error instanceof Error ? error.message : String(error);
10960
+ if (this.isTransportError(reason)) {
10961
+ throw error instanceof Error ? error : new Error(reason);
10962
+ }
10963
+ const preview = this.summarizeRaw(raw);
10964
+ const detail = preview ? ` (reason=${reason}; raw=${preview})` : ` (reason=${reason})`;
10965
+ const state = this.errorState(`Failed to parse ${this.agentName} state${detail}`);
10593
10966
  if (this.lastSuccessState?.messages?.length) {
10594
10967
  state.messages = this.lastSuccessState.messages;
10595
10968
  }
@@ -10686,6 +11059,9 @@ var DaemonAgentStreamManager = class {
10686
11059
  getActiveSessionId(parentSessionId) {
10687
11060
  return this.activeSessionIdByParent.get(parentSessionId) || null;
10688
11061
  }
11062
+ isRecoverableSessionError(message) {
11063
+ 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");
11064
+ }
10689
11065
  getSessionTarget(sessionId) {
10690
11066
  return this.sessionRegistry?.get(sessionId);
10691
11067
  }
@@ -10787,6 +11163,10 @@ var DaemonAgentStreamManager = class {
10787
11163
  const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
10788
11164
  const state = await agent.adapter.readChat(evaluate);
10789
11165
  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") : ""}`);
11166
+ const stateError = String(state.error || state._error || "");
11167
+ if (state.status === "error" && this.isRecoverableSessionError(stateError)) {
11168
+ throw new Error(stateError);
11169
+ }
10790
11170
  agent.lastState = state;
10791
11171
  agent.lastError = null;
10792
11172
  if (state.status === "panel_hidden") {
@@ -10797,7 +11177,7 @@ var DaemonAgentStreamManager = class {
10797
11177
  const errorMsg = e?.message || String(e);
10798
11178
  this.logFn(`[AgentStream] readChat(${type}) error: ${errorMsg.slice(0, 200)}`);
10799
11179
  agent.lastError = errorMsg;
10800
- if (errorMsg.includes("timeout") || errorMsg.includes("not connected") || errorMsg.includes("Session")) {
11180
+ if (this.isRecoverableSessionError(errorMsg)) {
10801
11181
  try {
10802
11182
  await cdp.detachAgent(agent.cdpSessionId);
10803
11183
  } catch {
@@ -11285,11 +11665,11 @@ var ProviderInstanceManager = class {
11285
11665
 
11286
11666
  // src/providers/version-archive.ts
11287
11667
  import * as fs8 from "fs";
11288
- import * as path11 from "path";
11668
+ import * as path12 from "path";
11289
11669
  import * as os14 from "os";
11290
11670
  import { execSync as execSync5 } from "child_process";
11291
11671
  import { platform as platform8 } from "os";
11292
- var ARCHIVE_PATH = path11.join(os14.homedir(), ".adhdev", "version-history.json");
11672
+ var ARCHIVE_PATH = path12.join(os14.homedir(), ".adhdev", "version-history.json");
11293
11673
  var MAX_ENTRIES_PER_PROVIDER = 20;
11294
11674
  var VersionArchive = class {
11295
11675
  history = {};
@@ -11336,7 +11716,7 @@ var VersionArchive = class {
11336
11716
  }
11337
11717
  save() {
11338
11718
  try {
11339
- fs8.mkdirSync(path11.dirname(ARCHIVE_PATH), { recursive: true });
11719
+ fs8.mkdirSync(path12.dirname(ARCHIVE_PATH), { recursive: true });
11340
11720
  fs8.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
11341
11721
  } catch {
11342
11722
  }
@@ -11377,7 +11757,7 @@ function checkPathExists2(paths) {
11377
11757
  for (const p of paths) {
11378
11758
  if (p.includes("*")) {
11379
11759
  const home = os14.homedir();
11380
- const resolved = p.replace(/\*/g, home.split(path11.sep).pop() || "");
11760
+ const resolved = p.replace(/\*/g, home.split(path12.sep).pop() || "");
11381
11761
  if (fs8.existsSync(resolved)) return resolved;
11382
11762
  } else {
11383
11763
  if (fs8.existsSync(p)) return p;
@@ -11387,7 +11767,7 @@ function checkPathExists2(paths) {
11387
11767
  }
11388
11768
  function getMacAppVersion(appPath) {
11389
11769
  if (platform8() !== "darwin" || !appPath.endsWith(".app")) return null;
11390
- const plistPath = path11.join(appPath, "Contents", "Info.plist");
11770
+ const plistPath = path12.join(appPath, "Contents", "Info.plist");
11391
11771
  if (!fs8.existsSync(plistPath)) return null;
11392
11772
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
11393
11773
  return raw || null;
@@ -11414,7 +11794,7 @@ async function detectAllVersions(loader, archive) {
11414
11794
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
11415
11795
  let resolvedBin = cliBin;
11416
11796
  if (!resolvedBin && appPath && currentOs === "darwin") {
11417
- const bundled = path11.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
11797
+ const bundled = path12.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
11418
11798
  if (provider.cli && fs8.existsSync(bundled)) resolvedBin = bundled;
11419
11799
  }
11420
11800
  info.installed = !!(appPath || resolvedBin);
@@ -11455,7 +11835,7 @@ async function detectAllVersions(loader, archive) {
11455
11835
  // src/daemon/dev-server.ts
11456
11836
  import * as http2 from "http";
11457
11837
  import * as fs11 from "fs";
11458
- import * as path14 from "path";
11838
+ import * as path15 from "path";
11459
11839
 
11460
11840
  // src/daemon/scaffold-template.ts
11461
11841
  function generateFiles(type, name, category, opts = {}) {
@@ -11792,7 +12172,7 @@ init_logger();
11792
12172
  // src/daemon/dev-cdp-handlers.ts
11793
12173
  init_logger();
11794
12174
  import * as fs9 from "fs";
11795
- import * as path12 from "path";
12175
+ import * as path13 from "path";
11796
12176
  async function handleCdpEvaluate(ctx, req, res) {
11797
12177
  const body = await ctx.readBody(req);
11798
12178
  const { expression, timeout, ideType } = body;
@@ -11970,17 +12350,17 @@ async function handleScriptHints(ctx, type, _req, res) {
11970
12350
  return;
11971
12351
  }
11972
12352
  let scriptsPath = "";
11973
- const directScripts = path12.join(dir, "scripts.js");
12353
+ const directScripts = path13.join(dir, "scripts.js");
11974
12354
  if (fs9.existsSync(directScripts)) {
11975
12355
  scriptsPath = directScripts;
11976
12356
  } else {
11977
- const scriptsDir = path12.join(dir, "scripts");
12357
+ const scriptsDir = path13.join(dir, "scripts");
11978
12358
  if (fs9.existsSync(scriptsDir)) {
11979
12359
  const versions = fs9.readdirSync(scriptsDir).filter((d) => {
11980
- return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
12360
+ return fs9.statSync(path13.join(scriptsDir, d)).isDirectory();
11981
12361
  }).sort().reverse();
11982
12362
  for (const ver of versions) {
11983
- const p = path12.join(scriptsDir, ver, "scripts.js");
12363
+ const p = path13.join(scriptsDir, ver, "scripts.js");
11984
12364
  if (fs9.existsSync(p)) {
11985
12365
  scriptsPath = p;
11986
12366
  break;
@@ -13035,7 +13415,7 @@ async function handleCliRaw(ctx, req, res) {
13035
13415
 
13036
13416
  // src/daemon/dev-auto-implement.ts
13037
13417
  import * as fs10 from "fs";
13038
- import * as path13 from "path";
13418
+ import * as path14 from "path";
13039
13419
  import * as os15 from "os";
13040
13420
  function getDefaultAutoImplReference(ctx, category, type) {
13041
13421
  if (category === "cli") {
@@ -13055,22 +13435,22 @@ function getLatestScriptVersionDir(scriptsDir) {
13055
13435
  if (!fs10.existsSync(scriptsDir)) return null;
13056
13436
  const versions = fs10.readdirSync(scriptsDir).filter((d) => {
13057
13437
  try {
13058
- return fs10.statSync(path13.join(scriptsDir, d)).isDirectory();
13438
+ return fs10.statSync(path14.join(scriptsDir, d)).isDirectory();
13059
13439
  } catch {
13060
13440
  return false;
13061
13441
  }
13062
13442
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
13063
13443
  if (versions.length === 0) return null;
13064
- return path13.join(scriptsDir, versions[0]);
13444
+ return path14.join(scriptsDir, versions[0]);
13065
13445
  }
13066
13446
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
13067
- const canonicalUserDir = path13.resolve(ctx.providerLoader.getUserProviderDir(category, type));
13068
- const desiredDir = requestedDir ? path13.resolve(requestedDir) : canonicalUserDir;
13069
- const upstreamRoot = path13.resolve(ctx.providerLoader.getUpstreamDir());
13070
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path13.sep}`)) {
13447
+ const canonicalUserDir = path14.resolve(ctx.providerLoader.getUserProviderDir(category, type));
13448
+ const desiredDir = requestedDir ? path14.resolve(requestedDir) : canonicalUserDir;
13449
+ const upstreamRoot = path14.resolve(ctx.providerLoader.getUpstreamDir());
13450
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path14.sep}`)) {
13071
13451
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
13072
13452
  }
13073
- if (path13.basename(desiredDir) !== type) {
13453
+ if (path14.basename(desiredDir) !== type) {
13074
13454
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
13075
13455
  }
13076
13456
  const sourceDir = ctx.findProviderDir(type);
@@ -13078,11 +13458,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
13078
13458
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
13079
13459
  }
13080
13460
  if (!fs10.existsSync(desiredDir)) {
13081
- fs10.mkdirSync(path13.dirname(desiredDir), { recursive: true });
13461
+ fs10.mkdirSync(path14.dirname(desiredDir), { recursive: true });
13082
13462
  fs10.cpSync(sourceDir, desiredDir, { recursive: true });
13083
13463
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
13084
13464
  }
13085
- const providerJson = path13.join(desiredDir, "provider.json");
13465
+ const providerJson = path14.join(desiredDir, "provider.json");
13086
13466
  if (!fs10.existsSync(providerJson)) {
13087
13467
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
13088
13468
  }
@@ -13105,13 +13485,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
13105
13485
  const refDir = ctx.findProviderDir(referenceType);
13106
13486
  if (!refDir || !fs10.existsSync(refDir)) return {};
13107
13487
  const referenceScripts = {};
13108
- const scriptsDir = path13.join(refDir, "scripts");
13488
+ const scriptsDir = path14.join(refDir, "scripts");
13109
13489
  const latestDir = getLatestScriptVersionDir(scriptsDir);
13110
13490
  if (!latestDir) return referenceScripts;
13111
13491
  for (const file of fs10.readdirSync(latestDir)) {
13112
13492
  if (!file.endsWith(".js")) continue;
13113
13493
  try {
13114
- referenceScripts[file] = fs10.readFileSync(path13.join(latestDir, file), "utf-8");
13494
+ referenceScripts[file] = fs10.readFileSync(path14.join(latestDir, file), "utf-8");
13115
13495
  } catch {
13116
13496
  }
13117
13497
  }
@@ -13162,9 +13542,9 @@ async function handleAutoImplement(ctx, type, req, res) {
13162
13542
  });
13163
13543
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
13164
13544
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference);
13165
- const tmpDir = path13.join(os15.tmpdir(), "adhdev-autoimpl");
13545
+ const tmpDir = path14.join(os15.tmpdir(), "adhdev-autoimpl");
13166
13546
  if (!fs10.existsSync(tmpDir)) fs10.mkdirSync(tmpDir, { recursive: true });
13167
- const promptFile = path13.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
13547
+ const promptFile = path14.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
13168
13548
  fs10.writeFileSync(promptFile, prompt, "utf-8");
13169
13549
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
13170
13550
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -13535,7 +13915,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
13535
13915
  setMode: "set_mode.js"
13536
13916
  };
13537
13917
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
13538
- const scriptsDir = path13.join(providerDir, "scripts");
13918
+ const scriptsDir = path14.join(providerDir, "scripts");
13539
13919
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
13540
13920
  if (latestScriptsDir) {
13541
13921
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -13546,7 +13926,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
13546
13926
  for (const file of fs10.readdirSync(latestScriptsDir)) {
13547
13927
  if (file.endsWith(".js") && targetFileNames.has(file)) {
13548
13928
  try {
13549
- const content = fs10.readFileSync(path13.join(latestScriptsDir, file), "utf-8");
13929
+ const content = fs10.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
13550
13930
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
13551
13931
  lines.push("```javascript");
13552
13932
  lines.push(content);
@@ -13563,7 +13943,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
13563
13943
  lines.push("");
13564
13944
  for (const file of refFiles) {
13565
13945
  try {
13566
- const content = fs10.readFileSync(path13.join(latestScriptsDir, file), "utf-8");
13946
+ const content = fs10.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
13567
13947
  lines.push(`### \`${file}\` \u{1F512}`);
13568
13948
  lines.push("```javascript");
13569
13949
  lines.push(content);
@@ -13604,10 +13984,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
13604
13984
  lines.push("");
13605
13985
  }
13606
13986
  }
13607
- const docsDir = path13.join(providerDir, "../../docs");
13987
+ const docsDir = path14.join(providerDir, "../../docs");
13608
13988
  const loadGuide = (name) => {
13609
13989
  try {
13610
- const p = path13.join(docsDir, name);
13990
+ const p = path14.join(docsDir, name);
13611
13991
  if (fs10.existsSync(p)) return fs10.readFileSync(p, "utf-8");
13612
13992
  } catch {
13613
13993
  }
@@ -13781,7 +14161,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
13781
14161
  parseApproval: "parse_approval.js"
13782
14162
  };
13783
14163
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
13784
- const scriptsDir = path13.join(providerDir, "scripts");
14164
+ const scriptsDir = path14.join(providerDir, "scripts");
13785
14165
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
13786
14166
  if (latestScriptsDir) {
13787
14167
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -13793,7 +14173,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
13793
14173
  if (!file.endsWith(".js")) continue;
13794
14174
  if (!targetFileNames.has(file)) continue;
13795
14175
  try {
13796
- const content = fs10.readFileSync(path13.join(latestScriptsDir, file), "utf-8");
14176
+ const content = fs10.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
13797
14177
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
13798
14178
  lines.push("```javascript");
13799
14179
  lines.push(content);
@@ -13809,7 +14189,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
13809
14189
  lines.push("");
13810
14190
  for (const file of refFiles) {
13811
14191
  try {
13812
- const content = fs10.readFileSync(path13.join(latestScriptsDir, file), "utf-8");
14192
+ const content = fs10.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
13813
14193
  lines.push(`### \`${file}\` \u{1F512}`);
13814
14194
  lines.push("```javascript");
13815
14195
  lines.push(content);
@@ -13842,10 +14222,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
13842
14222
  lines.push("");
13843
14223
  }
13844
14224
  }
13845
- const docsDir = path13.join(providerDir, "../../docs");
14225
+ const docsDir = path14.join(providerDir, "../../docs");
13846
14226
  const loadGuide = (name) => {
13847
14227
  try {
13848
- const p = path13.join(docsDir, name);
14228
+ const p = path14.join(docsDir, name);
13849
14229
  if (fs10.existsSync(p)) return fs10.readFileSync(p, "utf-8");
13850
14230
  } catch {
13851
14231
  }
@@ -14103,8 +14483,8 @@ var DevServer = class _DevServer {
14103
14483
  }
14104
14484
  getEndpointList() {
14105
14485
  return this.routes.map((r) => {
14106
- const path15 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
14107
- return `${r.method.padEnd(5)} ${path15}`;
14486
+ const path16 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
14487
+ return `${r.method.padEnd(5)} ${path16}`;
14108
14488
  });
14109
14489
  }
14110
14490
  async start(port = DEV_SERVER_PORT) {
@@ -14135,15 +14515,15 @@ var DevServer = class _DevServer {
14135
14515
  this.json(res, 500, { error: e.message });
14136
14516
  }
14137
14517
  });
14138
- return new Promise((resolve9, reject) => {
14518
+ return new Promise((resolve10, reject) => {
14139
14519
  this.server.listen(port, "127.0.0.1", () => {
14140
14520
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
14141
- resolve9();
14521
+ resolve10();
14142
14522
  });
14143
14523
  this.server.on("error", (e) => {
14144
14524
  if (e.code === "EADDRINUSE") {
14145
14525
  this.log(`Port ${port} in use, skipping dev server`);
14146
- resolve9();
14526
+ resolve10();
14147
14527
  } else {
14148
14528
  reject(e);
14149
14529
  }
@@ -14226,20 +14606,20 @@ var DevServer = class _DevServer {
14226
14606
  child.stderr?.on("data", (d) => {
14227
14607
  stderr += d.toString().slice(0, 2e3);
14228
14608
  });
14229
- await new Promise((resolve9) => {
14609
+ await new Promise((resolve10) => {
14230
14610
  const timer = setTimeout(() => {
14231
14611
  child.kill();
14232
- resolve9();
14612
+ resolve10();
14233
14613
  }, 3e3);
14234
14614
  child.on("exit", () => {
14235
14615
  clearTimeout(timer);
14236
- resolve9();
14616
+ resolve10();
14237
14617
  });
14238
14618
  child.stdout?.once("data", () => {
14239
14619
  setTimeout(() => {
14240
14620
  child.kill();
14241
14621
  clearTimeout(timer);
14242
- resolve9();
14622
+ resolve10();
14243
14623
  }, 500);
14244
14624
  });
14245
14625
  });
@@ -14386,12 +14766,12 @@ var DevServer = class _DevServer {
14386
14766
  // ─── DevConsole SPA ───
14387
14767
  getConsoleDistDir() {
14388
14768
  const candidates = [
14389
- path14.resolve(__dirname, "../../web-devconsole/dist"),
14390
- path14.resolve(__dirname, "../../../web-devconsole/dist"),
14391
- path14.join(process.cwd(), "packages/web-devconsole/dist")
14769
+ path15.resolve(__dirname, "../../web-devconsole/dist"),
14770
+ path15.resolve(__dirname, "../../../web-devconsole/dist"),
14771
+ path15.join(process.cwd(), "packages/web-devconsole/dist")
14392
14772
  ];
14393
14773
  for (const dir of candidates) {
14394
- if (fs11.existsSync(path14.join(dir, "index.html"))) return dir;
14774
+ if (fs11.existsSync(path15.join(dir, "index.html"))) return dir;
14395
14775
  }
14396
14776
  return null;
14397
14777
  }
@@ -14401,7 +14781,7 @@ var DevServer = class _DevServer {
14401
14781
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
14402
14782
  return;
14403
14783
  }
14404
- const htmlPath = path14.join(distDir, "index.html");
14784
+ const htmlPath = path15.join(distDir, "index.html");
14405
14785
  try {
14406
14786
  const html = fs11.readFileSync(htmlPath, "utf-8");
14407
14787
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -14426,15 +14806,15 @@ var DevServer = class _DevServer {
14426
14806
  this.json(res, 404, { error: "Not found" });
14427
14807
  return;
14428
14808
  }
14429
- const safePath = path14.normalize(pathname).replace(/^\.\.\//, "");
14430
- const filePath = path14.join(distDir, safePath);
14809
+ const safePath = path15.normalize(pathname).replace(/^\.\.\//, "");
14810
+ const filePath = path15.join(distDir, safePath);
14431
14811
  if (!filePath.startsWith(distDir)) {
14432
14812
  this.json(res, 403, { error: "Forbidden" });
14433
14813
  return;
14434
14814
  }
14435
14815
  try {
14436
14816
  const content = fs11.readFileSync(filePath);
14437
- const ext = path14.extname(filePath);
14817
+ const ext = path15.extname(filePath);
14438
14818
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
14439
14819
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
14440
14820
  res.end(content);
@@ -14547,9 +14927,9 @@ var DevServer = class _DevServer {
14547
14927
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
14548
14928
  if (entry.isDirectory()) {
14549
14929
  files.push({ path: rel, size: 0, type: "dir" });
14550
- scan(path14.join(d, entry.name), rel);
14930
+ scan(path15.join(d, entry.name), rel);
14551
14931
  } else {
14552
- const stat = fs11.statSync(path14.join(d, entry.name));
14932
+ const stat = fs11.statSync(path15.join(d, entry.name));
14553
14933
  files.push({ path: rel, size: stat.size, type: "file" });
14554
14934
  }
14555
14935
  }
@@ -14572,7 +14952,7 @@ var DevServer = class _DevServer {
14572
14952
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
14573
14953
  return;
14574
14954
  }
14575
- const fullPath = path14.resolve(dir, path14.normalize(filePath));
14955
+ const fullPath = path15.resolve(dir, path15.normalize(filePath));
14576
14956
  if (!fullPath.startsWith(dir)) {
14577
14957
  this.json(res, 403, { error: "Forbidden" });
14578
14958
  return;
@@ -14597,14 +14977,14 @@ var DevServer = class _DevServer {
14597
14977
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
14598
14978
  return;
14599
14979
  }
14600
- const fullPath = path14.resolve(dir, path14.normalize(filePath));
14980
+ const fullPath = path15.resolve(dir, path15.normalize(filePath));
14601
14981
  if (!fullPath.startsWith(dir)) {
14602
14982
  this.json(res, 403, { error: "Forbidden" });
14603
14983
  return;
14604
14984
  }
14605
14985
  try {
14606
14986
  if (fs11.existsSync(fullPath)) fs11.copyFileSync(fullPath, fullPath + ".bak");
14607
- fs11.mkdirSync(path14.dirname(fullPath), { recursive: true });
14987
+ fs11.mkdirSync(path15.dirname(fullPath), { recursive: true });
14608
14988
  fs11.writeFileSync(fullPath, content, "utf-8");
14609
14989
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
14610
14990
  this.providerLoader.reload();
@@ -14621,7 +15001,7 @@ var DevServer = class _DevServer {
14621
15001
  return;
14622
15002
  }
14623
15003
  for (const name of ["scripts.js", "provider.json"]) {
14624
- const p = path14.join(dir, name);
15004
+ const p = path15.join(dir, name);
14625
15005
  if (fs11.existsSync(p)) {
14626
15006
  const source = fs11.readFileSync(p, "utf-8");
14627
15007
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -14642,8 +15022,8 @@ var DevServer = class _DevServer {
14642
15022
  this.json(res, 404, { error: `Provider not found: ${type}` });
14643
15023
  return;
14644
15024
  }
14645
- const target = fs11.existsSync(path14.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
14646
- const targetPath = path14.join(dir, target);
15025
+ const target = fs11.existsSync(path15.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
15026
+ const targetPath = path15.join(dir, target);
14647
15027
  try {
14648
15028
  if (fs11.existsSync(targetPath)) fs11.copyFileSync(targetPath, targetPath + ".bak");
14649
15029
  fs11.writeFileSync(targetPath, source, "utf-8");
@@ -14748,14 +15128,14 @@ var DevServer = class _DevServer {
14748
15128
  child.stderr?.on("data", (d) => {
14749
15129
  stderr += d.toString();
14750
15130
  });
14751
- await new Promise((resolve9) => {
15131
+ await new Promise((resolve10) => {
14752
15132
  const timer = setTimeout(() => {
14753
15133
  child.kill();
14754
- resolve9();
15134
+ resolve10();
14755
15135
  }, timeout);
14756
15136
  child.on("exit", () => {
14757
15137
  clearTimeout(timer);
14758
- resolve9();
15138
+ resolve10();
14759
15139
  });
14760
15140
  });
14761
15141
  const elapsed = Date.now() - start;
@@ -14803,7 +15183,7 @@ var DevServer = class _DevServer {
14803
15183
  }
14804
15184
  let targetDir;
14805
15185
  targetDir = this.providerLoader.getUserProviderDir(category, type);
14806
- const jsonPath = path14.join(targetDir, "provider.json");
15186
+ const jsonPath = path15.join(targetDir, "provider.json");
14807
15187
  if (fs11.existsSync(jsonPath)) {
14808
15188
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
14809
15189
  return;
@@ -14815,8 +15195,8 @@ var DevServer = class _DevServer {
14815
15195
  const createdFiles = ["provider.json"];
14816
15196
  if (result.files) {
14817
15197
  for (const [relPath, content] of Object.entries(result.files)) {
14818
- const fullPath = path14.join(targetDir, relPath);
14819
- fs11.mkdirSync(path14.dirname(fullPath), { recursive: true });
15198
+ const fullPath = path15.join(targetDir, relPath);
15199
+ fs11.mkdirSync(path15.dirname(fullPath), { recursive: true });
14820
15200
  fs11.writeFileSync(fullPath, content, "utf-8");
14821
15201
  createdFiles.push(relPath);
14822
15202
  }
@@ -14869,22 +15249,22 @@ var DevServer = class _DevServer {
14869
15249
  if (!fs11.existsSync(scriptsDir)) return null;
14870
15250
  const versions = fs11.readdirSync(scriptsDir).filter((d) => {
14871
15251
  try {
14872
- return fs11.statSync(path14.join(scriptsDir, d)).isDirectory();
15252
+ return fs11.statSync(path15.join(scriptsDir, d)).isDirectory();
14873
15253
  } catch {
14874
15254
  return false;
14875
15255
  }
14876
15256
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
14877
15257
  if (versions.length === 0) return null;
14878
- return path14.join(scriptsDir, versions[0]);
15258
+ return path15.join(scriptsDir, versions[0]);
14879
15259
  }
14880
15260
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
14881
- const canonicalUserDir = path14.resolve(this.providerLoader.getUserProviderDir(category, type));
14882
- const desiredDir = requestedDir ? path14.resolve(requestedDir) : canonicalUserDir;
14883
- const upstreamRoot = path14.resolve(this.providerLoader.getUpstreamDir());
14884
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path14.sep}`)) {
15261
+ const canonicalUserDir = path15.resolve(this.providerLoader.getUserProviderDir(category, type));
15262
+ const desiredDir = requestedDir ? path15.resolve(requestedDir) : canonicalUserDir;
15263
+ const upstreamRoot = path15.resolve(this.providerLoader.getUpstreamDir());
15264
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path15.sep}`)) {
14885
15265
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
14886
15266
  }
14887
- if (path14.basename(desiredDir) !== type) {
15267
+ if (path15.basename(desiredDir) !== type) {
14888
15268
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
14889
15269
  }
14890
15270
  const sourceDir = this.findProviderDir(type);
@@ -14892,11 +15272,11 @@ var DevServer = class _DevServer {
14892
15272
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
14893
15273
  }
14894
15274
  if (!fs11.existsSync(desiredDir)) {
14895
- fs11.mkdirSync(path14.dirname(desiredDir), { recursive: true });
15275
+ fs11.mkdirSync(path15.dirname(desiredDir), { recursive: true });
14896
15276
  fs11.cpSync(sourceDir, desiredDir, { recursive: true });
14897
15277
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
14898
15278
  }
14899
- const providerJson = path14.join(desiredDir, "provider.json");
15279
+ const providerJson = path15.join(desiredDir, "provider.json");
14900
15280
  if (!fs11.existsSync(providerJson)) {
14901
15281
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
14902
15282
  }
@@ -14944,7 +15324,7 @@ var DevServer = class _DevServer {
14944
15324
  setMode: "set_mode.js"
14945
15325
  };
14946
15326
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
14947
- const scriptsDir = path14.join(providerDir, "scripts");
15327
+ const scriptsDir = path15.join(providerDir, "scripts");
14948
15328
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
14949
15329
  if (latestScriptsDir) {
14950
15330
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -14955,7 +15335,7 @@ var DevServer = class _DevServer {
14955
15335
  for (const file of fs11.readdirSync(latestScriptsDir)) {
14956
15336
  if (file.endsWith(".js") && targetFileNames.has(file)) {
14957
15337
  try {
14958
- const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
15338
+ const content = fs11.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
14959
15339
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
14960
15340
  lines.push("```javascript");
14961
15341
  lines.push(content);
@@ -14972,7 +15352,7 @@ var DevServer = class _DevServer {
14972
15352
  lines.push("");
14973
15353
  for (const file of refFiles) {
14974
15354
  try {
14975
- const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
15355
+ const content = fs11.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
14976
15356
  lines.push(`### \`${file}\` \u{1F512}`);
14977
15357
  lines.push("```javascript");
14978
15358
  lines.push(content);
@@ -15013,10 +15393,10 @@ var DevServer = class _DevServer {
15013
15393
  lines.push("");
15014
15394
  }
15015
15395
  }
15016
- const docsDir = path14.join(providerDir, "../../docs");
15396
+ const docsDir = path15.join(providerDir, "../../docs");
15017
15397
  const loadGuide = (name) => {
15018
15398
  try {
15019
- const p = path14.join(docsDir, name);
15399
+ const p = path15.join(docsDir, name);
15020
15400
  if (fs11.existsSync(p)) return fs11.readFileSync(p, "utf-8");
15021
15401
  } catch {
15022
15402
  }
@@ -15190,7 +15570,7 @@ var DevServer = class _DevServer {
15190
15570
  parseApproval: "parse_approval.js"
15191
15571
  };
15192
15572
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
15193
- const scriptsDir = path14.join(providerDir, "scripts");
15573
+ const scriptsDir = path15.join(providerDir, "scripts");
15194
15574
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
15195
15575
  if (latestScriptsDir) {
15196
15576
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -15202,7 +15582,7 @@ var DevServer = class _DevServer {
15202
15582
  if (!file.endsWith(".js")) continue;
15203
15583
  if (!targetFileNames.has(file)) continue;
15204
15584
  try {
15205
- const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
15585
+ const content = fs11.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
15206
15586
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
15207
15587
  lines.push("```javascript");
15208
15588
  lines.push(content);
@@ -15218,7 +15598,7 @@ var DevServer = class _DevServer {
15218
15598
  lines.push("");
15219
15599
  for (const file of refFiles) {
15220
15600
  try {
15221
- const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
15601
+ const content = fs11.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
15222
15602
  lines.push(`### \`${file}\` \u{1F512}`);
15223
15603
  lines.push("```javascript");
15224
15604
  lines.push(content);
@@ -15251,10 +15631,10 @@ var DevServer = class _DevServer {
15251
15631
  lines.push("");
15252
15632
  }
15253
15633
  }
15254
- const docsDir = path14.join(providerDir, "../../docs");
15634
+ const docsDir = path15.join(providerDir, "../../docs");
15255
15635
  const loadGuide = (name) => {
15256
15636
  try {
15257
- const p = path14.join(docsDir, name);
15637
+ const p = path15.join(docsDir, name);
15258
15638
  if (fs11.existsSync(p)) return fs11.readFileSync(p, "utf-8");
15259
15639
  } catch {
15260
15640
  }
@@ -15411,14 +15791,14 @@ data: ${JSON.stringify(msg.data)}
15411
15791
  res.end(JSON.stringify(data, null, 2));
15412
15792
  }
15413
15793
  async readBody(req) {
15414
- return new Promise((resolve9) => {
15794
+ return new Promise((resolve10) => {
15415
15795
  let body = "";
15416
15796
  req.on("data", (chunk) => body += chunk);
15417
15797
  req.on("end", () => {
15418
15798
  try {
15419
- resolve9(JSON.parse(body));
15799
+ resolve10(JSON.parse(body));
15420
15800
  } catch {
15421
- resolve9({});
15801
+ resolve10({});
15422
15802
  }
15423
15803
  });
15424
15804
  });
@@ -15840,7 +16220,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
15840
16220
  const deadline = Date.now() + timeoutMs;
15841
16221
  while (Date.now() < deadline) {
15842
16222
  if (await canConnect(endpoint)) return;
15843
- await new Promise((resolve9) => setTimeout(resolve9, STARTUP_POLL_MS));
16223
+ await new Promise((resolve10) => setTimeout(resolve10, STARTUP_POLL_MS));
15844
16224
  }
15845
16225
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
15846
16226
  }
@@ -15995,10 +16375,10 @@ async function installExtension(ide, extension) {
15995
16375
  const buffer = Buffer.from(await res.arrayBuffer());
15996
16376
  const fs12 = await import("fs");
15997
16377
  fs12.writeFileSync(vsixPath, buffer);
15998
- return new Promise((resolve9) => {
16378
+ return new Promise((resolve10) => {
15999
16379
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
16000
16380
  exec2(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
16001
- resolve9({
16381
+ resolve10({
16002
16382
  extensionId: extension.id,
16003
16383
  marketplaceId: extension.marketplaceId,
16004
16384
  success: !error,
@@ -16011,11 +16391,11 @@ async function installExtension(ide, extension) {
16011
16391
  } catch (e) {
16012
16392
  }
16013
16393
  }
16014
- return new Promise((resolve9) => {
16394
+ return new Promise((resolve10) => {
16015
16395
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
16016
16396
  exec2(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
16017
16397
  if (error) {
16018
- resolve9({
16398
+ resolve10({
16019
16399
  extensionId: extension.id,
16020
16400
  marketplaceId: extension.marketplaceId,
16021
16401
  success: false,
@@ -16023,7 +16403,7 @@ async function installExtension(ide, extension) {
16023
16403
  error: stderr || error.message
16024
16404
  });
16025
16405
  } else {
16026
- resolve9({
16406
+ resolve10({
16027
16407
  extensionId: extension.id,
16028
16408
  marketplaceId: extension.marketplaceId,
16029
16409
  success: true,
@@ -16327,6 +16707,7 @@ export {
16327
16707
  SessionHostPtyTransportFactory,
16328
16708
  VersionArchive,
16329
16709
  addCliHistory,
16710
+ appendRecentActivity,
16330
16711
  buildSessionEntries,
16331
16712
  buildStatusSnapshot,
16332
16713
  connectCdpManager,
@@ -16340,6 +16721,7 @@ export {
16340
16721
  getAvailableIdeIds,
16341
16722
  getHostMemorySnapshot,
16342
16723
  getLogLevel,
16724
+ getRecentActivity,
16343
16725
  getRecentCommands,
16344
16726
  getRecentLogs,
16345
16727
  getWorkspaceActivity,