@adhdev/daemon-core 0.7.38 → 0.7.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/agent-stream/forward.d.ts +8 -0
  2. package/dist/agent-stream/index.d.ts +6 -0
  3. package/dist/agent-stream/manager.d.ts +59 -0
  4. package/dist/agent-stream/poller.d.ts +41 -0
  5. package/dist/agent-stream/provider-adapter.d.ts +29 -0
  6. package/dist/agent-stream/types.d.ts +62 -0
  7. package/dist/boot/daemon-lifecycle.d.ts +97 -0
  8. package/dist/cdp/devtools.d.ts +51 -0
  9. package/dist/cdp/initializer.d.ts +50 -0
  10. package/dist/cdp/manager.d.ts +145 -0
  11. package/dist/cdp/scanner.d.ts +58 -0
  12. package/dist/cdp/setup.d.ts +58 -0
  13. package/dist/cli-adapter-types.d.ts +25 -0
  14. package/dist/cli-adapters/provider-cli-adapter.d.ts +229 -0
  15. package/dist/cli-adapters/pty-transport.d.ts +43 -0
  16. package/dist/cli-adapters/session-host-transport.d.ts +19 -0
  17. package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +12 -0
  18. package/dist/cli-adapters/terminal-backends/types.d.ts +14 -0
  19. package/dist/cli-adapters/terminal-backends/xterm-backend.d.ts +13 -0
  20. package/dist/cli-adapters/terminal-screen.d.ts +27 -0
  21. package/dist/commands/cdp-commands.d.ts +15 -0
  22. package/dist/commands/chat-commands.d.ts +15 -0
  23. package/dist/commands/cli-manager.d.ts +82 -0
  24. package/dist/commands/handler.d.ts +101 -0
  25. package/dist/commands/router.d.ts +69 -0
  26. package/dist/commands/stream-commands.d.ts +13 -0
  27. package/dist/commands/workspace-commands.d.ts +11 -0
  28. package/dist/config/chat-history.d.ts +60 -0
  29. package/dist/config/config.d.ts +103 -0
  30. package/dist/config/recent-activity.d.ts +27 -0
  31. package/dist/config/workspaces.d.ts +82 -0
  32. package/dist/daemon/dev-auto-implement.d.ts +26 -0
  33. package/dist/daemon/dev-cdp-handlers.d.ts +22 -0
  34. package/dist/daemon/dev-cli-debug.d.ts +24 -0
  35. package/dist/daemon/dev-server-types.d.ts +43 -0
  36. package/dist/daemon/dev-server.d.ts +133 -0
  37. package/dist/daemon/scaffold-template.d.ts +32 -0
  38. package/dist/daemon-core.d.ts +36 -0
  39. package/dist/detection/cli-detector.d.ts +27 -0
  40. package/dist/detection/ide-detector.d.ts +34 -0
  41. package/dist/index.d.ts +72 -2499
  42. package/dist/index.js +673 -879
  43. package/dist/index.js.map +1 -1
  44. package/dist/index.mjs +680 -884
  45. package/dist/index.mjs.map +1 -1
  46. package/dist/installer.d.ts +50 -0
  47. package/dist/ipc-protocol.d.ts +111 -0
  48. package/dist/launch.d.ts +46 -0
  49. package/dist/logging/command-log.d.ts +31 -0
  50. package/dist/logging/logger.d.ts +87 -0
  51. package/dist/providers/acp-provider-instance.d.ts +101 -0
  52. package/dist/providers/cli-provider-instance.d.ts +43 -0
  53. package/dist/providers/contracts.d.ts +483 -0
  54. package/dist/providers/extension-provider-instance.d.ts +44 -0
  55. package/dist/providers/ide-provider-instance.d.ts +61 -0
  56. package/dist/providers/index.d.ts +5 -0
  57. package/dist/providers/provider-instance-manager.d.ts +84 -0
  58. package/dist/providers/provider-instance.d.ts +148 -0
  59. package/dist/providers/provider-loader.d.ts +270 -0
  60. package/dist/providers/status-monitor.d.ts +48 -0
  61. package/dist/providers/version-archive.d.ts +52 -0
  62. package/dist/session-host/runtime-support.d.ts +8 -0
  63. package/dist/sessions/registry.d.ts +24 -0
  64. package/dist/shared-types-extra.d.ts +29 -0
  65. package/dist/shared-types.d.ts +205 -0
  66. package/dist/status/builders.d.ts +33 -0
  67. package/dist/status/normalize.d.ts +14 -1
  68. package/dist/status/reporter.d.ts +69 -0
  69. package/dist/status/snapshot.d.ts +51 -0
  70. package/dist/system/host-memory.d.ts +19 -0
  71. package/dist/types.d.ts +123 -0
  72. package/node_modules/@adhdev/session-host-core/package.json +1 -1
  73. package/package.json +3 -2
  74. package/src/commands/cli-manager.ts +1 -26
  75. package/src/commands/handler.ts +0 -31
  76. package/src/commands/router.ts +27 -34
  77. package/src/commands/stream-commands.ts +2 -4
  78. package/src/commands/workspace-commands.ts +9 -23
  79. package/src/config/config.ts +7 -81
  80. package/src/config/recent-activity.ts +24 -12
  81. package/src/config/workspaces.ts +0 -24
  82. package/src/index.ts +16 -15
  83. package/src/providers/provider-loader.ts +13 -5
  84. package/src/shared-types-extra.ts +34 -0
  85. package/src/shared-types.d.ts +4 -6
  86. package/src/shared-types.ts +17 -38
  87. package/src/status/builders.ts +12 -0
  88. package/src/status/reporter.ts +2 -1
  89. package/src/status/snapshot.ts +70 -87
  90. package/src/types.ts +3 -8
  91. package/dist/index.d.mts +0 -2504
  92. package/dist/normalize-DVI4Lo5I.d.mts +0 -947
  93. package/dist/normalize-DVI4Lo5I.d.ts +0 -947
  94. package/dist/status/normalize.d.mts +0 -1
  95. package/src/config/workspace-activity.ts +0 -65
package/dist/index.mjs CHANGED
@@ -25,201 +25,9 @@ var __copyProps = (to, from, except, desc) => {
25
25
  };
26
26
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
27
 
