adhdev 0.5.3 → 0.5.5

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.
@@ -16369,6 +16369,190 @@ var require_dist = __commonJS({
16369
16369
  mod
16370
16370
  ));
16371
16371
  var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
16372
+ function expandPath(p) {
16373
+ const t = (p || "").trim();
16374
+ if (!t) return "";
16375
+ if (t.startsWith("~")) return path3.join(os3.homedir(), t.slice(1).replace(/^\//, ""));
16376
+ return path3.resolve(t);
16377
+ }
16378
+ function validateWorkspacePath(absPath) {
16379
+ try {
16380
+ if (!absPath) return { ok: false, error: "Path required" };
16381
+ if (!fs3.existsSync(absPath)) return { ok: false, error: "Path does not exist" };
16382
+ const st = fs3.statSync(absPath);
16383
+ if (!st.isDirectory()) return { ok: false, error: "Not a directory" };
16384
+ return { ok: true };
16385
+ } catch (e) {
16386
+ return { ok: false, error: e?.message || "Invalid path" };
16387
+ }
16388
+ }
16389
+ function defaultWorkspaceLabel(absPath) {
16390
+ const base = path3.basename(absPath) || absPath;
16391
+ return base;
16392
+ }
16393
+ function migrateWorkspacesFromRecent(config2) {
16394
+ if (!config2.workspaces) config2.workspaces = [];
16395
+ if (config2.workspaces.length > 0) return config2;
16396
+ const recent = config2.recentCliWorkspaces || [];
16397
+ const now = Date.now();
16398
+ for (const raw of recent) {
16399
+ const abs = expandPath(raw);
16400
+ if (!abs || validateWorkspacePath(abs).ok !== true) continue;
16401
+ if (config2.workspaces.some((w) => path3.resolve(w.path) === abs)) continue;
16402
+ config2.workspaces.push({
16403
+ id: (0, import_crypto.randomUUID)(),
16404
+ path: abs,
16405
+ label: defaultWorkspaceLabel(abs),
16406
+ addedAt: now
16407
+ });
16408
+ if (config2.workspaces.length >= MAX_WORKSPACES) break;
16409
+ }
16410
+ return config2;
16411
+ }
16412
+ function getDefaultWorkspacePath(config2) {
16413
+ const id = config2.defaultWorkspaceId;
16414
+ if (!id) return null;
16415
+ const w = (config2.workspaces || []).find((x) => x.id === id);
16416
+ if (!w) return null;
16417
+ const abs = expandPath(w.path);
16418
+ if (validateWorkspacePath(abs).ok !== true) return null;
16419
+ return abs;
16420
+ }
16421
+ function getWorkspaceState(config2) {
16422
+ const workspaces = [...config2.workspaces || []].sort((a, b) => b.addedAt - a.addedAt);
16423
+ const defaultWorkspacePath = getDefaultWorkspacePath(config2);
16424
+ return {
16425
+ workspaces,
16426
+ defaultWorkspaceId: config2.defaultWorkspaceId ?? null,
16427
+ defaultWorkspacePath
16428
+ };
16429
+ }
16430
+ function resolveLaunchDirectory(args, config2) {
16431
+ const a = args || {};
16432
+ if (a.dir != null && String(a.dir).trim()) {
16433
+ const abs = expandPath(String(a.dir).trim());
16434
+ if (abs && validateWorkspacePath(abs).ok === true) {
16435
+ return { ok: true, path: abs, source: "dir" };
16436
+ }
16437
+ return {
16438
+ ok: false,
16439
+ code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
16440
+ message: abs ? "Directory path is not valid or does not exist" : "Invalid directory path"
16441
+ };
16442
+ }
16443
+ if (a.workspaceId) {
16444
+ const w = (config2.workspaces || []).find((x) => x.id === a.workspaceId);
16445
+ if (w) {
16446
+ const abs = expandPath(w.path);
16447
+ if (validateWorkspacePath(abs).ok === true) {
16448
+ return { ok: true, path: abs, source: "workspaceId" };
16449
+ }
16450
+ }
16451
+ return {
16452
+ ok: false,
16453
+ code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
16454
+ message: "Saved workspace not found or path is no longer valid"
16455
+ };
16456
+ }
16457
+ if (a.useDefaultWorkspace === true) {
16458
+ const d = getDefaultWorkspacePath(config2);
16459
+ if (d) return { ok: true, path: d, source: "defaultWorkspace" };
16460
+ return {
16461
+ ok: false,
16462
+ code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
16463
+ message: "No default workspace is set"
16464
+ };
16465
+ }
16466
+ if (a.useHome === true) {
16467
+ return { ok: true, path: os3.homedir(), source: "home" };
16468
+ }
16469
+ return {
16470
+ ok: false,
16471
+ code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
16472
+ message: "Choose a directory, saved workspace, default workspace, or home before launching."
16473
+ };
16474
+ }
16475
+ function resolveIdeWorkspaceFromArgs(args, config2) {
16476
+ const ar = args || {};
16477
+ if (ar.workspace) {
16478
+ const abs = expandPath(ar.workspace);
16479
+ if (abs && validateWorkspacePath(abs).ok === true) return abs;
16480
+ }
16481
+ if (ar.workspaceId) {
16482
+ const w = (config2.workspaces || []).find((x) => x.id === ar.workspaceId);
16483
+ if (w) {
16484
+ const abs = expandPath(w.path);
16485
+ if (validateWorkspacePath(abs).ok === true) return abs;
16486
+ }
16487
+ }
16488
+ if (ar.useDefaultWorkspace === true) {
16489
+ return getDefaultWorkspacePath(config2) || void 0;
16490
+ }
16491
+ return void 0;
16492
+ }
16493
+ function resolveIdeLaunchWorkspace(args, config2) {
16494
+ const direct = resolveIdeWorkspaceFromArgs(args, config2);
16495
+ if (direct) return direct;
16496
+ if (args?.useDefaultWorkspace === false) return void 0;
16497
+ return getDefaultWorkspacePath(config2) || void 0;
16498
+ }
16499
+ function findWorkspaceByPath(config2, rawPath) {
16500
+ const abs = path3.resolve(expandPath(rawPath));
16501
+ if (!abs) return void 0;
16502
+ return (config2.workspaces || []).find((w) => path3.resolve(expandPath(w.path)) === abs);
16503
+ }
16504
+ function addWorkspaceEntry(config2, rawPath, label) {
16505
+ const abs = expandPath(rawPath);
16506
+ const v = validateWorkspacePath(abs);
16507
+ if (!v.ok) return { error: v.error };
16508
+ const list = [...config2.workspaces || []];
16509
+ if (list.some((w) => path3.resolve(w.path) === abs)) {
16510
+ return { error: "Workspace already in list" };
16511
+ }
16512
+ if (list.length >= MAX_WORKSPACES) {
16513
+ return { error: `Maximum ${MAX_WORKSPACES} workspaces` };
16514
+ }
16515
+ const entry = {
16516
+ id: (0, import_crypto.randomUUID)(),
16517
+ path: abs,
16518
+ label: (label || "").trim() || defaultWorkspaceLabel(abs),
16519
+ addedAt: Date.now()
16520
+ };
16521
+ list.push(entry);
16522
+ return { config: { ...config2, workspaces: list }, entry };
16523
+ }
16524
+ function removeWorkspaceEntry(config2, id) {
16525
+ const list = (config2.workspaces || []).filter((w) => w.id !== id);
16526
+ if (list.length === (config2.workspaces || []).length) return { error: "Workspace not found" };
16527
+ let defaultWorkspaceId = config2.defaultWorkspaceId;
16528
+ if (defaultWorkspaceId === id) defaultWorkspaceId = null;
16529
+ return { config: { ...config2, workspaces: list, defaultWorkspaceId } };
16530
+ }
16531
+ function setDefaultWorkspaceId(config2, id) {
16532
+ if (id === null) {
16533
+ return { config: { ...config2, defaultWorkspaceId: null } };
16534
+ }
16535
+ const w = (config2.workspaces || []).find((x) => x.id === id);
16536
+ if (!w) return { error: "Workspace not found" };
16537
+ const abs = expandPath(w.path);
16538
+ if (validateWorkspacePath(abs).ok !== true) return { error: "Workspace path is no longer valid" };
16539
+ return { config: { ...config2, defaultWorkspaceId: id } };
16540
+ }
16541
+ var fs3;
16542
+ var os3;
16543
+ var path3;
16544
+ var import_crypto;
16545
+ var MAX_WORKSPACES;
16546
+ var init_workspaces = __esm2({
16547
+ "src/config/workspaces.ts"() {
16548
+ "use strict";
16549
+ fs3 = __toESM2(require("fs"));
16550
+ os3 = __toESM2(require("os"));
16551
+ path3 = __toESM2(require("path"));
16552
+ import_crypto = require("crypto");
16553
+ MAX_WORKSPACES = 50;
16554
+ }
16555
+ });
16372
16556
  var config_exports = {};
16373
16557
  __export2(config_exports, {
16374
16558
  addCliHistory: () => addCliHistory,
@@ -16399,7 +16583,20 @@ var require_dist = __commonJS({
16399
16583
  try {
16400
16584
  const raw = (0, import_fs2.readFileSync)(configPath, "utf-8");
16401
16585
  const parsed = JSON.parse(raw);
16402
- return { ...DEFAULT_CONFIG, ...parsed };
16586
+ const merged = { ...DEFAULT_CONFIG, ...parsed };
16587
+ if (merged.defaultWorkspaceId == null && merged.activeWorkspaceId != null) {
16588
+ merged.defaultWorkspaceId = merged.activeWorkspaceId;
16589
+ }
16590
+ delete merged.activeWorkspaceId;
16591
+ const hadStoredWorkspaces = Array.isArray(parsed.workspaces) && parsed.workspaces.length > 0;
16592
+ migrateWorkspacesFromRecent(merged);
16593
+ if (!hadStoredWorkspaces && (merged.workspaces?.length || 0) > 0) {
16594
+ try {
16595
+ saveConfig2(merged);
16596
+ } catch {
16597
+ }
16598
+ }
16599
+ return merged;
16403
16600
  } catch {
16404
16601
  return { ...DEFAULT_CONFIG };
16405
16602
  }
@@ -16473,6 +16670,7 @@ var require_dist = __commonJS({
16473
16670
  import_os = require("os");
16474
16671
  import_path2 = require("path");
16475
16672
  import_fs2 = require("fs");
16673
+ init_workspaces();
16476
16674
  DEFAULT_CONFIG = {
16477
16675
  serverUrl: "https://api.adhf.dev",
16478
16676
  apiToken: null,
@@ -16489,6 +16687,9 @@ var require_dist = __commonJS({
16489
16687
  configuredCLIs: [],
16490
16688
  enabledIdes: [],
16491
16689
  recentCliWorkspaces: [],
16690
+ workspaces: [],
16691
+ defaultWorkspaceId: null,
16692
+ recentWorkspaceActivity: [],
16492
16693
  machineNickname: null,
16493
16694
  cliHistory: [],
16494
16695
  providerSettings: {},
@@ -16526,9 +16727,12 @@ var require_dist = __commonJS({
16526
16727
  detectIDEs: () => detectIDEs3,
16527
16728
  getAIExtensions: () => getAIExtensions2,
16528
16729
  getAvailableIdeIds: () => getAvailableIdeIds2,
16730
+ getHostMemorySnapshot: () => getHostMemorySnapshot,
16529
16731
  getLogLevel: () => getLogLevel,
16530
16732
  getRecentCommands: () => getRecentCommands,
16531
16733
  getRecentLogs: () => getRecentLogs,
16734
+ getWorkspaceActivity: () => getWorkspaceActivity,
16735
+ getWorkspaceState: () => getWorkspaceState,
16532
16736
  initDaemonComponents: () => initDaemonComponents2,
16533
16737
  installExtensions: () => installExtensions2,
16534
16738
  installGlobalInterceptor: () => installGlobalInterceptor,
@@ -16551,6 +16755,45 @@ var require_dist = __commonJS({
16551
16755
  });
16552
16756
  module2.exports = __toCommonJS2(index_exports);
16553
16757
  init_config();
16758
+ init_workspaces();
16759
+ var path22 = __toESM2(require("path"));
16760
+ init_workspaces();
16761
+ var MAX_ACTIVITY = 30;
16762
+ function normWorkspacePath(p) {
16763
+ try {
16764
+ return path22.resolve(expandPath(p));
16765
+ } catch {
16766
+ return path22.resolve(p);
16767
+ }
16768
+ }
16769
+ function appendWorkspaceActivity(config2, rawPath, meta3) {
16770
+ const abs = normWorkspacePath(rawPath);
16771
+ if (!abs) return config2;
16772
+ const prev = config2.recentWorkspaceActivity || [];
16773
+ const filtered = prev.filter((e) => normWorkspacePath(e.path) !== abs);
16774
+ const entry = {
16775
+ path: abs,
16776
+ lastUsedAt: Date.now(),
16777
+ kind: meta3?.kind,
16778
+ agentType: meta3?.agentType
16779
+ };
16780
+ const recentWorkspaceActivity = [entry, ...filtered].slice(0, MAX_ACTIVITY);
16781
+ return { ...config2, recentWorkspaceActivity };
16782
+ }
16783
+ function getWorkspaceActivity(config2, limit = 20) {
16784
+ const list = [...config2.recentWorkspaceActivity || []];
16785
+ list.sort((a, b) => b.lastUsedAt - a.lastUsedAt);
16786
+ return list.slice(0, limit);
16787
+ }
16788
+ function removeActivityForPath(config2, rawPath) {
16789
+ const n = normWorkspacePath(rawPath);
16790
+ return {
16791
+ ...config2,
16792
+ recentWorkspaceActivity: (config2.recentWorkspaceActivity || []).filter(
16793
+ (e) => normWorkspacePath(e.path) !== n
16794
+ )
16795
+ };
16796
+ }
16554
16797
  var import_child_process = require("child_process");
16555
16798
  var import_fs22 = require("fs");
16556
16799
  var import_os2 = require("os");
@@ -16608,20 +16851,20 @@ var require_dist = __commonJS({
16608
16851
  return null;
16609
16852
  }
16610
16853
  async function detectIDEs3() {
16611
- const os13 = (0, import_os2.platform)();
16854
+ const os15 = (0, import_os2.platform)();
16612
16855
  const results = [];
16613
16856
  for (const def of getMergedDefinitions()) {
16614
16857
  const cliPath = findCliCommand(def.cli);
16615
- const appPath = checkPathExists(def.paths[os13] || []);
16858
+ const appPath = checkPathExists(def.paths[os15] || []);
16616
16859
  const installed = !!(cliPath || appPath);
16617
16860
  let resolvedCli = cliPath;
16618
- if (!resolvedCli && appPath && os13 === "darwin") {
16861
+ if (!resolvedCli && appPath && os15 === "darwin") {
16619
16862
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
16620
16863
  if ((0, import_fs22.existsSync)(bundledCli)) resolvedCli = bundledCli;
16621
16864
  }
16622
- if (!resolvedCli && appPath && os13 === "win32") {
16623
- const { dirname: dirname5 } = await import("path");
16624
- const appDir = dirname5(appPath);
16865
+ if (!resolvedCli && appPath && os15 === "win32") {
16866
+ const { dirname: dirname6 } = await import("path");
16867
+ const appDir = dirname6(appPath);
16625
16868
  const candidates = [
16626
16869
  `${appDir}\\\\bin\\\\${def.cli}.cmd`,
16627
16870
  `${appDir}\\\\bin\\\\${def.cli}`,
@@ -16652,22 +16895,22 @@ var require_dist = __commonJS({
16652
16895
  return results;
16653
16896
  }
16654
16897
  var import_child_process2 = require("child_process");
16655
- var os3 = __toESM2(require("os"));
16898
+ var os22 = __toESM2(require("os"));
16656
16899
  function execAsync(cmd, timeoutMs = 5e3) {
16657
- return new Promise((resolve5) => {
16900
+ return new Promise((resolve7) => {
16658
16901
  const child = (0, import_child_process2.exec)(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
16659
16902
  if (err || !stdout?.trim()) {
16660
- resolve5(null);
16903
+ resolve7(null);
16661
16904
  } else {
16662
- resolve5(stdout.trim());
16905
+ resolve7(stdout.trim());
16663
16906
  }
16664
16907
  });
16665
- child.on("error", () => resolve5(null));
16908
+ child.on("error", () => resolve7(null));
16666
16909
  });
16667
16910
  }
16668
16911
  async function detectCLIs2(providerLoader) {
16669
- const platform7 = os3.platform();
16670
- const whichCmd = platform7 === "win32" ? "where" : "which";
16912
+ const platform8 = os22.platform();
16913
+ const whichCmd = platform8 === "win32" ? "where" : "which";
16671
16914
  const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
16672
16915
  const results = await Promise.all(
16673
16916
  cliList.map(async (cli) => {
@@ -16697,11 +16940,51 @@ var require_dist = __commonJS({
16697
16940
  const all = await detectCLIs2(providerLoader);
16698
16941
  return all.find((c) => c.id === resolvedId && c.installed) || null;
16699
16942
  }
16943
+ var os32 = __toESM2(require("os"));
16944
+ var import_child_process3 = require("child_process");
16945
+ function parseDarwinAvailableBytes(totalMem) {
16946
+ if (os32.platform() !== "darwin") return null;
16947
+ try {
16948
+ const out = (0, import_child_process3.execSync)("vm_stat", {
16949
+ encoding: "utf-8",
16950
+ timeout: 4e3,
16951
+ maxBuffer: 256 * 1024
16952
+ });
16953
+ const pageSizeMatch = out.match(/page size of (\d+)\s*bytes/i);
16954
+ const pageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : 4096;
16955
+ const counts = {};
16956
+ for (const line of out.split("\n")) {
16957
+ const m = line.match(/^\s*Pages\s+([^:]+):\s+([\d,]+)\s*\.?/);
16958
+ if (!m) continue;
16959
+ const key = m[1].trim().toLowerCase().replace(/\s+/g, "_");
16960
+ const n = parseInt(m[2].replace(/,/g, ""), 10);
16961
+ if (!Number.isNaN(n)) counts[key] = n;
16962
+ }
16963
+ const free = counts["free"] ?? 0;
16964
+ const inactive = counts["inactive"] ?? 0;
16965
+ const speculative = counts["speculative"] ?? 0;
16966
+ const purgeable = counts["purgeable"] ?? 0;
16967
+ const fileBacked = counts["file_backed"] ?? 0;
16968
+ const availPages = free + inactive + speculative + purgeable + fileBacked;
16969
+ const bytes = availPages * pageSize;
16970
+ if (!Number.isFinite(bytes) || bytes < 0) return null;
16971
+ return Math.min(bytes, totalMem);
16972
+ } catch {
16973
+ return null;
16974
+ }
16975
+ }
16976
+ function getHostMemorySnapshot() {
16977
+ const totalMem = os32.totalmem();
16978
+ const freeMem = os32.freemem();
16979
+ const darwinAvail = parseDarwinAvailableBytes(totalMem);
16980
+ const availableMem = darwinAvail != null ? darwinAvail : freeMem;
16981
+ return { totalMem, freeMem, availableMem };
16982
+ }
16700
16983
  var import_ws2 = __toESM2(require("ws"));
16701
16984
  var http = __toESM2(require("http"));
16702
- var fs3 = __toESM2(require("fs"));
16703
- var path3 = __toESM2(require("path"));
16704
- var os22 = __toESM2(require("os"));
16985
+ var fs22 = __toESM2(require("fs"));
16986
+ var path32 = __toESM2(require("path"));
16987
+ var os4 = __toESM2(require("os"));
16705
16988
  var LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
16706
16989
  var LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
16707
16990
  var currentLevel = "info";
@@ -16712,29 +16995,29 @@ var require_dist = __commonJS({
16712
16995
  function getLogLevel() {
16713
16996
  return currentLevel;
16714
16997
  }
16715
- var LOG_DIR = process.platform === "darwin" ? path3.join(os22.homedir(), "Library", "Logs", "adhdev") : path3.join(os22.homedir(), ".local", "share", "adhdev", "logs");
16998
+ var LOG_DIR = process.platform === "darwin" ? path32.join(os4.homedir(), "Library", "Logs", "adhdev") : path32.join(os4.homedir(), ".local", "share", "adhdev", "logs");
16716
16999
  var MAX_LOG_SIZE = 5 * 1024 * 1024;
16717
17000
  var MAX_LOG_DAYS = 7;
16718
17001
  try {
16719
- fs3.mkdirSync(LOG_DIR, { recursive: true });
17002
+ fs22.mkdirSync(LOG_DIR, { recursive: true });
16720
17003
  } catch {
16721
17004
  }
16722
17005
  function getDateStr() {
16723
17006
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
16724
17007
  }
16725
17008
  var currentDate = getDateStr();
16726
- var currentLogFile = path3.join(LOG_DIR, `daemon-${currentDate}.log`);
17009
+ var currentLogFile = path32.join(LOG_DIR, `daemon-${currentDate}.log`);
16727
17010
  function checkDateRotation() {
16728
17011
  const today = getDateStr();
16729
17012
  if (today !== currentDate) {
16730
17013
  currentDate = today;
16731
- currentLogFile = path3.join(LOG_DIR, `daemon-${currentDate}.log`);
17014
+ currentLogFile = path32.join(LOG_DIR, `daemon-${currentDate}.log`);
16732
17015
  cleanOldLogs();
16733
17016
  }
16734
17017
  }
16735
17018
  function cleanOldLogs() {
16736
17019
  try {
16737
- const files = fs3.readdirSync(LOG_DIR).filter((f) => f.startsWith("daemon-") && f.endsWith(".log"));
17020
+ const files = fs22.readdirSync(LOG_DIR).filter((f) => f.startsWith("daemon-") && f.endsWith(".log"));
16738
17021
  const cutoff = /* @__PURE__ */ new Date();
16739
17022
  cutoff.setDate(cutoff.getDate() - MAX_LOG_DAYS);
16740
17023
  const cutoffStr = cutoff.toISOString().slice(0, 10);
@@ -16742,7 +17025,7 @@ var require_dist = __commonJS({
16742
17025
  const dateMatch = file2.match(/daemon-(\d{4}-\d{2}-\d{2})/);
16743
17026
  if (dateMatch && dateMatch[1] < cutoffStr) {
16744
17027
  try {
16745
- fs3.unlinkSync(path3.join(LOG_DIR, file2));
17028
+ fs22.unlinkSync(path32.join(LOG_DIR, file2));
16746
17029
  } catch {
16747
17030
  }
16748
17031
  }
@@ -16752,29 +17035,29 @@ var require_dist = __commonJS({
16752
17035
  }
16753
17036
  function rotateSizeIfNeeded() {
16754
17037
  try {
16755
- const stat = fs3.statSync(currentLogFile);
17038
+ const stat = fs22.statSync(currentLogFile);
16756
17039
  if (stat.size > MAX_LOG_SIZE) {
16757
17040
  const backup = currentLogFile.replace(".log", ".1.log");
16758
17041
  try {
16759
- fs3.unlinkSync(backup);
17042
+ fs22.unlinkSync(backup);
16760
17043
  } catch {
16761
17044
  }
16762
- fs3.renameSync(currentLogFile, backup);
17045
+ fs22.renameSync(currentLogFile, backup);
16763
17046
  }
16764
17047
  } catch {
16765
17048
  }
16766
17049
  }
16767
17050
  cleanOldLogs();
16768
17051
  try {
16769
- const oldLog = path3.join(LOG_DIR, "daemon.log");
16770
- if (fs3.existsSync(oldLog)) {
16771
- const stat = fs3.statSync(oldLog);
17052
+ const oldLog = path32.join(LOG_DIR, "daemon.log");
17053
+ if (fs22.existsSync(oldLog)) {
17054
+ const stat = fs22.statSync(oldLog);
16772
17055
  const oldDate = stat.mtime.toISOString().slice(0, 10);
16773
- fs3.renameSync(oldLog, path3.join(LOG_DIR, `daemon-${oldDate}.log`));
17056
+ fs22.renameSync(oldLog, path32.join(LOG_DIR, `daemon-${oldDate}.log`));
16774
17057
  }
16775
- const oldLogBackup = path3.join(LOG_DIR, "daemon.log.old");
16776
- if (fs3.existsSync(oldLogBackup)) {
16777
- fs3.unlinkSync(oldLogBackup);
17058
+ const oldLogBackup = path32.join(LOG_DIR, "daemon.log.old");
17059
+ if (fs22.existsSync(oldLogBackup)) {
17060
+ fs22.unlinkSync(oldLogBackup);
16778
17061
  }
16779
17062
  } catch {
16780
17063
  }
@@ -16785,7 +17068,7 @@ var require_dist = __commonJS({
16785
17068
  checkDateRotation();
16786
17069
  rotateSizeIfNeeded();
16787
17070
  }
16788
- fs3.appendFileSync(currentLogFile, line + "\n");
17071
+ fs22.appendFileSync(currentLogFile, line + "\n");
16789
17072
  } catch {
16790
17073
  }
16791
17074
  }
@@ -16899,7 +17182,7 @@ var require_dist = __commonJS({
16899
17182
  writeToFile(`Log file: ${currentLogFile}`);
16900
17183
  writeToFile(`Log level: ${currentLevel}`);
16901
17184
  }
16902
- var LOG_PATH = path3.join(LOG_DIR, `daemon-${getDateStr()}.log`);
17185
+ var LOG_PATH = path32.join(LOG_DIR, `daemon-${getDateStr()}.log`);
16903
17186
  var DaemonCdpManager2 = class {
16904
17187
  ws = null;
16905
17188
  browserWs = null;
@@ -16972,7 +17255,7 @@ var require_dist = __commonJS({
16972
17255
  * Returns multiple entries if multiple IDE windows are open on same port
16973
17256
  */
16974
17257
  static listAllTargets(port) {
16975
- return new Promise((resolve5) => {
17258
+ return new Promise((resolve7) => {
16976
17259
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
16977
17260
  let data = "";
16978
17261
  res.on("data", (chunk) => data += chunk.toString());
@@ -16988,16 +17271,16 @@ var require_dist = __commonJS({
16988
17271
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
16989
17272
  );
16990
17273
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
16991
- resolve5(mainPages.length > 0 ? mainPages : fallbackPages);
17274
+ resolve7(mainPages.length > 0 ? mainPages : fallbackPages);
16992
17275
  } catch {
16993
- resolve5([]);
17276
+ resolve7([]);
16994
17277
  }
16995
17278
  });
16996
17279
  });
16997
- req.on("error", () => resolve5([]));
17280
+ req.on("error", () => resolve7([]));
16998
17281
  req.setTimeout(2e3, () => {
16999
17282
  req.destroy();
17000
- resolve5([]);
17283
+ resolve7([]);
17001
17284
  });
17002
17285
  });
17003
17286
  }
@@ -17037,7 +17320,7 @@ var require_dist = __commonJS({
17037
17320
  }
17038
17321
  }
17039
17322
  findTargetOnPort(port) {
17040
- return new Promise((resolve5) => {
17323
+ return new Promise((resolve7) => {
17041
17324
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
17042
17325
  let data = "";
17043
17326
  res.on("data", (chunk) => data += chunk.toString());
@@ -17048,7 +17331,7 @@ var require_dist = __commonJS({
17048
17331
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
17049
17332
  );
17050
17333
  if (pages.length === 0) {
17051
- resolve5(targets.find((t) => t.webSocketDebuggerUrl) || null);
17334
+ resolve7(targets.find((t) => t.webSocketDebuggerUrl) || null);
17052
17335
  return;
17053
17336
  }
17054
17337
  const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -17058,24 +17341,24 @@ var require_dist = __commonJS({
17058
17341
  const specific = list.find((t) => t.id === this._targetId);
17059
17342
  if (specific) {
17060
17343
  this._pageTitle = specific.title || "";
17061
- resolve5(specific);
17344
+ resolve7(specific);
17062
17345
  } else {
17063
17346
  this.log(`[CDP] Target ${this._targetId} not found in page list`);
17064
- resolve5(null);
17347
+ resolve7(null);
17065
17348
  }
17066
17349
  return;
17067
17350
  }
17068
17351
  this._pageTitle = list[0]?.title || "";
17069
- resolve5(list[0]);
17352
+ resolve7(list[0]);
17070
17353
  } catch {
17071
- resolve5(null);
17354
+ resolve7(null);
17072
17355
  }
17073
17356
  });
17074
17357
  });
17075
- req.on("error", () => resolve5(null));
17358
+ req.on("error", () => resolve7(null));
17076
17359
  req.setTimeout(2e3, () => {
17077
17360
  req.destroy();
17078
- resolve5(null);
17361
+ resolve7(null);
17079
17362
  });
17080
17363
  });
17081
17364
  }
@@ -17086,7 +17369,7 @@ var require_dist = __commonJS({
17086
17369
  this.extensionProviders = providers;
17087
17370
  }
17088
17371
  connectToTarget(wsUrl) {
17089
- return new Promise((resolve5) => {
17372
+ return new Promise((resolve7) => {
17090
17373
  this.ws = new import_ws2.default(wsUrl);
17091
17374
  this.ws.on("open", async () => {
17092
17375
  this._connected = true;
@@ -17096,17 +17379,17 @@ var require_dist = __commonJS({
17096
17379
  }
17097
17380
  this.connectBrowserWs().catch(() => {
17098
17381
  });
17099
- resolve5(true);
17382
+ resolve7(true);
17100
17383
  });
17101
17384
  this.ws.on("message", (data) => {
17102
17385
  try {
17103
17386
  const msg = JSON.parse(data.toString());
17104
17387
  if (msg.id && this.pending.has(msg.id)) {
17105
- const { resolve: resolve6, reject } = this.pending.get(msg.id);
17388
+ const { resolve: resolve8, reject } = this.pending.get(msg.id);
17106
17389
  this.pending.delete(msg.id);
17107
17390
  this.failureCount = 0;
17108
17391
  if (msg.error) reject(new Error(msg.error.message));
17109
- else resolve6(msg.result);
17392
+ else resolve8(msg.result);
17110
17393
  } else if (msg.method === "Runtime.executionContextCreated") {
17111
17394
  this.contexts.add(msg.params.context.id);
17112
17395
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -17129,7 +17412,7 @@ var require_dist = __commonJS({
17129
17412
  this.ws.on("error", (err) => {
17130
17413
  this.log(`[CDP] WebSocket error: ${err.message}`);
17131
17414
  this._connected = false;
17132
- resolve5(false);
17415
+ resolve7(false);
17133
17416
  });
17134
17417
  });
17135
17418
  }
@@ -17143,7 +17426,7 @@ var require_dist = __commonJS({
17143
17426
  return;
17144
17427
  }
17145
17428
  this.log(`[CDP] Connecting browser WS for target discovery...`);
17146
- await new Promise((resolve5, reject) => {
17429
+ await new Promise((resolve7, reject) => {
17147
17430
  this.browserWs = new import_ws2.default(browserWsUrl);
17148
17431
  this.browserWs.on("open", async () => {
17149
17432
  this._browserConnected = true;
@@ -17153,16 +17436,16 @@ var require_dist = __commonJS({
17153
17436
  } catch (e) {
17154
17437
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
17155
17438
  }
17156
- resolve5();
17439
+ resolve7();
17157
17440
  });
17158
17441
  this.browserWs.on("message", (data) => {
17159
17442
  try {
17160
17443
  const msg = JSON.parse(data.toString());
17161
17444
  if (msg.id && this.browserPending.has(msg.id)) {
17162
- const { resolve: resolve6, reject: reject2 } = this.browserPending.get(msg.id);
17445
+ const { resolve: resolve8, reject: reject2 } = this.browserPending.get(msg.id);
17163
17446
  this.browserPending.delete(msg.id);
17164
17447
  if (msg.error) reject2(new Error(msg.error.message));
17165
- else resolve6(msg.result);
17448
+ else resolve8(msg.result);
17166
17449
  }
17167
17450
  } catch {
17168
17451
  }
@@ -17182,31 +17465,31 @@ var require_dist = __commonJS({
17182
17465
  }
17183
17466
  }
17184
17467
  getBrowserWsUrl() {
17185
- return new Promise((resolve5) => {
17468
+ return new Promise((resolve7) => {
17186
17469
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
17187
17470
  let data = "";
17188
17471
  res.on("data", (chunk) => data += chunk.toString());
17189
17472
  res.on("end", () => {
17190
17473
  try {
17191
17474
  const info = JSON.parse(data);
17192
- resolve5(info.webSocketDebuggerUrl || null);
17475
+ resolve7(info.webSocketDebuggerUrl || null);
17193
17476
  } catch {
17194
- resolve5(null);
17477
+ resolve7(null);
17195
17478
  }
17196
17479
  });
17197
17480
  });
17198
- req.on("error", () => resolve5(null));
17481
+ req.on("error", () => resolve7(null));
17199
17482
  req.setTimeout(3e3, () => {
17200
17483
  req.destroy();
17201
- resolve5(null);
17484
+ resolve7(null);
17202
17485
  });
17203
17486
  });
17204
17487
  }
17205
17488
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
17206
- return new Promise((resolve5, reject) => {
17489
+ return new Promise((resolve7, reject) => {
17207
17490
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
17208
17491
  const id = this.browserMsgId++;
17209
- this.browserPending.set(id, { resolve: resolve5, reject });
17492
+ this.browserPending.set(id, { resolve: resolve7, reject });
17210
17493
  this.browserWs.send(JSON.stringify({ id, method, params }));
17211
17494
  setTimeout(() => {
17212
17495
  if (this.browserPending.has(id)) {
@@ -17246,11 +17529,11 @@ var require_dist = __commonJS({
17246
17529
  }
17247
17530
  // ─── CDP Protocol ────────────────────────────────────────
17248
17531
  sendInternal(method, params = {}, timeoutMs = 15e3) {
17249
- return new Promise((resolve5, reject) => {
17532
+ return new Promise((resolve7, reject) => {
17250
17533
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
17251
17534
  if (this.ws.readyState !== import_ws2.default.OPEN) return reject(new Error("WebSocket not open"));
17252
17535
  const id = this.msgId++;
17253
- this.pending.set(id, { resolve: resolve5, reject });
17536
+ this.pending.set(id, { resolve: resolve7, reject });
17254
17537
  this.ws.send(JSON.stringify({ id, method, params }));
17255
17538
  setTimeout(() => {
17256
17539
  if (this.pending.has(id)) {
@@ -17459,7 +17742,7 @@ var require_dist = __commonJS({
17459
17742
  const browserWs = this.browserWs;
17460
17743
  let msgId = this.browserMsgId;
17461
17744
  const sendWs = (method, params = {}, sessionId) => {
17462
- return new Promise((resolve5, reject) => {
17745
+ return new Promise((resolve7, reject) => {
17463
17746
  const mid = msgId++;
17464
17747
  this.browserMsgId = msgId;
17465
17748
  const handler = (raw) => {
@@ -17468,7 +17751,7 @@ var require_dist = __commonJS({
17468
17751
  if (msg.id === mid) {
17469
17752
  browserWs.removeListener("message", handler);
17470
17753
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
17471
- else resolve5(msg.result);
17754
+ else resolve7(msg.result);
17472
17755
  }
17473
17756
  } catch {
17474
17757
  }
@@ -17642,14 +17925,14 @@ var require_dist = __commonJS({
17642
17925
  if (!ws || ws.readyState !== import_ws2.default.OPEN) {
17643
17926
  throw new Error("CDP not connected");
17644
17927
  }
17645
- return new Promise((resolve5, reject) => {
17928
+ return new Promise((resolve7, reject) => {
17646
17929
  const id = getNextId();
17647
17930
  pendingMap.set(id, {
17648
17931
  resolve: (result) => {
17649
17932
  if (result?.result?.subtype === "error") {
17650
17933
  reject(new Error(result.result.description));
17651
17934
  } else {
17652
- resolve5(result?.result?.value);
17935
+ resolve7(result?.result?.value);
17653
17936
  }
17654
17937
  },
17655
17938
  reject
@@ -18220,10 +18503,10 @@ var require_dist = __commonJS({
18220
18503
  return events;
18221
18504
  }
18222
18505
  };
18223
- var fs22 = __toESM2(require("fs"));
18224
- var path22 = __toESM2(require("path"));
18225
- var os32 = __toESM2(require("os"));
18226
- var HISTORY_DIR = path22.join(os32.homedir(), ".adhdev", "history");
18506
+ var fs32 = __toESM2(require("fs"));
18507
+ var path4 = __toESM2(require("path"));
18508
+ var os5 = __toESM2(require("os"));
18509
+ var HISTORY_DIR = path4.join(os5.homedir(), ".adhdev", "history");
18227
18510
  var RETAIN_DAYS = 30;
18228
18511
  var ChatHistoryWriter = class {
18229
18512
  /** Last seen message count per agent (deduplication) */
@@ -18264,13 +18547,13 @@ var require_dist = __commonJS({
18264
18547
  });
18265
18548
  }
18266
18549
  if (newMessages.length === 0) return;
18267
- const dir = path22.join(HISTORY_DIR, this.sanitize(agentType));
18268
- fs22.mkdirSync(dir, { recursive: true });
18550
+ const dir = path4.join(HISTORY_DIR, this.sanitize(agentType));
18551
+ fs32.mkdirSync(dir, { recursive: true });
18269
18552
  const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
18270
18553
  const filePrefix = instanceId ? `${this.sanitize(instanceId)}_` : "";
18271
- const filePath = path22.join(dir, `${filePrefix}${date5}.jsonl`);
18554
+ const filePath = path4.join(dir, `${filePrefix}${date5}.jsonl`);
18272
18555
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
18273
- fs22.appendFileSync(filePath, lines, "utf-8");
18556
+ fs32.appendFileSync(filePath, lines, "utf-8");
18274
18557
  const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
18275
18558
  if (messages.length < prevCount * 0.5 && prevCount > 3) {
18276
18559
  seenHashes.clear();
@@ -18295,17 +18578,17 @@ var require_dist = __commonJS({
18295
18578
  /** Delete history files older than 30 days */
18296
18579
  async rotateOldFiles() {
18297
18580
  try {
18298
- if (!fs22.existsSync(HISTORY_DIR)) return;
18581
+ if (!fs32.existsSync(HISTORY_DIR)) return;
18299
18582
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
18300
- const agentDirs = fs22.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
18583
+ const agentDirs = fs32.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
18301
18584
  for (const dir of agentDirs) {
18302
- const dirPath = path22.join(HISTORY_DIR, dir.name);
18303
- const files = fs22.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl"));
18585
+ const dirPath = path4.join(HISTORY_DIR, dir.name);
18586
+ const files = fs32.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl"));
18304
18587
  for (const file2 of files) {
18305
- const filePath = path22.join(dirPath, file2);
18306
- const stat = fs22.statSync(filePath);
18588
+ const filePath = path4.join(dirPath, file2);
18589
+ const stat = fs32.statSync(filePath);
18307
18590
  if (stat.mtimeMs < cutoff) {
18308
- fs22.unlinkSync(filePath);
18591
+ fs32.unlinkSync(filePath);
18309
18592
  }
18310
18593
  }
18311
18594
  }
@@ -18320,10 +18603,10 @@ var require_dist = __commonJS({
18320
18603
  function readChatHistory2(agentType, offset = 0, limit = 30, instanceId) {
18321
18604
  try {
18322
18605
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
18323
- const dir = path22.join(HISTORY_DIR, sanitized);
18324
- if (!fs22.existsSync(dir)) return { messages: [], hasMore: false };
18606
+ const dir = path4.join(HISTORY_DIR, sanitized);
18607
+ if (!fs32.existsSync(dir)) return { messages: [], hasMore: false };
18325
18608
  const sanitizedInstance = instanceId?.replace(/[^a-zA-Z0-9_-]/g, "_");
18326
- const files = fs22.readdirSync(dir).filter((f) => {
18609
+ const files = fs32.readdirSync(dir).filter((f) => {
18327
18610
  if (!f.endsWith(".jsonl")) return false;
18328
18611
  if (sanitizedInstance) {
18329
18612
  return f.startsWith(`${sanitizedInstance}_`);
@@ -18334,8 +18617,8 @@ var require_dist = __commonJS({
18334
18617
  const needed = offset + limit + 1;
18335
18618
  for (const file2 of files) {
18336
18619
  if (allMessages.length >= needed) break;
18337
- const filePath = path22.join(dir, file2);
18338
- const content = fs22.readFileSync(filePath, "utf-8");
18620
+ const filePath = path4.join(dir, file2);
18621
+ const content = fs32.readFileSync(filePath, "utf-8");
18339
18622
  const lines = content.trim().split("\n").filter(Boolean);
18340
18623
  for (let i = lines.length - 1; i >= 0; i--) {
18341
18624
  if (allMessages.length >= needed) break;
@@ -18573,6 +18856,15 @@ var require_dist = __commonJS({
18573
18856
  const h = `${msg.role}:${(msg.content || "").slice(0, 100)}`;
18574
18857
  msg.receivedAt = prevByHash.get(h) || now;
18575
18858
  }
18859
+ if (raw.messages?.length > 0) {
18860
+ const hiddenKinds = /* @__PURE__ */ new Set();
18861
+ if (this.settings.showThinking === false) hiddenKinds.add("thought");
18862
+ if (this.settings.showToolCalls === false) hiddenKinds.add("tool");
18863
+ if (this.settings.showTerminal === false) hiddenKinds.add("terminal");
18864
+ if (hiddenKinds.size > 0) {
18865
+ raw.messages = raw.messages.filter((m) => !hiddenKinds.has(m.kind));
18866
+ }
18867
+ }
18576
18868
  this.cachedChat = { ...raw, activeModal };
18577
18869
  this.detectAgentTransitions(raw, now);
18578
18870
  if (raw.messages?.length > 0) {
@@ -19665,9 +19957,9 @@ var require_dist = __commonJS({
19665
19957
  }
19666
19958
  return { success: false, error: "resolveAction script not available for this provider" };
19667
19959
  }
19668
- var fs32 = __toESM2(require("fs"));
19669
- var path32 = __toESM2(require("path"));
19670
- var os4 = __toESM2(require("os"));
19960
+ var fs4 = __toESM2(require("fs"));
19961
+ var path5 = __toESM2(require("path"));
19962
+ var os6 = __toESM2(require("os"));
19671
19963
  async function handleCdpEval(h, args) {
19672
19964
  if (!h.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
19673
19965
  const expression = args?.expression || args?.script;
@@ -19819,21 +20111,21 @@ var require_dist = __commonJS({
19819
20111
  return { success: true, agents };
19820
20112
  }
19821
20113
  function resolveSafePath(requestedPath) {
19822
- const home = os4.homedir();
20114
+ const home = os6.homedir();
19823
20115
  let resolved;
19824
20116
  if (requestedPath.startsWith("~")) {
19825
- resolved = path32.join(home, requestedPath.slice(1));
19826
- } else if (path32.isAbsolute(requestedPath)) {
20117
+ resolved = path5.join(home, requestedPath.slice(1));
20118
+ } else if (path5.isAbsolute(requestedPath)) {
19827
20119
  resolved = requestedPath;
19828
20120
  } else {
19829
- resolved = path32.resolve(requestedPath);
20121
+ resolved = path5.resolve(requestedPath);
19830
20122
  }
19831
20123
  return resolved;
19832
20124
  }
19833
20125
  async function handleFileRead(h, args) {
19834
20126
  try {
19835
20127
  const filePath = resolveSafePath(args?.path);
19836
- const content = fs32.readFileSync(filePath, "utf-8");
20128
+ const content = fs4.readFileSync(filePath, "utf-8");
19837
20129
  return { success: true, content, path: filePath };
19838
20130
  } catch (e) {
19839
20131
  return { success: false, error: e.message };
@@ -19842,8 +20134,8 @@ var require_dist = __commonJS({
19842
20134
  async function handleFileWrite(h, args) {
19843
20135
  try {
19844
20136
  const filePath = resolveSafePath(args?.path);
19845
- fs32.mkdirSync(path32.dirname(filePath), { recursive: true });
19846
- fs32.writeFileSync(filePath, args?.content || "", "utf-8");
20137
+ fs4.mkdirSync(path5.dirname(filePath), { recursive: true });
20138
+ fs4.writeFileSync(filePath, args?.content || "", "utf-8");
19847
20139
  return { success: true, path: filePath };
19848
20140
  } catch (e) {
19849
20141
  return { success: false, error: e.message };
@@ -19852,11 +20144,11 @@ var require_dist = __commonJS({
19852
20144
  async function handleFileList(h, args) {
19853
20145
  try {
19854
20146
  const dirPath = resolveSafePath(args?.path || ".");
19855
- const entries = fs32.readdirSync(dirPath, { withFileTypes: true });
20147
+ const entries = fs4.readdirSync(dirPath, { withFileTypes: true });
19856
20148
  const files = entries.map((e) => ({
19857
20149
  name: e.name,
19858
20150
  type: e.isDirectory() ? "directory" : "file",
19859
- size: e.isFile() ? fs32.statSync(path32.join(dirPath, e.name)).size : void 0
20151
+ size: e.isFile() ? fs4.statSync(path5.join(dirPath, e.name)).size : void 0
19860
20152
  }));
19861
20153
  return { success: true, files, path: dirPath };
19862
20154
  } catch (e) {
@@ -20143,6 +20435,92 @@ var require_dist = __commonJS({
20143
20435
  }
20144
20436
  return { success: false, error: "Failed to save setting" };
20145
20437
  }
20438
+ init_config();
20439
+ init_workspaces();
20440
+ function handleWorkspaceList() {
20441
+ const config2 = loadConfig4();
20442
+ const state = getWorkspaceState(config2);
20443
+ return {
20444
+ success: true,
20445
+ workspaces: state.workspaces,
20446
+ defaultWorkspaceId: state.defaultWorkspaceId,
20447
+ defaultWorkspacePath: state.defaultWorkspacePath,
20448
+ legacyRecentPaths: config2.recentCliWorkspaces || [],
20449
+ activity: getWorkspaceActivity(config2, 25)
20450
+ };
20451
+ }
20452
+ function handleWorkspaceAdd(args) {
20453
+ const rawPath = (args?.path || args?.dir || "").trim();
20454
+ const label = (args?.label || "").trim() || void 0;
20455
+ if (!rawPath) return { success: false, error: "path required" };
20456
+ const config2 = loadConfig4();
20457
+ const result = addWorkspaceEntry(config2, rawPath, label);
20458
+ if ("error" in result) return { success: false, error: result.error };
20459
+ let cfg = appendWorkspaceActivity(result.config, result.entry.path, {});
20460
+ saveConfig2(cfg);
20461
+ const state = getWorkspaceState(cfg);
20462
+ return { success: true, entry: result.entry, ...state, activity: getWorkspaceActivity(cfg, 25) };
20463
+ }
20464
+ function handleWorkspaceRemove(args) {
20465
+ const id = (args?.id || "").trim();
20466
+ if (!id) return { success: false, error: "id required" };
20467
+ const config2 = loadConfig4();
20468
+ const removed = (config2.workspaces || []).find((w) => w.id === id);
20469
+ const result = removeWorkspaceEntry(config2, id);
20470
+ if ("error" in result) return { success: false, error: result.error };
20471
+ let cfg = result.config;
20472
+ if (removed) {
20473
+ cfg = removeActivityForPath(cfg, removed.path);
20474
+ }
20475
+ saveConfig2(cfg);
20476
+ const state = getWorkspaceState(cfg);
20477
+ return { success: true, removedId: id, ...state, activity: getWorkspaceActivity(cfg, 25) };
20478
+ }
20479
+ function handleWorkspaceSetDefault(args) {
20480
+ const clear = args?.clear === true || args?.id === null || args?.id === "";
20481
+ if (clear) {
20482
+ const config22 = loadConfig4();
20483
+ const result2 = setDefaultWorkspaceId(config22, null);
20484
+ if ("error" in result2) return { success: false, error: result2.error };
20485
+ saveConfig2(result2.config);
20486
+ const state2 = getWorkspaceState(result2.config);
20487
+ return {
20488
+ success: true,
20489
+ ...state2,
20490
+ activity: getWorkspaceActivity(result2.config, 25)
20491
+ };
20492
+ }
20493
+ const pathArg = args?.path != null && String(args.path).trim() ? String(args.path).trim() : "";
20494
+ const idArg = args?.id !== void 0 && args?.id !== null && String(args.id).trim() ? String(args.id).trim() : "";
20495
+ if (!pathArg && !idArg) {
20496
+ return { success: false, error: "id or path required (or clear: true)" };
20497
+ }
20498
+ let config2 = loadConfig4();
20499
+ let nextId;
20500
+ if (pathArg) {
20501
+ let w = findWorkspaceByPath(config2, pathArg);
20502
+ if (!w) {
20503
+ const add = addWorkspaceEntry(config2, pathArg);
20504
+ if ("error" in add) return { success: false, error: add.error };
20505
+ config2 = add.config;
20506
+ w = add.entry;
20507
+ }
20508
+ nextId = w.id;
20509
+ } else {
20510
+ nextId = idArg;
20511
+ }
20512
+ const result = setDefaultWorkspaceId(config2, nextId);
20513
+ if ("error" in result) return { success: false, error: result.error };
20514
+ let out = result.config;
20515
+ const ap = getDefaultWorkspacePath(out);
20516
+ if (ap) {
20517
+ out = appendWorkspaceActivity(out, ap, { kind: "default" });
20518
+ }
20519
+ saveConfig2(out);
20520
+ const state = getWorkspaceState(out);
20521
+ return { success: true, ...state, activity: getWorkspaceActivity(out, 25) };
20522
+ }
20523
+ init_workspaces();
20146
20524
  var DaemonCommandHandler = class {
20147
20525
  _ctx;
20148
20526
  _agentStream = null;
@@ -20251,6 +20629,9 @@ var require_dist = __commonJS({
20251
20629
  }
20252
20630
  /** Extract ideType from _targetInstance */
20253
20631
  extractIdeType(args) {
20632
+ if (args?.ideType && this._ctx.cdpManagers.has(args.ideType)) {
20633
+ return args.ideType;
20634
+ }
20254
20635
  if (args?._targetInstance) {
20255
20636
  let raw = args._targetInstance;
20256
20637
  const ideMatch = raw.match(/:ide:(.+)$/);
@@ -20262,8 +20643,19 @@ var require_dist = __commonJS({
20262
20643
  if (this._ctx.instanceIdMap?.has(raw)) {
20263
20644
  return this._ctx.instanceIdMap.get(raw);
20264
20645
  }
20646
+ if (this._ctx.cdpManagers.has(raw)) {
20647
+ return raw;
20648
+ }
20649
+ if (!ideMatch && !cliMatch && !acpMatch) {
20650
+ for (const [key, mgr] of this._ctx.cdpManagers.entries()) {
20651
+ if (mgr.isConnected) return key;
20652
+ }
20653
+ }
20265
20654
  const lastUnderscore = raw.lastIndexOf("_");
20266
- if (lastUnderscore > 0) return raw.substring(0, lastUnderscore);
20655
+ if (lastUnderscore > 0) {
20656
+ const stripped = raw.substring(0, lastUnderscore);
20657
+ if (this._ctx.cdpManagers.has(stripped)) return stripped;
20658
+ }
20267
20659
  return raw;
20268
20660
  }
20269
20661
  return void 0;
@@ -20359,6 +20751,19 @@ var require_dist = __commonJS({
20359
20751
  return { success: false, error: `${cmd} requires bridge-extension (removed)` };
20360
20752
  case "get_recent_workspaces":
20361
20753
  return this.handleGetRecentWorkspaces(args);
20754
+ case "get_cli_history": {
20755
+ const config2 = loadConfig4();
20756
+ return { success: true, history: config2.cliHistory || [] };
20757
+ }
20758
+ case "workspace_list":
20759
+ return handleWorkspaceList();
20760
+ case "workspace_add":
20761
+ return handleWorkspaceAdd(args);
20762
+ case "workspace_remove":
20763
+ return handleWorkspaceRemove(args);
20764
+ case "workspace_set_default":
20765
+ case "workspace_set_active":
20766
+ return handleWorkspaceSetDefault(args);
20362
20767
  // ─── Script manage ───────────────────
20363
20768
  case "refresh_scripts":
20364
20769
  return this.handleRefreshScripts(args);
@@ -20408,10 +20813,18 @@ var require_dist = __commonJS({
20408
20813
  }
20409
20814
  }
20410
20815
  // ─── Misc (kept in handler — too small to extract) ───────
20411
- async handleGetRecentWorkspaces(args) {
20816
+ async handleGetRecentWorkspaces(_args) {
20412
20817
  const config2 = loadConfig4();
20413
20818
  const cliRecent = config2.recentCliWorkspaces || [];
20414
- return { success: true, result: cliRecent };
20819
+ const ws = getWorkspaceState(config2);
20820
+ return {
20821
+ success: true,
20822
+ result: cliRecent,
20823
+ workspaces: ws.workspaces,
20824
+ defaultWorkspaceId: ws.defaultWorkspaceId,
20825
+ defaultWorkspacePath: ws.defaultWorkspacePath,
20826
+ activity: getWorkspaceActivity(config2, 25)
20827
+ };
20415
20828
  }
20416
20829
  async handleRefreshScripts(_args) {
20417
20830
  if (this._ctx.providerLoader) {
@@ -20421,13 +20834,13 @@ var require_dist = __commonJS({
20421
20834
  return { success: false, error: "ProviderLoader not initialized" };
20422
20835
  }
20423
20836
  };
20424
- var import_child_process3 = require("child_process");
20837
+ var import_child_process4 = require("child_process");
20425
20838
  var net = __toESM2(require("net"));
20426
- var os6 = __toESM2(require("os"));
20427
- var path5 = __toESM2(require("path"));
20428
- var fs4 = __toESM2(require("fs"));
20429
- var path4 = __toESM2(require("path"));
20430
- var os5 = __toESM2(require("os"));
20839
+ var os8 = __toESM2(require("os"));
20840
+ var path7 = __toESM2(require("path"));
20841
+ var fs5 = __toESM2(require("fs"));
20842
+ var path6 = __toESM2(require("path"));
20843
+ var os7 = __toESM2(require("os"));
20431
20844
  var ProviderLoader3 = class _ProviderLoader {
20432
20845
  providers = /* @__PURE__ */ new Map();
20433
20846
  builtinDirs;
@@ -20447,10 +20860,10 @@ var require_dist = __commonJS({
20447
20860
  if (options?.builtinDir) {
20448
20861
  this.builtinDirs = Array.isArray(options.builtinDir) ? options.builtinDir : [options.builtinDir];
20449
20862
  } else {
20450
- this.builtinDirs = [path4.resolve(__dirname, "../providers/_builtin")];
20863
+ this.builtinDirs = [path6.resolve(__dirname, "../providers/_builtin")];
20451
20864
  }
20452
- this.userDir = options?.userDir || path4.join(os5.homedir(), ".adhdev", "providers");
20453
- this.upstreamDir = path4.join(this.userDir, ".upstream");
20865
+ this.userDir = options?.userDir || path6.join(os7.homedir(), ".adhdev", "providers");
20866
+ this.upstreamDir = path6.join(this.userDir, ".upstream");
20454
20867
  this.logFn = options?.logFn || LOG5.forComponent("Provider").asLogFn();
20455
20868
  }
20456
20869
  log(msg) {
@@ -20468,19 +20881,19 @@ var require_dist = __commonJS({
20468
20881
  this.providers.clear();
20469
20882
  let builtinCount = 0;
20470
20883
  for (const dir of this.builtinDirs) {
20471
- if (fs4.existsSync(dir)) {
20884
+ if (fs5.existsSync(dir)) {
20472
20885
  builtinCount += this.loadDir(dir);
20473
20886
  }
20474
20887
  }
20475
20888
  this.log(`Loaded ${builtinCount} builtin providers`);
20476
20889
  let upstreamCount = 0;
20477
- if (fs4.existsSync(this.upstreamDir)) {
20890
+ if (fs5.existsSync(this.upstreamDir)) {
20478
20891
  upstreamCount = this.loadDir(this.upstreamDir);
20479
20892
  if (upstreamCount > 0) {
20480
20893
  this.log(`Loaded ${upstreamCount} upstream providers (auto-updated)`);
20481
20894
  }
20482
20895
  }
20483
- if (fs4.existsSync(this.userDir)) {
20896
+ if (fs5.existsSync(this.userDir)) {
20484
20897
  const userCount = this.loadDir(this.userDir, [".upstream"]);
20485
20898
  if (userCount > 0) {
20486
20899
  this.log(`Loaded ${userCount} user custom providers (never auto-updated)`);
@@ -20784,15 +21197,15 @@ var require_dist = __commonJS({
20784
21197
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
20785
21198
  return null;
20786
21199
  }
20787
- const dir = path4.join(providerDir, scriptDir);
20788
- if (!fs4.existsSync(dir)) {
21200
+ const dir = path6.join(providerDir, scriptDir);
21201
+ if (!fs5.existsSync(dir)) {
20789
21202
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
20790
21203
  return null;
20791
21204
  }
20792
21205
  const cached2 = this.scriptsCache.get(dir);
20793
21206
  if (cached2) return cached2;
20794
- const scriptsJs = path4.join(dir, "scripts.js");
20795
- if (fs4.existsSync(scriptsJs)) {
21207
+ const scriptsJs = path6.join(dir, "scripts.js");
21208
+ if (fs5.existsSync(scriptsJs)) {
20796
21209
  try {
20797
21210
  delete require.cache[require.resolve(scriptsJs)];
20798
21211
  const loaded = require(scriptsJs);
@@ -20814,15 +21227,15 @@ var require_dist = __commonJS({
20814
21227
  watch() {
20815
21228
  this.stopWatch();
20816
21229
  const watchDir = (dir) => {
20817
- if (!fs4.existsSync(dir)) {
21230
+ if (!fs5.existsSync(dir)) {
20818
21231
  try {
20819
- fs4.mkdirSync(dir, { recursive: true });
21232
+ fs5.mkdirSync(dir, { recursive: true });
20820
21233
  } catch {
20821
21234
  return;
20822
21235
  }
20823
21236
  }
20824
21237
  try {
20825
- const watcher = fs4.watch(dir, { recursive: true }, (event, filename) => {
21238
+ const watcher = fs5.watch(dir, { recursive: true }, (event, filename) => {
20826
21239
  if (filename?.endsWith(".js") || filename?.endsWith(".json")) {
20827
21240
  this.log(`File changed: ${filename}, reloading...`);
20828
21241
  this.loadAll();
@@ -20872,13 +21285,13 @@ var require_dist = __commonJS({
20872
21285
  */
20873
21286
  async fetchLatest() {
20874
21287
  const https = require("https");
20875
- const { execSync: execSync6 } = require("child_process");
20876
- const metaPath = path4.join(this.upstreamDir, _ProviderLoader.META_FILE);
21288
+ const { execSync: execSync7 } = require("child_process");
21289
+ const metaPath = path6.join(this.upstreamDir, _ProviderLoader.META_FILE);
20877
21290
  let prevEtag = "";
20878
21291
  let prevTimestamp = 0;
20879
21292
  try {
20880
- if (fs4.existsSync(metaPath)) {
20881
- const meta3 = JSON.parse(fs4.readFileSync(metaPath, "utf-8"));
21293
+ if (fs5.existsSync(metaPath)) {
21294
+ const meta3 = JSON.parse(fs5.readFileSync(metaPath, "utf-8"));
20882
21295
  prevEtag = meta3.etag || "";
20883
21296
  prevTimestamp = meta3.timestamp || 0;
20884
21297
  }
@@ -20890,7 +21303,7 @@ var require_dist = __commonJS({
20890
21303
  return { updated: false };
20891
21304
  }
20892
21305
  try {
20893
- const etag = await new Promise((resolve5, reject) => {
21306
+ const etag = await new Promise((resolve7, reject) => {
20894
21307
  const options = {
20895
21308
  method: "HEAD",
20896
21309
  hostname: "github.com",
@@ -20908,7 +21321,7 @@ var require_dist = __commonJS({
20908
21321
  headers: { "User-Agent": "adhdev-launcher" },
20909
21322
  timeout: 1e4
20910
21323
  }, (res2) => {
20911
- resolve5(res2.headers.etag || res2.headers["last-modified"] || "");
21324
+ resolve7(res2.headers.etag || res2.headers["last-modified"] || "");
20912
21325
  });
20913
21326
  req2.on("error", reject);
20914
21327
  req2.on("timeout", () => {
@@ -20917,7 +21330,7 @@ var require_dist = __commonJS({
20917
21330
  });
20918
21331
  req2.end();
20919
21332
  } else {
20920
- resolve5(res.headers.etag || res.headers["last-modified"] || "");
21333
+ resolve7(res.headers.etag || res.headers["last-modified"] || "");
20921
21334
  }
20922
21335
  });
20923
21336
  req.on("error", reject);
@@ -20933,39 +21346,39 @@ var require_dist = __commonJS({
20933
21346
  return { updated: false };
20934
21347
  }
20935
21348
  this.log("Downloading latest providers from GitHub...");
20936
- const tmpTar = path4.join(os5.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
20937
- const tmpExtract = path4.join(os5.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
21349
+ const tmpTar = path6.join(os7.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
21350
+ const tmpExtract = path6.join(os7.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
20938
21351
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
20939
- fs4.mkdirSync(tmpExtract, { recursive: true });
20940
- execSync6(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
20941
- const extracted = fs4.readdirSync(tmpExtract);
21352
+ fs5.mkdirSync(tmpExtract, { recursive: true });
21353
+ execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
21354
+ const extracted = fs5.readdirSync(tmpExtract);
20942
21355
  const rootDir = extracted.find(
20943
- (d) => fs4.statSync(path4.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
21356
+ (d) => fs5.statSync(path6.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
20944
21357
  );
20945
21358
  if (!rootDir) throw new Error("Unexpected tarball structure");
20946
- const sourceDir = path4.join(tmpExtract, rootDir);
21359
+ const sourceDir = path6.join(tmpExtract, rootDir);
20947
21360
  const backupDir = this.upstreamDir + ".bak";
20948
- if (fs4.existsSync(this.upstreamDir)) {
20949
- if (fs4.existsSync(backupDir)) fs4.rmSync(backupDir, { recursive: true, force: true });
20950
- fs4.renameSync(this.upstreamDir, backupDir);
21361
+ if (fs5.existsSync(this.upstreamDir)) {
21362
+ if (fs5.existsSync(backupDir)) fs5.rmSync(backupDir, { recursive: true, force: true });
21363
+ fs5.renameSync(this.upstreamDir, backupDir);
20951
21364
  }
20952
21365
  try {
20953
21366
  this.copyDirRecursive(sourceDir, this.upstreamDir);
20954
21367
  this.writeMeta(metaPath, etag || `ts-${Date.now()}`, Date.now());
20955
- if (fs4.existsSync(backupDir)) fs4.rmSync(backupDir, { recursive: true, force: true });
21368
+ if (fs5.existsSync(backupDir)) fs5.rmSync(backupDir, { recursive: true, force: true });
20956
21369
  } catch (e) {
20957
- if (fs4.existsSync(backupDir)) {
20958
- if (fs4.existsSync(this.upstreamDir)) fs4.rmSync(this.upstreamDir, { recursive: true, force: true });
20959
- fs4.renameSync(backupDir, this.upstreamDir);
21370
+ if (fs5.existsSync(backupDir)) {
21371
+ if (fs5.existsSync(this.upstreamDir)) fs5.rmSync(this.upstreamDir, { recursive: true, force: true });
21372
+ fs5.renameSync(backupDir, this.upstreamDir);
20960
21373
  }
20961
21374
  throw e;
20962
21375
  }
20963
21376
  try {
20964
- fs4.rmSync(tmpTar, { force: true });
21377
+ fs5.rmSync(tmpTar, { force: true });
20965
21378
  } catch {
20966
21379
  }
20967
21380
  try {
20968
- fs4.rmSync(tmpExtract, { recursive: true, force: true });
21381
+ fs5.rmSync(tmpExtract, { recursive: true, force: true });
20969
21382
  } catch {
20970
21383
  }
20971
21384
  const upstreamCount = this.countProviders(this.upstreamDir);
@@ -20981,7 +21394,7 @@ var require_dist = __commonJS({
20981
21394
  downloadFile(url2, destPath) {
20982
21395
  const https = require("https");
20983
21396
  const http3 = require("http");
20984
- return new Promise((resolve5, reject) => {
21397
+ return new Promise((resolve7, reject) => {
20985
21398
  const doRequest = (reqUrl, redirectCount = 0) => {
20986
21399
  if (redirectCount > 5) {
20987
21400
  reject(new Error("Too many redirects"));
@@ -20997,11 +21410,11 @@ var require_dist = __commonJS({
20997
21410
  reject(new Error(`HTTP ${res.statusCode}`));
20998
21411
  return;
20999
21412
  }
21000
- const ws = fs4.createWriteStream(destPath);
21413
+ const ws = fs5.createWriteStream(destPath);
21001
21414
  res.pipe(ws);
21002
21415
  ws.on("finish", () => {
21003
21416
  ws.close();
21004
- resolve5();
21417
+ resolve7();
21005
21418
  });
21006
21419
  ws.on("error", reject);
21007
21420
  });
@@ -21016,22 +21429,22 @@ var require_dist = __commonJS({
21016
21429
  }
21017
21430
  /** Recursive directory copy */
21018
21431
  copyDirRecursive(src, dest) {
21019
- fs4.mkdirSync(dest, { recursive: true });
21020
- for (const entry of fs4.readdirSync(src, { withFileTypes: true })) {
21021
- const srcPath = path4.join(src, entry.name);
21022
- const destPath = path4.join(dest, entry.name);
21432
+ fs5.mkdirSync(dest, { recursive: true });
21433
+ for (const entry of fs5.readdirSync(src, { withFileTypes: true })) {
21434
+ const srcPath = path6.join(src, entry.name);
21435
+ const destPath = path6.join(dest, entry.name);
21023
21436
  if (entry.isDirectory()) {
21024
21437
  this.copyDirRecursive(srcPath, destPath);
21025
21438
  } else {
21026
- fs4.copyFileSync(srcPath, destPath);
21439
+ fs5.copyFileSync(srcPath, destPath);
21027
21440
  }
21028
21441
  }
21029
21442
  }
21030
21443
  /** .meta.json save */
21031
21444
  writeMeta(metaPath, etag, timestamp) {
21032
21445
  try {
21033
- fs4.mkdirSync(path4.dirname(metaPath), { recursive: true });
21034
- fs4.writeFileSync(metaPath, JSON.stringify({
21446
+ fs5.mkdirSync(path6.dirname(metaPath), { recursive: true });
21447
+ fs5.writeFileSync(metaPath, JSON.stringify({
21035
21448
  etag,
21036
21449
  timestamp,
21037
21450
  lastCheck: new Date(timestamp).toISOString(),
@@ -21042,12 +21455,12 @@ var require_dist = __commonJS({
21042
21455
  }
21043
21456
  /** Count provider files (provider.js or provider.json) */
21044
21457
  countProviders(dir) {
21045
- if (!fs4.existsSync(dir)) return 0;
21458
+ if (!fs5.existsSync(dir)) return 0;
21046
21459
  let count = 0;
21047
21460
  const scan = (d) => {
21048
21461
  try {
21049
- for (const entry of fs4.readdirSync(d, { withFileTypes: true })) {
21050
- if (entry.isDirectory()) scan(path4.join(d, entry.name));
21462
+ for (const entry of fs5.readdirSync(d, { withFileTypes: true })) {
21463
+ if (entry.isDirectory()) scan(path6.join(d, entry.name));
21051
21464
  else if (entry.name === "provider.json") count++;
21052
21465
  }
21053
21466
  } catch {
@@ -21144,20 +21557,20 @@ var require_dist = __commonJS({
21144
21557
  const cat = provider2.category;
21145
21558
  const searchRoots = [this.userDir, this.upstreamDir, ...this.builtinDirs];
21146
21559
  for (const root of searchRoots) {
21147
- if (!fs4.existsSync(root)) continue;
21148
- for (const candidate of [path4.join(root, type), path4.join(root, cat, type)]) {
21149
- if (fs4.existsSync(path4.join(candidate, "provider.json"))) return candidate;
21560
+ if (!fs5.existsSync(root)) continue;
21561
+ for (const candidate of [path6.join(root, type), path6.join(root, cat, type)]) {
21562
+ if (fs5.existsSync(path6.join(candidate, "provider.json"))) return candidate;
21150
21563
  }
21151
- const catDir = path4.join(root, cat);
21152
- if (fs4.existsSync(catDir)) {
21564
+ const catDir = path6.join(root, cat);
21565
+ if (fs5.existsSync(catDir)) {
21153
21566
  try {
21154
- for (const entry of fs4.readdirSync(catDir, { withFileTypes: true })) {
21567
+ for (const entry of fs5.readdirSync(catDir, { withFileTypes: true })) {
21155
21568
  if (!entry.isDirectory()) continue;
21156
- const jsonPath = path4.join(catDir, entry.name, "provider.json");
21157
- if (fs4.existsSync(jsonPath)) {
21569
+ const jsonPath = path6.join(catDir, entry.name, "provider.json");
21570
+ if (fs5.existsSync(jsonPath)) {
21158
21571
  try {
21159
- const data = JSON.parse(fs4.readFileSync(jsonPath, "utf-8"));
21160
- if (data.type === type) return path4.join(catDir, entry.name);
21572
+ const data = JSON.parse(fs5.readFileSync(jsonPath, "utf-8"));
21573
+ if (data.type === type) return path6.join(catDir, entry.name);
21161
21574
  } catch {
21162
21575
  }
21163
21576
  }
@@ -21174,8 +21587,8 @@ var require_dist = __commonJS({
21174
21587
  * (template substitution is NOT applied here — scripts.js handles that)
21175
21588
  */
21176
21589
  buildScriptWrappersFromDir(dir) {
21177
- const scriptsJs = path4.join(dir, "scripts.js");
21178
- if (fs4.existsSync(scriptsJs)) {
21590
+ const scriptsJs = path6.join(dir, "scripts.js");
21591
+ if (fs5.existsSync(scriptsJs)) {
21179
21592
  try {
21180
21593
  delete require.cache[require.resolve(scriptsJs)];
21181
21594
  return require(scriptsJs);
@@ -21185,13 +21598,13 @@ var require_dist = __commonJS({
21185
21598
  const toCamel = (name) => name.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
21186
21599
  const result = {};
21187
21600
  try {
21188
- for (const file2 of fs4.readdirSync(dir)) {
21601
+ for (const file2 of fs5.readdirSync(dir)) {
21189
21602
  if (!file2.endsWith(".js")) continue;
21190
21603
  const scriptName = toCamel(file2.replace(".js", ""));
21191
- const filePath = path4.join(dir, file2);
21604
+ const filePath = path6.join(dir, file2);
21192
21605
  result[scriptName] = (..._args) => {
21193
21606
  try {
21194
- return fs4.readFileSync(filePath, "utf-8");
21607
+ return fs5.readFileSync(filePath, "utf-8");
21195
21608
  } catch {
21196
21609
  return "";
21197
21610
  }
@@ -21209,20 +21622,20 @@ var require_dist = __commonJS({
21209
21622
  * Structure: dir/category/agent-name/provider.{json,js}
21210
21623
  */
21211
21624
  loadDir(dir, excludeDirs) {
21212
- if (!fs4.existsSync(dir)) return 0;
21625
+ if (!fs5.existsSync(dir)) return 0;
21213
21626
  let count = 0;
21214
21627
  const scan = (d) => {
21215
21628
  let entries;
21216
21629
  try {
21217
- entries = fs4.readdirSync(d, { withFileTypes: true });
21630
+ entries = fs5.readdirSync(d, { withFileTypes: true });
21218
21631
  } catch {
21219
21632
  return;
21220
21633
  }
21221
21634
  const hasJson = entries.some((e) => e.name === "provider.json");
21222
21635
  if (hasJson) {
21223
- const jsonPath = path4.join(d, "provider.json");
21636
+ const jsonPath = path6.join(d, "provider.json");
21224
21637
  try {
21225
- const raw = fs4.readFileSync(jsonPath, "utf-8");
21638
+ const raw = fs5.readFileSync(jsonPath, "utf-8");
21226
21639
  const mod = JSON.parse(raw);
21227
21640
  if (!mod.type || !mod.name || !mod.category) {
21228
21641
  this.log(`\u26A0 Invalid provider at ${jsonPath}: missing type/name/category`);
@@ -21233,8 +21646,8 @@ var require_dist = __commonJS({
21233
21646
  delete mod.extensionIdPattern_flags;
21234
21647
  }
21235
21648
  const hasCompatibility = Array.isArray(mod.compatibility);
21236
- const scriptsPath = path4.join(d, "scripts.js");
21237
- if (!hasCompatibility && fs4.existsSync(scriptsPath)) {
21649
+ const scriptsPath = path6.join(d, "scripts.js");
21650
+ if (!hasCompatibility && fs5.existsSync(scriptsPath)) {
21238
21651
  try {
21239
21652
  delete require.cache[require.resolve(scriptsPath)];
21240
21653
  const scripts = require(scriptsPath);
@@ -21259,7 +21672,7 @@ var require_dist = __commonJS({
21259
21672
  if (!entry.isDirectory()) continue;
21260
21673
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
21261
21674
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
21262
- scan(path4.join(d, entry.name));
21675
+ scan(path6.join(d, entry.name));
21263
21676
  }
21264
21677
  }
21265
21678
  };
@@ -21336,17 +21749,17 @@ var require_dist = __commonJS({
21336
21749
  throw new Error("No free port found");
21337
21750
  }
21338
21751
  function checkPortFree(port) {
21339
- return new Promise((resolve5) => {
21752
+ return new Promise((resolve7) => {
21340
21753
  const server = net.createServer();
21341
21754
  server.unref();
21342
- server.on("error", () => resolve5(false));
21755
+ server.on("error", () => resolve7(false));
21343
21756
  server.listen(port, "127.0.0.1", () => {
21344
- server.close(() => resolve5(true));
21757
+ server.close(() => resolve7(true));
21345
21758
  });
21346
21759
  });
21347
21760
  }
21348
21761
  async function isCdpActive(port) {
21349
- return new Promise((resolve5) => {
21762
+ return new Promise((resolve7) => {
21350
21763
  const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
21351
21764
  timeout: 2e3
21352
21765
  }, (res) => {
@@ -21355,52 +21768,52 @@ var require_dist = __commonJS({
21355
21768
  res.on("end", () => {
21356
21769
  try {
21357
21770
  const info = JSON.parse(data);
21358
- resolve5(!!info["WebKit-Version"] || !!info["Browser"]);
21771
+ resolve7(!!info["WebKit-Version"] || !!info["Browser"]);
21359
21772
  } catch {
21360
- resolve5(false);
21773
+ resolve7(false);
21361
21774
  }
21362
21775
  });
21363
21776
  });
21364
- req.on("error", () => resolve5(false));
21777
+ req.on("error", () => resolve7(false));
21365
21778
  req.on("timeout", () => {
21366
21779
  req.destroy();
21367
- resolve5(false);
21780
+ resolve7(false);
21368
21781
  });
21369
21782
  });
21370
21783
  }
21371
21784
  async function killIdeProcess(ideId) {
21372
- const plat = os6.platform();
21785
+ const plat = os8.platform();
21373
21786
  const appName = getMacAppIdentifiers()[ideId];
21374
21787
  const winProcesses = getWinProcessNames()[ideId];
21375
21788
  try {
21376
21789
  if (plat === "darwin" && appName) {
21377
21790
  try {
21378
- (0, import_child_process3.execSync)(`osascript -e 'tell application "${appName}" to quit' 2>/dev/null`, {
21791
+ (0, import_child_process4.execSync)(`osascript -e 'tell application "${appName}" to quit' 2>/dev/null`, {
21379
21792
  timeout: 5e3
21380
21793
  });
21381
21794
  } catch {
21382
21795
  try {
21383
- (0, import_child_process3.execSync)(`pkill -f "${appName}" 2>/dev/null`);
21796
+ (0, import_child_process4.execSync)(`pkill -f "${appName}" 2>/dev/null`);
21384
21797
  } catch {
21385
21798
  }
21386
21799
  }
21387
21800
  } else if (plat === "win32" && winProcesses) {
21388
21801
  for (const proc of winProcesses) {
21389
21802
  try {
21390
- (0, import_child_process3.execSync)(`taskkill /IM "${proc}" /F 2>nul`, { timeout: 5e3 });
21803
+ (0, import_child_process4.execSync)(`taskkill /IM "${proc}" /F 2>nul`, { timeout: 5e3 });
21391
21804
  } catch {
21392
21805
  }
21393
21806
  }
21394
21807
  try {
21395
21808
  const exeName = winProcesses[0].replace(".exe", "");
21396
- (0, import_child_process3.execSync)(`powershell -Command "Get-Process -Name '${exeName}' -ErrorAction SilentlyContinue | Stop-Process -Force"`, {
21809
+ (0, import_child_process4.execSync)(`powershell -Command "Get-Process -Name '${exeName}' -ErrorAction SilentlyContinue | Stop-Process -Force"`, {
21397
21810
  timeout: 1e4
21398
21811
  });
21399
21812
  } catch {
21400
21813
  }
21401
21814
  } else {
21402
21815
  try {
21403
- (0, import_child_process3.execSync)(`pkill -f "${ideId}" 2>/dev/null`);
21816
+ (0, import_child_process4.execSync)(`pkill -f "${ideId}" 2>/dev/null`);
21404
21817
  } catch {
21405
21818
  }
21406
21819
  }
@@ -21410,13 +21823,13 @@ var require_dist = __commonJS({
21410
21823
  }
21411
21824
  if (plat === "darwin" && appName) {
21412
21825
  try {
21413
- (0, import_child_process3.execSync)(`pkill -9 -f "${appName}" 2>/dev/null`);
21826
+ (0, import_child_process4.execSync)(`pkill -9 -f "${appName}" 2>/dev/null`);
21414
21827
  } catch {
21415
21828
  }
21416
21829
  } else if (plat === "win32" && winProcesses) {
21417
21830
  for (const proc of winProcesses) {
21418
21831
  try {
21419
- (0, import_child_process3.execSync)(`taskkill /IM "${proc}" /F 2>nul`);
21832
+ (0, import_child_process4.execSync)(`taskkill /IM "${proc}" /F 2>nul`);
21420
21833
  } catch {
21421
21834
  }
21422
21835
  }
@@ -21428,26 +21841,26 @@ var require_dist = __commonJS({
21428
21841
  }
21429
21842
  }
21430
21843
  function isIdeRunning(ideId) {
21431
- const plat = os6.platform();
21844
+ const plat = os8.platform();
21432
21845
  try {
21433
21846
  if (plat === "darwin") {
21434
21847
  const appName = getMacAppIdentifiers()[ideId];
21435
21848
  if (!appName) return false;
21436
- const result = (0, import_child_process3.execSync)(`pgrep -f "${appName}" 2>/dev/null`, { encoding: "utf-8" });
21849
+ const result = (0, import_child_process4.execSync)(`pgrep -f "${appName}" 2>/dev/null`, { encoding: "utf-8" });
21437
21850
  return result.trim().length > 0;
21438
21851
  } else if (plat === "win32") {
21439
21852
  const winProcesses = getWinProcessNames()[ideId];
21440
21853
  if (!winProcesses) return false;
21441
21854
  for (const proc of winProcesses) {
21442
21855
  try {
21443
- const result = (0, import_child_process3.execSync)(`tasklist /FI "IMAGENAME eq ${proc}" /NH 2>nul`, { encoding: "utf-8" });
21856
+ const result = (0, import_child_process4.execSync)(`tasklist /FI "IMAGENAME eq ${proc}" /NH 2>nul`, { encoding: "utf-8" });
21444
21857
  if (result.includes(proc)) return true;
21445
21858
  } catch {
21446
21859
  }
21447
21860
  }
21448
21861
  try {
21449
21862
  const exeName = winProcesses[0].replace(".exe", "");
21450
- const result = (0, import_child_process3.execSync)(
21863
+ const result = (0, import_child_process4.execSync)(
21451
21864
  `powershell -Command "(Get-Process -Name '${exeName}' -ErrorAction SilentlyContinue).Count"`,
21452
21865
  { encoding: "utf-8", timeout: 5e3 }
21453
21866
  );
@@ -21456,7 +21869,7 @@ var require_dist = __commonJS({
21456
21869
  }
21457
21870
  return false;
21458
21871
  } else {
21459
- const result = (0, import_child_process3.execSync)(`pgrep -f "${ideId}" 2>/dev/null`, { encoding: "utf-8" });
21872
+ const result = (0, import_child_process4.execSync)(`pgrep -f "${ideId}" 2>/dev/null`, { encoding: "utf-8" });
21460
21873
  return result.trim().length > 0;
21461
21874
  }
21462
21875
  } catch {
@@ -21464,12 +21877,12 @@ var require_dist = __commonJS({
21464
21877
  }
21465
21878
  }
21466
21879
  function detectCurrentWorkspace(ideId) {
21467
- const plat = os6.platform();
21880
+ const plat = os8.platform();
21468
21881
  if (plat === "darwin") {
21469
21882
  try {
21470
21883
  const appName = getMacAppIdentifiers()[ideId];
21471
21884
  if (!appName) return void 0;
21472
- const result = (0, import_child_process3.execSync)(
21885
+ const result = (0, import_child_process4.execSync)(
21473
21886
  `lsof -c "${appName}" 2>/dev/null | grep cwd | head -1 | awk '{print $NF}'`,
21474
21887
  { encoding: "utf-8", timeout: 3e3 }
21475
21888
  );
@@ -21479,17 +21892,17 @@ var require_dist = __commonJS({
21479
21892
  }
21480
21893
  } else if (plat === "win32") {
21481
21894
  try {
21482
- const fs9 = require("fs");
21895
+ const fs10 = require("fs");
21483
21896
  const appNameMap = getMacAppIdentifiers();
21484
21897
  const appName = appNameMap[ideId];
21485
21898
  if (appName) {
21486
- const storagePath = path5.join(
21487
- process.env.APPDATA || path5.join(os6.homedir(), "AppData", "Roaming"),
21899
+ const storagePath = path7.join(
21900
+ process.env.APPDATA || path7.join(os8.homedir(), "AppData", "Roaming"),
21488
21901
  appName,
21489
21902
  "storage.json"
21490
21903
  );
21491
- if (fs9.existsSync(storagePath)) {
21492
- const data = JSON.parse(fs9.readFileSync(storagePath, "utf-8"));
21904
+ if (fs10.existsSync(storagePath)) {
21905
+ const data = JSON.parse(fs10.readFileSync(storagePath, "utf-8"));
21493
21906
  const workspaces = data?.openedPathsList?.workspaces3 || data?.openedPathsList?.entries || [];
21494
21907
  if (workspaces.length > 0) {
21495
21908
  const recent = workspaces[0];
@@ -21506,7 +21919,7 @@ var require_dist = __commonJS({
21506
21919
  return void 0;
21507
21920
  }
21508
21921
  async function launchWithCdp2(options = {}) {
21509
- const platform7 = os6.platform();
21922
+ const platform8 = os8.platform();
21510
21923
  let targetIde;
21511
21924
  const ides = await detectIDEs3();
21512
21925
  if (options.ideId) {
@@ -21575,9 +21988,9 @@ var require_dist = __commonJS({
21575
21988
  }
21576
21989
  const port = await findFreePort(portPair);
21577
21990
  try {
21578
- if (platform7 === "darwin") {
21991
+ if (platform8 === "darwin") {
21579
21992
  await launchMacOS(targetIde, port, workspace, options.newWindow);
21580
- } else if (platform7 === "win32") {
21993
+ } else if (platform8 === "win32") {
21581
21994
  await launchWindows(targetIde, port, workspace, options.newWindow);
21582
21995
  } else {
21583
21996
  await launchLinux(targetIde, port, workspace, options.newWindow);
@@ -21617,9 +22030,9 @@ var require_dist = __commonJS({
21617
22030
  if (workspace) args.push(workspace);
21618
22031
  if (appName) {
21619
22032
  const openArgs = ["-a", appName, "--args", ...args];
21620
- (0, import_child_process3.spawn)("open", openArgs, { detached: true, stdio: "ignore" }).unref();
22033
+ (0, import_child_process4.spawn)("open", openArgs, { detached: true, stdio: "ignore" }).unref();
21621
22034
  } else if (ide.cliCommand) {
21622
- (0, import_child_process3.spawn)(ide.cliCommand, args, { detached: true, stdio: "ignore" }).unref();
22035
+ (0, import_child_process4.spawn)(ide.cliCommand, args, { detached: true, stdio: "ignore" }).unref();
21623
22036
  } else {
21624
22037
  throw new Error(`No app identifier or CLI for ${ide.displayName}`);
21625
22038
  }
@@ -21645,19 +22058,21 @@ var require_dist = __commonJS({
21645
22058
  const args = ["--remote-debugging-port=" + port];
21646
22059
  if (newWindow) args.push("--new-window");
21647
22060
  if (workspace) args.push(workspace);
21648
- (0, import_child_process3.spawn)(cli, args, { detached: true, stdio: "ignore" }).unref();
22061
+ (0, import_child_process4.spawn)(cli, args, { detached: true, stdio: "ignore" }).unref();
21649
22062
  }
21650
22063
  function getAvailableIdeIds2() {
21651
22064
  return getProviderLoader().getAvailableIdeTypes();
21652
22065
  }
21653
- var fs5 = __toESM2(require("fs"));
21654
- var path6 = __toESM2(require("path"));
21655
- var os7 = __toESM2(require("os"));
21656
- var LOG_DIR2 = process.platform === "darwin" ? path6.join(os7.homedir(), "Library", "Logs", "adhdev") : path6.join(os7.homedir(), ".local", "share", "adhdev", "logs");
22066
+ init_config();
22067
+ init_workspaces();
22068
+ var fs6 = __toESM2(require("fs"));
22069
+ var path8 = __toESM2(require("path"));
22070
+ var os9 = __toESM2(require("os"));
22071
+ var LOG_DIR2 = process.platform === "darwin" ? path8.join(os9.homedir(), "Library", "Logs", "adhdev") : path8.join(os9.homedir(), ".local", "share", "adhdev", "logs");
21657
22072
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
21658
22073
  var MAX_DAYS = 7;
21659
22074
  try {
21660
- fs5.mkdirSync(LOG_DIR2, { recursive: true });
22075
+ fs6.mkdirSync(LOG_DIR2, { recursive: true });
21661
22076
  } catch {
21662
22077
  }
21663
22078
  var SENSITIVE_KEYS = /* @__PURE__ */ new Set([
@@ -21691,19 +22106,19 @@ var require_dist = __commonJS({
21691
22106
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
21692
22107
  }
21693
22108
  var currentDate2 = getDateStr2();
21694
- var currentFile = path6.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
22109
+ var currentFile = path8.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
21695
22110
  var writeCount2 = 0;
21696
22111
  function checkRotation() {
21697
22112
  const today = getDateStr2();
21698
22113
  if (today !== currentDate2) {
21699
22114
  currentDate2 = today;
21700
- currentFile = path6.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
22115
+ currentFile = path8.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
21701
22116
  cleanOldFiles();
21702
22117
  }
21703
22118
  }
21704
22119
  function cleanOldFiles() {
21705
22120
  try {
21706
- const files = fs5.readdirSync(LOG_DIR2).filter((f) => f.startsWith("commands-") && f.endsWith(".jsonl"));
22121
+ const files = fs6.readdirSync(LOG_DIR2).filter((f) => f.startsWith("commands-") && f.endsWith(".jsonl"));
21707
22122
  const cutoff = /* @__PURE__ */ new Date();
21708
22123
  cutoff.setDate(cutoff.getDate() - MAX_DAYS);
21709
22124
  const cutoffStr = cutoff.toISOString().slice(0, 10);
@@ -21711,7 +22126,7 @@ var require_dist = __commonJS({
21711
22126
  const dateMatch = file2.match(/commands-(\d{4}-\d{2}-\d{2})/);
21712
22127
  if (dateMatch && dateMatch[1] < cutoffStr) {
21713
22128
  try {
21714
- fs5.unlinkSync(path6.join(LOG_DIR2, file2));
22129
+ fs6.unlinkSync(path8.join(LOG_DIR2, file2));
21715
22130
  } catch {
21716
22131
  }
21717
22132
  }
@@ -21721,14 +22136,14 @@ var require_dist = __commonJS({
21721
22136
  }
21722
22137
  function checkSize() {
21723
22138
  try {
21724
- const stat = fs5.statSync(currentFile);
22139
+ const stat = fs6.statSync(currentFile);
21725
22140
  if (stat.size > MAX_FILE_SIZE) {
21726
22141
  const backup = currentFile.replace(".jsonl", ".1.jsonl");
21727
22142
  try {
21728
- fs5.unlinkSync(backup);
22143
+ fs6.unlinkSync(backup);
21729
22144
  } catch {
21730
22145
  }
21731
- fs5.renameSync(currentFile, backup);
22146
+ fs6.renameSync(currentFile, backup);
21732
22147
  }
21733
22148
  } catch {
21734
22149
  }
@@ -21753,14 +22168,14 @@ var require_dist = __commonJS({
21753
22168
  ...entry.error ? { err: entry.error } : {},
21754
22169
  ...entry.durationMs !== void 0 ? { ms: entry.durationMs } : {}
21755
22170
  });
21756
- fs5.appendFileSync(currentFile, line + "\n");
22171
+ fs6.appendFileSync(currentFile, line + "\n");
21757
22172
  } catch {
21758
22173
  }
21759
22174
  }
21760
22175
  function getRecentCommands(count = 50) {
21761
22176
  try {
21762
- if (!fs5.existsSync(currentFile)) return [];
21763
- const content = fs5.readFileSync(currentFile, "utf-8");
22177
+ if (!fs6.existsSync(currentFile)) return [];
22178
+ const content = fs6.readFileSync(currentFile, "utf-8");
21764
22179
  const lines = content.trim().split("\n").filter(Boolean);
21765
22180
  return lines.slice(-count).map((line) => {
21766
22181
  try {
@@ -21783,7 +22198,7 @@ var require_dist = __commonJS({
21783
22198
  }
21784
22199
  }
21785
22200
  cleanOldFiles();
21786
- var fs6 = __toESM2(require("fs"));
22201
+ var fs7 = __toESM2(require("fs"));
21787
22202
  var CHAT_COMMANDS = [
21788
22203
  "send_chat",
21789
22204
  "new_chat",
@@ -21853,8 +22268,8 @@ var require_dist = __commonJS({
21853
22268
  if (logs.length > 0) {
21854
22269
  return { success: true, logs, totalBuffered: logs.length };
21855
22270
  }
21856
- if (fs6.existsSync(LOG_PATH)) {
21857
- const content = fs6.readFileSync(LOG_PATH, "utf-8");
22271
+ if (fs7.existsSync(LOG_PATH)) {
22272
+ const content = fs7.readFileSync(LOG_PATH, "utf-8");
21858
22273
  const allLines = content.split("\n");
21859
22274
  const recent = allLines.slice(-count).join("\n");
21860
22275
  return { success: true, logs: recent, totalLines: allLines.length };
@@ -21893,8 +22308,20 @@ var require_dist = __commonJS({
21893
22308
  }
21894
22309
  // ─── IDE launch + CDP connect ───
21895
22310
  case "launch_ide": {
21896
- const launchArgs = { ...args, ideId: args?.ideId || args?.ideType };
21897
- const ideKey = launchArgs.ideId;
22311
+ const ideKey = args?.ideId || args?.ideType;
22312
+ const resolvedWorkspace = resolveIdeLaunchWorkspace(
22313
+ {
22314
+ workspace: args?.workspace,
22315
+ workspaceId: args?.workspaceId,
22316
+ useDefaultWorkspace: args?.useDefaultWorkspace
22317
+ },
22318
+ loadConfig4()
22319
+ );
22320
+ const launchArgs = {
22321
+ ideId: ideKey,
22322
+ workspace: resolvedWorkspace,
22323
+ newWindow: args?.newWindow
22324
+ };
21898
22325
  LOG5.info("LaunchIDE", `target=${ideKey || "auto"}`);
21899
22326
  const result = await launchWithCdp2(launchArgs);
21900
22327
  if (result.success && result.port && result.ideId && !this.deps.cdpManagers.has(result.ideId)) {
@@ -21911,6 +22338,15 @@ var require_dist = __commonJS({
21911
22338
  }
21912
22339
  }
21913
22340
  this.deps.onIdeConnected?.();
22341
+ if (result.success && resolvedWorkspace) {
22342
+ try {
22343
+ saveConfig2(appendWorkspaceActivity(loadConfig4(), resolvedWorkspace, {
22344
+ kind: "ide",
22345
+ agentType: result.ideId
22346
+ }));
22347
+ } catch {
22348
+ }
22349
+ }
21914
22350
  return { success: result.success, ...result };
21915
22351
  }
21916
22352
  // ─── IDE detection ───
@@ -21918,6 +22354,12 @@ var require_dist = __commonJS({
21918
22354
  this.deps.detectedIdes.value = await detectIDEs3();
21919
22355
  return { success: true, ides: this.deps.detectedIdes.value };
21920
22356
  }
22357
+ // ─── Machine Settings ───
22358
+ case "set_machine_nickname": {
22359
+ const nickname = args?.nickname;
22360
+ updateConfig2({ machineNickname: nickname || null });
22361
+ return { success: true };
22362
+ }
21921
22363
  }
21922
22364
  return null;
21923
22365
  }
@@ -21952,8 +22394,9 @@ var require_dist = __commonJS({
21952
22394
  LOG5.info("StopIDE", `IDE stopped: ${ideType}`);
21953
22395
  }
21954
22396
  };
21955
- var os8 = __toESM2(require("os"));
22397
+ var os10 = __toESM2(require("os"));
21956
22398
  init_config();
22399
+ init_workspaces();
21957
22400
  var DaemonStatusReporter2 = class {
21958
22401
  deps;
21959
22402
  log;
@@ -22020,6 +22463,10 @@ var require_dist = __commonJS({
22020
22463
  // (agent-stream polling backward compat)
22021
22464
  updateAgentStreams(_ideType, _streams) {
22022
22465
  }
22466
+ /** Reset P2P dedup hash — forces next send to transmit even if content unchanged */
22467
+ resetP2PHash() {
22468
+ this.lastP2PStatusHash = "";
22469
+ }
22023
22470
  // ─── Core ────────────────────────────────────────
22024
22471
  ts() {
22025
22472
  return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
@@ -22099,18 +22546,26 @@ var require_dist = __commonJS({
22099
22546
  acpConfigOptions: s.acpConfigOptions,
22100
22547
  acpModes: s.acpModes
22101
22548
  }));
22549
+ const cfg = loadConfig4();
22550
+ const wsState = getWorkspaceState(cfg);
22551
+ const memSnap = getHostMemorySnapshot();
22102
22552
  const payload = {
22103
22553
  daemonMode: true,
22104
- machineNickname: loadConfig4().machineNickname || null,
22554
+ machineNickname: cfg.machineNickname || null,
22555
+ workspaces: wsState.workspaces,
22556
+ defaultWorkspaceId: wsState.defaultWorkspaceId,
22557
+ defaultWorkspacePath: wsState.defaultWorkspacePath,
22558
+ workspaceActivity: getWorkspaceActivity(cfg, 15),
22105
22559
  machine: {
22106
- hostname: os8.hostname(),
22107
- platform: os8.platform(),
22108
- arch: os8.arch(),
22109
- cpus: os8.cpus().length,
22110
- totalMem: os8.totalmem(),
22111
- freeMem: os8.freemem(),
22112
- loadavg: os8.loadavg(),
22113
- uptime: os8.uptime()
22560
+ hostname: os10.hostname(),
22561
+ platform: os10.platform(),
22562
+ arch: os10.arch(),
22563
+ cpus: os10.cpus().length,
22564
+ totalMem: memSnap.totalMem,
22565
+ freeMem: memSnap.freeMem,
22566
+ availableMem: memSnap.availableMem,
22567
+ loadavg: os10.loadavg(),
22568
+ uptime: os10.uptime()
22114
22569
  },
22115
22570
  managedIdes,
22116
22571
  managedClis,
@@ -22142,6 +22597,8 @@ var require_dist = __commonJS({
22142
22597
  const wsPayload = {
22143
22598
  daemonMode: true,
22144
22599
  machineNickname: payload.machineNickname,
22600
+ defaultWorkspaceId: wsState.defaultWorkspaceId,
22601
+ workspaceCount: (wsState.workspaces || []).length,
22145
22602
  // managedIdes: server only saves id, type, cdpConnected
22146
22603
  managedIdes: managedIdes.map((ide) => ({
22147
22604
  ideType: ide.ideType,
@@ -22172,7 +22629,7 @@ var require_dist = __commonJS({
22172
22629
  sendP2PPayload(payload) {
22173
22630
  const { timestamp: _ts, system: _sys, ...hashTarget } = payload;
22174
22631
  if (hashTarget.machine) {
22175
- const { freeMem: _f, loadavg: _l, uptime: _u, ...stableMachine } = hashTarget.machine;
22632
+ const { freeMem: _f, availableMem: _a2, loadavg: _l, uptime: _u, ...stableMachine } = hashTarget.machine;
22176
22633
  hashTarget.machine = stableMachine;
22177
22634
  }
22178
22635
  const h = this.simpleHash(JSON.stringify(hashTarget));
@@ -22192,15 +22649,32 @@ var require_dist = __commonJS({
22192
22649
  return h.toString(36);
22193
22650
  }
22194
22651
  };
22195
- var os10 = __toESM2(require("os"));
22196
- var path7 = __toESM2(require("path"));
22652
+ var os12 = __toESM2(require("os"));
22653
+ var path10 = __toESM2(require("path"));
22197
22654
  var crypto4 = __toESM2(require("crypto"));
22198
22655
  var import_chalk4 = __toESM2(require("chalk"));
22199
- var os9 = __toESM2(require("os"));
22200
- var import_child_process4 = require("child_process");
22656
+ var os11 = __toESM2(require("os"));
22657
+ var path9 = __toESM2(require("path"));
22658
+ var import_child_process5 = require("child_process");
22201
22659
  var pty;
22202
22660
  try {
22203
22661
  pty = require("node-pty");
22662
+ if (os11.platform() !== "win32") {
22663
+ try {
22664
+ const fs10 = require("fs");
22665
+ const ptyDir = path9.dirname(require.resolve("node-pty"));
22666
+ const arch3 = os11.arch() === "arm64" ? "darwin-arm64" : "darwin-x64";
22667
+ const helper = path9.join(ptyDir, "prebuilds", arch3, "spawn-helper");
22668
+ if (fs10.existsSync(helper)) {
22669
+ const stat = fs10.statSync(helper);
22670
+ if (!(stat.mode & 73)) {
22671
+ fs10.chmodSync(helper, stat.mode | 493);
22672
+ LOG5.info("CLI", "[node-pty] Fixed spawn-helper permissions");
22673
+ }
22674
+ }
22675
+ } catch {
22676
+ }
22677
+ }
22204
22678
  } catch {
22205
22679
  LOG5.error("CLI", "[ProviderCliAdapter] node-pty not found. Install: npm install node-pty@1.0.0");
22206
22680
  }
@@ -22208,21 +22682,121 @@ var require_dist = __commonJS({
22208
22682
  return str.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][^\x1B]*\x1B\\/g, "");
22209
22683
  }
22210
22684
  function findBinary(name) {
22211
- const isWin = os9.platform() === "win32";
22685
+ const isWin = os11.platform() === "win32";
22212
22686
  try {
22213
22687
  const cmd = isWin ? `where ${name}` : `which ${name}`;
22214
- return (0, import_child_process4.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0].trim();
22688
+ return (0, import_child_process5.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0].trim();
22215
22689
  } catch {
22216
22690
  return isWin ? `${name}.cmd` : name;
22217
22691
  }
22218
22692
  }
22693
+ function isScriptBinary(binaryPath) {
22694
+ if (!path9.isAbsolute(binaryPath)) return false;
22695
+ try {
22696
+ const fs10 = require("fs");
22697
+ const resolved = fs10.realpathSync(binaryPath);
22698
+ const head = Buffer.alloc(8);
22699
+ const fd = fs10.openSync(resolved, "r");
22700
+ fs10.readSync(fd, head, 0, 8, 0);
22701
+ fs10.closeSync(fd);
22702
+ let i = 0;
22703
+ if (head[0] === 239 && head[1] === 187 && head[2] === 191) i = 3;
22704
+ return head[i] === 35 && head[i + 1] === 33;
22705
+ } catch {
22706
+ return false;
22707
+ }
22708
+ }
22709
+ function looksLikeMachOOrElf(filePath) {
22710
+ if (!path9.isAbsolute(filePath)) return false;
22711
+ try {
22712
+ const fs10 = require("fs");
22713
+ const resolved = fs10.realpathSync(filePath);
22714
+ const buf = Buffer.alloc(8);
22715
+ const fd = fs10.openSync(resolved, "r");
22716
+ fs10.readSync(fd, buf, 0, 8, 0);
22717
+ fs10.closeSync(fd);
22718
+ let i = 0;
22719
+ if (buf[0] === 239 && buf[1] === 187 && buf[2] === 191) i = 3;
22720
+ const b = buf.subarray(i);
22721
+ if (b.length < 4) return false;
22722
+ if (b[0] === 127 && b[1] === 69 && b[2] === 76 && b[3] === 70) return true;
22723
+ const le = b.readUInt32LE(0);
22724
+ const be = b.readUInt32BE(0);
22725
+ const magics = [4277009102, 4277009103, 3405691582, 3199925962];
22726
+ return magics.some((m) => m === le || m === be);
22727
+ } catch {
22728
+ return false;
22729
+ }
22730
+ }
22731
+ function shSingleQuote(arg) {
22732
+ if (/^[a-zA-Z0-9@%_+=:,./-]+$/.test(arg)) return arg;
22733
+ return `'${arg.replace(/'/g, `'\\''`)}'`;
22734
+ }
22735
+ function parsePatternEntry(x) {
22736
+ if (x instanceof RegExp) return x;
22737
+ if (x && typeof x === "object" && typeof x.source === "string") {
22738
+ try {
22739
+ const s = x;
22740
+ return new RegExp(s.source, s.flags || "");
22741
+ } catch {
22742
+ return null;
22743
+ }
22744
+ }
22745
+ return null;
22746
+ }
22747
+ function coercePatternArray(raw, fallbacks) {
22748
+ if (!Array.isArray(raw)) return [...fallbacks];
22749
+ const parsed = raw.map(parsePatternEntry).filter((r) => r != null);
22750
+ return parsed.length > 0 ? parsed : [...fallbacks];
22751
+ }
22752
+ var FALLBACK_PROMPT = [
22753
+ /Type your message/i,
22754
+ />\s*$/,
22755
+ /[›➤]\s*$/,
22756
+ /for shortcuts/i,
22757
+ /\?\s*for help/i,
22758
+ /Press enter/i,
22759
+ /^[\s\u2500-\u257f]*>\s*$/m
22760
+ ];
22761
+ var FALLBACK_GENERATING = [
22762
+ /thinking/i,
22763
+ /writing/i,
22764
+ /Claude is/i,
22765
+ /Opus|Sonnet|Haiku/i,
22766
+ /[\u2800-\u28ff]/
22767
+ // Braille spinner blocks
22768
+ ];
22769
+ var FALLBACK_APPROVAL = [
22770
+ /approve/i,
22771
+ /Allow( once)?/i,
22772
+ /\(y\/n\)/i,
22773
+ /\[Y\/n\]/i,
22774
+ /continue\?/i,
22775
+ /Run this command/i
22776
+ ];
22777
+ function defaultCleanOutput(raw, _lastUserInput) {
22778
+ return stripAnsi(raw).trim();
22779
+ }
22780
+ function normalizeCliProviderForRuntime(raw) {
22781
+ const patterns = raw?.patterns || {};
22782
+ return {
22783
+ ...raw,
22784
+ patterns: {
22785
+ prompt: coercePatternArray(patterns.prompt, FALLBACK_PROMPT),
22786
+ generating: coercePatternArray(patterns.generating, FALLBACK_GENERATING),
22787
+ approval: coercePatternArray(patterns.approval, FALLBACK_APPROVAL),
22788
+ ready: coercePatternArray(patterns.ready, [])
22789
+ },
22790
+ cleanOutput: typeof raw?.cleanOutput === "function" ? raw.cleanOutput : defaultCleanOutput
22791
+ };
22792
+ }
22219
22793
  var ProviderCliAdapter = class {
22220
22794
  constructor(provider2, workingDir, extraArgs = []) {
22221
22795
  this.extraArgs = extraArgs;
22222
- this.provider = provider2;
22796
+ this.provider = normalizeCliProviderForRuntime(provider2);
22223
22797
  this.cliType = provider2.type;
22224
22798
  this.cliName = provider2.name;
22225
- this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/, os9.homedir()) : workingDir;
22799
+ this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/, os11.homedir()) : workingDir;
22226
22800
  const t = provider2.timeouts || {};
22227
22801
  this.timeouts = {
22228
22802
  ptyFlush: t.ptyFlush ?? 50,
@@ -22280,20 +22854,25 @@ var require_dist = __commonJS({
22280
22854
  if (!pty) throw new Error("node-pty is not installed");
22281
22855
  const { spawn: spawnConfig } = this.provider;
22282
22856
  const binaryPath = findBinary(spawnConfig.command);
22283
- const isWin = os9.platform() === "win32";
22857
+ const isWin = os11.platform() === "win32";
22284
22858
  const allArgs = [...spawnConfig.args, ...this.extraArgs];
22285
22859
  LOG5.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
22286
22860
  let shellCmd;
22287
22861
  let shellArgs;
22288
- if (spawnConfig.shell) {
22862
+ const useShellUnix = !isWin && (!!spawnConfig.shell || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
22863
+ const useShell = isWin ? !!spawnConfig.shell : useShellUnix;
22864
+ if (useShell) {
22865
+ if (!spawnConfig.shell && !isWin) {
22866
+ LOG5.info("CLI", `[${this.cliType}] Using login shell (script shim or non-native binary)`);
22867
+ }
22289
22868
  shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
22290
- const fullCmd = [binaryPath, ...allArgs].join(" ");
22869
+ const fullCmd = [binaryPath, ...allArgs].map(shSingleQuote).join(" ");
22291
22870
  shellArgs = isWin ? ["/c", fullCmd] : ["-l", "-c", fullCmd];
22292
22871
  } else {
22293
22872
  shellCmd = binaryPath;
22294
22873
  shellArgs = allArgs;
22295
22874
  }
22296
- this.ptyProcess = pty.spawn(shellCmd, shellArgs, {
22875
+ const ptyOpts = {
22297
22876
  name: "xterm-256color",
22298
22877
  cols: 120,
22299
22878
  rows: 40,
@@ -22302,7 +22881,21 @@ var require_dist = __commonJS({
22302
22881
  ...process.env,
22303
22882
  ...spawnConfig.env
22304
22883
  }
22305
- });
22884
+ };
22885
+ try {
22886
+ this.ptyProcess = pty.spawn(shellCmd, shellArgs, ptyOpts);
22887
+ } catch (err) {
22888
+ const msg = err?.message || String(err);
22889
+ if (!isWin && !useShell && /posix_spawn|spawn/i.test(msg)) {
22890
+ LOG5.warn("CLI", `[${this.cliType}] Direct spawn failed (${msg}), retrying via login shell`);
22891
+ shellCmd = process.env.SHELL || "/bin/zsh";
22892
+ const fullCmd = [binaryPath, ...allArgs].map(shSingleQuote).join(" ");
22893
+ shellArgs = ["-l", "-c", fullCmd];
22894
+ this.ptyProcess = pty.spawn(shellCmd, shellArgs, ptyOpts);
22895
+ } else {
22896
+ throw err;
22897
+ }
22898
+ }
22306
22899
  this.ptyProcess.onData((data) => {
22307
22900
  this.handleOutput(data);
22308
22901
  if (this.onPtyDataCallback) {
@@ -22518,6 +23111,7 @@ var require_dist = __commonJS({
22518
23111
  }
22519
23112
  };
22520
23113
  init_config();
23114
+ init_workspaces();
22521
23115
  var crypto3 = __toESM2(require("crypto"));
22522
23116
  var CliProviderInstance = class {
22523
23117
  constructor(provider2, workingDir, cliArgs = [], instanceId) {
@@ -22679,7 +23273,7 @@ var require_dist = __commonJS({
22679
23273
  }
22680
23274
  };
22681
23275
  var import_stream = require("stream");
22682
- var import_child_process5 = require("child_process");
23276
+ var import_child_process6 = require("child_process");
22683
23277
  var import_sdk = (init_acp(), __toCommonJS(acp_exports));
22684
23278
  function flattenContent(content) {
22685
23279
  if (typeof content === "string") return content;
@@ -22996,7 +23590,7 @@ var require_dist = __commonJS({
22996
23590
  this.errorMessage = null;
22997
23591
  this.errorReason = null;
22998
23592
  this.stderrBuffer = [];
22999
- this.process = (0, import_child_process5.spawn)(command, args, {
23593
+ this.process = (0, import_child_process6.spawn)(command, args, {
23000
23594
  cwd: this.workingDir,
23001
23595
  env,
23002
23596
  stdio: ["pipe", "pipe", "pipe"],
@@ -23100,13 +23694,13 @@ var require_dist = __commonJS({
23100
23694
  }
23101
23695
  this.currentStatus = "waiting_approval";
23102
23696
  this.detectStatusTransition();
23103
- const approved = await new Promise((resolve5) => {
23104
- this.permissionResolvers.push(resolve5);
23697
+ const approved = await new Promise((resolve7) => {
23698
+ this.permissionResolvers.push(resolve7);
23105
23699
  setTimeout(() => {
23106
- const idx = this.permissionResolvers.indexOf(resolve5);
23700
+ const idx = this.permissionResolvers.indexOf(resolve7);
23107
23701
  if (idx >= 0) {
23108
23702
  this.permissionResolvers.splice(idx, 1);
23109
- resolve5(false);
23703
+ resolve7(false);
23110
23704
  }
23111
23705
  }, 3e5);
23112
23706
  });
@@ -23574,6 +24168,24 @@ var require_dist = __commonJS({
23574
24168
  const hash2 = require("crypto").createHash("md5").update(require("path").resolve(dir)).digest("hex").slice(0, 8);
23575
24169
  return `${cliType}_${hash2}`;
23576
24170
  }
24171
+ persistRecentDir(cliType, dir) {
24172
+ try {
24173
+ const normalizedType = this.providerLoader.resolveAlias(cliType);
24174
+ const provider2 = this.providerLoader.getByAlias(cliType);
24175
+ const actKind = provider2?.category === "acp" ? "acp" : "cli";
24176
+ let next = loadConfig4();
24177
+ console.log(import_chalk4.default.cyan(` \u{1F4C2} Saving recent workspace: ${dir}`));
24178
+ const recent = next.recentCliWorkspaces || [];
24179
+ if (!recent.includes(dir)) {
24180
+ next = { ...next, recentCliWorkspaces: [dir, ...recent].slice(0, 10) };
24181
+ }
24182
+ next = appendWorkspaceActivity(next, dir, { kind: actKind, agentType: normalizedType });
24183
+ saveConfig2(next);
24184
+ console.log(import_chalk4.default.green(` \u2713 Recent workspace saved: ${dir}`));
24185
+ } catch (e) {
24186
+ console.error(import_chalk4.default.red(` \u2717 Failed to save recent workspace: ${e}`));
24187
+ }
24188
+ }
23577
24189
  createAdapter(cliType, workingDir, cliArgs) {
23578
24190
  const normalizedType = this.providerLoader.resolveAlias(cliType);
23579
24191
  const provider2 = this.providerLoader.getMeta(normalizedType);
@@ -23585,8 +24197,9 @@ var require_dist = __commonJS({
23585
24197
  }
23586
24198
  // ─── Session start/management ──────────────────────────────
23587
24199
  async startSession(cliType, workingDir, cliArgs, initialModel) {
23588
- const trimmed = (workingDir || os10.homedir()).trim();
23589
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) : path7.resolve(trimmed);
24200
+ const trimmed = (workingDir || "").trim();
24201
+ if (!trimmed) throw new Error("working directory required");
24202
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os12.homedir()) : path10.resolve(trimmed);
23590
24203
  const normalizedType = this.providerLoader.resolveAlias(cliType);
23591
24204
  const provider2 = this.providerLoader.getByAlias(cliType);
23592
24205
  const key = crypto4.randomUUID();
@@ -23596,8 +24209,8 @@ var require_dist = __commonJS({
23596
24209
  const spawnCmd = provider2.spawn?.command;
23597
24210
  if (spawnCmd) {
23598
24211
  try {
23599
- const { execSync: execSync6 } = require("child_process");
23600
- execSync6(`which ${spawnCmd}`, { stdio: "ignore" });
24212
+ const { execSync: execSync7 } = require("child_process");
24213
+ execSync7(`which ${spawnCmd}`, { stdio: "ignore" });
23601
24214
  } catch {
23602
24215
  const installInfo = provider2.install || `Install: check ${provider2.displayName || provider2.name} documentation`;
23603
24216
  throw new Error(
@@ -23664,18 +24277,52 @@ ${installInfo}`
23664
24277
  const instanceManager = this.deps.getInstanceManager();
23665
24278
  if (provider2 && instanceManager) {
23666
24279
  const cliInstance = new CliProviderInstance(provider2, resolvedDir, cliArgs, key);
23667
- await instanceManager.addInstance(key, cliInstance, {
23668
- serverConn: this.deps.getServerConn(),
23669
- settings: {},
23670
- onPtyData: (data) => {
23671
- this.deps.getP2p()?.broadcastPtyOutput(key, data);
23672
- }
23673
- });
24280
+ try {
24281
+ await instanceManager.addInstance(key, cliInstance, {
24282
+ serverConn: this.deps.getServerConn(),
24283
+ settings: {},
24284
+ onPtyData: (data) => {
24285
+ this.deps.getP2p()?.broadcastPtyOutput(key, data);
24286
+ }
24287
+ });
24288
+ } catch (spawnErr) {
24289
+ LOG5.error("CLI", `[${cliType}] Spawn failed: ${spawnErr?.message}`);
24290
+ instanceManager.removeInstance(key);
24291
+ throw new Error(`Failed to start ${cliInfo.displayName}: ${spawnErr?.message}`);
24292
+ }
23674
24293
  this.adapters.set(key, cliInstance.getAdapter());
23675
24294
  console.log(import_chalk4.default.green(` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
24295
+ const checkStopped = setInterval(() => {
24296
+ try {
24297
+ const adapter = this.adapters.get(key);
24298
+ if (!adapter) {
24299
+ clearInterval(checkStopped);
24300
+ return;
24301
+ }
24302
+ const status = adapter.getStatus?.();
24303
+ if (status?.status === "stopped" || status?.status === "error") {
24304
+ clearInterval(checkStopped);
24305
+ setTimeout(() => {
24306
+ if (this.adapters.has(key)) {
24307
+ this.adapters.delete(key);
24308
+ this.deps.removeAgentTracking(key);
24309
+ instanceManager.removeInstance(key);
24310
+ LOG5.info("CLI", `\u{1F9F9} Auto-cleaned ${status.status} CLI: ${cliType}`);
24311
+ this.deps.onStatusChange();
24312
+ }
24313
+ }, 5e3);
24314
+ }
24315
+ } catch {
24316
+ }
24317
+ }, 3e3);
23676
24318
  } else {
23677
24319
  const adapter = this.createAdapter(cliType, resolvedDir, cliArgs);
23678
- await adapter.spawn();
24320
+ try {
24321
+ await adapter.spawn();
24322
+ } catch (spawnErr) {
24323
+ LOG5.error("CLI", `[${cliType}] Spawn failed: ${spawnErr?.message}`);
24324
+ throw new Error(`Failed to start ${cliInfo.displayName}: ${spawnErr?.message}`);
24325
+ }
23679
24326
  const serverConn = this.deps.getServerConn();
23680
24327
  if (serverConn && typeof adapter.setServerConn === "function") {
23681
24328
  adapter.setServerConn(serverConn);
@@ -23683,12 +24330,12 @@ ${installInfo}`
23683
24330
  adapter.setOnStatusChange(() => {
23684
24331
  this.deps.onStatusChange();
23685
24332
  const status = adapter.getStatus?.();
23686
- if (status?.status === "stopped") {
24333
+ if (status?.status === "stopped" || status?.status === "error") {
23687
24334
  setTimeout(() => {
23688
24335
  if (this.adapters.get(key) === adapter) {
23689
24336
  this.adapters.delete(key);
23690
24337
  this.deps.removeAgentTracking(key);
23691
- console.log(import_chalk4.default.yellow(` \u{1F9F9} Auto-cleaned stopped CLI: ${adapter.cliType}`));
24338
+ LOG5.info("CLI", `\u{1F9F9} Auto-cleaned ${status.status} CLI: ${adapter.cliType}`);
23692
24339
  this.deps.onStatusChange();
23693
24340
  }
23694
24341
  }, 3e3);
@@ -23712,12 +24359,24 @@ ${installInfo}`
23712
24359
  async stopSession(key) {
23713
24360
  const adapter = this.adapters.get(key);
23714
24361
  if (adapter) {
23715
- adapter.shutdown();
24362
+ try {
24363
+ adapter.shutdown();
24364
+ } catch (e) {
24365
+ LOG5.warn("CLI", `Shutdown error for ${adapter.cliType}: ${e?.message} (force-cleaning)`);
24366
+ }
23716
24367
  this.adapters.delete(key);
23717
24368
  this.deps.removeAgentTracking(key);
23718
24369
  this.deps.getInstanceManager()?.removeInstance(key);
23719
- console.log(import_chalk4.default.yellow(` \u{1F6D1} CLI Agent stopped: ${adapter.cliType} in ${adapter.workingDir}`));
24370
+ LOG5.info("CLI", `\u{1F6D1} Agent stopped: ${adapter.cliType} in ${adapter.workingDir}`);
23720
24371
  this.deps.onStatusChange();
24372
+ } else {
24373
+ const im = this.deps.getInstanceManager();
24374
+ if (im) {
24375
+ im.removeInstance(key);
24376
+ this.deps.removeAgentTracking(key);
24377
+ LOG5.warn("CLI", `\u{1F9F9} Force-removed orphan entry: ${key}`);
24378
+ this.deps.onStatusChange();
24379
+ }
23721
24380
  }
23722
24381
  }
23723
24382
  shutdownAll() {
@@ -23758,8 +24417,28 @@ ${installInfo}`
23758
24417
  switch (cmd) {
23759
24418
  case "launch_cli": {
23760
24419
  const cliType = args?.cliType;
23761
- const defaultedToHome = !args?.dir;
23762
- const dir = args?.dir || os10.homedir();
24420
+ const config2 = loadConfig4();
24421
+ const resolved = resolveLaunchDirectory(
24422
+ {
24423
+ dir: args?.dir,
24424
+ workspaceId: args?.workspaceId,
24425
+ useDefaultWorkspace: args?.useDefaultWorkspace === true,
24426
+ useHome: args?.useHome === true
24427
+ },
24428
+ config2
24429
+ );
24430
+ if (!resolved.ok) {
24431
+ const ws = getWorkspaceState(config2);
24432
+ return {
24433
+ success: false,
24434
+ error: resolved.message,
24435
+ code: resolved.code,
24436
+ workspaces: ws.workspaces,
24437
+ defaultWorkspacePath: ws.defaultWorkspacePath
24438
+ };
24439
+ }
24440
+ const dir = resolved.path;
24441
+ const launchSource = resolved.source;
23763
24442
  if (!cliType) throw new Error("cliType required");
23764
24443
  await this.startSession(cliType, dir, args?.cliArgs, args?.initialModel);
23765
24444
  let newKey = null;
@@ -23768,19 +24447,8 @@ ${installInfo}`
23768
24447
  newKey = k;
23769
24448
  }
23770
24449
  }
23771
- try {
23772
- const config2 = loadConfig4();
23773
- console.log(import_chalk4.default.cyan(` \u{1F4C2} Saving recent workspace: ${dir}`));
23774
- const recent = config2.recentCliWorkspaces || [];
23775
- if (!recent.includes(dir)) {
23776
- const updated = [dir, ...recent].slice(0, 10);
23777
- saveConfig2({ ...config2, recentCliWorkspaces: updated });
23778
- console.log(import_chalk4.default.green(` \u2713 Recent workspace saved: ${dir}`));
23779
- }
23780
- } catch (e) {
23781
- console.error(import_chalk4.default.red(` \u2717 Failed to save recent workspace: ${e}`));
23782
- }
23783
- return { success: true, cliType, dir, id: newKey, defaultedToHome };
24450
+ this.persistRecentDir(cliType, dir);
24451
+ return { success: true, cliType, dir, id: newKey, launchSource };
23784
24452
  }
23785
24453
  case "stop_cli": {
23786
24454
  const cliType = args?.cliType;
@@ -23796,11 +24464,32 @@ ${installInfo}`
23796
24464
  }
23797
24465
  case "restart_session": {
23798
24466
  const cliType = args?.cliType || args?.agentType || args?.ideType;
23799
- const dir = args?.dir || process.cwd();
24467
+ const cfg = loadConfig4();
24468
+ const rdir = resolveLaunchDirectory(
24469
+ {
24470
+ dir: args?.dir,
24471
+ workspaceId: args?.workspaceId,
24472
+ useDefaultWorkspace: args?.useDefaultWorkspace === true,
24473
+ useHome: args?.useHome === true
24474
+ },
24475
+ cfg
24476
+ );
24477
+ if (!rdir.ok) {
24478
+ const ws = getWorkspaceState(cfg);
24479
+ return {
24480
+ success: false,
24481
+ error: rdir.message,
24482
+ code: rdir.code,
24483
+ workspaces: ws.workspaces,
24484
+ defaultWorkspacePath: ws.defaultWorkspacePath
24485
+ };
24486
+ }
24487
+ const dir = rdir.path;
23800
24488
  if (!cliType) throw new Error("cliType required");
23801
24489
  const found = this.findAdapter(cliType, { instanceKey: args?._targetInstance, dir });
23802
24490
  if (found) await this.stopSession(found.key);
23803
24491
  await this.startSession(cliType, dir);
24492
+ this.persistRecentDir(cliType, dir);
23804
24493
  return { success: true, restarted: true };
23805
24494
  }
23806
24495
  case "agent_command": {
@@ -24428,12 +25117,12 @@ ${installInfo}`
24428
25117
  this.eventListeners = [];
24429
25118
  }
24430
25119
  };
24431
- var fs7 = __toESM2(require("fs"));
24432
- var path8 = __toESM2(require("path"));
24433
- var os11 = __toESM2(require("os"));
24434
- var import_child_process6 = require("child_process");
25120
+ var fs8 = __toESM2(require("fs"));
25121
+ var path11 = __toESM2(require("path"));
25122
+ var os13 = __toESM2(require("os"));
25123
+ var import_child_process7 = require("child_process");
24435
25124
  var import_os3 = require("os");
24436
- var ARCHIVE_PATH = path8.join(os11.homedir(), ".adhdev", "version-history.json");
25125
+ var ARCHIVE_PATH = path11.join(os13.homedir(), ".adhdev", "version-history.json");
24437
25126
  var MAX_ENTRIES_PER_PROVIDER = 20;
24438
25127
  var VersionArchive2 = class {
24439
25128
  history = {};
@@ -24442,8 +25131,8 @@ ${installInfo}`
24442
25131
  }
24443
25132
  load() {
24444
25133
  try {
24445
- if (fs7.existsSync(ARCHIVE_PATH)) {
24446
- this.history = JSON.parse(fs7.readFileSync(ARCHIVE_PATH, "utf-8"));
25134
+ if (fs8.existsSync(ARCHIVE_PATH)) {
25135
+ this.history = JSON.parse(fs8.readFileSync(ARCHIVE_PATH, "utf-8"));
24447
25136
  }
24448
25137
  } catch {
24449
25138
  this.history = {};
@@ -24480,15 +25169,15 @@ ${installInfo}`
24480
25169
  }
24481
25170
  save() {
24482
25171
  try {
24483
- fs7.mkdirSync(path8.dirname(ARCHIVE_PATH), { recursive: true });
24484
- fs7.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
25172
+ fs8.mkdirSync(path11.dirname(ARCHIVE_PATH), { recursive: true });
25173
+ fs8.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
24485
25174
  } catch {
24486
25175
  }
24487
25176
  }
24488
25177
  };
24489
25178
  function runCommand(cmd, timeout = 1e4) {
24490
25179
  try {
24491
- return (0, import_child_process6.execSync)(cmd, {
25180
+ return (0, import_child_process7.execSync)(cmd, {
24492
25181
  encoding: "utf-8",
24493
25182
  timeout,
24494
25183
  stdio: ["pipe", "pipe", "pipe"]
@@ -24520,19 +25209,19 @@ ${installInfo}`
24520
25209
  function checkPathExists2(paths) {
24521
25210
  for (const p of paths) {
24522
25211
  if (p.includes("*")) {
24523
- const home = os11.homedir();
24524
- const resolved = p.replace(/\*/g, home.split(path8.sep).pop() || "");
24525
- if (fs7.existsSync(resolved)) return resolved;
25212
+ const home = os13.homedir();
25213
+ const resolved = p.replace(/\*/g, home.split(path11.sep).pop() || "");
25214
+ if (fs8.existsSync(resolved)) return resolved;
24526
25215
  } else {
24527
- if (fs7.existsSync(p)) return p;
25216
+ if (fs8.existsSync(p)) return p;
24528
25217
  }
24529
25218
  }
24530
25219
  return null;
24531
25220
  }
24532
25221
  function getMacAppVersion(appPath) {
24533
25222
  if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
24534
- const plistPath = path8.join(appPath, "Contents", "Info.plist");
24535
- if (!fs7.existsSync(plistPath)) return null;
25223
+ const plistPath = path11.join(appPath, "Contents", "Info.plist");
25224
+ if (!fs8.existsSync(plistPath)) return null;
24536
25225
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
24537
25226
  return raw || null;
24538
25227
  }
@@ -24557,8 +25246,8 @@ ${installInfo}`
24557
25246
  const cliBin = provider2.cli ? findBinary2(provider2.cli) : null;
24558
25247
  let resolvedBin = cliBin;
24559
25248
  if (!resolvedBin && appPath && currentOs === "darwin") {
24560
- const bundled = path8.join(appPath, "Contents", "Resources", "app", "bin", provider2.cli || "");
24561
- if (provider2.cli && fs7.existsSync(bundled)) resolvedBin = bundled;
25249
+ const bundled = path11.join(appPath, "Contents", "Resources", "app", "bin", provider2.cli || "");
25250
+ if (provider2.cli && fs8.existsSync(bundled)) resolvedBin = bundled;
24562
25251
  }
24563
25252
  info.installed = !!(appPath || resolvedBin);
24564
25253
  info.path = appPath || null;
@@ -24595,9 +25284,9 @@ ${installInfo}`
24595
25284
  return results;
24596
25285
  }
24597
25286
  var http2 = __toESM2(require("http"));
24598
- var fs8 = __toESM2(require("fs"));
24599
- var path9 = __toESM2(require("path"));
24600
- var os12 = __toESM2(require("os"));
25287
+ var fs9 = __toESM2(require("fs"));
25288
+ var path12 = __toESM2(require("path"));
25289
+ var os14 = __toESM2(require("os"));
24601
25290
  function generateFiles(type, name, category, opts = {}) {
24602
25291
  const { cdpPorts, cli, processName, installPath, binary, extensionId, version: version2 = "0.1" } = opts;
24603
25292
  if (category === "cli" || category === "acp") {
@@ -24996,8 +25685,8 @@ async (params) => {
24996
25685
  }
24997
25686
  getEndpointList() {
24998
25687
  return this.routes.map((r) => {
24999
- const path10 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
25000
- return `${r.method.padEnd(5)} ${path10}`;
25688
+ const path13 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
25689
+ return `${r.method.padEnd(5)} ${path13}`;
25001
25690
  });
25002
25691
  }
25003
25692
  async start(port = DEV_SERVER_PORT) {
@@ -25028,15 +25717,15 @@ async (params) => {
25028
25717
  this.json(res, 500, { error: e.message });
25029
25718
  }
25030
25719
  });
25031
- return new Promise((resolve5, reject) => {
25720
+ return new Promise((resolve7, reject) => {
25032
25721
  this.server.listen(port, "127.0.0.1", () => {
25033
25722
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
25034
- resolve5();
25723
+ resolve7();
25035
25724
  });
25036
25725
  this.server.on("error", (e) => {
25037
25726
  if (e.code === "EADDRINUSE") {
25038
25727
  this.log(`Port ${port} in use, skipping dev server`);
25039
- resolve5();
25728
+ resolve7();
25040
25729
  } else {
25041
25730
  reject(e);
25042
25731
  }
@@ -25119,20 +25808,20 @@ async (params) => {
25119
25808
  child.stderr?.on("data", (d) => {
25120
25809
  stderr += d.toString().slice(0, 2e3);
25121
25810
  });
25122
- await new Promise((resolve5) => {
25811
+ await new Promise((resolve7) => {
25123
25812
  const timer = setTimeout(() => {
25124
25813
  child.kill();
25125
- resolve5();
25814
+ resolve7();
25126
25815
  }, 3e3);
25127
25816
  child.on("exit", () => {
25128
25817
  clearTimeout(timer);
25129
- resolve5();
25818
+ resolve7();
25130
25819
  });
25131
25820
  child.stdout?.once("data", () => {
25132
25821
  setTimeout(() => {
25133
25822
  child.kill();
25134
25823
  clearTimeout(timer);
25135
- resolve5();
25824
+ resolve7();
25136
25825
  }, 500);
25137
25826
  });
25138
25827
  });
@@ -25342,12 +26031,12 @@ async (params) => {
25342
26031
  // ─── DevConsole SPA ───
25343
26032
  getConsoleDistDir() {
25344
26033
  const candidates = [
25345
- path9.resolve(__dirname, "../../web-devconsole/dist"),
25346
- path9.resolve(__dirname, "../../../web-devconsole/dist"),
25347
- path9.join(process.cwd(), "packages/web-devconsole/dist")
26034
+ path12.resolve(__dirname, "../../web-devconsole/dist"),
26035
+ path12.resolve(__dirname, "../../../web-devconsole/dist"),
26036
+ path12.join(process.cwd(), "packages/web-devconsole/dist")
25348
26037
  ];
25349
26038
  for (const dir of candidates) {
25350
- if (fs8.existsSync(path9.join(dir, "index.html"))) return dir;
26039
+ if (fs9.existsSync(path12.join(dir, "index.html"))) return dir;
25351
26040
  }
25352
26041
  return null;
25353
26042
  }
@@ -25357,9 +26046,9 @@ async (params) => {
25357
26046
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
25358
26047
  return;
25359
26048
  }
25360
- const htmlPath = path9.join(distDir, "index.html");
26049
+ const htmlPath = path12.join(distDir, "index.html");
25361
26050
  try {
25362
- const html = fs8.readFileSync(htmlPath, "utf-8");
26051
+ const html = fs9.readFileSync(htmlPath, "utf-8");
25363
26052
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
25364
26053
  res.end(html);
25365
26054
  } catch (e) {
@@ -25382,15 +26071,15 @@ async (params) => {
25382
26071
  this.json(res, 404, { error: "Not found" });
25383
26072
  return;
25384
26073
  }
25385
- const safePath = path9.normalize(pathname).replace(/^\.\.\//, "");
25386
- const filePath = path9.join(distDir, safePath);
26074
+ const safePath = path12.normalize(pathname).replace(/^\.\.\//, "");
26075
+ const filePath = path12.join(distDir, safePath);
25387
26076
  if (!filePath.startsWith(distDir)) {
25388
26077
  this.json(res, 403, { error: "Forbidden" });
25389
26078
  return;
25390
26079
  }
25391
26080
  try {
25392
- const content = fs8.readFileSync(filePath);
25393
- const ext = path9.extname(filePath);
26081
+ const content = fs9.readFileSync(filePath);
26082
+ const ext = path12.extname(filePath);
25394
26083
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
25395
26084
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
25396
26085
  res.end(content);
@@ -25489,26 +26178,26 @@ async (params) => {
25489
26178
  const provider2 = this.providerLoader.getMeta(type);
25490
26179
  if (!provider2) return null;
25491
26180
  const cat = provider2.category;
25492
- const builtinDir = this.providerLoader.builtinDir || path9.resolve(__dirname, "../providers/_builtin");
25493
- const userDir = path9.join(os12.homedir(), ".adhdev", "providers");
26181
+ const builtinDir = this.providerLoader.builtinDir || path12.resolve(__dirname, "../providers/_builtin");
26182
+ const userDir = path12.join(os14.homedir(), ".adhdev", "providers");
25494
26183
  const directCandidates = [
25495
- path9.join(userDir, type),
25496
- path9.join(builtinDir, cat, type),
25497
- path9.join(builtinDir, type)
26184
+ path12.join(userDir, type),
26185
+ path12.join(builtinDir, cat, type),
26186
+ path12.join(builtinDir, type)
25498
26187
  ];
25499
26188
  for (const d of directCandidates) {
25500
- if (fs8.existsSync(path9.join(d, "provider.json"))) return d;
26189
+ if (fs9.existsSync(path12.join(d, "provider.json"))) return d;
25501
26190
  }
25502
- const catDir = path9.join(builtinDir, cat);
25503
- if (fs8.existsSync(catDir)) {
26191
+ const catDir = path12.join(builtinDir, cat);
26192
+ if (fs9.existsSync(catDir)) {
25504
26193
  try {
25505
- for (const entry of fs8.readdirSync(catDir, { withFileTypes: true })) {
26194
+ for (const entry of fs9.readdirSync(catDir, { withFileTypes: true })) {
25506
26195
  if (!entry.isDirectory()) continue;
25507
- const jsonPath = path9.join(catDir, entry.name, "provider.json");
25508
- if (fs8.existsSync(jsonPath)) {
26196
+ const jsonPath = path12.join(catDir, entry.name, "provider.json");
26197
+ if (fs9.existsSync(jsonPath)) {
25509
26198
  try {
25510
- const data = JSON.parse(fs8.readFileSync(jsonPath, "utf-8"));
25511
- if (data.type === type) return path9.join(catDir, entry.name);
26199
+ const data = JSON.parse(fs9.readFileSync(jsonPath, "utf-8"));
26200
+ if (data.type === type) return path12.join(catDir, entry.name);
25512
26201
  } catch {
25513
26202
  }
25514
26203
  }
@@ -25528,14 +26217,14 @@ async (params) => {
25528
26217
  const files = [];
25529
26218
  const scan = (d, prefix) => {
25530
26219
  try {
25531
- for (const entry of fs8.readdirSync(d, { withFileTypes: true })) {
26220
+ for (const entry of fs9.readdirSync(d, { withFileTypes: true })) {
25532
26221
  if (entry.name.startsWith(".") || entry.name.endsWith(".bak")) continue;
25533
26222
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
25534
26223
  if (entry.isDirectory()) {
25535
26224
  files.push({ path: rel, size: 0, type: "dir" });
25536
- scan(path9.join(d, entry.name), rel);
26225
+ scan(path12.join(d, entry.name), rel);
25537
26226
  } else {
25538
- const stat = fs8.statSync(path9.join(d, entry.name));
26227
+ const stat = fs9.statSync(path12.join(d, entry.name));
25539
26228
  files.push({ path: rel, size: stat.size, type: "file" });
25540
26229
  }
25541
26230
  }
@@ -25558,16 +26247,16 @@ async (params) => {
25558
26247
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
25559
26248
  return;
25560
26249
  }
25561
- const fullPath = path9.resolve(dir, path9.normalize(filePath));
26250
+ const fullPath = path12.resolve(dir, path12.normalize(filePath));
25562
26251
  if (!fullPath.startsWith(dir)) {
25563
26252
  this.json(res, 403, { error: "Forbidden" });
25564
26253
  return;
25565
26254
  }
25566
- if (!fs8.existsSync(fullPath) || fs8.statSync(fullPath).isDirectory()) {
26255
+ if (!fs9.existsSync(fullPath) || fs9.statSync(fullPath).isDirectory()) {
25567
26256
  this.json(res, 404, { error: `File not found: ${filePath}` });
25568
26257
  return;
25569
26258
  }
25570
- const content = fs8.readFileSync(fullPath, "utf-8");
26259
+ const content = fs9.readFileSync(fullPath, "utf-8");
25571
26260
  this.json(res, 200, { type, path: filePath, content, lines: content.split("\n").length });
25572
26261
  }
25573
26262
  /** POST /api/providers/:type/file — write a file { path, content } */
@@ -25583,15 +26272,15 @@ async (params) => {
25583
26272
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
25584
26273
  return;
25585
26274
  }
25586
- const fullPath = path9.resolve(dir, path9.normalize(filePath));
26275
+ const fullPath = path12.resolve(dir, path12.normalize(filePath));
25587
26276
  if (!fullPath.startsWith(dir)) {
25588
26277
  this.json(res, 403, { error: "Forbidden" });
25589
26278
  return;
25590
26279
  }
25591
26280
  try {
25592
- if (fs8.existsSync(fullPath)) fs8.copyFileSync(fullPath, fullPath + ".bak");
25593
- fs8.mkdirSync(path9.dirname(fullPath), { recursive: true });
25594
- fs8.writeFileSync(fullPath, content, "utf-8");
26281
+ if (fs9.existsSync(fullPath)) fs9.copyFileSync(fullPath, fullPath + ".bak");
26282
+ fs9.mkdirSync(path12.dirname(fullPath), { recursive: true });
26283
+ fs9.writeFileSync(fullPath, content, "utf-8");
25595
26284
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
25596
26285
  this.providerLoader.reload();
25597
26286
  this.json(res, 200, { saved: true, path: filePath, chars: content.length });
@@ -25607,9 +26296,9 @@ async (params) => {
25607
26296
  return;
25608
26297
  }
25609
26298
  for (const name of ["scripts.js", "provider.json"]) {
25610
- const p = path9.join(dir, name);
25611
- if (fs8.existsSync(p)) {
25612
- const source = fs8.readFileSync(p, "utf-8");
26299
+ const p = path12.join(dir, name);
26300
+ if (fs9.existsSync(p)) {
26301
+ const source = fs9.readFileSync(p, "utf-8");
25613
26302
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
25614
26303
  return;
25615
26304
  }
@@ -25628,11 +26317,11 @@ async (params) => {
25628
26317
  this.json(res, 404, { error: `Provider not found: ${type}` });
25629
26318
  return;
25630
26319
  }
25631
- const target = fs8.existsSync(path9.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
25632
- const targetPath = path9.join(dir, target);
26320
+ const target = fs9.existsSync(path12.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
26321
+ const targetPath = path12.join(dir, target);
25633
26322
  try {
25634
- if (fs8.existsSync(targetPath)) fs8.copyFileSync(targetPath, targetPath + ".bak");
25635
- fs8.writeFileSync(targetPath, source, "utf-8");
26323
+ if (fs9.existsSync(targetPath)) fs9.copyFileSync(targetPath, targetPath + ".bak");
26324
+ fs9.writeFileSync(targetPath, source, "utf-8");
25636
26325
  this.log(`Saved provider: ${targetPath} (${source.length} chars)`);
25637
26326
  this.providerLoader.reload();
25638
26327
  this.json(res, 200, { saved: true, path: targetPath, chars: source.length });
@@ -25647,18 +26336,18 @@ async (params) => {
25647
26336
  return;
25648
26337
  }
25649
26338
  let scriptsPath = "";
25650
- const directScripts = path9.join(dir, "scripts.js");
25651
- if (fs8.existsSync(directScripts)) {
26339
+ const directScripts = path12.join(dir, "scripts.js");
26340
+ if (fs9.existsSync(directScripts)) {
25652
26341
  scriptsPath = directScripts;
25653
26342
  } else {
25654
- const scriptsDir = path9.join(dir, "scripts");
25655
- if (fs8.existsSync(scriptsDir)) {
25656
- const versions = fs8.readdirSync(scriptsDir).filter((d) => {
25657
- return fs8.statSync(path9.join(scriptsDir, d)).isDirectory();
26343
+ const scriptsDir = path12.join(dir, "scripts");
26344
+ if (fs9.existsSync(scriptsDir)) {
26345
+ const versions = fs9.readdirSync(scriptsDir).filter((d) => {
26346
+ return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
25658
26347
  }).sort().reverse();
25659
26348
  for (const ver of versions) {
25660
- const p = path9.join(scriptsDir, ver, "scripts.js");
25661
- if (fs8.existsSync(p)) {
26349
+ const p = path12.join(scriptsDir, ver, "scripts.js");
26350
+ if (fs9.existsSync(p)) {
25662
26351
  scriptsPath = p;
25663
26352
  break;
25664
26353
  }
@@ -25670,7 +26359,7 @@ async (params) => {
25670
26359
  return;
25671
26360
  }
25672
26361
  try {
25673
- const source = fs8.readFileSync(scriptsPath, "utf-8");
26362
+ const source = fs9.readFileSync(scriptsPath, "utf-8");
25674
26363
  const hints = {};
25675
26364
  const funcRegex = /module\.exports\.(\w+)\s*=\s*function\s+\w+\s*\(params\)/g;
25676
26365
  let match;
@@ -25814,14 +26503,14 @@ async (params) => {
25814
26503
  child.stderr?.on("data", (d) => {
25815
26504
  stderr += d.toString();
25816
26505
  });
25817
- await new Promise((resolve5) => {
26506
+ await new Promise((resolve7) => {
25818
26507
  const timer = setTimeout(() => {
25819
26508
  child.kill();
25820
- resolve5();
26509
+ resolve7();
25821
26510
  }, timeout);
25822
26511
  child.on("exit", () => {
25823
26512
  clearTimeout(timer);
25824
- resolve5();
26513
+ resolve7();
25825
26514
  });
25826
26515
  });
25827
26516
  const elapsed = Date.now() - start;
@@ -25871,26 +26560,26 @@ async (params) => {
25871
26560
  }
25872
26561
  let targetDir;
25873
26562
  if (location === "user") {
25874
- targetDir = path9.join(os12.homedir(), ".adhdev", "providers", type);
26563
+ targetDir = path12.join(os14.homedir(), ".adhdev", "providers", type);
25875
26564
  } else {
25876
- const builtinDir = path9.resolve(__dirname, "../providers/_builtin");
25877
- targetDir = path9.join(builtinDir, category, type);
26565
+ const builtinDir = path12.resolve(__dirname, "../providers/_builtin");
26566
+ targetDir = path12.join(builtinDir, category, type);
25878
26567
  }
25879
- const jsonPath = path9.join(targetDir, "provider.json");
25880
- if (fs8.existsSync(jsonPath)) {
26568
+ const jsonPath = path12.join(targetDir, "provider.json");
26569
+ if (fs9.existsSync(jsonPath)) {
25881
26570
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
25882
26571
  return;
25883
26572
  }
25884
26573
  try {
25885
26574
  const result = generateFiles(type, name, category, { cdpPorts, cli, processName, installPath, binary, extensionId, version: version2 });
25886
- fs8.mkdirSync(targetDir, { recursive: true });
25887
- fs8.writeFileSync(jsonPath, result["provider.json"], "utf-8");
26575
+ fs9.mkdirSync(targetDir, { recursive: true });
26576
+ fs9.writeFileSync(jsonPath, result["provider.json"], "utf-8");
25888
26577
  const createdFiles = ["provider.json"];
25889
26578
  if (result.files) {
25890
26579
  for (const [relPath, content] of Object.entries(result.files)) {
25891
- const fullPath = path9.join(targetDir, relPath);
25892
- fs8.mkdirSync(path9.dirname(fullPath), { recursive: true });
25893
- fs8.writeFileSync(fullPath, content, "utf-8");
26580
+ const fullPath = path12.join(targetDir, relPath);
26581
+ fs9.mkdirSync(path12.dirname(fullPath), { recursive: true });
26582
+ fs9.writeFileSync(fullPath, content, "utf-8");
25894
26583
  createdFiles.push(relPath);
25895
26584
  }
25896
26585
  }
@@ -26725,24 +27414,24 @@ async (params) => {
26725
27414
  }
26726
27415
  this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "loading_reference", message: `\uB808\uD37C\uB7F0\uC2A4 \uC2A4\uD06C\uB9BD\uD2B8 \uB85C\uB4DC \uC911 (${reference})...` } });
26727
27416
  let referenceScripts = {};
26728
- const builtinDir = this.providerLoader.builtinDir || path9.resolve(__dirname, "../providers/_builtin");
26729
- const refDir = path9.join(builtinDir, "ide", reference);
26730
- if (fs8.existsSync(refDir)) {
26731
- const scriptsDir = path9.join(refDir, "scripts");
26732
- if (fs8.existsSync(scriptsDir)) {
26733
- const versions = fs8.readdirSync(scriptsDir).filter((d) => {
27417
+ const builtinDir = this.providerLoader.builtinDir || path12.resolve(__dirname, "../providers/_builtin");
27418
+ const refDir = path12.join(builtinDir, "ide", reference);
27419
+ if (fs9.existsSync(refDir)) {
27420
+ const scriptsDir = path12.join(refDir, "scripts");
27421
+ if (fs9.existsSync(scriptsDir)) {
27422
+ const versions = fs9.readdirSync(scriptsDir).filter((d) => {
26734
27423
  try {
26735
- return fs8.statSync(path9.join(scriptsDir, d)).isDirectory();
27424
+ return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
26736
27425
  } catch {
26737
27426
  return false;
26738
27427
  }
26739
27428
  }).sort().reverse();
26740
27429
  if (versions.length > 0) {
26741
- const latestDir = path9.join(scriptsDir, versions[0]);
26742
- for (const file2 of fs8.readdirSync(latestDir)) {
27430
+ const latestDir = path12.join(scriptsDir, versions[0]);
27431
+ for (const file2 of fs9.readdirSync(latestDir)) {
26743
27432
  if (file2.endsWith(".js")) {
26744
27433
  try {
26745
- referenceScripts[file2] = fs8.readFileSync(path9.join(latestDir, file2), "utf-8");
27434
+ referenceScripts[file2] = fs9.readFileSync(path12.join(latestDir, file2), "utf-8");
26746
27435
  } catch {
26747
27436
  }
26748
27437
  }
@@ -26751,16 +27440,16 @@ async (params) => {
26751
27440
  }
26752
27441
  }
26753
27442
  const prompt = this.buildAutoImplPrompt(type, provider2, providerDir, functions, domContext, referenceScripts);
26754
- const tmpDir = path9.join(os12.tmpdir(), "adhdev-autoimpl");
26755
- if (!fs8.existsSync(tmpDir)) fs8.mkdirSync(tmpDir, { recursive: true });
26756
- const promptFile = path9.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
26757
- fs8.writeFileSync(promptFile, prompt, "utf-8");
27443
+ const tmpDir = path12.join(os14.tmpdir(), "adhdev-autoimpl");
27444
+ if (!fs9.existsSync(tmpDir)) fs9.mkdirSync(tmpDir, { recursive: true });
27445
+ const promptFile = path12.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
27446
+ fs9.writeFileSync(promptFile, prompt, "utf-8");
26758
27447
  this.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
26759
27448
  const agentProvider = this.providerLoader.resolve(agent) || this.providerLoader.getMeta(agent);
26760
27449
  const spawn3 = agentProvider?.spawn;
26761
27450
  if (!spawn3?.command) {
26762
27451
  try {
26763
- fs8.unlinkSync(promptFile);
27452
+ fs9.unlinkSync(promptFile);
26764
27453
  } catch {
26765
27454
  }
26766
27455
  this.json(res, 400, { error: `Agent '${agent}' has no spawn config. Select a CLI provider with a spawn configuration.` });
@@ -26861,7 +27550,7 @@ async (params) => {
26861
27550
  } catch {
26862
27551
  }
26863
27552
  try {
26864
- fs8.unlinkSync(promptFile);
27553
+ fs9.unlinkSync(promptFile);
26865
27554
  } catch {
26866
27555
  }
26867
27556
  this.log(`Auto-implement (ACP) ${success2 ? "completed" : "failed"}: ${type} (exit: ${code})`);
@@ -26917,12 +27606,12 @@ async (params) => {
26917
27606
  } else {
26918
27607
  args = [...baseArgs];
26919
27608
  }
26920
- const { execSync: execSync6 } = await import("child_process");
27609
+ const { execSync: execSync7 } = await import("child_process");
26921
27610
  try {
26922
- execSync6(`which ${command}`, { stdio: "pipe" });
27611
+ execSync7(`which ${command}`, { stdio: "pipe" });
26923
27612
  } catch {
26924
27613
  try {
26925
- fs8.unlinkSync(promptFile);
27614
+ fs9.unlinkSync(promptFile);
26926
27615
  } catch {
26927
27616
  }
26928
27617
  this.json(res, 400, { error: `Agent binary '${command}' not found on PATH. Install it first: ${agentProvider?.install || "check provider docs"}` });
@@ -26978,7 +27667,7 @@ async (params) => {
26978
27667
  } catch {
26979
27668
  }
26980
27669
  try {
26981
- fs8.unlinkSync(promptFile);
27670
+ fs9.unlinkSync(promptFile);
26982
27671
  } catch {
26983
27672
  }
26984
27673
  this.log(`Auto-implement ${success2 ? "completed" : "failed"}: ${type} (exit: ${code})`);
@@ -27008,23 +27697,23 @@ async (params) => {
27008
27697
  lines.push("## Current Target Files");
27009
27698
  lines.push("These are the files you need to EDIT. They contain TODO stubs \u2014 replace them with working implementations.");
27010
27699
  lines.push("");
27011
- const scriptsDir = path9.join(providerDir, "scripts");
27012
- if (fs8.existsSync(scriptsDir)) {
27013
- const versions = fs8.readdirSync(scriptsDir).filter((d) => {
27700
+ const scriptsDir = path12.join(providerDir, "scripts");
27701
+ if (fs9.existsSync(scriptsDir)) {
27702
+ const versions = fs9.readdirSync(scriptsDir).filter((d) => {
27014
27703
  try {
27015
- return fs8.statSync(path9.join(scriptsDir, d)).isDirectory();
27704
+ return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
27016
27705
  } catch {
27017
27706
  return false;
27018
27707
  }
27019
27708
  }).sort().reverse();
27020
27709
  if (versions.length > 0) {
27021
- const vDir = path9.join(scriptsDir, versions[0]);
27710
+ const vDir = path12.join(scriptsDir, versions[0]);
27022
27711
  lines.push(`Scripts version directory: \`${vDir}\``);
27023
27712
  lines.push("");
27024
- for (const file2 of fs8.readdirSync(vDir)) {
27713
+ for (const file2 of fs9.readdirSync(vDir)) {
27025
27714
  if (file2.endsWith(".js")) {
27026
27715
  try {
27027
- const content = fs8.readFileSync(path9.join(vDir, file2), "utf-8");
27716
+ const content = fs9.readFileSync(path12.join(vDir, file2), "utf-8");
27028
27717
  lines.push(`### \`${file2}\``);
27029
27718
  lines.push("```javascript");
27030
27719
  lines.push(content);
@@ -27095,7 +27784,7 @@ async (params) => {
27095
27784
  lines.push("## Required Return Format");
27096
27785
  lines.push("| Function | Return JSON |");
27097
27786
  lines.push("|---|---|");
27098
- lines.push("| readChat | `{ id, status, title, messages: [{role, content, index}], inputContent, activeModal }` |");
27787
+ lines.push("| readChat | `{ id, status, title, messages: [{role, content, index, kind?, meta?}], inputContent, activeModal }` \u2014 optional `kind`: standard, thought, tool, terminal; optional `meta`: e.g. `{ label, isRunning }` for dashboard |");
27099
27788
  lines.push("| sendMessage | `{ sent: false, needsTypeAndSend: true, selector }` |");
27100
27789
  lines.push("| resolveAction | `{ resolved: true/false, clicked? }` |");
27101
27790
  lines.push("| listSessions | `{ sessions: [{ id, title, active, index }] }` |");
@@ -27219,20 +27908,20 @@ data: ${JSON.stringify(msg.data)}
27219
27908
  res.end(JSON.stringify(data, null, 2));
27220
27909
  }
27221
27910
  async readBody(req) {
27222
- return new Promise((resolve5) => {
27911
+ return new Promise((resolve7) => {
27223
27912
  let body = "";
27224
27913
  req.on("data", (chunk) => body += chunk);
27225
27914
  req.on("end", () => {
27226
27915
  try {
27227
- resolve5(JSON.parse(body));
27916
+ resolve7(JSON.parse(body));
27228
27917
  } catch {
27229
- resolve5({});
27918
+ resolve7({});
27230
27919
  }
27231
27920
  });
27232
27921
  });
27233
27922
  }
27234
27923
  };
27235
- var import_child_process7 = require("child_process");
27924
+ var import_child_process8 = require("child_process");
27236
27925
  var EXTENSION_CATALOG = [
27237
27926
  // AI Agent extensions
27238
27927
  {
@@ -27309,7 +27998,7 @@ data: ${JSON.stringify(msg.data)}
27309
27998
  function isExtensionInstalled(ide, marketplaceId) {
27310
27999
  if (!ide.cliCommand) return false;
27311
28000
  try {
27312
- const result = (0, import_child_process7.execSync)(`"${ide.cliCommand}" --list-extensions`, {
28001
+ const result = (0, import_child_process8.execSync)(`"${ide.cliCommand}" --list-extensions`, {
27313
28002
  encoding: "utf-8",
27314
28003
  timeout: 15e3,
27315
28004
  stdio: ["pipe", "pipe", "pipe"]
@@ -27346,12 +28035,12 @@ data: ${JSON.stringify(msg.data)}
27346
28035
  const res = await fetch(extension.vsixUrl);
27347
28036
  if (res.ok) {
27348
28037
  const buffer = Buffer.from(await res.arrayBuffer());
27349
- const fs9 = await import("fs");
27350
- fs9.writeFileSync(vsixPath, buffer);
27351
- return new Promise((resolve5) => {
28038
+ const fs10 = await import("fs");
28039
+ fs10.writeFileSync(vsixPath, buffer);
28040
+ return new Promise((resolve7) => {
27352
28041
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
27353
- (0, import_child_process7.exec)(cmd, { timeout: 6e4 }, (error48, _stdout, stderr) => {
27354
- resolve5({
28042
+ (0, import_child_process8.exec)(cmd, { timeout: 6e4 }, (error48, _stdout, stderr) => {
28043
+ resolve7({
27355
28044
  extensionId: extension.id,
27356
28045
  marketplaceId: extension.marketplaceId,
27357
28046
  success: !error48,
@@ -27364,11 +28053,11 @@ data: ${JSON.stringify(msg.data)}
27364
28053
  } catch (e) {
27365
28054
  }
27366
28055
  }
27367
- return new Promise((resolve5) => {
28056
+ return new Promise((resolve7) => {
27368
28057
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
27369
- (0, import_child_process7.exec)(cmd, { timeout: 6e4 }, (error48, stdout, stderr) => {
28058
+ (0, import_child_process8.exec)(cmd, { timeout: 6e4 }, (error48, stdout, stderr) => {
27370
28059
  if (error48) {
27371
- resolve5({
28060
+ resolve7({
27372
28061
  extensionId: extension.id,
27373
28062
  marketplaceId: extension.marketplaceId,
27374
28063
  success: false,
@@ -27376,7 +28065,7 @@ data: ${JSON.stringify(msg.data)}
27376
28065
  error: stderr || error48.message
27377
28066
  });
27378
28067
  } else {
27379
- resolve5({
28068
+ resolve7({
27380
28069
  extensionId: extension.id,
27381
28070
  marketplaceId: extension.marketplaceId,
27382
28071
  success: true,
@@ -27403,7 +28092,7 @@ data: ${JSON.stringify(msg.data)}
27403
28092
  if (!ide.cliCommand) return false;
27404
28093
  try {
27405
28094
  const args = workspacePath ? `"${workspacePath}"` : "";
27406
- (0, import_child_process7.exec)(`"${ide.cliCommand}" ${args}`, { timeout: 1e4 });
28095
+ (0, import_child_process8.exec)(`"${ide.cliCommand}" ${args}`, { timeout: 1e4 });
27407
28096
  return true;
27408
28097
  } catch {
27409
28098
  return false;
@@ -27762,7 +28451,7 @@ var init_server_connection = __esm({
27762
28451
  });
27763
28452
 
27764
28453
  // src/daemon-p2p.ts
27765
- var fs, import_daemon_core2, path, os, logFile, log, logDebug, DaemonP2PSender;
28454
+ var fs, import_daemon_core2, path, os, import_node_module, import_meta, esmRequire, logFile, log, logDebug, DaemonP2PSender;
27766
28455
  var init_daemon_p2p = __esm({
27767
28456
  "src/daemon-p2p.ts"() {
27768
28457
  "use strict";
@@ -27770,6 +28459,9 @@ var init_daemon_p2p = __esm({
27770
28459
  import_daemon_core2 = __toESM(require_dist());
27771
28460
  path = __toESM(require("path"));
27772
28461
  os = __toESM(require("os"));
28462
+ import_node_module = require("module");
28463
+ import_meta = {};
28464
+ esmRequire = (0, import_node_module.createRequire)(import_meta.url);
27773
28465
  logFile = path.join(os.tmpdir(), "adhdev_daemon_p2p.log");
27774
28466
  log = (msg) => {
27775
28467
  import_daemon_core2.LOG.info("P2P", `[${(/* @__PURE__ */ new Date()).toISOString()}] [P2P] ${msg}`);
@@ -27814,12 +28506,13 @@ var init_daemon_p2p = __esm({
27814
28506
  /** node-datachannel Load */
27815
28507
  tryLoadNodeDatachannel() {
27816
28508
  try {
27817
- this.nodeDatachannel = require("node-datachannel");
28509
+ this.nodeDatachannel = esmRequire("node-datachannel");
27818
28510
  const keys = Object.keys(this.nodeDatachannel).join(",");
27819
28511
  log(`node-datachannel loaded \u2705 (keys: ${keys.substring(0, 100)})`);
27820
28512
  return;
27821
28513
  } catch (e) {
27822
- log(`node-datachannel not found: ${e?.message}`);
28514
+ log(`node-datachannel not found: ${e?.message}
28515
+ ${e?.stack || ""}`);
27823
28516
  }
27824
28517
  const platform2 = process.platform;
27825
28518
  const arch = process.arch;
@@ -27838,10 +28531,10 @@ var init_daemon_p2p = __esm({
27838
28531
  fs.mkdirSync(targetDir, { recursive: true });
27839
28532
  fs.copyFileSync(prebuildPath, targetPath);
27840
28533
  try {
27841
- delete require.cache[require.resolve("node-datachannel")];
28534
+ delete esmRequire.cache[esmRequire.resolve("node-datachannel")];
27842
28535
  } catch {
27843
28536
  }
27844
- this.nodeDatachannel = require("node-datachannel");
28537
+ this.nodeDatachannel = esmRequire("node-datachannel");
27845
28538
  log(`node-datachannel loaded from prebuild (${prebuildKey}) \u2705`);
27846
28539
  return;
27847
28540
  }
@@ -27917,7 +28610,7 @@ var init_daemon_p2p = __esm({
27917
28610
  token = config2.connectionToken || "";
27918
28611
  } catch {
27919
28612
  }
27920
- const http = require("https");
28613
+ const http = esmRequire("https");
27921
28614
  const data = await new Promise((resolve, reject) => {
27922
28615
  const req = http.get(`${serverUrl}/api/v1/turn/credentials`, {
27923
28616
  headers: { "Authorization": `Bearer ${token}` }
@@ -28015,14 +28708,27 @@ var init_daemon_p2p = __esm({
28015
28708
  converted.push(url2);
28016
28709
  } else if ((url2.startsWith("turn:") || url2.startsWith("turns:")) && server.username && server.credential) {
28017
28710
  const cleanUrl = url2.split("?")[0];
28018
- const parts = cleanUrl.split(":");
28019
- converted.push(`${parts[0]}:${parts[1]}:${parts[2] || "3478"}:${server.username}:${server.credential}`);
28711
+ const transport = url2.includes("transport=tcp") ? "tcp" : "udp";
28712
+ const isTls = url2.startsWith("turns:");
28713
+ const parts = cleanUrl.replace(/^turns?:/, "").split(":");
28714
+ const hostname4 = parts[0];
28715
+ const port = parseInt(parts[1]) || (isTls ? 5349 : 3478);
28716
+ let relayType = "TurnUdp";
28717
+ if (isTls) relayType = "TurnTls";
28718
+ else if (transport === "tcp") relayType = "TurnTcp";
28719
+ converted.push({
28720
+ hostname: hostname4,
28721
+ port,
28722
+ username: server.username,
28723
+ password: server.credential,
28724
+ relayType
28725
+ });
28020
28726
  }
28021
28727
  }
28022
28728
  }
28023
28729
  if (converted.length > 0) {
28024
28730
  iceServers = converted;
28025
- const hasTurn = converted.some((s) => s.startsWith("turn"));
28731
+ const hasTurn = converted.some((s) => typeof s === "object");
28026
28732
  log(`ICE servers from auth: ${converted.length} (TURN: ${hasTurn ? "\u2705" : "\u274C"})`);
28027
28733
  }
28028
28734
  }
@@ -28046,17 +28752,18 @@ var init_daemon_p2p = __esm({
28046
28752
  const timeout = setTimeout(() => {
28047
28753
  const peer = this.peers.get(pid);
28048
28754
  if (peer?.state === "connecting") {
28049
- log(`connection timeout (15s) for peer ${pid}`);
28755
+ log(`connection timeout (30s) for peer ${pid}`);
28050
28756
  peer.state = "failed";
28051
28757
  this.notifyStateChange();
28052
28758
  }
28053
- }, 15e3);
28759
+ }, 3e4);
28054
28760
  try {
28055
28761
  pc.onLocalDescription((sdp, type) => {
28056
28762
  log(`onLocalDescription for peer ${pid}: type=${type}`);
28057
28763
  this.serverConn.sendMessage("p2p_offer", { sdp, type, peerId: pid });
28058
28764
  });
28059
28765
  pc.onLocalCandidate((candidate, mid) => {
28766
+ log(`onLocalCandidate for peer ${pid}: ${candidate.substring(0, 80)}`);
28060
28767
  this.serverConn.sendMessage("p2p_ice", { candidate, mid, peerId: pid });
28061
28768
  });
28062
28769
  pc.onStateChange((pcState) => {
@@ -28401,6 +29108,10 @@ var init_daemon_p2p = __esm({
28401
29108
  log(`p2p_answer for unknown peer ${peerId} \u2014 ignoring`);
28402
29109
  return;
28403
29110
  }
29111
+ if (peer.remoteDescriptionSet) {
29112
+ log(`p2p_answer ignored: already applied for peer ${peerId} (duplicate relay)`);
29113
+ return;
29114
+ }
28404
29115
  const pcState = peer.pc.state();
28405
29116
  if (pcState === "closed" || pcState === "failed") {
28406
29117
  log(`p2p_answer ignored: peer ${peerId} PC state is ${pcState}`);
@@ -28433,11 +29144,13 @@ var init_daemon_p2p = __esm({
28433
29144
  }
28434
29145
  const peer = this.peers.get(peerId);
28435
29146
  if (peer?.pc && payload.candidate) {
29147
+ log(`p2p_ice received from peer ${peerId}: ${String(payload.candidate).substring(0, 80)}`);
28436
29148
  if (!peer.remoteDescriptionSet) {
28437
29149
  peer.pendingCandidates.push({
28438
29150
  candidate: payload.candidate,
28439
29151
  mid: payload.mid || payload.sdpMid || "0"
28440
29152
  });
29153
+ log(`Queued ICE candidate (remoteDesc not set yet), queue size: ${peer.pendingCandidates.length}`);
28441
29154
  } else {
28442
29155
  try {
28443
29156
  peer.pc.addRemoteCandidate(payload.candidate, payload.mid || payload.sdpMid || "0");
@@ -28445,6 +29158,8 @@ var init_daemon_p2p = __esm({
28445
29158
  log(`ICE candidate error for peer ${peerId}: ${e?.message}`);
28446
29159
  }
28447
29160
  }
29161
+ } else {
29162
+ log(`p2p_ice ignored: peer=${!!peer}, pc=${!!peer?.pc}, candidate=${!!payload.candidate}`);
28448
29163
  }
28449
29164
  return;
28450
29165
  }
@@ -28865,8 +29580,10 @@ var init_adhdev_daemon = __esm({
28865
29580
  this.p2p.onStateChange((state) => {
28866
29581
  if (state === "connected") {
28867
29582
  import_daemon_core4.LOG.info("P2P", "Peer connected \u2192 sending immediate full status report");
29583
+ this.statusReporter?.resetP2PHash();
28868
29584
  this.statusReporter?.sendUnifiedStatusReport().catch((e) => import_daemon_core4.LOG.warn("P2P", `Immediate status report failed: ${e?.message}`));
28869
29585
  setTimeout(() => {
29586
+ this.statusReporter?.resetP2PHash();
28870
29587
  this.statusReporter?.sendUnifiedStatusReport().catch(() => {
28871
29588
  });
28872
29589
  }, 2e3);
@@ -28998,6 +29715,7 @@ var init_adhdev_daemon = __esm({
28998
29715
  "open_recent",
28999
29716
  "get_commands",
29000
29717
  "get_recent_workspaces",
29718
+ "get_cli_history",
29001
29719
  "open_panel",
29002
29720
  "open_file",
29003
29721
  "create_terminal",
@@ -29054,6 +29772,7 @@ var init_adhdev_daemon = __esm({
29054
29772
  return;
29055
29773
  }
29056
29774
  const result = await this.components.router.execute(cmd, args, source);
29775
+ if (cmd.startsWith("workspace_")) this.statusReporter?.throttledReport();
29057
29776
  this.sendResult(msg, result.success, result);
29058
29777
  } catch (e) {
29059
29778
  console.error(import_chalk.default.red(` \u2717 Command failed: ${e.message}`));
@@ -29085,7 +29804,9 @@ var init_adhdev_daemon = __esm({
29085
29804
  return { success: true, history };
29086
29805
  }
29087
29806
  }
29088
- return await this.components.router.execute(cmdType, data, "p2p");
29807
+ const routed = await this.components.router.execute(cmdType, data, "p2p");
29808
+ if (cmdType.startsWith("workspace_")) this.statusReporter?.throttledReport();
29809
+ return routed;
29089
29810
  } catch (e) {
29090
29811
  (0, import_daemon_core4.logCommand)({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd: cmdType, source: "p2p", success: false, error: e.message, durationMs: Date.now() - cmdStart });
29091
29812
  return { success: false, error: e.message };
@@ -29146,9 +29867,16 @@ var init_adhdev_daemon = __esm({
29146
29867
  }
29147
29868
  return null;
29148
29869
  }
29149
- /** Return CDP manager for specific IDE */
29870
+ /** Return CDP manager for specific IDE (exact match first, then prefix match for multi-window keys) */
29150
29871
  getCdpFor(ideType) {
29151
- return this.components?.cdpManagers.get(ideType.toLowerCase()) || null;
29872
+ if (!this.components) return null;
29873
+ const key = ideType.toLowerCase();
29874
+ const exact = this.components.cdpManagers.get(key);
29875
+ if (exact) return exact;
29876
+ for (const [k, m] of this.components.cdpManagers.entries()) {
29877
+ if (k.startsWith(key + "_") && m.isConnected) return m;
29878
+ }
29879
+ return null;
29152
29880
  }
29153
29881
  };
29154
29882
  }
@@ -29693,7 +30421,7 @@ program.name("adhdev").description("\u{1F9A6} ADHDev \u2014 Agent Dashboard Hub
29693
30421
  program.command("setup").description("Run the interactive setup wizard (detect IDEs, login)").option("-f, --force", "Force re-run setup even if already configured").action(async (options) => {
29694
30422
  await runWizard({ force: options.force });
29695
30423
  });
29696
- program.command("launch [target]").description("Launch IDE with CDP or start CLI agent (e.g. cursor, gemini, claude)").option("-w, --workspace <path>", "Workspace/folder to open").option("-n, --new-window", "Open in a new window").option("-d, --dir <path>", "Working directory for CLI agent", process.cwd()).action(async (targetArg, options) => {
30424
+ program.command("launch [target]").description("Launch IDE with CDP or start CLI agent (e.g. cursor, gemini, claude)").option("-w, --workspace <path>", "Workspace directory to open").option("-n, --new-window", "Open in a new window").option("-d, --dir <path>", "Working directory for CLI agent", process.cwd()).action(async (targetArg, options) => {
29697
30425
  const resolvedType = targetArg ? _cliProviderLoader.resolveAlias(targetArg.toLowerCase()) : null;
29698
30426
  const resolvedProvider = resolvedType ? _cliProviderLoader.get(resolvedType) : null;
29699
30427
  const cliType = resolvedProvider && (resolvedProvider.category === "cli" || resolvedProvider.category === "acp") ? resolvedType : null;