28
- // src/config/workspaces.ts
29
- import * as fs from "fs";
30
- import * as os from "os";
31
- import * as path from "path";
32
- import { randomUUID } from "crypto";
33
- function expandPath(p) {
34
- const t = (p || "").trim();
35
- if (!t) return "";
36
- if (t.startsWith("~")) return path.join(os.homedir(), t.slice(1).replace(/^\//, ""));
37
- return path.resolve(t);
38
- }
39
- function validateWorkspacePath(absPath) {
40
- try {
41
- if (!absPath) return { ok: false, error: "Path required" };
42
- if (!fs.existsSync(absPath)) return { ok: false, error: "Path does not exist" };
43
- const st = fs.statSync(absPath);
44
- if (!st.isDirectory()) return { ok: false, error: "Not a directory" };
45
- return { ok: true };
46
- } catch (e) {
47
- return { ok: false, error: e?.message || "Invalid path" };
48
- }
49
- }
50
- function defaultWorkspaceLabel(absPath) {
51
- const base = path.basename(absPath) || absPath;
52
- return base;
53
- }
54
- function migrateWorkspacesFromRecent(config) {
55
- if (!config.workspaces) config.workspaces = [];
56
- if (config.workspaces.length > 0) return config;
57
- const recent = config.recentCliWorkspaces || [];
58
- const now = Date.now();
59
- for (const raw of recent) {
60
- const abs = expandPath(raw);
61
- if (!abs || validateWorkspacePath(abs).ok !== true) continue;
62
- if (config.workspaces.some((w) => path.resolve(w.path) === abs)) continue;
63
- config.workspaces.push({
64
- id: randomUUID(),
65
- path: abs,
66
- label: defaultWorkspaceLabel(abs),
67
- addedAt: now
68
- });
69
- if (config.workspaces.length >= MAX_WORKSPACES) break;
70
- }
71
- return config;
72
- }
73
- function getDefaultWorkspacePath(config) {
74
- const id = config.defaultWorkspaceId;
75
- if (!id) return null;
76
- const w = (config.workspaces || []).find((x) => x.id === id);
77
- if (!w) return null;
78
- const abs = expandPath(w.path);
79
- if (validateWorkspacePath(abs).ok !== true) return null;
80
- return abs;
81
- }
82
- function getWorkspaceState(config) {
83
- const workspaces = [...config.workspaces || []].sort((a, b) => b.addedAt - a.addedAt);
84
- const defaultWorkspacePath = getDefaultWorkspacePath(config);
85
- return {
86
- workspaces,
87
- defaultWorkspaceId: config.defaultWorkspaceId ?? null,
88
- defaultWorkspacePath
89
- };
90
- }
91
- function resolveLaunchDirectory(args, config) {
92
- const a = args || {};
93
- if (a.dir != null && String(a.dir).trim()) {
94
- const abs = expandPath(String(a.dir).trim());
95
- if (abs && validateWorkspacePath(abs).ok === true) {
96
- return { ok: true, path: abs, source: "dir" };
97
- }
98
- return {
99
- ok: false,
100
- code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
101
- message: abs ? "Directory path is not valid or does not exist" : "Invalid directory path"
102
- };
103
- }
104
- if (a.workspaceId) {
105
- const w = (config.workspaces || []).find((x) => x.id === a.workspaceId);
106
- if (w) {
107
- const abs = expandPath(w.path);
108
- if (validateWorkspacePath(abs).ok === true) {
109
- return { ok: true, path: abs, source: "workspaceId" };
110
- }
111
- }
112
- return {
113
- ok: false,
114
- code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
115
- message: "Saved workspace not found or path is no longer valid"
116
- };
117
- }
118
- if (a.useDefaultWorkspace === true) {
119
- const d = getDefaultWorkspacePath(config);
120
- if (d) return { ok: true, path: d, source: "defaultWorkspace" };
121
- return {
122
- ok: false,
123
- code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
124
- message: "No default workspace is set"
125
- };
126
- }
127
- if (a.useHome === true) {
128
- return { ok: true, path: os.homedir(), source: "home" };
129
- }
130
- return {
131
- ok: false,
132
- code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
133
- message: "Choose a directory, saved workspace, default workspace, or home before launching."
134
- };
135
- }
136
- function resolveIdeWorkspaceFromArgs(args, config) {
137
- const ar = args || {};
138
- if (ar.workspace) {
139
- const abs = expandPath(ar.workspace);
140
- if (abs && validateWorkspacePath(abs).ok === true) return abs;
141
- }
142
- if (ar.workspaceId) {
143
- const w = (config.workspaces || []).find((x) => x.id === ar.workspaceId);
144
- if (w) {
145
- const abs = expandPath(w.path);
146
- if (validateWorkspacePath(abs).ok === true) return abs;
147
- }
148
- }
149
- if (ar.useDefaultWorkspace === true) {
150
- return getDefaultWorkspacePath(config) || void 0;
151
- }
152
- return void 0;
153
- }
154
- function resolveIdeLaunchWorkspace(args, config) {
155
- const direct = resolveIdeWorkspaceFromArgs(args, config);
156
- if (direct) return direct;
157
- if (args?.useDefaultWorkspace === false) return void 0;
158
- return getDefaultWorkspacePath(config) || void 0;
159
- }
160
- function findWorkspaceByPath(config, rawPath) {
161
- const abs = path.resolve(expandPath(rawPath));
162
- if (!abs) return void 0;
163
- return (config.workspaces || []).find((w) => path.resolve(expandPath(w.path)) === abs);
164
- }
165
- function addWorkspaceEntry(config, rawPath, label, options) {
166
- const abs = expandPath(rawPath);
167
- const createIfMissing = options?.createIfMissing === true;
168
- if (!abs) return { error: "Path required" };
169
- if (!fs.existsSync(abs) && createIfMissing) {
170
- try {
171
- fs.mkdirSync(abs, { recursive: true });
172
- } catch (e) {
173
- return { error: e?.message || "Could not create directory" };
174
- }
175
- }
176
- const v = validateWorkspacePath(abs);
177
- if (!v.ok) return { error: v.error };
178
- const list = [...config.workspaces || []];
179
- if (list.some((w) => path.resolve(w.path) === abs)) {
180
- return { error: "Workspace already in list" };
181
- }
182
- if (list.length >= MAX_WORKSPACES) {
183
- return { error: `Maximum ${MAX_WORKSPACES} workspaces` };
184
- }
185
- const entry = {
186
- id: randomUUID(),
187
- path: abs,
188
- label: (label || "").trim() || defaultWorkspaceLabel(abs),
189
- addedAt: Date.now()
190
- };
191
- list.push(entry);
192
- return { config: { ...config, workspaces: list }, entry };
193
- }
194
- function removeWorkspaceEntry(config, id) {
195
- const list = (config.workspaces || []).filter((w) => w.id !== id);
196
- if (list.length === (config.workspaces || []).length) return { error: "Workspace not found" };
197
- let defaultWorkspaceId = config.defaultWorkspaceId;
198
- if (defaultWorkspaceId === id) defaultWorkspaceId = null;
199
- return { config: { ...config, workspaces: list, defaultWorkspaceId } };
200
- }
201
- function setDefaultWorkspaceId(config, id) {
202
- if (id === null) {
203
- return { config: { ...config, defaultWorkspaceId: null } };
204
- }
205
- const w = (config.workspaces || []).find((x) => x.id === id);
206
- if (!w) return { error: "Workspace not found" };
207
- const abs = expandPath(w.path);
208
- if (validateWorkspacePath(abs).ok !== true) return { error: "Workspace path is no longer valid" };
209
- return { config: { ...config, defaultWorkspaceId: id } };
210
- }
211
- var MAX_WORKSPACES;
212
- var init_workspaces = __esm({
213
- "src/config/workspaces.ts"() {
214
- "use strict";
215
- MAX_WORKSPACES = 50;
216
- }
217
- });
218
-
219
28
  // src/config/config.ts
220
29
  var config_exports = {};
221
30
  __export(config_exports, {
222
- addCliHistory: () => addCliHistory,
223
31
  generateConnectionToken: () => generateConnectionToken,
224
32
  generateMachineId: () => generateMachineId,
225
33
  getConfigDir: () => getConfigDir,
@@ -231,12 +39,12 @@ __export(config_exports, {
231
39
  saveConfig: () => saveConfig,
232
40
  updateConfig: () => updateConfig
233
41
  });
234
- import { homedir as homedir2 } from "os";
235
- import { join as join2 } from "path";
236
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync, writeFileSync, chmodSync } from "fs";
237
- import { randomUUID as randomUUID2 } from "crypto";
42
+ import { homedir } from "os";
43
+ import { join } from "path";
44
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync } from "fs";
45
+ import { randomUUID } from "crypto";
238
46
  function generateMachineId() {
239
- return `${MACHINE_ID_PREFIX}${randomUUID2().replace(/-/g, "")}`;
47
+ return `${MACHINE_ID_PREFIX}${randomUUID().replace(/-/g, "")}`;
240
48
  }
241
49
  function isStableMachineId(machineId) {
242
50
  return typeof machineId === "string" && machineId.startsWith(MACHINE_ID_PREFIX);
@@ -256,18 +64,18 @@ function ensureMachineId(config) {
256
64
  };
257
65
  }
258
66
  function getConfigDir() {
259
- const dir = join2(homedir2(), ".adhdev");
260
- if (!existsSync2(dir)) {
261
- mkdirSync2(dir, { recursive: true });
67
+ const dir = join(homedir(), ".adhdev");
68
+ if (!existsSync(dir)) {
69
+ mkdirSync(dir, { recursive: true });
262
70
  }
263
71
  return dir;
264
72
  }
265
73
  function getConfigPath() {
266
- return join2(getConfigDir(), "config.json");
74
+ return join(getConfigDir(), "config.json");
267
75
  }
268
76
  function loadConfig() {
269
77
  const configPath = getConfigPath();
270
- if (!existsSync2(configPath)) {
78
+ if (!existsSync(configPath)) {
271
79
  const initialized = ensureMachineId({ ...DEFAULT_CONFIG });
272
80
  try {
273
81
  saveConfig(initialized.config);
@@ -283,15 +91,9 @@ function loadConfig() {
283
91
  merged.defaultWorkspaceId = merged.activeWorkspaceId;
284
92
  }
285
93
  delete merged.activeWorkspaceId;
286
- const hadStoredWorkspaces = Array.isArray(parsed.workspaces) && parsed.workspaces.length > 0;
287
94
  const ensured = ensureMachineId(merged);
288
95
  const normalized = ensured.config;
289
- migrateWorkspacesFromRecent(normalized);
290
- let configChanged = ensured.changed;
291
- if (!hadStoredWorkspaces && (normalized.workspaces?.length || 0) > 0) {
292
- configChanged = true;
293
- }
294
- if (configChanged) {
96
+ if (ensured.changed) {
295
97
  try {
296
98
  saveConfig(normalized);
297
99
  } catch {
@@ -306,8 +108,8 @@ function loadConfig() {
306
108
  function saveConfig(config) {
307
109
  const configPath = getConfigPath();
308
110
  const dir = getConfigDir();
309
- if (!existsSync2(dir)) {
310
- mkdirSync2(dir, { recursive: true, mode: 448 });
111
+ if (!existsSync(dir)) {
112
+ mkdirSync(dir, { recursive: true, mode: 448 });
311
113
  }
312
114
  writeFileSync(configPath, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
313
115
  try {
@@ -346,39 +148,10 @@ function generateConnectionToken() {
346
148
  }
347
149
  return token;
348
150
  }
349
- function addCliHistory(entry) {
350
- const config = loadConfig();
351
- const history = config.cliHistory || [];
352
- const argsKey = (entry.cliArgs || []).join(" ");
353
- const category = entry.category || "cli";
354
- const workspaceKey = entry.workspace || "";
355
- const modelKey = entry.model || "";
356
- const filtered = history.filter((h) => {
357
- const hArgsKey = (h.cliArgs || []).join(" ");
358
- return !((h.category || "cli") === category && h.cliType === entry.cliType && h.dir === entry.dir && hArgsKey === argsKey && (h.workspace || "") === workspaceKey && (h.model || "") === modelKey);
359
- });
360
- filtered.unshift({
361
- ...entry,
362
- category,
363
- timestamp: Date.now(),
364
- label: entry.label || (() => {
365
- const base = `${entry.cliType} \xB7 ${entry.dir.split("/").filter(Boolean).pop() || "root"}`;
366
- const suffix = [];
367
- if (entry.workspace && entry.workspace !== entry.dir) suffix.push(entry.workspace.split("/").filter(Boolean).pop() || entry.workspace);
368
- if (entry.model) suffix.push(`model=${entry.model}`);
369
- if (argsKey) suffix.push(argsKey);
370
- if (entry.newWindow) suffix.push("new window");
371
- return suffix.length > 0 ? `${base} (${suffix.join(" \xB7 ")})` : base;
372
- })()
373
- });
374
- config.cliHistory = filtered.slice(0, 20);
375
- saveConfig(config);
376
- }
377
151
  var DEFAULT_CONFIG, MACHINE_ID_PREFIX;
378
152
  var init_config = __esm({
379
153
  "src/config/config.ts"() {
380
154
  "use strict";
381
- init_workspaces();
382
155
  DEFAULT_CONFIG = {
383
156
  serverUrl: "https://api.adhf.dev",
384
157
  apiToken: null,
@@ -394,17 +167,15 @@ var init_config = __esm({
394
167
  setupDate: null,
395
168
  configuredCLIs: [],
396
169
  enabledIdes: [],
397
- recentCliWorkspaces: [],
398
170
  workspaces: [],
399
171
  defaultWorkspaceId: null,
400
- recentWorkspaceActivity: [],
401
172
  recentActivity: [],
402
- recentSessionReads: {},
173
+ sessionReads: {},
174
+ sessionReadMarkers: {},
403
175
  machineNickname: null,
404
176
  machineId: void 0,
405
177
  machineSecret: null,
406
178
  registeredMachineId: void 0,
407
- cliHistory: [],
408
179
  providerSettings: {},
409
180
  ideSettings: {},
410
181
  disableUpstream: false
@@ -415,7 +186,7 @@ var init_config = __esm({
415
186
 
416
187
  // src/logging/logger.ts
417
188
  import * as fs2 from "fs";
418
- import * as path4 from "path";
189
+ import * as path3 from "path";
419
190
  import * as os4 from "os";
420
191
  function setLogLevel(level) {
421
192
  currentLevel = level;
@@ -431,7 +202,7 @@ function checkDateRotation() {
431
202
  const today = getDateStr();
432
203
  if (today !== currentDate) {
433
204
  currentDate = today;
434
- currentLogFile = path4.join(LOG_DIR, `daemon-${currentDate}.log`);
205
+ currentLogFile = path3.join(LOG_DIR, `daemon-${currentDate}.log`);
435
206
  cleanOldLogs();
436
207
  }
437
208
  }
@@ -445,7 +216,7 @@ function cleanOldLogs() {
445
216
  const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
446
217
  if (dateMatch && dateMatch[1] < cutoffStr) {
447
218
  try {
448
- fs2.unlinkSync(path4.join(LOG_DIR, file));
219
+ fs2.unlinkSync(path3.join(LOG_DIR, file));
449
220
  } catch {
450
221
  }
451
222
  }
@@ -569,7 +340,7 @@ var init_logger = __esm({
569
340
  LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
570
341
  LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
571
342
  currentLevel = "info";
572
- LOG_DIR = process.platform === "win32" ? path4.join(process.env.LOCALAPPDATA || process.env.APPDATA || path4.join(os4.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path4.join(os4.homedir(), "Library", "Logs", "adhdev") : path4.join(os4.homedir(), ".local", "share", "adhdev", "logs");
343
+ LOG_DIR = process.platform === "win32" ? path3.join(process.env.LOCALAPPDATA || process.env.APPDATA || path3.join(os4.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path3.join(os4.homedir(), "Library", "Logs", "adhdev") : path3.join(os4.homedir(), ".local", "share", "adhdev", "logs");
573
344
  MAX_LOG_SIZE = 5 * 1024 * 1024;
574
345
  MAX_LOG_DAYS = 7;
575
346
  try {
@@ -577,16 +348,16 @@ var init_logger = __esm({
577
348
  } catch {
578
349
  }
579
350
  currentDate = getDateStr();
580
- currentLogFile = path4.join(LOG_DIR, `daemon-${currentDate}.log`);
351
+ currentLogFile = path3.join(LOG_DIR, `daemon-${currentDate}.log`);
581
352
  cleanOldLogs();
582
353
  try {
583
- const oldLog = path4.join(LOG_DIR, "daemon.log");
354
+ const oldLog = path3.join(LOG_DIR, "daemon.log");
584
355
  if (fs2.existsSync(oldLog)) {
585
356
  const stat = fs2.statSync(oldLog);
586
357
  const oldDate = stat.mtime.toISOString().slice(0, 10);
587
- fs2.renameSync(oldLog, path4.join(LOG_DIR, `daemon-${oldDate}.log`));
358
+ fs2.renameSync(oldLog, path3.join(LOG_DIR, `daemon-${oldDate}.log`));
588
359
  }
589
- const oldLogBackup = path4.join(LOG_DIR, "daemon.log.old");
360
+ const oldLogBackup = path3.join(LOG_DIR, "daemon.log.old");
590
361
  if (fs2.existsSync(oldLogBackup)) {
591
362
  fs2.unlinkSync(oldLogBackup);
592
363
  }
@@ -618,7 +389,7 @@ var init_logger = __esm({
618
389
  }
619
390
  };
620
391
  interceptorInstalled = false;
621
- LOG_PATH = path4.join(LOG_DIR, `daemon-${getDateStr()}.log`);
392
+ LOG_PATH = path3.join(LOG_DIR, `daemon-${getDateStr()}.log`);
622
393
  }
623
394
  });
624
395
 
@@ -928,7 +699,7 @@ __export(provider_cli_adapter_exports, {
928
699
  normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
929
700
  });
930
701
  import * as os12 from "os";
931
- import * as path10 from "path";
702
+ import * as path9 from "path";
932
703
  import { execSync as execSync4 } from "child_process";
933
704
  function stripAnsi(str) {
934
705
  return str.replace(/\x1B\[\d*[A-HJKSTfG]/g, " ").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][^\x1B]*\x1B\\/g, "").replace(/ +/g, " ");
@@ -949,7 +720,7 @@ function findBinary(name) {
949
720
  }
950
721
  }
951
722
  function isScriptBinary(binaryPath) {
952
- if (!path10.isAbsolute(binaryPath)) return false;
723
+ if (!path9.isAbsolute(binaryPath)) return false;
953
724
  try {
954
725
  const fs12 = __require("fs");
955
726
  const resolved = fs12.realpathSync(binaryPath);
@@ -965,7 +736,7 @@ function isScriptBinary(binaryPath) {
965
736
  }
966
737
  }
967
738
  function looksLikeMachOOrElf(filePath) {
968
- if (!path10.isAbsolute(filePath)) return false;
739
+ if (!path9.isAbsolute(filePath)) return false;
969
740
  try {
970
741
  const fs12 = __require("fs");
971
742
  const resolved = fs12.realpathSync(filePath);
@@ -1091,9 +862,9 @@ var init_provider_cli_adapter = __esm({
1091
862
  if (os12.platform() !== "win32") {
1092
863
  try {
1093
864
  const fs12 = __require("fs");
1094
- const ptyDir = path10.resolve(path10.dirname(__require.resolve("node-pty")), "..");
865
+ const ptyDir = path9.resolve(path9.dirname(__require.resolve("node-pty")), "..");
1095
866
  const platformArch = `${os12.platform()}-${os12.arch()}`;
1096
- const helper = path10.join(ptyDir, "prebuilds", platformArch, "spawn-helper");
867
+ const helper = path9.join(ptyDir, "prebuilds", platformArch, "spawn-helper");
1097
868
  if (fs12.existsSync(helper)) {
1098
869
  const stat = fs12.statSync(helper);
1099
870
  if (!(stat.mode & 73)) {
@@ -1282,7 +1053,7 @@ var init_provider_cli_adapter = __esm({
1282
1053
  LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
1283
1054
  let shellCmd;
1284
1055
  let shellArgs;
1285
- const useShellUnix = !isWin && (!!spawnConfig.shell || !path10.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1056
+ const useShellUnix = !isWin && (!!spawnConfig.shell || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1286
1057
  const useShell = isWin ? !!spawnConfig.shell : useShellUnix;
1287
1058
  if (useShell) {
1288
1059
  if (!spawnConfig.shell && !isWin) {
@@ -1707,7 +1478,7 @@ ${data.message || ""}`.trim();
1707
1478
  if (this.startupParseGate) {
1708
1479
  const deadline = Date.now() + 1e4;
1709
1480
  while (this.startupParseGate && Date.now() < deadline) {
1710
- await new Promise((resolve10) => setTimeout(resolve10, 50));
1481
+ await new Promise((resolve9) => setTimeout(resolve9, 50));
1711
1482
  }
1712
1483
  }
1713
1484
  if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
@@ -1875,17 +1646,17 @@ ${data.message || ""}`.trim();
1875
1646
  }
1876
1647
  }
1877
1648
  waitForStopped(timeoutMs) {
1878
- return new Promise((resolve10) => {
1649
+ return new Promise((resolve9) => {
1879
1650
  const startedAt = Date.now();
1880
1651
  const timer = setInterval(() => {
1881
1652
  if (!this.ptyProcess || this.currentStatus === "stopped") {
1882
1653
  clearInterval(timer);
1883
- resolve10(true);
1654
+ resolve9(true);
1884
1655
  return;
1885
1656
  }
1886
1657
  if (Date.now() - startedAt >= timeoutMs) {
1887
1658
  clearInterval(timer);
1888
- resolve10(false);
1659
+ resolve9(false);
1889
1660
  }
1890
1661
  }, 100);
1891
1662
  });
@@ -2077,58 +1848,182 @@ ${data.message || ""}`.trim();
2077
1848
 
2078
1849
  // src/index.ts
2079
1850
  init_config();
2080
- init_workspaces();
2081
1851
 
2082
- // src/config/workspace-activity.ts
2083
- init_workspaces();
2084
- import * as path2 from "path";
2085
- var MAX_ACTIVITY = 30;
2086
- function normWorkspacePath(p) {
1852
+ // src/config/workspaces.ts
1853
+ import * as fs from "fs";
1854
+ import * as os from "os";
1855
+ import * as path from "path";
1856
+ import { randomUUID as randomUUID2 } from "crypto";
1857
+ var MAX_WORKSPACES = 50;
1858
+ function expandPath(p) {
1859
+ const t = (p || "").trim();
1860
+ if (!t) return "";
1861
+ if (t.startsWith("~")) return path.join(os.homedir(), t.slice(1).replace(/^\//, ""));
1862
+ return path.resolve(t);
1863
+ }
1864
+ function validateWorkspacePath(absPath) {
2087
1865
  try {
2088
- return path2.resolve(expandPath(p));
2089
- } catch {
2090
- return path2.resolve(p);
1866
+ if (!absPath) return { ok: false, error: "Path required" };
1867
+ if (!fs.existsSync(absPath)) return { ok: false, error: "Path does not exist" };
1868
+ const st = fs.statSync(absPath);
1869
+ if (!st.isDirectory()) return { ok: false, error: "Not a directory" };
1870
+ return { ok: true };
1871
+ } catch (e) {
1872
+ return { ok: false, error: e?.message || "Invalid path" };
2091
1873
  }
2092
1874
  }
2093
- function appendWorkspaceActivity(config, rawPath, meta) {
2094
- const abs = normWorkspacePath(rawPath);
2095
- if (!abs) return config;
2096
- const prev = config.recentWorkspaceActivity || [];
2097
- const filtered = prev.filter((e) => normWorkspacePath(e.path) !== abs);
1875
+ function defaultWorkspaceLabel(absPath) {
1876
+ const base = path.basename(absPath) || absPath;
1877
+ return base;
1878
+ }
1879
+ function getDefaultWorkspacePath(config) {
1880
+ const id = config.defaultWorkspaceId;
1881
+ if (!id) return null;
1882
+ const w = (config.workspaces || []).find((x) => x.id === id);
1883
+ if (!w) return null;
1884
+ const abs = expandPath(w.path);
1885
+ if (validateWorkspacePath(abs).ok !== true) return null;
1886
+ return abs;
1887
+ }
1888
+ function getWorkspaceState(config) {
1889
+ const workspaces = [...config.workspaces || []].sort((a, b) => b.addedAt - a.addedAt);
1890
+ const defaultWorkspacePath = getDefaultWorkspacePath(config);
1891
+ return {
1892
+ workspaces,
1893
+ defaultWorkspaceId: config.defaultWorkspaceId ?? null,
1894
+ defaultWorkspacePath
1895
+ };
1896
+ }
1897
+ function resolveLaunchDirectory(args, config) {
1898
+ const a = args || {};
1899
+ if (a.dir != null && String(a.dir).trim()) {
1900
+ const abs = expandPath(String(a.dir).trim());
1901
+ if (abs && validateWorkspacePath(abs).ok === true) {
1902
+ return { ok: true, path: abs, source: "dir" };
1903
+ }
1904
+ return {
1905
+ ok: false,
1906
+ code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
1907
+ message: abs ? "Directory path is not valid or does not exist" : "Invalid directory path"
1908
+ };
1909
+ }
1910
+ if (a.workspaceId) {
1911
+ const w = (config.workspaces || []).find((x) => x.id === a.workspaceId);
1912
+ if (w) {
1913
+ const abs = expandPath(w.path);
1914
+ if (validateWorkspacePath(abs).ok === true) {
1915
+ return { ok: true, path: abs, source: "workspaceId" };
1916
+ }
1917
+ }
1918
+ return {
1919
+ ok: false,
1920
+ code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
1921
+ message: "Saved workspace not found or path is no longer valid"
1922
+ };
1923
+ }
1924
+ if (a.useDefaultWorkspace === true) {
1925
+ const d = getDefaultWorkspacePath(config);
1926
+ if (d) return { ok: true, path: d, source: "defaultWorkspace" };
1927
+ return {
1928
+ ok: false,
1929
+ code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
1930
+ message: "No default workspace is set"
1931
+ };
1932
+ }
1933
+ if (a.useHome === true) {
1934
+ return { ok: true, path: os.homedir(), source: "home" };
1935
+ }
1936
+ return {
1937
+ ok: false,
1938
+ code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
1939
+ message: "Choose a directory, saved workspace, default workspace, or home before launching."
1940
+ };
1941
+ }
1942
+ function resolveIdeWorkspaceFromArgs(args, config) {
1943
+ const ar = args || {};
1944
+ if (ar.workspace) {
1945
+ const abs = expandPath(ar.workspace);
1946
+ if (abs && validateWorkspacePath(abs).ok === true) return abs;
1947
+ }
1948
+ if (ar.workspaceId) {
1949
+ const w = (config.workspaces || []).find((x) => x.id === ar.workspaceId);
1950
+ if (w) {
1951
+ const abs = expandPath(w.path);
1952
+ if (validateWorkspacePath(abs).ok === true) return abs;
1953
+ }
1954
+ }
1955
+ if (ar.useDefaultWorkspace === true) {
1956
+ return getDefaultWorkspacePath(config) || void 0;
1957
+ }
1958
+ return void 0;
1959
+ }
1960
+ function resolveIdeLaunchWorkspace(args, config) {
1961
+ const direct = resolveIdeWorkspaceFromArgs(args, config);
1962
+ if (direct) return direct;
1963
+ if (args?.useDefaultWorkspace === false) return void 0;
1964
+ return getDefaultWorkspacePath(config) || void 0;
1965
+ }
1966
+ function findWorkspaceByPath(config, rawPath) {
1967
+ const abs = path.resolve(expandPath(rawPath));
1968
+ if (!abs) return void 0;
1969
+ return (config.workspaces || []).find((w) => path.resolve(expandPath(w.path)) === abs);
1970
+ }
1971
+ function addWorkspaceEntry(config, rawPath, label, options) {
1972
+ const abs = expandPath(rawPath);
1973
+ const createIfMissing = options?.createIfMissing === true;
1974
+ if (!abs) return { error: "Path required" };
1975
+ if (!fs.existsSync(abs) && createIfMissing) {
1976
+ try {
1977
+ fs.mkdirSync(abs, { recursive: true });
1978
+ } catch (e) {
1979
+ return { error: e?.message || "Could not create directory" };
1980
+ }
1981
+ }
1982
+ const v = validateWorkspacePath(abs);
1983
+ if (!v.ok) return { error: v.error };
1984
+ const list = [...config.workspaces || []];
1985
+ if (list.some((w) => path.resolve(w.path) === abs)) {
1986
+ return { error: "Workspace already in list" };
1987
+ }
1988
+ if (list.length >= MAX_WORKSPACES) {
1989
+ return { error: `Maximum ${MAX_WORKSPACES} workspaces` };
1990
+ }
2098
1991
  const entry = {
1992
+ id: randomUUID2(),
2099
1993
  path: abs,
2100
- lastUsedAt: Date.now(),
2101
- kind: meta?.kind,
2102
- agentType: meta?.agentType
1994
+ label: (label || "").trim() || defaultWorkspaceLabel(abs),
1995
+ addedAt: Date.now()
2103
1996
  };
2104
- const recentWorkspaceActivity = [entry, ...filtered].slice(0, MAX_ACTIVITY);
2105
- return { ...config, recentWorkspaceActivity };
1997
+ list.push(entry);
1998
+ return { config: { ...config, workspaces: list }, entry };
2106
1999
  }
2107
- function getWorkspaceActivity(config, limit = 20) {
2108
- const list = [...config.recentWorkspaceActivity || []];
2109
- list.sort((a, b) => b.lastUsedAt - a.lastUsedAt);
2110
- return list.slice(0, limit);
2000
+ function removeWorkspaceEntry(config, id) {
2001
+ const list = (config.workspaces || []).filter((w) => w.id !== id);
2002
+ if (list.length === (config.workspaces || []).length) return { error: "Workspace not found" };
2003
+ let defaultWorkspaceId = config.defaultWorkspaceId;
2004
+ if (defaultWorkspaceId === id) defaultWorkspaceId = null;
2005
+ return { config: { ...config, workspaces: list, defaultWorkspaceId } };
2111
2006
  }
2112
- function removeActivityForPath(config, rawPath) {
2113
- const n = normWorkspacePath(rawPath);
2114
- return {
2115
- ...config,
2116
- recentWorkspaceActivity: (config.recentWorkspaceActivity || []).filter(
2117
- (e) => normWorkspacePath(e.path) !== n
2118
- )
2119
- };
2007
+ function setDefaultWorkspaceId(config, id) {
2008
+ if (id === null) {
2009
+ return { config: { ...config, defaultWorkspaceId: null } };
2010
+ }
2011
+ const w = (config.workspaces || []).find((x) => x.id === id);
2012
+ if (!w) return { error: "Workspace not found" };
2013
+ const abs = expandPath(w.path);
2014
+ if (validateWorkspacePath(abs).ok !== true) return { error: "Workspace path is no longer valid" };
2015
+ return { config: { ...config, defaultWorkspaceId: id } };
2120
2016
  }
2121
2017
 
2122
2018
  // src/config/recent-activity.ts
2123
- init_workspaces();
2124
- import * as path3 from "path";
2125
- var MAX_ACTIVITY2 = 30;
2019
+ import * as path2 from "path";
2020
+ var MAX_ACTIVITY = 30;
2126
2021
  function normalizeWorkspace(workspace) {
2127
2022
  if (!workspace) return "";
2128
2023
  try {
2129
- return path3.resolve(expandPath(workspace));
2024
+ return path2.resolve(expandPath(workspace));
2130
2025
  } catch {
2131
- return path3.resolve(workspace);
2026
+ return path2.resolve(workspace);
2132
2027
  }
2133
2028
  }
2134
2029
  function buildRecentActivityKey(entry) {
@@ -2144,24 +2039,33 @@ function appendRecentActivity(config, entry) {
2144
2039
  const filtered = (config.recentActivity || []).filter((item) => item.id !== nextEntry.id);
2145
2040
  return {
2146
2041
  ...config,
2147
- recentActivity: [nextEntry, ...filtered].slice(0, MAX_ACTIVITY2)
2042
+ recentActivity: [nextEntry, ...filtered].slice(0, MAX_ACTIVITY)
2148
2043
  };
2149
2044
  }
2150
2045
  function getRecentActivity(config, limit = 20) {
2151
2046
  return [...config.recentActivity || []].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, limit);
2152
2047
  }
2153
- function getRecentSessionSeenAt(config, recentKey) {
2154
- return config.recentSessionReads?.[recentKey] || 0;
2048
+ function getSessionSeenAt(config, sessionId) {
2049
+ return config.sessionReads?.[sessionId] || 0;
2050
+ }
2051
+ function getSessionSeenMarker(config, sessionId) {
2052
+ return config.sessionReadMarkers?.[sessionId] || "";
2155
2053
  }
2156
- function markRecentSessionSeen(config, recentKey, seenAt = Date.now()) {
2157
- const prev = config.recentSessionReads || {};
2158
- const nextSeenAt = Math.max(prev[recentKey] || 0, seenAt);
2054
+ function markSessionSeen(config, sessionId, seenAt = Date.now(), completionMarker) {
2055
+ const prev = config.sessionReads || {};
2056
+ const nextSeenAt = Math.max(prev[sessionId] || 0, seenAt);
2057
+ const prevMarkers = config.sessionReadMarkers || {};
2058
+ const nextMarker = typeof completionMarker === "string" ? completionMarker : "";
2159
2059
  return {
2160
2060
  ...config,
2161
- recentSessionReads: {
2061
+ sessionReads: {
2162
2062
  ...prev,
2163
- [recentKey]: nextSeenAt
2164
- }
2063
+ [sessionId]: nextSeenAt
2064
+ },
2065
+ sessionReadMarkers: nextMarker ? {
2066
+ ...prevMarkers,
2067
+ [sessionId]: nextMarker
2068
+ } : prevMarkers
2165
2069
  };
2166
2070
  }
2167
2071
 
@@ -2272,15 +2176,15 @@ function parseVersion(raw) {
2272
2176
  return match ? match[1] : raw.split("\n")[0].slice(0, 100);
2273
2177
  }
2274
2178
  function execAsync(cmd, timeoutMs = 5e3) {
2275
- return new Promise((resolve10) => {
2179
+ return new Promise((resolve9) => {
2276
2180
  const child = exec(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
2277
2181
  if (err || !stdout?.trim()) {
2278
- resolve10(null);
2182
+ resolve9(null);
2279
2183
  } else {
2280
- resolve10(stdout.trim());
2184
+ resolve9(stdout.trim());
2281
2185
  }
2282
2186
  });
2283
- child.on("error", () => resolve10(null));
2187
+ child.on("error", () => resolve9(null));
2284
2188
  });
2285
2189
  }
2286
2190
  async function detectCLIs(providerLoader) {
@@ -2447,7 +2351,7 @@ var DaemonCdpManager = class {
2447
2351
  * Returns multiple entries if multiple IDE windows are open on same port
2448
2352
  */
2449
2353
  static listAllTargets(port) {
2450
- return new Promise((resolve10) => {
2354
+ return new Promise((resolve9) => {
2451
2355
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
2452
2356
  let data = "";
2453
2357
  res.on("data", (chunk) => data += chunk.toString());
@@ -2463,16 +2367,16 @@ var DaemonCdpManager = class {
2463
2367
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
2464
2368
  );
2465
2369
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
2466
- resolve10(mainPages.length > 0 ? mainPages : fallbackPages);
2370
+ resolve9(mainPages.length > 0 ? mainPages : fallbackPages);
2467
2371
  } catch {
2468
- resolve10([]);
2372
+ resolve9([]);
2469
2373
  }
2470
2374
  });
2471
2375
  });
2472
- req.on("error", () => resolve10([]));
2376
+ req.on("error", () => resolve9([]));
2473
2377
  req.setTimeout(2e3, () => {
2474
2378
  req.destroy();
2475
- resolve10([]);
2379
+ resolve9([]);
2476
2380
  });
2477
2381
  });
2478
2382
  }
@@ -2512,7 +2416,7 @@ var DaemonCdpManager = class {
2512
2416
  }
2513
2417
  }
2514
2418
  findTargetOnPort(port) {
2515
- return new Promise((resolve10) => {
2419
+ return new Promise((resolve9) => {
2516
2420
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
2517
2421
  let data = "";
2518
2422
  res.on("data", (chunk) => data += chunk.toString());
@@ -2523,7 +2427,7 @@ var DaemonCdpManager = class {
2523
2427
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
2524
2428
  );
2525
2429
  if (pages.length === 0) {
2526
- resolve10(targets.find((t) => t.webSocketDebuggerUrl) || null);
2430
+ resolve9(targets.find((t) => t.webSocketDebuggerUrl) || null);
2527
2431
  return;
2528
2432
  }
2529
2433
  const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -2533,24 +2437,24 @@ var DaemonCdpManager = class {
2533
2437
  const specific = list.find((t) => t.id === this._targetId);
2534
2438
  if (specific) {
2535
2439
  this._pageTitle = specific.title || "";
2536
- resolve10(specific);
2440
+ resolve9(specific);
2537
2441
  } else {
2538
2442
  this.log(`[CDP] Target ${this._targetId} not found in page list`);
2539
- resolve10(null);
2443
+ resolve9(null);
2540
2444
  }
2541
2445
  return;
2542
2446
  }
2543
2447
  this._pageTitle = list[0]?.title || "";
2544
- resolve10(list[0]);
2448
+ resolve9(list[0]);
2545
2449
  } catch {
2546
- resolve10(null);
2450
+ resolve9(null);
2547
2451
  }
2548
2452
  });
2549
2453
  });
2550
- req.on("error", () => resolve10(null));
2454
+ req.on("error", () => resolve9(null));
2551
2455
  req.setTimeout(2e3, () => {
2552
2456
  req.destroy();
2553
- resolve10(null);
2457
+ resolve9(null);
2554
2458
  });
2555
2459
  });
2556
2460
  }
@@ -2561,7 +2465,7 @@ var DaemonCdpManager = class {
2561
2465
  this.extensionProviders = providers;
2562
2466
  }
2563
2467
  connectToTarget(wsUrl) {
2564
- return new Promise((resolve10) => {
2468
+ return new Promise((resolve9) => {
2565
2469
  this.ws = new WebSocket(wsUrl);
2566
2470
  this.ws.on("open", async () => {
2567
2471
  this._connected = true;
@@ -2571,17 +2475,17 @@ var DaemonCdpManager = class {
2571
2475
  }
2572
2476
  this.connectBrowserWs().catch(() => {
2573
2477
  });
2574
- resolve10(true);
2478
+ resolve9(true);
2575
2479
  });
2576
2480
  this.ws.on("message", (data) => {
2577
2481
  try {
2578
2482
  const msg = JSON.parse(data.toString());
2579
2483
  if (msg.id && this.pending.has(msg.id)) {
2580
- const { resolve: resolve11, reject } = this.pending.get(msg.id);
2484
+ const { resolve: resolve10, reject } = this.pending.get(msg.id);
2581
2485
  this.pending.delete(msg.id);
2582
2486
  this.failureCount = 0;
2583
2487
  if (msg.error) reject(new Error(msg.error.message));
2584
- else resolve11(msg.result);
2488
+ else resolve10(msg.result);
2585
2489
  } else if (msg.method === "Runtime.executionContextCreated") {
2586
2490
  this.contexts.add(msg.params.context.id);
2587
2491
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -2604,7 +2508,7 @@ var DaemonCdpManager = class {
2604
2508
  this.ws.on("error", (err) => {
2605
2509
  this.log(`[CDP] WebSocket error: ${err.message}`);
2606
2510
  this._connected = false;
2607
- resolve10(false);
2511
+ resolve9(false);
2608
2512
  });
2609
2513
  });
2610
2514
  }
@@ -2618,7 +2522,7 @@ var DaemonCdpManager = class {
2618
2522
  return;
2619
2523
  }
2620
2524
  this.log(`[CDP] Connecting browser WS for target discovery...`);
2621
- await new Promise((resolve10, reject) => {
2525
+ await new Promise((resolve9, reject) => {
2622
2526
  this.browserWs = new WebSocket(browserWsUrl);
2623
2527
  this.browserWs.on("open", async () => {
2624
2528
  this._browserConnected = true;
@@ -2628,16 +2532,16 @@ var DaemonCdpManager = class {
2628
2532
  } catch (e) {
2629
2533
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
2630
2534
  }
2631
- resolve10();
2535
+ resolve9();
2632
2536
  });
2633
2537
  this.browserWs.on("message", (data) => {
2634
2538
  try {
2635
2539
  const msg = JSON.parse(data.toString());
2636
2540
  if (msg.id && this.browserPending.has(msg.id)) {
2637
- const { resolve: resolve11, reject: reject2 } = this.browserPending.get(msg.id);
2541
+ const { resolve: resolve10, reject: reject2 } = this.browserPending.get(msg.id);
2638
2542
  this.browserPending.delete(msg.id);
2639
2543
  if (msg.error) reject2(new Error(msg.error.message));
2640
- else resolve11(msg.result);
2544
+ else resolve10(msg.result);
2641
2545
  }
2642
2546
  } catch {
2643
2547
  }
@@ -2657,31 +2561,31 @@ var DaemonCdpManager = class {
2657
2561
  }
2658
2562
  }
2659
2563
  getBrowserWsUrl() {
2660
- return new Promise((resolve10) => {
2564
+ return new Promise((resolve9) => {
2661
2565
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
2662
2566
  let data = "";
2663
2567
  res.on("data", (chunk) => data += chunk.toString());
2664
2568
  res.on("end", () => {
2665
2569
  try {
2666
2570
  const info = JSON.parse(data);
2667
- resolve10(info.webSocketDebuggerUrl || null);
2571
+ resolve9(info.webSocketDebuggerUrl || null);
2668
2572
  } catch {
2669
- resolve10(null);
2573
+ resolve9(null);
2670
2574
  }
2671
2575
  });
2672
2576
  });
2673
- req.on("error", () => resolve10(null));
2577
+ req.on("error", () => resolve9(null));
2674
2578
  req.setTimeout(3e3, () => {
2675
2579
  req.destroy();
2676
- resolve10(null);
2580
+ resolve9(null);
2677
2581
  });
2678
2582
  });
2679
2583
  }
2680
2584
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
2681
- return new Promise((resolve10, reject) => {
2585
+ return new Promise((resolve9, reject) => {
2682
2586
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
2683
2587
  const id = this.browserMsgId++;
2684
- this.browserPending.set(id, { resolve: resolve10, reject });
2588
+ this.browserPending.set(id, { resolve: resolve9, reject });
2685
2589
  this.browserWs.send(JSON.stringify({ id, method, params }));
2686
2590
  setTimeout(() => {
2687
2591
  if (this.browserPending.has(id)) {
@@ -2721,11 +2625,11 @@ var DaemonCdpManager = class {
2721
2625
  }
2722
2626
  // ─── CDP Protocol ────────────────────────────────────────
2723
2627
  sendInternal(method, params = {}, timeoutMs = 15e3) {
2724
- return new Promise((resolve10, reject) => {
2628
+ return new Promise((resolve9, reject) => {
2725
2629
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
2726
2630
  if (this.ws.readyState !== WebSocket.OPEN) return reject(new Error("WebSocket not open"));
2727
2631
  const id = this.msgId++;
2728
- this.pending.set(id, { resolve: resolve10, reject });
2632
+ this.pending.set(id, { resolve: resolve9, reject });
2729
2633
  this.ws.send(JSON.stringify({ id, method, params }));
2730
2634
  setTimeout(() => {
2731
2635
  if (this.pending.has(id)) {
@@ -2974,7 +2878,7 @@ var DaemonCdpManager = class {
2974
2878
  const browserWs = this.browserWs;
2975
2879
  let msgId = this.browserMsgId;
2976
2880
  const sendWs = (method, params = {}, sessionId) => {
2977
- return new Promise((resolve10, reject) => {
2881
+ return new Promise((resolve9, reject) => {
2978
2882
  const mid = msgId++;
2979
2883
  this.browserMsgId = msgId;
2980
2884
  const handler = (raw) => {
@@ -2983,7 +2887,7 @@ var DaemonCdpManager = class {
2983
2887
  if (msg.id === mid) {
2984
2888
  browserWs.removeListener("message", handler);
2985
2889
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
2986
- else resolve10(msg.result);
2890
+ else resolve9(msg.result);
2987
2891
  }
2988
2892
  } catch {
2989
2893
  }
@@ -3174,14 +3078,14 @@ var DaemonCdpManager = class {
3174
3078
  if (!ws || ws.readyState !== WebSocket.OPEN) {
3175
3079
  throw new Error("CDP not connected");
3176
3080
  }
3177
- return new Promise((resolve10, reject) => {
3081
+ return new Promise((resolve9, reject) => {
3178
3082
  const id = getNextId();
3179
3083
  pendingMap.set(id, {
3180
3084
  resolve: (result) => {
3181
3085
  if (result?.result?.subtype === "error") {
3182
3086
  reject(new Error(result.result.description));
3183
3087
  } else {
3184
- resolve10(result?.result?.value);
3088
+ resolve9(result?.result?.value);
3185
3089
  }
3186
3090
  },
3187
3091
  reject
@@ -3213,10 +3117,10 @@ var DaemonCdpManager = class {
3213
3117
  throw new Error("CDP not connected");
3214
3118
  }
3215
3119
  const sendViaSession = (method, params = {}) => {
3216
- return new Promise((resolve10, reject) => {
3120
+ return new Promise((resolve9, reject) => {
3217
3121
  const pendingMap = this._browserConnected ? this.browserPending : this.pending;
3218
3122
  const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
3219
- pendingMap.set(id, { resolve: resolve10, reject });
3123
+ pendingMap.set(id, { resolve: resolve9, reject });
3220
3124
  ws.send(JSON.stringify({ id, sessionId, method, params }));
3221
3125
  setTimeout(() => {
3222
3126
  if (pendingMap.has(id)) {
@@ -3923,9 +3827,9 @@ var ExtensionProviderInstance = class {
3923
3827
 
3924
3828
  // src/config/chat-history.ts
3925
3829
  import * as fs3 from "fs";
3926
- import * as path5 from "path";
3830
+ import * as path4 from "path";
3927
3831
  import * as os5 from "os";
3928
- var HISTORY_DIR = path5.join(os5.homedir(), ".adhdev", "history");
3832
+ var HISTORY_DIR = path4.join(os5.homedir(), ".adhdev", "history");
3929
3833
  var RETAIN_DAYS = 30;
3930
3834
  var ChatHistoryWriter = class {
3931
3835
  /** Last seen message count per agent (deduplication) */
@@ -3968,11 +3872,11 @@ var ChatHistoryWriter = class {
3968
3872
  });
3969
3873
  }
3970
3874
  if (newMessages.length === 0) return;
3971
- const dir = path5.join(HISTORY_DIR, this.sanitize(agentType));
3875
+ const dir = path4.join(HISTORY_DIR, this.sanitize(agentType));
3972
3876
  fs3.mkdirSync(dir, { recursive: true });
3973
3877
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3974
3878
  const filePrefix = instanceId ? `${this.sanitize(instanceId)}_` : "";
3975
- const filePath = path5.join(dir, `${filePrefix}${date}.jsonl`);
3879
+ const filePath = path4.join(dir, `${filePrefix}${date}.jsonl`);
3976
3880
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
3977
3881
  fs3.appendFileSync(filePath, lines, "utf-8");
3978
3882
  const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
@@ -4016,11 +3920,11 @@ ${next}`;
4016
3920
  this.lastSeenTerminal.set(dedupKey, next);
4017
3921
  return;
4018
3922
  }
4019
- const dir = path5.join(HISTORY_DIR, this.sanitize(agentType));
3923
+ const dir = path4.join(HISTORY_DIR, this.sanitize(agentType));
4020
3924
  fs3.mkdirSync(dir, { recursive: true });
4021
3925
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4022
3926
  const filePrefix = instanceId ? `${this.sanitize(instanceId)}_` : "";
4023
- const filePath = path5.join(dir, `${filePrefix}${date}.terminal.log`);
3927
+ const filePath = path4.join(dir, `${filePrefix}${date}.terminal.log`);
4024
3928
  fs3.appendFileSync(filePath, delta, "utf-8");
4025
3929
  this.lastSeenTerminal.set(dedupKey, next);
4026
3930
  if (!this.rotated) {
@@ -4044,10 +3948,10 @@ ${next}`;
4044
3948
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
4045
3949
  const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
4046
3950
  for (const dir of agentDirs) {
4047
- const dirPath = path5.join(HISTORY_DIR, dir.name);
3951
+ const dirPath = path4.join(HISTORY_DIR, dir.name);
4048
3952
  const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
4049
3953
  for (const file of files) {
4050
- const filePath = path5.join(dirPath, file);
3954
+ const filePath = path4.join(dirPath, file);
4051
3955
  const stat = fs3.statSync(filePath);
4052
3956
  if (stat.mtimeMs < cutoff) {
4053
3957
  fs3.unlinkSync(filePath);
@@ -4065,7 +3969,7 @@ ${next}`;
4065
3969
  function readChatHistory(agentType, offset = 0, limit = 30, instanceId) {
4066
3970
  try {
4067
3971
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
4068
- const dir = path5.join(HISTORY_DIR, sanitized);
3972
+ const dir = path4.join(HISTORY_DIR, sanitized);
4069
3973
  if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
4070
3974
  const sanitizedInstance = instanceId?.replace(/[^a-zA-Z0-9_-]/g, "_");
4071
3975
  const files = fs3.readdirSync(dir).filter((f) => {
@@ -4079,7 +3983,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, instanceId) {
4079
3983
  const needed = offset + limit + 1;
4080
3984
  for (const file of files) {
4081
3985
  if (allMessages.length >= needed) break;
4082
- const filePath = path5.join(dir, file);
3986
+ const filePath = path4.join(dir, file);
4083
3987
  const content = fs3.readFileSync(filePath, "utf-8");
4084
3988
  const lines = content.trim().split("\n").filter(Boolean);
4085
3989
  for (let i = lines.length - 1; i >= 0; i--) {
@@ -5147,11 +5051,18 @@ function buildSessionEntries(allStates, cdpManagers) {
5147
5051
  for (const state of acpStates) {
5148
5052
  sessions.push(buildAcpSession(state));
5149
5053
  }
5054
+ const extensionParentIds = new Set(
5055
+ sessions.filter((session) => session.transport === "cdp-webview" && !!session.parentId).map((session) => session.parentId)
5056
+ );
5057
+ for (const session of sessions) {
5058
+ if (session.transport === "cdp-page" && extensionParentIds.has(session.id)) {
5059
+ session.surfaceHidden = true;
5060
+ }
5061
+ }
5150
5062
  return sessions;
5151
5063
  }
5152
5064
 
5153
5065
  // src/commands/handler.ts
5154
- init_config();
5155
5066
  init_logger();
5156
5067
 
5157
5068
  // src/commands/chat-commands.ts
@@ -5976,7 +5887,7 @@ async function handleResolveAction(h, args) {
5976
5887
 
5977
5888
  // src/commands/cdp-commands.ts
5978
5889
  import * as fs4 from "fs";
5979
- import * as path6 from "path";
5890
+ import * as path5 from "path";
5980
5891
  import * as os6 from "os";
5981
5892
  var KEY_TO_VK = {
5982
5893
  Backspace: 8,
@@ -6207,11 +6118,11 @@ function resolveSafePath(requestedPath) {
6207
6118
  const home = os6.homedir();
6208
6119
  let resolved;
6209
6120
  if (requestedPath.startsWith("~")) {
6210
- resolved = path6.join(home, requestedPath.slice(1));
6211
- } else if (path6.isAbsolute(requestedPath)) {
6121
+ resolved = path5.join(home, requestedPath.slice(1));
6122
+ } else if (path5.isAbsolute(requestedPath)) {
6212
6123
  resolved = requestedPath;
6213
6124
  } else {
6214
- resolved = path6.resolve(requestedPath);
6125
+ resolved = path5.resolve(requestedPath);
6215
6126
  }
6216
6127
  return resolved;
6217
6128
  }
@@ -6227,7 +6138,7 @@ async function handleFileRead(h, args) {
6227
6138
  async function handleFileWrite(h, args) {
6228
6139
  try {
6229
6140
  const filePath = resolveSafePath(args?.path);
6230
- fs4.mkdirSync(path6.dirname(filePath), { recursive: true });
6141
+ fs4.mkdirSync(path5.dirname(filePath), { recursive: true });
6231
6142
  fs4.writeFileSync(filePath, args?.content || "", "utf-8");
6232
6143
  return { success: true, path: filePath };
6233
6144
  } catch (e) {
@@ -6241,7 +6152,7 @@ async function handleFileList(h, args) {
6241
6152
  const files = entries.map((e) => ({
6242
6153
  name: e.name,
6243
6154
  type: e.isDirectory() ? "directory" : "file",
6244
- size: e.isFile() ? fs4.statSync(path6.join(dirPath, e.name)).size : void 0
6155
+ size: e.isFile() ? fs4.statSync(path5.join(dirPath, e.name)).size : void 0
6245
6156
  }));
6246
6157
  return { success: true, files, path: dirPath };
6247
6158
  } catch (e) {
@@ -6253,7 +6164,6 @@ async function handleFileListBrowse(h, args) {
6253
6164
  }
6254
6165
 
6255
6166
  // src/commands/stream-commands.ts
6256
- init_config();
6257
6167
  init_logger();
6258
6168
  async function handleFocusSession(h, args) {
6259
6169
  if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
@@ -6407,13 +6317,12 @@ function handleGetIdeExtensions(h, args) {
6407
6317
  const loader = h.ctx.providerLoader;
6408
6318
  if (!loader) return { success: false, error: "ProviderLoader not initialized" };
6409
6319
  const allExtProviders = loader.getByCategory?.("extension") || [];
6410
- const config = loadConfig();
6411
6320
  if (ideType) {
6412
6321
  const extensions = allExtProviders.map((p) => ({
6413
6322
  type: p.type,
6414
6323
  name: p.name,
6415
6324
  extensionId: p.extensionId,
6416
- enabled: config.ideSettings?.[ideType]?.extensions?.[p.type]?.enabled === true
6325
+ enabled: loader.getIdeExtensionEnabledState?.(ideType, p.type) === true
6417
6326
  }));
6418
6327
  return { success: true, ideType, extensions };
6419
6328
  }
@@ -6424,7 +6333,7 @@ function handleGetIdeExtensions(h, args) {
6424
6333
  type: p.type,
6425
6334
  name: p.name,
6426
6335
  extensionId: p.extensionId,
6427
- enabled: config.ideSettings?.[ide]?.extensions?.[p.type]?.enabled === true
6336
+ enabled: loader.getIdeExtensionEnabledState?.(ide, p.type) === true
6428
6337
  }));
6429
6338
  }
6430
6339
  return { success: true, ideExtensions: result };
@@ -6447,7 +6356,6 @@ function handleSetIdeExtension(h, args) {
6447
6356
 
6448
6357
  // src/commands/workspace-commands.ts
6449
6358
  init_config();
6450
- init_workspaces();
6451
6359
  function handleWorkspaceList() {
6452
6360
  const config = loadConfig();
6453
6361
  const state = getWorkspaceState(config);
@@ -6455,9 +6363,7 @@ function handleWorkspaceList() {
6455
6363
  success: true,
6456
6364
  workspaces: state.workspaces,
6457
6365
  defaultWorkspaceId: state.defaultWorkspaceId,
6458
- defaultWorkspacePath: state.defaultWorkspacePath,
6459
- legacyRecentPaths: config.recentCliWorkspaces || [],
6460
- activity: getWorkspaceActivity(config, 25)
6366
+ defaultWorkspacePath: state.defaultWorkspacePath
6461
6367
  };
6462
6368
  }
6463
6369
  function handleWorkspaceAdd(args) {
@@ -6468,10 +6374,9 @@ function handleWorkspaceAdd(args) {
6468
6374
  const config = loadConfig();
6469
6375
  const result = addWorkspaceEntry(config, rawPath, label, { createIfMissing });
6470
6376
  if ("error" in result) return { success: false, error: result.error };
6471
- let cfg = appendWorkspaceActivity(result.config, result.entry.path, {});
6472
- saveConfig(cfg);
6473
- const state = getWorkspaceState(cfg);
6474
- return { success: true, entry: result.entry, ...state, activity: getWorkspaceActivity(cfg, 25) };
6377
+ saveConfig(result.config);
6378
+ const state = getWorkspaceState(result.config);
6379
+ return { success: true, entry: result.entry, ...state };
6475
6380
  }
6476
6381
  function handleWorkspaceRemove(args) {
6477
6382
  const id = (args?.id || "").trim();
@@ -6480,13 +6385,9 @@ function handleWorkspaceRemove(args) {
6480
6385
  const removed = (config.workspaces || []).find((w) => w.id === id);
6481
6386
  const result = removeWorkspaceEntry(config, id);
6482
6387
  if ("error" in result) return { success: false, error: result.error };
6483
- let cfg = result.config;
6484
- if (removed) {
6485
- cfg = removeActivityForPath(cfg, removed.path);
6486
- }
6487
- saveConfig(cfg);
6488
- const state = getWorkspaceState(cfg);
6489
- return { success: true, removedId: id, ...state, activity: getWorkspaceActivity(cfg, 25) };
6388
+ saveConfig(result.config);
6389
+ const state = getWorkspaceState(result.config);
6390
+ return { success: true, removedId: id, ...state };
6490
6391
  }
6491
6392
  function handleWorkspaceSetDefault(args) {
6492
6393
  const clear = args?.clear === true || args?.id === null || args?.id === "";
@@ -6498,8 +6399,7 @@ function handleWorkspaceSetDefault(args) {
6498
6399
  const state2 = getWorkspaceState(result2.config);
6499
6400
  return {
6500
6401
  success: true,
6501
- ...state2,
6502
- activity: getWorkspaceActivity(result2.config, 25)
6402
+ ...state2
6503
6403
  };
6504
6404
  }
6505
6405
  const pathArg = args?.path != null && String(args.path).trim() ? String(args.path).trim() : "";
@@ -6523,18 +6423,12 @@ function handleWorkspaceSetDefault(args) {
6523
6423
  }
6524
6424
  const result = setDefaultWorkspaceId(config, nextId);
6525
6425
  if ("error" in result) return { success: false, error: result.error };
6526
- let out = result.config;
6527
- const ap = getDefaultWorkspacePath(out);
6528
- if (ap) {
6529
- out = appendWorkspaceActivity(out, ap, { kind: "default" });
6530
- }
6531
- saveConfig(out);
6532
- const state = getWorkspaceState(out);
6533
- return { success: true, ...state, activity: getWorkspaceActivity(out, 25) };
6426
+ saveConfig(result.config);
6427
+ const state = getWorkspaceState(result.config);
6428
+ return { success: true, ...state };
6534
6429
  }
6535
6430
 
6536
6431
  // src/commands/handler.ts
6537
- init_workspaces();
6538
6432
  var COMMAND_DEBUG_LEVELS = /* @__PURE__ */ new Set([
6539
6433
  "pty_input",
6540
6434
  "pty_resize",
@@ -6861,22 +6755,7 @@ var DaemonCommandHandler = class {
6861
6755
  return handleFileList(this, args);
6862
6756
  case "file_list_browse":
6863
6757
  return handleFileListBrowse(this, args);
6864
- // ─── VSCode API commands (not available) ────
6865
- case "vscode_command_exec":
6866
- case "execute_vscode_command": {
6867
- const resolvedCmd = args?.commandId || args?.command;
6868
- if (resolvedCmd === "adhdev.captureCdpScreenshot") {
6869
- return handleScreenshot(this, args);
6870
- }
6871
- return { success: false, error: `VSCode command not available: ${resolvedCmd || cmd}` };
6872
- }
6873
6758
  // ─── Workspace cmds ──────────────
6874
- case "get_recent_workspaces":
6875
- return this.handleGetRecentWorkspaces(args);
6876
- case "get_cli_history": {
6877
- const config = loadConfig();
6878
- return { success: true, history: config.cliHistory || [] };
6879
- }
6880
6759
  case "workspace_list":
6881
6760
  return handleWorkspaceList();
6882
6761
  case "workspace_add":
@@ -6884,7 +6763,6 @@ var DaemonCommandHandler = class {
6884
6763
  case "workspace_remove":
6885
6764
  return handleWorkspaceRemove(args);
6886
6765
  case "workspace_set_default":
6887
- case "workspace_set_active":
6888
6766
  return handleWorkspaceSetDefault(args);
6889
6767
  // ─── Script manage ───────────────────
6890
6768
  case "refresh_scripts":
@@ -6930,19 +6808,6 @@ var DaemonCommandHandler = class {
6930
6808
  }
6931
6809
  }
6932
6810
  // ─── Misc (kept in handler — too small to extract) ───────
6933
- async handleGetRecentWorkspaces(_args) {
6934
- const config = loadConfig();
6935
- const cliRecent = config.recentCliWorkspaces || [];
6936
- const ws = getWorkspaceState(config);
6937
- return {
6938
- success: true,
6939
- result: cliRecent,
6940
- workspaces: ws.workspaces,
6941
- defaultWorkspaceId: ws.defaultWorkspaceId,
6942
- defaultWorkspacePath: ws.defaultWorkspacePath,
6943
- activity: getWorkspaceActivity(config, 25)
6944
- };
6945
- }
6946
6811
  async handleRefreshScripts(_args) {
6947
6812
  if (this._ctx.providerLoader) {
6948
6813
  await this._ctx.providerLoader.fetchLatest().catch(() => {
@@ -6960,7 +6825,7 @@ var DaemonCommandHandler = class {
6960
6825
  try {
6961
6826
  const http3 = await import("http");
6962
6827
  const postData = JSON.stringify(body);
6963
- const result = await new Promise((resolve10, reject) => {
6828
+ const result = await new Promise((resolve9, reject) => {
6964
6829
  const req = http3.request({
6965
6830
  hostname: "127.0.0.1",
6966
6831
  port: 19280,
@@ -6972,9 +6837,9 @@ var DaemonCommandHandler = class {
6972
6837
  res.on("data", (chunk) => data += chunk);
6973
6838
  res.on("end", () => {
6974
6839
  try {
6975
- resolve10(JSON.parse(data));
6840
+ resolve9(JSON.parse(data));
6976
6841
  } catch {
6977
- resolve10({ raw: data });
6842
+ resolve9({ raw: data });
6978
6843
  }
6979
6844
  });
6980
6845
  });
@@ -6992,15 +6857,15 @@ var DaemonCommandHandler = class {
6992
6857
  if (!providerType) return { success: false, error: "providerType required" };
6993
6858
  try {
6994
6859
  const http3 = await import("http");
6995
- const result = await new Promise((resolve10, reject) => {
6860
+ const result = await new Promise((resolve9, reject) => {
6996
6861
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
6997
6862
  let data = "";
6998
6863
  res.on("data", (chunk) => data += chunk);
6999
6864
  res.on("end", () => {
7000
6865
  try {
7001
- resolve10(JSON.parse(data));
6866
+ resolve9(JSON.parse(data));
7002
6867
  } catch {
7003
- resolve10({ raw: data });
6868
+ resolve9({ raw: data });
7004
6869
  }
7005
6870
  });
7006
6871
  }).on("error", reject);
@@ -7014,7 +6879,7 @@ var DaemonCommandHandler = class {
7014
6879
  try {
7015
6880
  const http3 = await import("http");
7016
6881
  const postData = JSON.stringify(args || {});
7017
- const result = await new Promise((resolve10, reject) => {
6882
+ const result = await new Promise((resolve9, reject) => {
7018
6883
  const req = http3.request({
7019
6884
  hostname: "127.0.0.1",
7020
6885
  port: 19280,
@@ -7026,9 +6891,9 @@ var DaemonCommandHandler = class {
7026
6891
  res.on("data", (chunk) => data += chunk);
7027
6892
  res.on("end", () => {
7028
6893
  try {
7029
- resolve10(JSON.parse(data));
6894
+ resolve9(JSON.parse(data));
7030
6895
  } catch {
7031
- resolve10({ raw: data });
6896
+ resolve9({ raw: data });
7032
6897
  }
7033
6898
  });
7034
6899
  });
@@ -7047,11 +6912,11 @@ var DaemonCommandHandler = class {
7047
6912
  import { execSync as execSync3, spawn } from "child_process";
7048
6913
  import * as net from "net";
7049
6914
  import * as os8 from "os";
7050
- import * as path8 from "path";
6915
+ import * as path7 from "path";
7051
6916
 
7052
6917
  // src/providers/provider-loader.ts
7053
6918
  import * as fs5 from "fs";
7054
- import * as path7 from "path";
6919
+ import * as path6 from "path";
7055
6920
  import * as os7 from "os";
7056
6921
  import * as chokidar from "chokidar";
7057
6922
  init_logger();
@@ -7072,12 +6937,12 @@ var ProviderLoader = class _ProviderLoader {
7072
6937
  static META_FILE = ".meta.json";
7073
6938
  constructor(options) {
7074
6939
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
7075
- const defaultProvidersDir = path7.join(os7.homedir(), ".adhdev", "providers");
6940
+ const defaultProvidersDir = path6.join(os7.homedir(), ".adhdev", "providers");
7076
6941
  if (options?.userDir) {
7077
6942
  this.userDir = options.userDir;
7078
6943
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
7079
6944
  } else {
7080
- const localRepoPath = path7.resolve(__dirname, "../../../../../adhdev-providers");
6945
+ const localRepoPath = path6.resolve(__dirname, "../../../../../adhdev-providers");
7081
6946
  if (fs5.existsSync(localRepoPath)) {
7082
6947
  this.userDir = localRepoPath;
7083
6948
  this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
@@ -7086,7 +6951,7 @@ var ProviderLoader = class _ProviderLoader {
7086
6951
  this.log(`Using default user providers directory: ${this.userDir}`);
7087
6952
  }
7088
6953
  }
7089
- this.upstreamDir = path7.join(defaultProvidersDir, ".upstream");
6954
+ this.upstreamDir = path6.join(defaultProvidersDir, ".upstream");
7090
6955
  this.disableUpstream = options?.disableUpstream ?? false;
7091
6956
  }
7092
6957
  log(msg) {
@@ -7116,7 +6981,7 @@ var ProviderLoader = class _ProviderLoader {
7116
6981
  * Canonical provider directory shape for a given root.
7117
6982
  */
7118
6983
  getProviderDir(root, category, type) {
7119
- return path7.join(root, category, type);
6984
+ return path6.join(root, category, type);
7120
6985
  }
7121
6986
  /**
7122
6987
  * Canonical user override directory for a provider.
@@ -7143,7 +7008,7 @@ var ProviderLoader = class _ProviderLoader {
7143
7008
  resolveProviderFile(type, ...segments) {
7144
7009
  const dir = this.findProviderDirInternal(type);
7145
7010
  if (!dir) return null;
7146
- return path7.join(dir, ...segments);
7011
+ return path6.join(dir, ...segments);
7147
7012
  }
7148
7013
  /**
7149
7014
  * Load all providers (3-tier priority)
@@ -7181,7 +7046,7 @@ var ProviderLoader = class _ProviderLoader {
7181
7046
  if (!fs5.existsSync(this.upstreamDir)) return false;
7182
7047
  try {
7183
7048
  return fs5.readdirSync(this.upstreamDir).some(
7184
- (d) => fs5.statSync(path7.join(this.upstreamDir, d)).isDirectory()
7049
+ (d) => fs5.statSync(path6.join(this.upstreamDir, d)).isDirectory()
7185
7050
  );
7186
7051
  } catch {
7187
7052
  return false;
@@ -7266,16 +7131,23 @@ var ProviderLoader = class _ProviderLoader {
7266
7131
  isEnabled(type, ideType) {
7267
7132
  if (!ideType) return true;
7268
7133
  try {
7269
- const { loadConfig: loadConfig2 } = (init_config(), __toCommonJS(config_exports));
7270
- const config = loadConfig2();
7271
- const baseIdeType = ideType.split("_")[0];
7272
- const val = config.ideSettings?.[baseIdeType]?.extensions?.[type]?.enabled;
7273
- return val === true;
7134
+ return this.getIdeExtensionEnabledState(ideType, type);
7274
7135
  } catch {
7275
7136
  return false;
7276
7137
  }
7277
7138
  }
7278
7139
  /**
7140
+ * Resolve per-IDE extension enabled state using the same normalization
7141
+ * that runtime attach/remove uses.
7142
+ */
7143
+ getIdeExtensionEnabledState(ideType, extensionType) {
7144
+ const { loadConfig: loadConfig2 } = (init_config(), __toCommonJS(config_exports));
7145
+ const config = loadConfig2();
7146
+ const baseIdeType = ideType.split("_")[0];
7147
+ const val = config.ideSettings?.[baseIdeType]?.extensions?.[extensionType]?.enabled;
7148
+ return val === true;
7149
+ }
7150
+ /**
7279
7151
  * Save IDE extension enabled setting
7280
7152
  */
7281
7153
  setIdeExtensionEnabled(ideType, extensionType, enabled) {
@@ -7473,14 +7345,14 @@ var ProviderLoader = class _ProviderLoader {
7473
7345
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
7474
7346
  return null;
7475
7347
  }
7476
- const dir = path7.join(providerDir, scriptDir);
7348
+ const dir = path6.join(providerDir, scriptDir);
7477
7349
  if (!fs5.existsSync(dir)) {
7478
7350
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
7479
7351
  return null;
7480
7352
  }
7481
7353
  const cached = this.scriptsCache.get(dir);
7482
7354
  if (cached) return cached;
7483
- const scriptsJs = path7.join(dir, "scripts.js");
7355
+ const scriptsJs = path6.join(dir, "scripts.js");
7484
7356
  if (fs5.existsSync(scriptsJs)) {
7485
7357
  try {
7486
7358
  delete __require.cache[__require.resolve(scriptsJs)];
@@ -7519,7 +7391,7 @@ var ProviderLoader = class _ProviderLoader {
7519
7391
  });
7520
7392
  const handleChange = (filePath) => {
7521
7393
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
7522
- this.log(`File changed: ${path7.basename(filePath)}, reloading...`);
7394
+ this.log(`File changed: ${path6.basename(filePath)}, reloading...`);
7523
7395
  this.reload();
7524
7396
  }
7525
7397
  };
@@ -7574,7 +7446,7 @@ var ProviderLoader = class _ProviderLoader {
7574
7446
  }
7575
7447
  const https = __require("https");
7576
7448
  const { execSync: execSync7 } = __require("child_process");
7577
- const metaPath = path7.join(this.upstreamDir, _ProviderLoader.META_FILE);
7449
+ const metaPath = path6.join(this.upstreamDir, _ProviderLoader.META_FILE);
7578
7450
  let prevEtag = "";
7579
7451
  let prevTimestamp = 0;
7580
7452
  try {
@@ -7591,7 +7463,7 @@ var ProviderLoader = class _ProviderLoader {
7591
7463
  return { updated: false };
7592
7464
  }
7593
7465
  try {
7594
- const etag = await new Promise((resolve10, reject) => {
7466
+ const etag = await new Promise((resolve9, reject) => {
7595
7467
  const options = {
7596
7468
  method: "HEAD",
7597
7469
  hostname: "github.com",
@@ -7609,7 +7481,7 @@ var ProviderLoader = class _ProviderLoader {
7609
7481
  headers: { "User-Agent": "adhdev-launcher" },
7610
7482
  timeout: 1e4
7611
7483
  }, (res2) => {
7612
- resolve10(res2.headers.etag || res2.headers["last-modified"] || "");
7484
+ resolve9(res2.headers.etag || res2.headers["last-modified"] || "");
7613
7485
  });
7614
7486
  req2.on("error", reject);
7615
7487
  req2.on("timeout", () => {
@@ -7618,7 +7490,7 @@ var ProviderLoader = class _ProviderLoader {
7618
7490
  });
7619
7491
  req2.end();
7620
7492
  } else {
7621
- resolve10(res.headers.etag || res.headers["last-modified"] || "");
7493
+ resolve9(res.headers.etag || res.headers["last-modified"] || "");
7622
7494
  }
7623
7495
  });
7624
7496
  req.on("error", reject);
@@ -7634,17 +7506,17 @@ var ProviderLoader = class _ProviderLoader {
7634
7506
  return { updated: false };
7635
7507
  }
7636
7508
  this.log("Downloading latest providers from GitHub...");
7637
- const tmpTar = path7.join(os7.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
7638
- const tmpExtract = path7.join(os7.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
7509
+ const tmpTar = path6.join(os7.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
7510
+ const tmpExtract = path6.join(os7.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
7639
7511
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
7640
7512
  fs5.mkdirSync(tmpExtract, { recursive: true });
7641
7513
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
7642
7514
  const extracted = fs5.readdirSync(tmpExtract);
7643
7515
  const rootDir = extracted.find(
7644
- (d) => fs5.statSync(path7.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
7516
+ (d) => fs5.statSync(path6.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
7645
7517
  );
7646
7518
  if (!rootDir) throw new Error("Unexpected tarball structure");
7647
- const sourceDir = path7.join(tmpExtract, rootDir);
7519
+ const sourceDir = path6.join(tmpExtract, rootDir);
7648
7520
  const backupDir = this.upstreamDir + ".bak";
7649
7521
  if (fs5.existsSync(this.upstreamDir)) {
7650
7522
  if (fs5.existsSync(backupDir)) fs5.rmSync(backupDir, { recursive: true, force: true });
@@ -7682,7 +7554,7 @@ var ProviderLoader = class _ProviderLoader {
7682
7554
  downloadFile(url, destPath) {
7683
7555
  const https = __require("https");
7684
7556
  const http3 = __require("http");
7685
- return new Promise((resolve10, reject) => {
7557
+ return new Promise((resolve9, reject) => {
7686
7558
  const doRequest = (reqUrl, redirectCount = 0) => {
7687
7559
  if (redirectCount > 5) {
7688
7560
  reject(new Error("Too many redirects"));
@@ -7702,7 +7574,7 @@ var ProviderLoader = class _ProviderLoader {
7702
7574
  res.pipe(ws);
7703
7575
  ws.on("finish", () => {
7704
7576
  ws.close();
7705
- resolve10();
7577
+ resolve9();
7706
7578
  });
7707
7579
  ws.on("error", reject);
7708
7580
  });
@@ -7719,8 +7591,8 @@ var ProviderLoader = class _ProviderLoader {
7719
7591
  copyDirRecursive(src, dest) {
7720
7592
  fs5.mkdirSync(dest, { recursive: true });
7721
7593
  for (const entry of fs5.readdirSync(src, { withFileTypes: true })) {
7722
- const srcPath = path7.join(src, entry.name);
7723
- const destPath = path7.join(dest, entry.name);
7594
+ const srcPath = path6.join(src, entry.name);
7595
+ const destPath = path6.join(dest, entry.name);
7724
7596
  if (entry.isDirectory()) {
7725
7597
  this.copyDirRecursive(srcPath, destPath);
7726
7598
  } else {
@@ -7731,7 +7603,7 @@ var ProviderLoader = class _ProviderLoader {
7731
7603
  /** .meta.json save */
7732
7604
  writeMeta(metaPath, etag, timestamp) {
7733
7605
  try {
7734
- fs5.mkdirSync(path7.dirname(metaPath), { recursive: true });
7606
+ fs5.mkdirSync(path6.dirname(metaPath), { recursive: true });
7735
7607
  fs5.writeFileSync(metaPath, JSON.stringify({
7736
7608
  etag,
7737
7609
  timestamp,
@@ -7748,7 +7620,7 @@ var ProviderLoader = class _ProviderLoader {
7748
7620
  const scan = (d) => {
7749
7621
  try {
7750
7622
  for (const entry of fs5.readdirSync(d, { withFileTypes: true })) {
7751
- if (entry.isDirectory()) scan(path7.join(d, entry.name));
7623
+ if (entry.isDirectory()) scan(path6.join(d, entry.name));
7752
7624
  else if (entry.name === "provider.json") count++;
7753
7625
  }
7754
7626
  } catch {
@@ -7847,17 +7719,17 @@ var ProviderLoader = class _ProviderLoader {
7847
7719
  for (const root of searchRoots) {
7848
7720
  if (!fs5.existsSync(root)) continue;
7849
7721
  const candidate = this.getProviderDir(root, cat, type);
7850
- if (fs5.existsSync(path7.join(candidate, "provider.json"))) return candidate;
7851
- const catDir = path7.join(root, cat);
7722
+ if (fs5.existsSync(path6.join(candidate, "provider.json"))) return candidate;
7723
+ const catDir = path6.join(root, cat);
7852
7724
  if (fs5.existsSync(catDir)) {
7853
7725
  try {
7854
7726
  for (const entry of fs5.readdirSync(catDir, { withFileTypes: true })) {
7855
7727
  if (!entry.isDirectory()) continue;
7856
- const jsonPath = path7.join(catDir, entry.name, "provider.json");
7728
+ const jsonPath = path6.join(catDir, entry.name, "provider.json");
7857
7729
  if (fs5.existsSync(jsonPath)) {
7858
7730
  try {
7859
7731
  const data = JSON.parse(fs5.readFileSync(jsonPath, "utf-8"));
7860
- if (data.type === type) return path7.join(catDir, entry.name);
7732
+ if (data.type === type) return path6.join(catDir, entry.name);
7861
7733
  } catch {
7862
7734
  }
7863
7735
  }
@@ -7874,7 +7746,7 @@ var ProviderLoader = class _ProviderLoader {
7874
7746
  * (template substitution is NOT applied here — scripts.js handles that)
7875
7747
  */
7876
7748
  buildScriptWrappersFromDir(dir) {
7877
- const scriptsJs = path7.join(dir, "scripts.js");
7749
+ const scriptsJs = path6.join(dir, "scripts.js");
7878
7750
  if (fs5.existsSync(scriptsJs)) {
7879
7751
  try {
7880
7752
  delete __require.cache[__require.resolve(scriptsJs)];
@@ -7888,7 +7760,7 @@ var ProviderLoader = class _ProviderLoader {
7888
7760
  for (const file of fs5.readdirSync(dir)) {
7889
7761
  if (!file.endsWith(".js")) continue;
7890
7762
  const scriptName = toCamel(file.replace(".js", ""));
7891
- const filePath = path7.join(dir, file);
7763
+ const filePath = path6.join(dir, file);
7892
7764
  result[scriptName] = (...args) => {
7893
7765
  try {
7894
7766
  let content = fs5.readFileSync(filePath, "utf-8");
@@ -7948,7 +7820,7 @@ var ProviderLoader = class _ProviderLoader {
7948
7820
  }
7949
7821
  const hasJson = entries.some((e) => e.name === "provider.json");
7950
7822
  if (hasJson) {
7951
- const jsonPath = path7.join(d, "provider.json");
7823
+ const jsonPath = path6.join(d, "provider.json");
7952
7824
  try {
7953
7825
  const raw = fs5.readFileSync(jsonPath, "utf-8");
7954
7826
  const mod = JSON.parse(raw);
@@ -7961,7 +7833,7 @@ var ProviderLoader = class _ProviderLoader {
7961
7833
  delete mod.extensionIdPattern_flags;
7962
7834
  }
7963
7835
  const hasCompatibility = Array.isArray(mod.compatibility);
7964
- const scriptsPath = path7.join(d, "scripts.js");
7836
+ const scriptsPath = path6.join(d, "scripts.js");
7965
7837
  if (!hasCompatibility && fs5.existsSync(scriptsPath)) {
7966
7838
  try {
7967
7839
  delete __require.cache[__require.resolve(scriptsPath)];
@@ -7987,7 +7859,7 @@ var ProviderLoader = class _ProviderLoader {
7987
7859
  if (!entry.isDirectory()) continue;
7988
7860
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
7989
7861
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
7990
- scan(path7.join(d, entry.name));
7862
+ scan(path6.join(d, entry.name));
7991
7863
  }
7992
7864
  }
7993
7865
  };
@@ -8067,17 +7939,17 @@ async function findFreePort(ports) {
8067
7939
  throw new Error("No free port found");
8068
7940
  }
8069
7941
  function checkPortFree(port) {
8070
- return new Promise((resolve10) => {
7942
+ return new Promise((resolve9) => {
8071
7943
  const server = net.createServer();
8072
7944
  server.unref();
8073
- server.on("error", () => resolve10(false));
7945
+ server.on("error", () => resolve9(false));
8074
7946
  server.listen(port, "127.0.0.1", () => {
8075
- server.close(() => resolve10(true));
7947
+ server.close(() => resolve9(true));
8076
7948
  });
8077
7949
  });
8078
7950
  }
8079
7951
  async function isCdpActive(port) {
8080
- return new Promise((resolve10) => {
7952
+ return new Promise((resolve9) => {
8081
7953
  const req = __require("http").get(`http://127.0.0.1:${port}/json/version`, {
8082
7954
  timeout: 2e3
8083
7955
  }, (res) => {
@@ -8086,16 +7958,16 @@ async function isCdpActive(port) {
8086
7958
  res.on("end", () => {
8087
7959
  try {
8088
7960
  const info = JSON.parse(data);
8089
- resolve10(!!info["WebKit-Version"] || !!info["Browser"]);
7961
+ resolve9(!!info["WebKit-Version"] || !!info["Browser"]);
8090
7962
  } catch {
8091
- resolve10(false);
7963
+ resolve9(false);
8092
7964
  }
8093
7965
  });
8094
7966
  });
8095
- req.on("error", () => resolve10(false));
7967
+ req.on("error", () => resolve9(false));
8096
7968
  req.on("timeout", () => {
8097
7969
  req.destroy();
8098
- resolve10(false);
7970
+ resolve9(false);
8099
7971
  });
8100
7972
  });
8101
7973
  }
@@ -8214,8 +8086,8 @@ function detectCurrentWorkspace(ideId) {
8214
8086
  const appNameMap = getMacAppIdentifiers();
8215
8087
  const appName = appNameMap[ideId];
8216
8088
  if (appName) {
8217
- const storagePath = path8.join(
8218
- process.env.APPDATA || path8.join(os8.homedir(), "AppData", "Roaming"),
8089
+ const storagePath = path7.join(
8090
+ process.env.APPDATA || path7.join(os8.homedir(), "AppData", "Roaming"),
8219
8091
  appName,
8220
8092
  "storage.json"
8221
8093
  );
@@ -8384,15 +8256,13 @@ function getAvailableIdeIds() {
8384
8256
 
8385
8257
  // src/commands/router.ts
8386
8258
  init_config();
8387
- init_workspaces();
8388
- init_config();
8389
8259
  init_logger();
8390
8260
 
8391
8261
  // src/logging/command-log.ts
8392
8262
  import * as fs6 from "fs";
8393
- import * as path9 from "path";
8263
+ import * as path8 from "path";
8394
8264
  import * as os9 from "os";
8395
- var LOG_DIR2 = process.platform === "win32" ? path9.join(process.env.LOCALAPPDATA || process.env.APPDATA || path9.join(os9.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path9.join(os9.homedir(), "Library", "Logs", "adhdev") : path9.join(os9.homedir(), ".local", "share", "adhdev", "logs");
8265
+ var LOG_DIR2 = process.platform === "win32" ? path8.join(process.env.LOCALAPPDATA || process.env.APPDATA || path8.join(os9.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path8.join(os9.homedir(), "Library", "Logs", "adhdev") : path8.join(os9.homedir(), ".local", "share", "adhdev", "logs");
8396
8266
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
8397
8267
  var MAX_DAYS = 7;
8398
8268
  try {
@@ -8430,13 +8300,13 @@ function getDateStr2() {
8430
8300
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8431
8301
  }
8432
8302
  var currentDate2 = getDateStr2();
8433
- var currentFile = path9.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
8303
+ var currentFile = path8.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
8434
8304
  var writeCount2 = 0;
8435
8305
  function checkRotation() {
8436
8306
  const today = getDateStr2();
8437
8307
  if (today !== currentDate2) {
8438
8308
  currentDate2 = today;
8439
- currentFile = path9.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
8309
+ currentFile = path8.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
8440
8310
  cleanOldFiles();
8441
8311
  }
8442
8312
  }
@@ -8450,7 +8320,7 @@ function cleanOldFiles() {
8450
8320
  const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
8451
8321
  if (dateMatch && dateMatch[1] < cutoffStr) {
8452
8322
  try {
8453
- fs6.unlinkSync(path9.join(LOG_DIR2, file));
8323
+ fs6.unlinkSync(path8.join(LOG_DIR2, file));
8454
8324
  } catch {
8455
8325
  }
8456
8326
  }
@@ -8472,59 +8342,202 @@ function checkSize() {
8472
8342
  } catch {
8473
8343
  }
8474
8344
  }
8475
- var SKIP_COMMANDS = /* @__PURE__ */ new Set([
8476
- "heartbeat",
8477
- "status_report"
8478
- ]);
8479
- function logCommand(entry) {
8480
- if (SKIP_COMMANDS.has(entry.cmd)) return;
8481
- try {
8482
- if (++writeCount2 % 500 === 0) {
8483
- checkRotation();
8484
- checkSize();
8485
- }
8486
- const line = JSON.stringify({
8487
- ts: entry.ts,
8488
- cmd: entry.cmd,
8489
- src: entry.source,
8490
- ...entry.args ? { args: maskArgs(entry.args) } : {},
8491
- ...entry.success !== void 0 ? { ok: entry.success } : {},
8492
- ...entry.error ? { err: entry.error } : {},
8493
- ...entry.durationMs !== void 0 ? { ms: entry.durationMs } : {}
8494
- });
8495
- fs6.appendFileSync(currentFile, line + "\n");
8496
- } catch {
8345
+ var SKIP_COMMANDS = /* @__PURE__ */ new Set([
8346
+ "heartbeat",
8347
+ "status_report"
8348
+ ]);
8349
+ function logCommand(entry) {
8350
+ if (SKIP_COMMANDS.has(entry.cmd)) return;
8351
+ try {
8352
+ if (++writeCount2 % 500 === 0) {
8353
+ checkRotation();
8354
+ checkSize();
8355
+ }
8356
+ const line = JSON.stringify({
8357
+ ts: entry.ts,
8358
+ cmd: entry.cmd,
8359
+ src: entry.source,
8360
+ ...entry.args ? { args: maskArgs(entry.args) } : {},
8361
+ ...entry.success !== void 0 ? { ok: entry.success } : {},
8362
+ ...entry.error ? { err: entry.error } : {},
8363
+ ...entry.durationMs !== void 0 ? { ms: entry.durationMs } : {}
8364
+ });
8365
+ fs6.appendFileSync(currentFile, line + "\n");
8366
+ } catch {
8367
+ }
8368
+ }
8369
+ function getRecentCommands(count = 50) {
8370
+ try {
8371
+ if (!fs6.existsSync(currentFile)) return [];
8372
+ const content = fs6.readFileSync(currentFile, "utf-8");
8373
+ const lines = content.trim().split("\n").filter(Boolean);
8374
+ return lines.slice(-count).map((line) => {
8375
+ try {
8376
+ const parsed = JSON.parse(line);
8377
+ return {
8378
+ ts: parsed.ts,
8379
+ cmd: parsed.cmd,
8380
+ source: parsed.src,
8381
+ args: parsed.args,
8382
+ success: parsed.ok,
8383
+ error: parsed.err,
8384
+ durationMs: parsed.ms
8385
+ };
8386
+ } catch {
8387
+ return { ts: "", cmd: "parse_error", source: "unknown" };
8388
+ }
8389
+ });
8390
+ } catch {
8391
+ return [];
8392
+ }
8393
+ }
8394
+ cleanOldFiles();
8395
+
8396
+ // src/commands/router.ts
8397
+ init_logger();
8398
+
8399
+ // src/status/snapshot.ts
8400
+ init_config();
8401
+ import * as os10 from "os";
8402
+ init_terminal_screen();
8403
+ init_logger();
8404
+ var READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
8405
+ function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
8406
+ return detectedIdes.filter((ide) => ide.installed !== false).map((ide) => ({
8407
+ id: ide.id,
8408
+ type: ide.id,
8409
+ name: ide.displayName || ide.name || ide.id,
8410
+ running: isCdpConnected(cdpManagers, ide.id),
8411
+ ...ide.path ? { path: ide.path } : {}
8412
+ }));
8413
+ }
8414
+ function buildAvailableProviders(providerLoader) {
8415
+ return providerLoader.getAll().map((provider) => ({
8416
+ type: provider.type,
8417
+ name: provider.displayName || provider.type,
8418
+ displayName: provider.displayName || provider.type,
8419
+ icon: provider.icon || "\u{1F4BB}",
8420
+ category: provider.category
8421
+ }));
8422
+ }
8423
+ function parseMessageTime(value) {
8424
+ if (typeof value === "number" && Number.isFinite(value)) return value;
8425
+ if (typeof value === "string") {
8426
+ const parsed = Date.parse(value);
8427
+ if (Number.isFinite(parsed)) return parsed;
8428
+ }
8429
+ return 0;
8430
+ }
8431
+ function getSessionMessageUpdatedAt(session) {
8432
+ const lastMessage = session.activeChat?.messages?.at?.(-1);
8433
+ if (!lastMessage) return 0;
8434
+ return parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt) || 0;
8435
+ }
8436
+ function getSessionCompletionMarker(session) {
8437
+ const lastMessage = session.activeChat?.messages?.at?.(-1);
8438
+ if (!lastMessage) return "";
8439
+ const role = typeof lastMessage.role === "string" ? lastMessage.role : "";
8440
+ if (role === "user" || role === "human") return "";
8441
+ if (typeof lastMessage._turnKey === "string" && lastMessage._turnKey) return `turn:${lastMessage._turnKey}`;
8442
+ if (typeof lastMessage.id === "string" && lastMessage.id) return `id:${lastMessage.id}`;
8443
+ if (typeof lastMessage.index === "number" && Number.isFinite(lastMessage.index)) return `idx:${lastMessage.index}`;
8444
+ const timestamp = parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt);
8445
+ return timestamp > 0 ? `ts:${timestamp}` : "";
8446
+ }
8447
+ function getSessionLastUsedAt(session) {
8448
+ return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
8449
+ }
8450
+ function getLastMessageRole(session) {
8451
+ const role = session.activeChat?.messages?.at?.(-1)?.role;
8452
+ return typeof role === "string" ? role : "";
8453
+ }
8454
+ function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole, completionMarker, seenCompletionMarker) {
8455
+ if (status === "waiting_approval") {
8456
+ return { unread: false, inboxBucket: "needs_attention" };
8457
+ }
8458
+ if (status === "generating" || status === "starting") {
8459
+ return { unread: false, inboxBucket: "working" };
8497
8460
  }
8461
+ const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
8462
+ return { unread, inboxBucket: unread ? "task_complete" : "idle" };
8498
8463
  }
8499
- function getRecentCommands(count = 50) {
8500
- try {
8501
- if (!fs6.existsSync(currentFile)) return [];
8502
- const content = fs6.readFileSync(currentFile, "utf-8");
8503
- const lines = content.trim().split("\n").filter(Boolean);
8504
- return lines.slice(-count).map((line) => {
8505
- try {
8506
- const parsed = JSON.parse(line);
8507
- return {
8508
- ts: parsed.ts,
8509
- cmd: parsed.cmd,
8510
- source: parsed.src,
8511
- args: parsed.args,
8512
- success: parsed.ok,
8513
- error: parsed.err,
8514
- durationMs: parsed.ms
8515
- };
8516
- } catch {
8517
- return { ts: "", cmd: "parse_error", source: "unknown" };
8518
- }
8519
- });
8520
- } catch {
8521
- return [];
8464
+ function buildRecentLaunches(recentActivity) {
8465
+ return recentActivity.map((item) => ({
8466
+ id: item.id,
8467
+ providerType: item.providerType,
8468
+ providerName: item.providerName,
8469
+ kind: item.kind,
8470
+ title: item.title || item.providerName,
8471
+ workspace: item.workspace,
8472
+ currentModel: item.currentModel,
8473
+ lastLaunchedAt: item.lastUsedAt
8474
+ })).sort((a, b) => b.lastLaunchedAt - a.lastLaunchedAt).slice(0, 12);
8475
+ }
8476
+ function buildStatusSnapshot(options) {
8477
+ const cfg = loadConfig();
8478
+ const wsState = getWorkspaceState(cfg);
8479
+ const memSnap = getHostMemorySnapshot();
8480
+ const recentActivity = getRecentActivity(cfg, 20);
8481
+ const sessions = buildSessionEntries(
8482
+ options.allStates,
8483
+ options.cdpManagers
8484
+ );
8485
+ for (const session of sessions) {
8486
+ const lastSeenAt = getSessionSeenAt(cfg, session.id);
8487
+ const seenCompletionMarker = getSessionSeenMarker(cfg, session.id);
8488
+ const lastUsedAt = getSessionLastUsedAt(session);
8489
+ const completionMarker = getSessionCompletionMarker(session);
8490
+ const { unread, inboxBucket } = session.surfaceHidden ? { unread: false, inboxBucket: "idle" } : getUnreadState(
8491
+ getSessionMessageUpdatedAt(session) > 0,
8492
+ session.status,
8493
+ lastUsedAt,
8494
+ lastSeenAt,
8495
+ getLastMessageRole(session),
8496
+ completionMarker,
8497
+ seenCompletionMarker
8498
+ );
8499
+ session.lastSeenAt = lastSeenAt;
8500
+ session.unread = unread;
8501
+ session.inboxBucket = inboxBucket;
8502
+ if (READ_DEBUG_ENABLED && (session.unread || session.inboxBucket !== "idle" || session.providerType.includes("codex"))) {
8503
+ LOG.info(
8504
+ "RecentRead",
8505
+ `snapshot session id=${session.id} provider=${session.providerType} status=${String(session.status || "")} bucket=${inboxBucket} unread=${String(unread)} lastSeenAt=${lastSeenAt} completionMarker=${completionMarker || "-"} seenMarker=${seenCompletionMarker || "-"} lastUpdated=${String(session.lastUpdated || 0)} lastUsedAt=${lastUsedAt} lastRole=${getLastMessageRole(session)} msgUpdatedAt=${getSessionMessageUpdatedAt(session)}`
8506
+ );
8507
+ }
8522
8508
  }
8509
+ const terminalBackend = getTerminalBackendRuntimeStatus();
8510
+ return {
8511
+ instanceId: options.instanceId,
8512
+ version: options.version,
8513
+ daemonMode: options.daemonMode,
8514
+ machine: {
8515
+ hostname: os10.hostname(),
8516
+ platform: os10.platform(),
8517
+ arch: os10.arch(),
8518
+ cpus: os10.cpus().length,
8519
+ totalMem: memSnap.totalMem,
8520
+ freeMem: memSnap.freeMem,
8521
+ availableMem: memSnap.availableMem,
8522
+ loadavg: os10.loadavg(),
8523
+ uptime: os10.uptime(),
8524
+ release: os10.release()
8525
+ },
8526
+ machineNickname: options.machineNickname ?? cfg.machineNickname ?? null,
8527
+ timestamp: options.timestamp ?? Date.now(),
8528
+ detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
8529
+ ...options.p2p ? { p2p: options.p2p } : {},
8530
+ sessions,
8531
+ workspaces: wsState.workspaces,
8532
+ defaultWorkspaceId: wsState.defaultWorkspaceId,
8533
+ defaultWorkspacePath: wsState.defaultWorkspacePath,
8534
+ recentLaunches: buildRecentLaunches(recentActivity),
8535
+ terminalBackend,
8536
+ availableProviders: buildAvailableProviders(options.providerLoader)
8537
+ };
8523
8538
  }
8524
- cleanOldFiles();
8525
8539
 
8526
8540
  // src/commands/router.ts
8527
- init_logger();
8528
8541
  import * as fs7 from "fs";
8529
8542
  var CHAT_COMMANDS = [
8530
8543
  "send_chat",
@@ -8533,6 +8546,7 @@ var CHAT_COMMANDS = [
8533
8546
  "set_mode",
8534
8547
  "change_model"
8535
8548
  ];
8549
+ var READ_DEBUG_ENABLED2 = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
8536
8550
  var DaemonCommandRouter = class {
8537
8551
  deps;
8538
8552
  constructor(deps) {
@@ -8651,18 +8665,6 @@ var DaemonCommandRouter = class {
8651
8665
  };
8652
8666
  LOG.info("LaunchIDE", `target=${ideKey || "auto"}`);
8653
8667
  const result = await launchWithCdp(launchArgs);
8654
- if (result.success && (result.ideId || ideKey)) {
8655
- try {
8656
- addCliHistory({
8657
- category: "ide",
8658
- cliType: result.ideId || ideKey,
8659
- dir: resolvedWorkspace || "",
8660
- workspace: resolvedWorkspace || "",
8661
- newWindow: args?.newWindow === true
8662
- });
8663
- } catch {
8664
- }
8665
- }
8666
8668
  if (result.success && result.port && result.ideId && !this.deps.cdpManagers.has(result.ideId)) {
8667
8669
  const logFn = this.deps.getCdpLogFn ? this.deps.getCdpLogFn(result.ideId) : LOG.forComponent(`CDP:${result.ideId}`).asLogFn();
8668
8670
  const provider = this.deps.providerLoader.getMeta(result.ideId);
@@ -8679,11 +8681,7 @@ var DaemonCommandRouter = class {
8679
8681
  this.deps.onIdeConnected?.();
8680
8682
  if (result.success && resolvedWorkspace) {
8681
8683
  try {
8682
- let next = appendWorkspaceActivity(loadConfig(), resolvedWorkspace, {
8683
- kind: "ide",
8684
- agentType: result.ideId
8685
- });
8686
- next = appendRecentActivity(next, {
8684
+ const next = appendRecentActivity(loadConfig(), {
8687
8685
  kind: "ide",
8688
8686
  providerType: result.ideId || ideKey,
8689
8687
  providerName: result.ideId || ideKey,
@@ -8719,28 +8717,35 @@ var DaemonCommandRouter = class {
8719
8717
  updateConfig({ userName: name });
8720
8718
  return { success: true, userName: name };
8721
8719
  }
8722
- case "mark_recent_seen": {
8723
- const kind = args?.kind;
8724
- const providerType = args?.providerType;
8725
- if (!kind || !providerType) {
8726
- return { success: false, error: "kind and providerType are required" };
8720
+ case "mark_session_seen": {
8721
+ const sessionId = args?.sessionId;
8722
+ if (!sessionId || typeof sessionId !== "string") {
8723
+ return { success: false, error: "sessionId is required" };
8727
8724
  }
8728
- const recentKey = args?.recentKey || buildRecentActivityKey({
8729
- kind,
8730
- providerType,
8731
- workspace: args?.workspace || null
8732
- });
8733
- const next = markRecentSessionSeen(
8734
- loadConfig(),
8735
- recentKey,
8736
- typeof args?.seenAt === "number" ? args.seenAt : Date.now()
8725
+ const currentConfig = loadConfig();
8726
+ const prevSeenAt = currentConfig.sessionReads?.[sessionId] || 0;
8727
+ const sessionEntries = buildSessionEntries(
8728
+ this.deps.instanceManager.collectAllStates(),
8729
+ this.deps.cdpManagers
8737
8730
  );
8731
+ const targetSession = sessionEntries.find((entry) => entry.id === sessionId);
8732
+ const completionMarker = targetSession ? getSessionCompletionMarker(targetSession) : "";
8733
+ const next = markSessionSeen(
8734
+ currentConfig,
8735
+ sessionId,
8736
+ typeof args?.seenAt === "number" ? args.seenAt : Date.now(),
8737
+ completionMarker
8738
+ );
8739
+ if (READ_DEBUG_ENABLED2) {
8740
+ LOG.info("RecentRead", `mark_session_seen sessionId=${sessionId} seenAt=${String(args?.seenAt || "")} prevSeenAt=${String(prevSeenAt)} nextSeenAt=${String(next.sessionReads?.[sessionId] || 0)} marker=${completionMarker || "-"}`);
8741
+ }
8738
8742
  saveConfig(next);
8739
8743
  this.deps.onStatusChange?.();
8740
8744
  return {
8741
8745
  success: true,
8742
- recentKey,
8743
- seenAt: next.recentSessionReads?.[recentKey] || Date.now()
8746
+ sessionId,
8747
+ seenAt: next.sessionReads?.[sessionId] || Date.now(),
8748
+ completionMarker
8744
8749
  };
8745
8750
  }
8746
8751
  // ─── Daemon Self-Upgrade ───
@@ -8761,9 +8766,9 @@ var DaemonCommandRouter = class {
8761
8766
  setTimeout(() => {
8762
8767
  LOG.info("Upgrade", "Restarting daemon with new version...");
8763
8768
  try {
8764
- const path16 = __require("path");
8769
+ const path15 = __require("path");
8765
8770
  const fs12 = __require("fs");
8766
- const pidFile = path16.join(process.env.HOME || process.env.USERPROFILE || "", ".adhdev", "daemon.pid");
8771
+ const pidFile = path15.join(process.env.HOME || process.env.USERPROFILE || "", ".adhdev", "daemon.pid");
8767
8772
  if (fs12.existsSync(pidFile)) fs12.unlinkSync(pidFile);
8768
8773
  } catch {
8769
8774
  }
@@ -8857,183 +8862,6 @@ var DaemonCommandRouter = class {
8857
8862
 
8858
8863
  // src/status/reporter.ts
8859
8864
  init_logger();
8860
-
8861
- // src/status/snapshot.ts
8862
- init_config();
8863
- import * as os10 from "os";
8864
- init_workspaces();
8865
- init_terminal_screen();
8866
- function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
8867
- return detectedIdes.filter((ide) => ide.installed !== false).map((ide) => ({
8868
- id: ide.id,
8869
- type: ide.id,
8870
- name: ide.displayName || ide.name || ide.id,
8871
- running: isCdpConnected(cdpManagers, ide.id),
8872
- ...ide.path ? { path: ide.path } : {}
8873
- }));
8874
- }
8875
- function buildAvailableProviders(providerLoader) {
8876
- return providerLoader.getAll().map((provider) => ({
8877
- type: provider.type,
8878
- name: provider.displayName || provider.type,
8879
- displayName: provider.displayName || provider.type,
8880
- icon: provider.icon || "\u{1F4BB}",
8881
- category: provider.category
8882
- }));
8883
- }
8884
- function parseMessageTime(value) {
8885
- if (typeof value === "number" && Number.isFinite(value)) return value;
8886
- if (typeof value === "string") {
8887
- const parsed = Date.parse(value);
8888
- if (Number.isFinite(parsed)) return parsed;
8889
- }
8890
- return 0;
8891
- }
8892
- function getSessionMessageUpdatedAt(session) {
8893
- const lastMessage = session.activeChat?.messages?.at?.(-1);
8894
- if (!lastMessage) return 0;
8895
- return parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt) || 0;
8896
- }
8897
- function getSessionLastUsedAt(session) {
8898
- return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
8899
- }
8900
- function getSessionKind(session) {
8901
- return session.transport === "cdp-page" || session.transport === "cdp-webview" ? "ide" : session.transport === "acp" ? "acp" : "cli";
8902
- }
8903
- function getLastMessageRole(session) {
8904
- const role = session.activeChat?.messages?.at?.(-1)?.role;
8905
- return typeof role === "string" ? role : "";
8906
- }
8907
- function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole) {
8908
- if (status === "waiting_approval") {
8909
- return { unread: false, inboxBucket: "needs_attention" };
8910
- }
8911
- if (status === "generating" || status === "starting") {
8912
- return { unread: false, inboxBucket: "working" };
8913
- }
8914
- const unread = hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
8915
- return { unread, inboxBucket: unread ? "task_complete" : "idle" };
8916
- }
8917
- function buildRecentSessions(sessions, recentActivity, readState) {
8918
- const live = sessions.filter((session) => !session.parentId && session.status !== "stopped").map((session) => {
8919
- const kind = getSessionKind(session);
8920
- const recentKey = buildRecentActivityKey({
8921
- kind,
8922
- providerType: session.providerType,
8923
- workspace: session.workspace
8924
- });
8925
- const lastSeenAt = readState[recentKey] || 0;
8926
- const lastUsedAt = getSessionLastUsedAt(session);
8927
- const { unread, inboxBucket } = getUnreadState(
8928
- getSessionMessageUpdatedAt(session) > 0,
8929
- session.status,
8930
- lastUsedAt,
8931
- lastSeenAt,
8932
- getLastMessageRole(session)
8933
- );
8934
- return {
8935
- id: session.id,
8936
- recentKey,
8937
- sessionId: session.id,
8938
- providerType: session.providerType,
8939
- providerName: session.providerName,
8940
- kind,
8941
- title: session.activeChat?.title || session.title || session.providerName,
8942
- workspace: session.workspace,
8943
- currentModel: session.currentModel,
8944
- status: session.status,
8945
- lastUsedAt,
8946
- unread,
8947
- lastSeenAt,
8948
- inboxBucket
8949
- };
8950
- });
8951
- const seen = new Set(live.map((item) => `${item.kind}:${item.providerType}:${item.workspace || ""}`));
8952
- const persisted = recentActivity.filter((item) => !seen.has(`${item.kind}:${item.providerType}:${item.workspace || ""}`)).map((item) => {
8953
- const lastSeenAt = readState[item.id] || 0;
8954
- const unread = item.lastUsedAt > lastSeenAt;
8955
- return {
8956
- id: item.id,
8957
- recentKey: item.id,
8958
- sessionId: item.sessionId || null,
8959
- providerType: item.providerType,
8960
- providerName: item.providerName,
8961
- kind: item.kind,
8962
- title: item.title || item.providerName,
8963
- workspace: item.workspace,
8964
- currentModel: item.currentModel,
8965
- lastUsedAt: item.lastUsedAt,
8966
- unread,
8967
- lastSeenAt,
8968
- inboxBucket: unread ? "task_complete" : "idle"
8969
- };
8970
- });
8971
- return [...live, ...persisted].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, 12);
8972
- }
8973
- function buildStatusSnapshot(options) {
8974
- const cfg = loadConfig();
8975
- const wsState = getWorkspaceState(cfg);
8976
- const memSnap = getHostMemorySnapshot();
8977
- const recentActivity = getRecentActivity(cfg, 20);
8978
- const sessions = buildSessionEntries(
8979
- options.allStates,
8980
- options.cdpManagers
8981
- );
8982
- const readState = cfg.recentSessionReads || {};
8983
- for (const session of sessions) {
8984
- const kind = getSessionKind(session);
8985
- const recentKey = buildRecentActivityKey({
8986
- kind,
8987
- providerType: session.providerType,
8988
- workspace: session.workspace
8989
- });
8990
- const lastSeenAt = getRecentSessionSeenAt(cfg, recentKey);
8991
- const lastUsedAt = getSessionLastUsedAt(session);
8992
- const { unread, inboxBucket } = getUnreadState(
8993
- getSessionMessageUpdatedAt(session) > 0,
8994
- session.status,
8995
- lastUsedAt,
8996
- lastSeenAt,
8997
- getLastMessageRole(session)
8998
- );
8999
- session.recentKey = recentKey;
9000
- session.lastSeenAt = lastSeenAt;
9001
- session.unread = unread;
9002
- session.inboxBucket = inboxBucket;
9003
- }
9004
- const terminalBackend = getTerminalBackendRuntimeStatus();
9005
- return {
9006
- instanceId: options.instanceId,
9007
- version: options.version,
9008
- daemonMode: options.daemonMode,
9009
- machine: {
9010
- hostname: os10.hostname(),
9011
- platform: os10.platform(),
9012
- arch: os10.arch(),
9013
- cpus: os10.cpus().length,
9014
- totalMem: memSnap.totalMem,
9015
- freeMem: memSnap.freeMem,
9016
- availableMem: memSnap.availableMem,
9017
- loadavg: os10.loadavg(),
9018
- uptime: os10.uptime(),
9019
- release: os10.release()
9020
- },
9021
- machineNickname: options.machineNickname ?? cfg.machineNickname ?? null,
9022
- timestamp: options.timestamp ?? Date.now(),
9023
- detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
9024
- ...options.p2p ? { p2p: options.p2p } : {},
9025
- sessions,
9026
- workspaces: wsState.workspaces,
9027
- defaultWorkspaceId: wsState.defaultWorkspaceId,
9028
- defaultWorkspacePath: wsState.defaultWorkspacePath,
9029
- workspaceActivity: getWorkspaceActivity(cfg, 15),
9030
- recentSessions: buildRecentSessions(sessions, recentActivity, readState),
9031
- terminalBackend,
9032
- availableProviders: buildAvailableProviders(options.providerLoader)
9033
- };
9034
- }
9035
-
9036
- // src/status/reporter.ts
9037
8865
  var DaemonStatusReporter = class {
9038
8866
  deps;
9039
8867
  log;
@@ -9181,10 +9009,11 @@ var DaemonStatusReporter = class {
9181
9009
  currentModel: session.currentModel,
9182
9010
  currentPlan: session.currentPlan,
9183
9011
  currentAutoApprove: session.currentAutoApprove,
9184
- recentKey: session.recentKey,
9012
+ lastUpdated: session.lastUpdated,
9185
9013
  unread: session.unread,
9186
9014
  lastSeenAt: session.lastSeenAt,
9187
9015
  inboxBucket: session.inboxBucket,
9016
+ surfaceHidden: session.surfaceHidden,
9188
9017
  controlValues: session.controlValues,
9189
9018
  providerControls: session.providerControls,
9190
9019
  acpConfigOptions: session.acpConfigOptions,
@@ -9227,11 +9056,10 @@ init_logger();
9227
9056
  // src/commands/cli-manager.ts
9228
9057
  init_provider_cli_adapter();
9229
9058
  import * as os13 from "os";
9230
- import * as path11 from "path";
9059
+ import * as path10 from "path";
9231
9060
  import * as crypto4 from "crypto";
9232
9061
  import chalk from "chalk";
9233
9062
  init_config();
9234
- init_workspaces();
9235
9063
 
9236
9064
  // src/providers/cli-provider-instance.ts
9237
9065
  init_provider_cli_adapter();
@@ -9912,13 +9740,13 @@ var AcpProviderInstance = class {
9912
9740
  }
9913
9741
  this.currentStatus = "waiting_approval";
9914
9742
  this.detectStatusTransition();
9915
- const approved = await new Promise((resolve10) => {
9916
- this.permissionResolvers.push(resolve10);
9743
+ const approved = await new Promise((resolve9) => {
9744
+ this.permissionResolvers.push(resolve9);
9917
9745
  setTimeout(() => {
9918
- const idx = this.permissionResolvers.indexOf(resolve10);
9746
+ const idx = this.permissionResolvers.indexOf(resolve9);
9919
9747
  if (idx >= 0) {
9920
9748
  this.permissionResolvers.splice(idx, 1);
9921
- resolve10(false);
9749
+ resolve9(false);
9922
9750
  }
9923
9751
  }, 3e5);
9924
9752
  });
@@ -10393,24 +10221,6 @@ var DaemonCliManager = class {
10393
10221
  const hash = __require("crypto").createHash("md5").update(__require("path").resolve(dir)).digest("hex").slice(0, 8);
10394
10222
  return `${cliType}_${hash}`;
10395
10223
  }
10396
- persistRecentDir(cliType, dir) {
10397
- try {
10398
- const normalizedType = this.providerLoader.resolveAlias(cliType);
10399
- const provider = this.providerLoader.getByAlias(cliType);
10400
- const actKind = provider?.category === "acp" ? "acp" : "cli";
10401
- let next = loadConfig();
10402
- console.log(colorize("cyan", ` \u{1F4C2} Saving recent workspace: ${dir}`));
10403
- const recent = next.recentCliWorkspaces || [];
10404
- if (!recent.includes(dir)) {
10405
- next = { ...next, recentCliWorkspaces: [dir, ...recent].slice(0, 10) };
10406
- }
10407
- next = appendWorkspaceActivity(next, dir, { kind: actKind, agentType: normalizedType });
10408
- saveConfig(next);
10409
- console.log(colorize("green", ` \u2713 Recent workspace saved: ${dir}`));
10410
- } catch (e) {
10411
- console.error(colorize("red", ` \u2717 Failed to save recent workspace: ${e}`));
10412
- }
10413
- }
10414
10224
  persistRecentActivity(entry) {
10415
10225
  try {
10416
10226
  saveConfig(appendRecentActivity(loadConfig(), entry));
@@ -10500,7 +10310,7 @@ var DaemonCliManager = class {
10500
10310
  async startSession(cliType, workingDir, cliArgs, initialModel) {
10501
10311
  const trimmed = (workingDir || "").trim();
10502
10312
  if (!trimmed) throw new Error("working directory required");
10503
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path11.resolve(trimmed);
10313
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path10.resolve(trimmed);
10504
10314
  const normalizedType = this.providerLoader.resolveAlias(cliType);
10505
10315
  const provider = this.providerLoader.getByAlias(cliType);
10506
10316
  const key = crypto4.randomUUID();
@@ -10571,11 +10381,6 @@ ${installInfo}`
10571
10381
  LOG.warn("CLI", `[ACP] Initial model set failed: ${e?.message}`);
10572
10382
  }
10573
10383
  }
10574
- try {
10575
- addCliHistory({ category: "acp", cliType: normalizedType, dir: resolvedDir, workspace: resolvedDir, cliArgs, model: initialModel });
10576
- } catch (e) {
10577
- LOG.warn("CLI", `ACP history save failed: ${e?.message}`);
10578
- }
10579
10384
  this.persistRecentActivity({
10580
10385
  kind: "acp",
10581
10386
  providerType: normalizedType,
@@ -10642,11 +10447,6 @@ ${installInfo}`
10642
10447
  this.adapters.set(key, adapter);
10643
10448
  console.log(colorize("green", ` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
10644
10449
  }
10645
- try {
10646
- addCliHistory({ category: "cli", cliType, dir: resolvedDir, workspace: resolvedDir, cliArgs, model: initialModel });
10647
- } catch (e) {
10648
- LOG.warn("CLI", `CLI history save failed: ${e?.message}`);
10649
- }
10650
10450
  this.persistRecentActivity({
10651
10451
  kind: "cli",
10652
10452
  providerType: normalizedType,
@@ -10799,7 +10599,6 @@ ${installInfo}`
10799
10599
  newKey = k;
10800
10600
  }
10801
10601
  }
10802
- this.persistRecentDir(cliType, dir);
10803
10602
  return { success: true, cliType, dir, id: newKey, launchSource };
10804
10603
  }
10805
10604
  case "stop_cli": {
@@ -10842,7 +10641,6 @@ ${installInfo}`
10842
10641
  const found = this.findAdapter(cliType, { instanceKey: args?.targetSessionId, dir });
10843
10642
  if (found) await this.stopSession(found.key);
10844
10643
  await this.startSession(cliType, dir);
10845
- this.persistRecentDir(cliType, dir);
10846
10644
  return { success: true, restarted: true };
10847
10645
  }
10848
10646
  case "agent_command": {
@@ -11665,11 +11463,11 @@ var ProviderInstanceManager = class {
11665
11463
 
11666
11464
  // src/providers/version-archive.ts
11667
11465
  import * as fs8 from "fs";
11668
- import * as path12 from "path";
11466
+ import * as path11 from "path";
11669
11467
  import * as os14 from "os";
11670
11468
  import { execSync as execSync5 } from "child_process";
11671
11469
  import { platform as platform8 } from "os";
11672
- var ARCHIVE_PATH = path12.join(os14.homedir(), ".adhdev", "version-history.json");
11470
+ var ARCHIVE_PATH = path11.join(os14.homedir(), ".adhdev", "version-history.json");
11673
11471
  var MAX_ENTRIES_PER_PROVIDER = 20;
11674
11472
  var VersionArchive = class {
11675
11473
  history = {};
@@ -11716,7 +11514,7 @@ var VersionArchive = class {
11716
11514
  }
11717
11515
  save() {
11718
11516
  try {
11719
- fs8.mkdirSync(path12.dirname(ARCHIVE_PATH), { recursive: true });
11517
+ fs8.mkdirSync(path11.dirname(ARCHIVE_PATH), { recursive: true });
11720
11518
  fs8.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
11721
11519
  } catch {
11722
11520
  }
@@ -11757,7 +11555,7 @@ function checkPathExists2(paths) {
11757
11555
  for (const p of paths) {
11758
11556
  if (p.includes("*")) {
11759
11557
  const home = os14.homedir();
11760
- const resolved = p.replace(/\*/g, home.split(path12.sep).pop() || "");
11558
+ const resolved = p.replace(/\*/g, home.split(path11.sep).pop() || "");
11761
11559
  if (fs8.existsSync(resolved)) return resolved;
11762
11560
  } else {
11763
11561
  if (fs8.existsSync(p)) return p;
@@ -11767,7 +11565,7 @@ function checkPathExists2(paths) {
11767
11565
  }
11768
11566
  function getMacAppVersion(appPath) {
11769
11567
  if (platform8() !== "darwin" || !appPath.endsWith(".app")) return null;
11770
- const plistPath = path12.join(appPath, "Contents", "Info.plist");
11568
+ const plistPath = path11.join(appPath, "Contents", "Info.plist");
11771
11569
  if (!fs8.existsSync(plistPath)) return null;
11772
11570
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
11773
11571
  return raw || null;
@@ -11794,7 +11592,7 @@ async function detectAllVersions(loader, archive) {
11794
11592
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
11795
11593
  let resolvedBin = cliBin;
11796
11594
  if (!resolvedBin && appPath && currentOs === "darwin") {
11797
- const bundled = path12.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
11595
+ const bundled = path11.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
11798
11596
  if (provider.cli && fs8.existsSync(bundled)) resolvedBin = bundled;
11799
11597
  }
11800
11598
  info.installed = !!(appPath || resolvedBin);
@@ -11835,7 +11633,7 @@ async function detectAllVersions(loader, archive) {
11835
11633
  // src/daemon/dev-server.ts
11836
11634
  import * as http2 from "http";
11837
11635
  import * as fs11 from "fs";
11838
- import * as path15 from "path";
11636
+ import * as path14 from "path";
11839
11637
 
11840
11638
  // src/daemon/scaffold-template.ts
11841
11639
  function generateFiles(type, name, category, opts = {}) {
@@ -12172,7 +11970,7 @@ init_logger();
12172
11970
  // src/daemon/dev-cdp-handlers.ts
12173
11971
  init_logger();
12174
11972
  import * as fs9 from "fs";
12175
- import * as path13 from "path";
11973
+ import * as path12 from "path";
12176
11974
  async function handleCdpEvaluate(ctx, req, res) {
12177
11975
  const body = await ctx.readBody(req);
12178
11976
  const { expression, timeout, ideType } = body;
@@ -12350,17 +12148,17 @@ async function handleScriptHints(ctx, type, _req, res) {
12350
12148
  return;
12351
12149
  }
12352
12150
  let scriptsPath = "";
12353
- const directScripts = path13.join(dir, "scripts.js");
12151
+ const directScripts = path12.join(dir, "scripts.js");
12354
12152
  if (fs9.existsSync(directScripts)) {
12355
12153
  scriptsPath = directScripts;
12356
12154
  } else {
12357
- const scriptsDir = path13.join(dir, "scripts");
12155
+ const scriptsDir = path12.join(dir, "scripts");
12358
12156
  if (fs9.existsSync(scriptsDir)) {
12359
12157
  const versions = fs9.readdirSync(scriptsDir).filter((d) => {
12360
- return fs9.statSync(path13.join(scriptsDir, d)).isDirectory();
12158
+ return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
12361
12159
  }).sort().reverse();
12362
12160
  for (const ver of versions) {
12363
- const p = path13.join(scriptsDir, ver, "scripts.js");
12161
+ const p = path12.join(scriptsDir, ver, "scripts.js");
12364
12162
  if (fs9.existsSync(p)) {
12365
12163
  scriptsPath = p;
12366
12164
  break;
@@ -13415,7 +13213,7 @@ async function handleCliRaw(ctx, req, res) {
13415
13213
 
13416
13214
  // src/daemon/dev-auto-implement.ts
13417
13215
  import * as fs10 from "fs";
13418
- import * as path14 from "path";
13216
+ import * as path13 from "path";
13419
13217
  import * as os15 from "os";
13420
13218
  function getDefaultAutoImplReference(ctx, category, type) {
13421
13219
  if (category === "cli") {
@@ -13435,22 +13233,22 @@ function getLatestScriptVersionDir(scriptsDir) {
13435
13233
  if (!fs10.existsSync(scriptsDir)) return null;
13436
13234
  const versions = fs10.readdirSync(scriptsDir).filter((d) => {
13437
13235
  try {
13438
- return fs10.statSync(path14.join(scriptsDir, d)).isDirectory();
13236
+ return fs10.statSync(path13.join(scriptsDir, d)).isDirectory();
13439
13237
  } catch {
13440
13238
  return false;
13441
13239
  }
13442
13240
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
13443
13241
  if (versions.length === 0) return null;
13444
- return path14.join(scriptsDir, versions[0]);
13242
+ return path13.join(scriptsDir, versions[0]);
13445
13243
  }
13446
13244
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
13447
- const canonicalUserDir = path14.resolve(ctx.providerLoader.getUserProviderDir(category, type));
13448
- const desiredDir = requestedDir ? path14.resolve(requestedDir) : canonicalUserDir;
13449
- const upstreamRoot = path14.resolve(ctx.providerLoader.getUpstreamDir());
13450
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path14.sep}`)) {
13245
+ const canonicalUserDir = path13.resolve(ctx.providerLoader.getUserProviderDir(category, type));
13246
+ const desiredDir = requestedDir ? path13.resolve(requestedDir) : canonicalUserDir;
13247
+ const upstreamRoot = path13.resolve(ctx.providerLoader.getUpstreamDir());
13248
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path13.sep}`)) {
13451
13249
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
13452
13250
  }
13453
- if (path14.basename(desiredDir) !== type) {
13251
+ if (path13.basename(desiredDir) !== type) {
13454
13252
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
13455
13253
  }
13456
13254
  const sourceDir = ctx.findProviderDir(type);
@@ -13458,11 +13256,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
13458
13256
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
13459
13257
  }
13460
13258
  if (!fs10.existsSync(desiredDir)) {
13461
- fs10.mkdirSync(path14.dirname(desiredDir), { recursive: true });
13259
+ fs10.mkdirSync(path13.dirname(desiredDir), { recursive: true });
13462
13260
  fs10.cpSync(sourceDir, desiredDir, { recursive: true });
13463
13261
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
13464
13262
  }
13465
- const providerJson = path14.join(desiredDir, "provider.json");
13263
+ const providerJson = path13.join(desiredDir, "provider.json");
13466
13264
  if (!fs10.existsSync(providerJson)) {
13467
13265
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
13468
13266
  }
@@ -13485,13 +13283,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
13485
13283
  const refDir = ctx.findProviderDir(referenceType);
13486
13284
  if (!refDir || !fs10.existsSync(refDir)) return {};
13487
13285
  const referenceScripts = {};
13488
- const scriptsDir = path14.join(refDir, "scripts");
13286
+ const scriptsDir = path13.join(refDir, "scripts");
13489
13287
  const latestDir = getLatestScriptVersionDir(scriptsDir);
13490
13288
  if (!latestDir) return referenceScripts;
13491
13289
  for (const file of fs10.readdirSync(latestDir)) {
13492
13290
  if (!file.endsWith(".js")) continue;
13493
13291
  try {
13494
- referenceScripts[file] = fs10.readFileSync(path14.join(latestDir, file), "utf-8");
13292
+ referenceScripts[file] = fs10.readFileSync(path13.join(latestDir, file), "utf-8");
13495
13293
  } catch {
13496
13294
  }
13497
13295
  }
@@ -13542,9 +13340,9 @@ async function handleAutoImplement(ctx, type, req, res) {
13542
13340
  });
13543
13341
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
13544
13342
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference);
13545
- const tmpDir = path14.join(os15.tmpdir(), "adhdev-autoimpl");
13343
+ const tmpDir = path13.join(os15.tmpdir(), "adhdev-autoimpl");
13546
13344
  if (!fs10.existsSync(tmpDir)) fs10.mkdirSync(tmpDir, { recursive: true });
13547
- const promptFile = path14.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
13345
+ const promptFile = path13.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
13548
13346
  fs10.writeFileSync(promptFile, prompt, "utf-8");
13549
13347
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
13550
13348
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -13915,7 +13713,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
13915
13713
  setMode: "set_mode.js"
13916
13714
  };
13917
13715
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
13918
- const scriptsDir = path14.join(providerDir, "scripts");
13716
+ const scriptsDir = path13.join(providerDir, "scripts");
13919
13717
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
13920
13718
  if (latestScriptsDir) {
13921
13719
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -13926,7 +13724,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
13926
13724
  for (const file of fs10.readdirSync(latestScriptsDir)) {
13927
13725
  if (file.endsWith(".js") && targetFileNames.has(file)) {
13928
13726
  try {
13929
- const content = fs10.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
13727
+ const content = fs10.readFileSync(path13.join(latestScriptsDir, file), "utf-8");
13930
13728
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
13931
13729
  lines.push("```javascript");
13932
13730
  lines.push(content);
@@ -13943,7 +13741,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
13943
13741
  lines.push("");
13944
13742
  for (const file of refFiles) {
13945
13743
  try {
13946
- const content = fs10.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
13744
+ const content = fs10.readFileSync(path13.join(latestScriptsDir, file), "utf-8");
13947
13745
  lines.push(`### \`${file}\` \u{1F512}`);
13948
13746
  lines.push("```javascript");
13949
13747
  lines.push(content);
@@ -13984,10 +13782,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
13984
13782
  lines.push("");
13985
13783
  }
13986
13784
  }
13987
- const docsDir = path14.join(providerDir, "../../docs");
13785
+ const docsDir = path13.join(providerDir, "../../docs");
13988
13786
  const loadGuide = (name) => {
13989
13787
  try {
13990
- const p = path14.join(docsDir, name);
13788
+ const p = path13.join(docsDir, name);
13991
13789
  if (fs10.existsSync(p)) return fs10.readFileSync(p, "utf-8");
13992
13790
  } catch {
13993
13791
  }
@@ -14161,7 +13959,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
14161
13959
  parseApproval: "parse_approval.js"
14162
13960
  };
14163
13961
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
14164
- const scriptsDir = path14.join(providerDir, "scripts");
13962
+ const scriptsDir = path13.join(providerDir, "scripts");
14165
13963
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
14166
13964
  if (latestScriptsDir) {
14167
13965
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -14173,7 +13971,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
14173
13971
  if (!file.endsWith(".js")) continue;
14174
13972
  if (!targetFileNames.has(file)) continue;
14175
13973
  try {
14176
- const content = fs10.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
13974
+ const content = fs10.readFileSync(path13.join(latestScriptsDir, file), "utf-8");
14177
13975
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
14178
13976
  lines.push("```javascript");
14179
13977
  lines.push(content);
@@ -14189,7 +13987,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
14189
13987
  lines.push("");
14190
13988
  for (const file of refFiles) {
14191
13989
  try {
14192
- const content = fs10.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
13990
+ const content = fs10.readFileSync(path13.join(latestScriptsDir, file), "utf-8");
14193
13991
  lines.push(`### \`${file}\` \u{1F512}`);
14194
13992
  lines.push("```javascript");
14195
13993
  lines.push(content);
@@ -14222,10 +14020,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
14222
14020
  lines.push("");
14223
14021
  }
14224
14022
  }
14225
- const docsDir = path14.join(providerDir, "../../docs");
14023
+ const docsDir = path13.join(providerDir, "../../docs");
14226
14024
  const loadGuide = (name) => {
14227
14025
  try {
14228
- const p = path14.join(docsDir, name);
14026
+ const p = path13.join(docsDir, name);
14229
14027
  if (fs10.existsSync(p)) return fs10.readFileSync(p, "utf-8");
14230
14028
  } catch {
14231
14029
  }
@@ -14483,8 +14281,8 @@ var DevServer = class _DevServer {
14483
14281
  }
14484
14282
  getEndpointList() {
14485
14283
  return this.routes.map((r) => {
14486
- const path16 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
14487
- return `${r.method.padEnd(5)} ${path16}`;
14284
+ const path15 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
14285
+ return `${r.method.padEnd(5)} ${path15}`;
14488
14286
  });
14489
14287
  }
14490
14288
  async start(port = DEV_SERVER_PORT) {
@@ -14515,15 +14313,15 @@ var DevServer = class _DevServer {
14515
14313
  this.json(res, 500, { error: e.message });
14516
14314
  }
14517
14315
  });
14518
- return new Promise((resolve10, reject) => {
14316
+ return new Promise((resolve9, reject) => {
14519
14317
  this.server.listen(port, "127.0.0.1", () => {
14520
14318
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
14521
- resolve10();
14319
+ resolve9();
14522
14320
  });
14523
14321
  this.server.on("error", (e) => {
14524
14322
  if (e.code === "EADDRINUSE") {
14525
14323
  this.log(`Port ${port} in use, skipping dev server`);
14526
- resolve10();
14324
+ resolve9();
14527
14325
  } else {
14528
14326
  reject(e);
14529
14327
  }
@@ -14606,20 +14404,20 @@ var DevServer = class _DevServer {
14606
14404
  child.stderr?.on("data", (d) => {
14607
14405
  stderr += d.toString().slice(0, 2e3);
14608
14406
  });
14609
- await new Promise((resolve10) => {
14407
+ await new Promise((resolve9) => {
14610
14408
  const timer = setTimeout(() => {
14611
14409
  child.kill();
14612
- resolve10();
14410
+ resolve9();
14613
14411
  }, 3e3);
14614
14412
  child.on("exit", () => {
14615
14413
  clearTimeout(timer);
14616
- resolve10();
14414
+ resolve9();
14617
14415
  });
14618
14416
  child.stdout?.once("data", () => {
14619
14417
  setTimeout(() => {
14620
14418
  child.kill();
14621
14419
  clearTimeout(timer);
14622
- resolve10();
14420
+ resolve9();
14623
14421
  }, 500);
14624
14422
  });
14625
14423
  });
@@ -14766,12 +14564,12 @@ var DevServer = class _DevServer {
14766
14564
  // ─── DevConsole SPA ───
14767
14565
  getConsoleDistDir() {
14768
14566
  const candidates = [
14769
- path15.resolve(__dirname, "../../web-devconsole/dist"),
14770
- path15.resolve(__dirname, "../../../web-devconsole/dist"),
14771
- path15.join(process.cwd(), "packages/web-devconsole/dist")
14567
+ path14.resolve(__dirname, "../../web-devconsole/dist"),
14568
+ path14.resolve(__dirname, "../../../web-devconsole/dist"),
14569
+ path14.join(process.cwd(), "packages/web-devconsole/dist")
14772
14570
  ];
14773
14571
  for (const dir of candidates) {
14774
- if (fs11.existsSync(path15.join(dir, "index.html"))) return dir;
14572
+ if (fs11.existsSync(path14.join(dir, "index.html"))) return dir;
14775
14573
  }
14776
14574
  return null;
14777
14575
  }
@@ -14781,7 +14579,7 @@ var DevServer = class _DevServer {
14781
14579
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
14782
14580
  return;
14783
14581
  }
14784
- const htmlPath = path15.join(distDir, "index.html");
14582
+ const htmlPath = path14.join(distDir, "index.html");
14785
14583
  try {
14786
14584
  const html = fs11.readFileSync(htmlPath, "utf-8");
14787
14585
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -14806,15 +14604,15 @@ var DevServer = class _DevServer {
14806
14604
  this.json(res, 404, { error: "Not found" });
14807
14605
  return;
14808
14606
  }
14809
- const safePath = path15.normalize(pathname).replace(/^\.\.\//, "");
14810
- const filePath = path15.join(distDir, safePath);
14607
+ const safePath = path14.normalize(pathname).replace(/^\.\.\//, "");
14608
+ const filePath = path14.join(distDir, safePath);
14811
14609
  if (!filePath.startsWith(distDir)) {
14812
14610
  this.json(res, 403, { error: "Forbidden" });
14813
14611
  return;
14814
14612
  }
14815
14613
  try {
14816
14614
  const content = fs11.readFileSync(filePath);
14817
- const ext = path15.extname(filePath);
14615
+ const ext = path14.extname(filePath);
14818
14616
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
14819
14617
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
14820
14618
  res.end(content);
@@ -14927,9 +14725,9 @@ var DevServer = class _DevServer {
14927
14725
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
14928
14726
  if (entry.isDirectory()) {
14929
14727
  files.push({ path: rel, size: 0, type: "dir" });
14930
- scan(path15.join(d, entry.name), rel);
14728
+ scan(path14.join(d, entry.name), rel);
14931
14729
  } else {
14932
- const stat = fs11.statSync(path15.join(d, entry.name));
14730
+ const stat = fs11.statSync(path14.join(d, entry.name));
14933
14731
  files.push({ path: rel, size: stat.size, type: "file" });
14934
14732
  }
14935
14733
  }
@@ -14952,7 +14750,7 @@ var DevServer = class _DevServer {
14952
14750
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
14953
14751
  return;
14954
14752
  }
14955
- const fullPath = path15.resolve(dir, path15.normalize(filePath));
14753
+ const fullPath = path14.resolve(dir, path14.normalize(filePath));
14956
14754
  if (!fullPath.startsWith(dir)) {
14957
14755
  this.json(res, 403, { error: "Forbidden" });
14958
14756
  return;
@@ -14977,14 +14775,14 @@ var DevServer = class _DevServer {
14977
14775
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
14978
14776
  return;
14979
14777
  }
14980
- const fullPath = path15.resolve(dir, path15.normalize(filePath));
14778
+ const fullPath = path14.resolve(dir, path14.normalize(filePath));
14981
14779
  if (!fullPath.startsWith(dir)) {
14982
14780
  this.json(res, 403, { error: "Forbidden" });
14983
14781
  return;
14984
14782
  }
14985
14783
  try {
14986
14784
  if (fs11.existsSync(fullPath)) fs11.copyFileSync(fullPath, fullPath + ".bak");
14987
- fs11.mkdirSync(path15.dirname(fullPath), { recursive: true });
14785
+ fs11.mkdirSync(path14.dirname(fullPath), { recursive: true });
14988
14786
  fs11.writeFileSync(fullPath, content, "utf-8");
14989
14787
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
14990
14788
  this.providerLoader.reload();
@@ -15001,7 +14799,7 @@ var DevServer = class _DevServer {
15001
14799
  return;
15002
14800
  }
15003
14801
  for (const name of ["scripts.js", "provider.json"]) {
15004
- const p = path15.join(dir, name);
14802
+ const p = path14.join(dir, name);
15005
14803
  if (fs11.existsSync(p)) {
15006
14804
  const source = fs11.readFileSync(p, "utf-8");
15007
14805
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -15022,8 +14820,8 @@ var DevServer = class _DevServer {
15022
14820
  this.json(res, 404, { error: `Provider not found: ${type}` });
15023
14821
  return;
15024
14822
  }
15025
- const target = fs11.existsSync(path15.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
15026
- const targetPath = path15.join(dir, target);
14823
+ const target = fs11.existsSync(path14.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
14824
+ const targetPath = path14.join(dir, target);
15027
14825
  try {
15028
14826
  if (fs11.existsSync(targetPath)) fs11.copyFileSync(targetPath, targetPath + ".bak");
15029
14827
  fs11.writeFileSync(targetPath, source, "utf-8");
@@ -15128,14 +14926,14 @@ var DevServer = class _DevServer {
15128
14926
  child.stderr?.on("data", (d) => {
15129
14927
  stderr += d.toString();
15130
14928
  });
15131
- await new Promise((resolve10) => {
14929
+ await new Promise((resolve9) => {
15132
14930
  const timer = setTimeout(() => {
15133
14931
  child.kill();
15134
- resolve10();
14932
+ resolve9();
15135
14933
  }, timeout);
15136
14934
  child.on("exit", () => {
15137
14935
  clearTimeout(timer);
15138
- resolve10();
14936
+ resolve9();
15139
14937
  });
15140
14938
  });
15141
14939
  const elapsed = Date.now() - start;
@@ -15183,7 +14981,7 @@ var DevServer = class _DevServer {
15183
14981
  }
15184
14982
  let targetDir;
15185
14983
  targetDir = this.providerLoader.getUserProviderDir(category, type);
15186
- const jsonPath = path15.join(targetDir, "provider.json");
14984
+ const jsonPath = path14.join(targetDir, "provider.json");
15187
14985
  if (fs11.existsSync(jsonPath)) {
15188
14986
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
15189
14987
  return;
@@ -15195,8 +14993,8 @@ var DevServer = class _DevServer {
15195
14993
  const createdFiles = ["provider.json"];
15196
14994
  if (result.files) {
15197
14995
  for (const [relPath, content] of Object.entries(result.files)) {
15198
- const fullPath = path15.join(targetDir, relPath);
15199
- fs11.mkdirSync(path15.dirname(fullPath), { recursive: true });
14996
+ const fullPath = path14.join(targetDir, relPath);
14997
+ fs11.mkdirSync(path14.dirname(fullPath), { recursive: true });
15200
14998
  fs11.writeFileSync(fullPath, content, "utf-8");
15201
14999
  createdFiles.push(relPath);
15202
15000
  }
@@ -15249,22 +15047,22 @@ var DevServer = class _DevServer {
15249
15047
  if (!fs11.existsSync(scriptsDir)) return null;
15250
15048
  const versions = fs11.readdirSync(scriptsDir).filter((d) => {
15251
15049
  try {
15252
- return fs11.statSync(path15.join(scriptsDir, d)).isDirectory();
15050
+ return fs11.statSync(path14.join(scriptsDir, d)).isDirectory();
15253
15051
  } catch {
15254
15052
  return false;
15255
15053
  }
15256
15054
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
15257
15055
  if (versions.length === 0) return null;
15258
- return path15.join(scriptsDir, versions[0]);
15056
+ return path14.join(scriptsDir, versions[0]);
15259
15057
  }
15260
15058
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
15261
- const canonicalUserDir = path15.resolve(this.providerLoader.getUserProviderDir(category, type));
15262
- const desiredDir = requestedDir ? path15.resolve(requestedDir) : canonicalUserDir;
15263
- const upstreamRoot = path15.resolve(this.providerLoader.getUpstreamDir());
15264
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path15.sep}`)) {
15059
+ const canonicalUserDir = path14.resolve(this.providerLoader.getUserProviderDir(category, type));
15060
+ const desiredDir = requestedDir ? path14.resolve(requestedDir) : canonicalUserDir;
15061
+ const upstreamRoot = path14.resolve(this.providerLoader.getUpstreamDir());
15062
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path14.sep}`)) {
15265
15063
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
15266
15064
  }
15267
- if (path15.basename(desiredDir) !== type) {
15065
+ if (path14.basename(desiredDir) !== type) {
15268
15066
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
15269
15067
  }
15270
15068
  const sourceDir = this.findProviderDir(type);
@@ -15272,11 +15070,11 @@ var DevServer = class _DevServer {
15272
15070
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
15273
15071
  }
15274
15072
  if (!fs11.existsSync(desiredDir)) {
15275
- fs11.mkdirSync(path15.dirname(desiredDir), { recursive: true });
15073
+ fs11.mkdirSync(path14.dirname(desiredDir), { recursive: true });
15276
15074
  fs11.cpSync(sourceDir, desiredDir, { recursive: true });
15277
15075
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
15278
15076
  }
15279
- const providerJson = path15.join(desiredDir, "provider.json");
15077
+ const providerJson = path14.join(desiredDir, "provider.json");
15280
15078
  if (!fs11.existsSync(providerJson)) {
15281
15079
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
15282
15080
  }
@@ -15324,7 +15122,7 @@ var DevServer = class _DevServer {
15324
15122
  setMode: "set_mode.js"
15325
15123
  };
15326
15124
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
15327
- const scriptsDir = path15.join(providerDir, "scripts");
15125
+ const scriptsDir = path14.join(providerDir, "scripts");
15328
15126
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
15329
15127
  if (latestScriptsDir) {
15330
15128
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -15335,7 +15133,7 @@ var DevServer = class _DevServer {
15335
15133
  for (const file of fs11.readdirSync(latestScriptsDir)) {
15336
15134
  if (file.endsWith(".js") && targetFileNames.has(file)) {
15337
15135
  try {
15338
- const content = fs11.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
15136
+ const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
15339
15137
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
15340
15138
  lines.push("```javascript");
15341
15139
  lines.push(content);
@@ -15352,7 +15150,7 @@ var DevServer = class _DevServer {
15352
15150
  lines.push("");
15353
15151
  for (const file of refFiles) {
15354
15152
  try {
15355
- const content = fs11.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
15153
+ const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
15356
15154
  lines.push(`### \`${file}\` \u{1F512}`);
15357
15155
  lines.push("```javascript");
15358
15156
  lines.push(content);
@@ -15393,10 +15191,10 @@ var DevServer = class _DevServer {
15393
15191
  lines.push("");
15394
15192
  }
15395
15193
  }
15396
- const docsDir = path15.join(providerDir, "../../docs");
15194
+ const docsDir = path14.join(providerDir, "../../docs");
15397
15195
  const loadGuide = (name) => {
15398
15196
  try {
15399
- const p = path15.join(docsDir, name);
15197
+ const p = path14.join(docsDir, name);
15400
15198
  if (fs11.existsSync(p)) return fs11.readFileSync(p, "utf-8");
15401
15199
  } catch {
15402
15200
  }
@@ -15570,7 +15368,7 @@ var DevServer = class _DevServer {
15570
15368
  parseApproval: "parse_approval.js"
15571
15369
  };
15572
15370
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
15573
- const scriptsDir = path15.join(providerDir, "scripts");
15371
+ const scriptsDir = path14.join(providerDir, "scripts");
15574
15372
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
15575
15373
  if (latestScriptsDir) {
15576
15374
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -15582,7 +15380,7 @@ var DevServer = class _DevServer {
15582
15380
  if (!file.endsWith(".js")) continue;
15583
15381
  if (!targetFileNames.has(file)) continue;
15584
15382
  try {
15585
- const content = fs11.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
15383
+ const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
15586
15384
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
15587
15385
  lines.push("```javascript");
15588
15386
  lines.push(content);
@@ -15598,7 +15396,7 @@ var DevServer = class _DevServer {
15598
15396
  lines.push("");
15599
15397
  for (const file of refFiles) {
15600
15398
  try {
15601
- const content = fs11.readFileSync(path15.join(latestScriptsDir, file), "utf-8");
15399
+ const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
15602
15400
  lines.push(`### \`${file}\` \u{1F512}`);
15603
15401
  lines.push("```javascript");
15604
15402
  lines.push(content);
@@ -15631,10 +15429,10 @@ var DevServer = class _DevServer {
15631
15429
  lines.push("");
15632
15430
  }
15633
15431
  }
15634
- const docsDir = path15.join(providerDir, "../../docs");
15432
+ const docsDir = path14.join(providerDir, "../../docs");
15635
15433
  const loadGuide = (name) => {
15636
15434
  try {
15637
- const p = path15.join(docsDir, name);
15435
+ const p = path14.join(docsDir, name);
15638
15436
  if (fs11.existsSync(p)) return fs11.readFileSync(p, "utf-8");
15639
15437
  } catch {
15640
15438
  }
@@ -15791,14 +15589,14 @@ data: ${JSON.stringify(msg.data)}
15791
15589
  res.end(JSON.stringify(data, null, 2));
15792
15590
  }
15793
15591
  async readBody(req) {
15794
- return new Promise((resolve10) => {
15592
+ return new Promise((resolve9) => {
15795
15593
  let body = "";
15796
15594
  req.on("data", (chunk) => body += chunk);
15797
15595
  req.on("end", () => {
15798
15596
  try {
15799
- resolve10(JSON.parse(body));
15597
+ resolve9(JSON.parse(body));
15800
15598
  } catch {
15801
- resolve10({});
15599
+ resolve9({});
15802
15600
  }
15803
15601
  });
15804
15602
  });
@@ -16220,7 +16018,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
16220
16018
  const deadline = Date.now() + timeoutMs;
16221
16019
  while (Date.now() < deadline) {
16222
16020
  if (await canConnect(endpoint)) return;
16223
- await new Promise((resolve10) => setTimeout(resolve10, STARTUP_POLL_MS));
16021
+ await new Promise((resolve9) => setTimeout(resolve9, STARTUP_POLL_MS));
16224
16022
  }
16225
16023
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
16226
16024
  }
@@ -16375,10 +16173,10 @@ async function installExtension(ide, extension) {
16375
16173
  const buffer = Buffer.from(await res.arrayBuffer());
16376
16174
  const fs12 = await import("fs");
16377
16175
  fs12.writeFileSync(vsixPath, buffer);
16378
- return new Promise((resolve10) => {
16176
+ return new Promise((resolve9) => {
16379
16177
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
16380
16178
  exec2(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
16381
- resolve10({
16179
+ resolve9({
16382
16180
  extensionId: extension.id,
16383
16181
  marketplaceId: extension.marketplaceId,
16384
16182
  success: !error,
@@ -16391,11 +16189,11 @@ async function installExtension(ide, extension) {
16391
16189
  } catch (e) {
16392
16190
  }
16393
16191
  }
16394
- return new Promise((resolve10) => {
16192
+ return new Promise((resolve9) => {
16395
16193
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
16396
16194
  exec2(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
16397
16195
  if (error) {
16398
- resolve10({
16196
+ resolve9({
16399
16197
  extensionId: extension.id,
16400
16198
  marketplaceId: extension.marketplaceId,
16401
16199
  success: false,
@@ -16403,7 +16201,7 @@ async function installExtension(ide, extension) {
16403
16201
  error: stderr || error.message
16404
16202
  });
16405
16203
  } else {
16406
- resolve10({
16204
+ resolve9({
16407
16205
  extensionId: extension.id,
16408
16206
  marketplaceId: extension.marketplaceId,
16409
16207
  success: true,
@@ -16706,7 +16504,6 @@ export {
16706
16504
  ProviderLoader,
16707
16505
  SessionHostPtyTransportFactory,
16708
16506
  VersionArchive,
16709
- addCliHistory,
16710
16507
  appendRecentActivity,
16711
16508
  buildSessionEntries,
16712
16509
  buildStatusSnapshot,
@@ -16724,7 +16521,6 @@ export {
16724
16521
  getRecentActivity,
16725
16522
  getRecentCommands,
16726
16523
  getRecentLogs,
16727
- getWorkspaceActivity,
16728
16524
  getWorkspaceState,
16729
16525
  hasCdpManager,
16730
16526
  initDaemonComponents,