adhdev 0.7.39 → 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.
package/dist/cli/index.js CHANGED
@@ -176,7 +176,8 @@ var init_config = __esm({
176
176
  workspaces: [],
177
177
  defaultWorkspaceId: null,
178
178
  recentActivity: [],
179
- recentSessionReads: {},
179
+ sessionReads: {},
180
+ sessionReadMarkers: {},
180
181
  machineNickname: null,
181
182
  machineId: void 0,
182
183
  machineSecret: null,
@@ -389,18 +390,27 @@ function appendRecentActivity(config2, entry) {
389
390
  function getRecentActivity(config2, limit = 20) {
390
391
  return [...config2.recentActivity || []].sort((a, b2) => b2.lastUsedAt - a.lastUsedAt).slice(0, limit);
391
392
  }
392
- function getRecentSessionSeenAt(config2, recentKey) {
393
- return config2.recentSessionReads?.[recentKey] || 0;
393
+ function getSessionSeenAt(config2, sessionId) {
394
+ return config2.sessionReads?.[sessionId] || 0;
394
395
  }
395
- function markRecentSessionSeen(config2, recentKey, seenAt = Date.now()) {
396
- const prev = config2.recentSessionReads || {};
397
- const nextSeenAt = Math.max(prev[recentKey] || 0, seenAt);
396
+ function getSessionSeenMarker(config2, sessionId) {
397
+ return config2.sessionReadMarkers?.[sessionId] || "";
398
+ }
399
+ function markSessionSeen(config2, sessionId, seenAt = Date.now(), completionMarker) {
400
+ const prev = config2.sessionReads || {};
401
+ const nextSeenAt = Math.max(prev[sessionId] || 0, seenAt);
402
+ const prevMarkers = config2.sessionReadMarkers || {};
403
+ const nextMarker = typeof completionMarker === "string" ? completionMarker : "";
398
404
  return {
399
405
  ...config2,
400
- recentSessionReads: {
406
+ sessionReads: {
401
407
  ...prev,
402
- [recentKey]: nextSeenAt
403
- }
408
+ [sessionId]: nextSeenAt
409
+ },
410
+ sessionReadMarkers: nextMarker ? {
411
+ ...prevMarkers,
412
+ [sessionId]: nextMarker
413
+ } : prevMarkers
404
414
  };
405
415
  }
406
416
  var path2, MAX_ACTIVITY;
@@ -8838,337 +8848,6 @@ var init_command_log = __esm({
8838
8848
  }
8839
8849
  });
8840
8850
 
8841
- // ../../oss/packages/daemon-core/src/commands/router.ts
8842
- var fs7, CHAT_COMMANDS, DaemonCommandRouter;
8843
- var init_router = __esm({
8844
- "../../oss/packages/daemon-core/src/commands/router.ts"() {
8845
- "use strict";
8846
- init_manager();
8847
- init_setup();
8848
- init_launch();
8849
- init_config();
8850
- init_workspaces();
8851
- init_recent_activity();
8852
- init_ide_detector();
8853
- init_logger();
8854
- init_command_log();
8855
- init_logger();
8856
- fs7 = __toESM(require("fs"));
8857
- CHAT_COMMANDS = [
8858
- "send_chat",
8859
- "new_chat",
8860
- "switch_chat",
8861
- "set_mode",
8862
- "change_model"
8863
- ];
8864
- DaemonCommandRouter = class {
8865
- deps;
8866
- constructor(deps) {
8867
- this.deps = deps;
8868
- }
8869
- /**
8870
- * Unified command routing.
8871
- * Returns result for all commands:
8872
- * 1. Daemon-level commands (launch_ide, stop_ide, etc.)
8873
- * 2. CLI commands (launch_cli, stop_cli, agent_command)
8874
- * 3. DaemonCommandHandler delegation (CDP/agent-stream/file commands)
8875
- *
8876
- * @param cmd Command name
8877
- * @param args Command arguments
8878
- * @param source Log source ('ws' | 'p2p' | 'standalone' | etc.)
8879
- */
8880
- async execute(cmd, args, source = "unknown") {
8881
- const cmdStart = Date.now();
8882
- try {
8883
- const daemonResult = await this.executeDaemonCommand(cmd, args);
8884
- if (daemonResult) {
8885
- logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source, args, success: daemonResult.success, durationMs: Date.now() - cmdStart });
8886
- return daemonResult;
8887
- }
8888
- const handlerResult = await this.deps.commandHandler.handle(cmd, args);
8889
- logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source, args, success: handlerResult.success, durationMs: Date.now() - cmdStart });
8890
- if (CHAT_COMMANDS.includes(cmd) && this.deps.onPostChatCommand) {
8891
- this.deps.onPostChatCommand();
8892
- }
8893
- return handlerResult;
8894
- } catch (e) {
8895
- logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source, args, success: false, error: e.message, durationMs: Date.now() - cmdStart });
8896
- throw e;
8897
- }
8898
- }
8899
- // ─── Daemon-level command core ───────────────────
8900
- /**
8901
- * Daemon-level command execution (IDE start/stop/restart, CLI, detect, logs).
8902
- * Returns null if not handled at this level → caller delegates to CommandHandler.
8903
- */
8904
- async executeDaemonCommand(cmd, args) {
8905
- switch (cmd) {
8906
- // ─── CLI / ACP commands ───
8907
- case "launch_cli":
8908
- case "stop_cli":
8909
- case "agent_command": {
8910
- return this.deps.cliManager.handleCliCommand(cmd, args);
8911
- }
8912
- // ─── Logs ───
8913
- case "get_logs": {
8914
- const count = parseInt(args?.count) || parseInt(args?.lines) || 100;
8915
- const minLevel = args?.minLevel || "info";
8916
- const sinceTs = args?.since || 0;
8917
- try {
8918
- let logs = getRecentLogs(count, minLevel);
8919
- if (sinceTs > 0) {
8920
- logs = logs.filter((l) => l.ts > sinceTs);
8921
- }
8922
- if (logs.length > 0) {
8923
- return { success: true, logs, totalBuffered: logs.length };
8924
- }
8925
- if (fs7.existsSync(LOG_PATH)) {
8926
- const content = fs7.readFileSync(LOG_PATH, "utf-8");
8927
- const allLines = content.split("\n");
8928
- const recent = allLines.slice(-count).join("\n");
8929
- return { success: true, logs: recent, totalLines: allLines.length };
8930
- }
8931
- return { success: true, logs: [], totalBuffered: 0 };
8932
- } catch (e) {
8933
- return { success: false, error: e.message };
8934
- }
8935
- }
8936
- // ─── restart_session: IDE / CLI / ACP unified ───
8937
- case "restart_session": {
8938
- const targetType = args?.cliType || args?.agentType || args?.ideType;
8939
- if (!targetType) throw new Error("cliType or ideType required");
8940
- const isIde = this.deps.cdpManagers.has(targetType) || this.deps.providerLoader.getMeta(targetType)?.category === "ide";
8941
- if (isIde) {
8942
- await this.stopIde(targetType, true);
8943
- const launchResult = await this.executeDaemonCommand("launch_ide", { ideType: targetType, enableCdp: true, workspace: args?.workspace });
8944
- return { success: true, restarted: true, ideType: targetType, launch: launchResult };
8945
- }
8946
- return this.deps.cliManager.handleCliCommand(cmd, args);
8947
- }
8948
- // ─── IDE stop ───
8949
- case "stop_ide": {
8950
- const ideType = args?.ideType;
8951
- if (!ideType) throw new Error("ideType required");
8952
- const killProcess = args?.killProcess !== false;
8953
- await this.stopIde(ideType, killProcess);
8954
- return { success: true, ideType, stopped: true, processKilled: killProcess };
8955
- }
8956
- // ─── IDE restart ───
8957
- case "restart_ide": {
8958
- const ideType = args?.ideType;
8959
- if (!ideType) throw new Error("ideType required");
8960
- await this.stopIde(ideType, true);
8961
- const launchResult = await this.executeDaemonCommand("launch_ide", { ideType, enableCdp: true, workspace: args?.workspace });
8962
- return { success: true, ideType, restarted: true, launch: launchResult };
8963
- }
8964
- // ─── IDE launch + CDP connect ───
8965
- case "launch_ide": {
8966
- const ideKey = args?.ideId || args?.ideType;
8967
- const resolvedWorkspace = resolveIdeLaunchWorkspace(
8968
- {
8969
- workspace: args?.workspace,
8970
- workspaceId: args?.workspaceId,
8971
- useDefaultWorkspace: args?.useDefaultWorkspace
8972
- },
8973
- loadConfig()
8974
- );
8975
- const launchArgs = {
8976
- ideId: ideKey,
8977
- workspace: resolvedWorkspace,
8978
- newWindow: args?.newWindow
8979
- };
8980
- LOG.info("LaunchIDE", `target=${ideKey || "auto"}`);
8981
- const result = await launchWithCdp(launchArgs);
8982
- if (result.success && result.port && result.ideId && !this.deps.cdpManagers.has(result.ideId)) {
8983
- const logFn = this.deps.getCdpLogFn ? this.deps.getCdpLogFn(result.ideId) : LOG.forComponent(`CDP:${result.ideId}`).asLogFn();
8984
- const provider = this.deps.providerLoader.getMeta(result.ideId);
8985
- const manager = new DaemonCdpManager(result.port, logFn, void 0, provider?.targetFilter);
8986
- const connected = await manager.connect();
8987
- if (connected) {
8988
- registerExtensionProviders(this.deps.providerLoader, manager, result.ideId);
8989
- this.deps.cdpManagers.set(result.ideId, manager);
8990
- LOG.info("CDP", `Connected: ${result.ideId} (port ${result.port})`);
8991
- LOG.info("CDP", `${this.deps.cdpManagers.size} IDE(s) connected`);
8992
- this.deps.onCdpManagerCreated?.(result.ideId, manager);
8993
- }
8994
- }
8995
- this.deps.onIdeConnected?.();
8996
- if (result.success && resolvedWorkspace) {
8997
- try {
8998
- const next = appendRecentActivity(loadConfig(), {
8999
- kind: "ide",
9000
- providerType: result.ideId || ideKey,
9001
- providerName: result.ideId || ideKey,
9002
- workspace: resolvedWorkspace,
9003
- title: result.ideId || ideKey
9004
- });
9005
- saveConfig(next);
9006
- } catch {
9007
- }
9008
- } else if (result.success && (result.ideId || ideKey)) {
9009
- try {
9010
- saveConfig(appendRecentActivity(loadConfig(), {
9011
- kind: "ide",
9012
- providerType: result.ideId || ideKey,
9013
- providerName: result.ideId || ideKey,
9014
- title: result.ideId || ideKey
9015
- }));
9016
- } catch {
9017
- }
9018
- }
9019
- return { success: result.success, ...result };
9020
- }
9021
- // ─── Detect IDEs ───
9022
- case "detect_ides": {
9023
- const results = await detectIDEs();
9024
- this.deps.detectedIdes.value = results;
9025
- return { success: true, detectedInfo: results };
9026
- }
9027
- // ─── Set User Name ───
9028
- case "set_user_name": {
9029
- const name = args?.userName;
9030
- if (!name || typeof name !== "string") throw new Error("userName required");
9031
- updateConfig({ userName: name });
9032
- return { success: true, userName: name };
9033
- }
9034
- case "mark_recent_seen": {
9035
- const kind = args?.kind;
9036
- const providerType = args?.providerType;
9037
- if (!kind || !providerType) {
9038
- return { success: false, error: "kind and providerType are required" };
9039
- }
9040
- const recentKey = args?.recentKey || buildRecentActivityKey({
9041
- kind,
9042
- providerType,
9043
- workspace: args?.workspace || null
9044
- });
9045
- const next = markRecentSessionSeen(
9046
- loadConfig(),
9047
- recentKey,
9048
- typeof args?.seenAt === "number" ? args.seenAt : Date.now()
9049
- );
9050
- saveConfig(next);
9051
- this.deps.onStatusChange?.();
9052
- return {
9053
- success: true,
9054
- recentKey,
9055
- seenAt: next.recentSessionReads?.[recentKey] || Date.now()
9056
- };
9057
- }
9058
- // ─── Daemon Self-Upgrade ───
9059
- case "daemon_upgrade": {
9060
- LOG.info("Upgrade", "Remote upgrade requested from dashboard");
9061
- try {
9062
- const { execSync: execSync7 } = await import("child_process");
9063
- const isStandalone = this.deps.packageName === "@adhdev/daemon-standalone" || process.argv[1]?.includes("daemon-standalone");
9064
- const pkgName = isStandalone ? "@adhdev/daemon-standalone" : "adhdev";
9065
- const latest = execSync7(`npm view ${pkgName} version`, { encoding: "utf-8", timeout: 1e4 }).trim();
9066
- LOG.info("Upgrade", `Latest ${pkgName}: v${latest}`);
9067
- execSync7(`npm install -g ${pkgName}@latest --force`, {
9068
- encoding: "utf-8",
9069
- timeout: 12e4,
9070
- stdio: ["pipe", "pipe", "pipe"]
9071
- });
9072
- LOG.info("Upgrade", `\u2705 Upgraded to v${latest}`);
9073
- setTimeout(() => {
9074
- LOG.info("Upgrade", "Restarting daemon with new version...");
9075
- try {
9076
- const path18 = require("path");
9077
- const fs16 = require("fs");
9078
- const pidFile = path18.join(process.env.HOME || process.env.USERPROFILE || "", ".adhdev", "daemon.pid");
9079
- if (fs16.existsSync(pidFile)) fs16.unlinkSync(pidFile);
9080
- } catch {
9081
- }
9082
- const { spawn: spawn4 } = require("child_process");
9083
- const child = spawn4(process.execPath, process.argv.slice(1), {
9084
- detached: true,
9085
- stdio: "ignore",
9086
- env: { ...process.env }
9087
- });
9088
- child.unref();
9089
- process.exit(0);
9090
- }, 3e3);
9091
- return { success: true, upgraded: true, version: latest };
9092
- } catch (e) {
9093
- LOG.error("Upgrade", `Failed: ${e.message}`);
9094
- return { success: false, error: e.message };
9095
- }
9096
- }
9097
- // ─── Machine Settings ───
9098
- case "set_machine_nickname": {
9099
- const nickname = args?.nickname;
9100
- updateConfig({ machineNickname: nickname || null });
9101
- return { success: true };
9102
- }
9103
- default:
9104
- break;
9105
- }
9106
- return null;
9107
- }
9108
- /**
9109
- * IDE stop: CDP disconnect + InstanceManager cleanup + optionally kill OS process
9110
- */
9111
- async stopIde(ideType, killProcess = false) {
9112
- const cdpKeysToRemove = [];
9113
- for (const key of this.deps.cdpManagers.keys()) {
9114
- if (key === ideType || key.startsWith(`${ideType}_`)) {
9115
- cdpKeysToRemove.push(key);
9116
- }
9117
- }
9118
- for (const key of cdpKeysToRemove) {
9119
- const cdp = this.deps.cdpManagers.get(key);
9120
- if (cdp) {
9121
- try {
9122
- cdp.disconnect();
9123
- } catch {
9124
- }
9125
- this.deps.cdpManagers.delete(key);
9126
- this.deps.sessionRegistry.unregisterByManagerKey(key);
9127
- LOG.info("StopIDE", `CDP disconnected: ${key}`);
9128
- }
9129
- }
9130
- const keysToRemove = [];
9131
- for (const key of this.deps.instanceManager.listInstanceIds()) {
9132
- if (key === `ide:${ideType}` || typeof key === "string" && key.startsWith(`ide:${ideType}_`)) {
9133
- keysToRemove.push(key);
9134
- }
9135
- }
9136
- for (const instanceKey of keysToRemove) {
9137
- const ideInstance = this.deps.instanceManager.getInstance(instanceKey);
9138
- if (ideInstance) {
9139
- this.deps.instanceManager.removeInstance(instanceKey);
9140
- LOG.info("StopIDE", `Instance removed: ${instanceKey}`);
9141
- }
9142
- }
9143
- if (keysToRemove.length === 0) {
9144
- const instanceKey = `ide:${ideType}`;
9145
- const ideInstance = this.deps.instanceManager.getInstance(instanceKey);
9146
- if (ideInstance) {
9147
- this.deps.instanceManager.removeInstance(instanceKey);
9148
- LOG.info("StopIDE", `Instance removed: ${instanceKey}`);
9149
- }
9150
- }
9151
- if (killProcess) {
9152
- const running = isIdeRunning(ideType);
9153
- if (running) {
9154
- LOG.info("StopIDE", `Killing IDE process: ${ideType}`);
9155
- const killed = await killIdeProcess(ideType);
9156
- if (killed) {
9157
- LOG.info("StopIDE", `\u2705 Process killed: ${ideType}`);
9158
- } else {
9159
- LOG.warn("StopIDE", `\u26A0 Could not kill process: ${ideType} (may need manual intervention)`);
9160
- }
9161
- } else {
9162
- LOG.info("StopIDE", `Process not running: ${ideType}`);
9163
- }
9164
- }
9165
- this.deps.onStatusChange?.();
9166
- LOG.info("StopIDE", `IDE stopped: ${ideType} (processKill=${killProcess})`);
9167
- }
9168
- };
9169
- }
9170
- });
9171
-
9172
8851
  // ../../oss/packages/daemon-core/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts
9173
8852
  function isModuleNotFoundError(error48, ref) {
9174
8853
  if (!(error48 instanceof Error)) return false;
@@ -9996,7 +9675,7 @@ function Ec(s15, t) {
9996
9675
  function Tc(s15) {
9997
9676
  return s15.keyCode === 16 || s15.keyCode === 17 || s15.keyCode === 18;
9998
9677
  }
9999
- var zs, Rl, Ll, M, S, Gs, mi, $s, _i, er, tr, ir, we, De, rt, q, js, Hn, Fn, F, rr, ge, Zs, xt, nr, H, sr, Js, Be, wt, nt, ae, Dt, ce, Qs, or, Re, lr, Wn, Bl, Un, bi, ar, Rt, cr, ro, so, At, lo, ao, oo, ur, zn, Wl, dt, hr, dr, Ee, D, ye, fe, kt, G, Ct, zl, mr, Gl, fo, $l, $, Mt, $n, po, br, Vn, gi, qn, Yn, Vl, Pt, ql, Yl, _r, v, jn, gr, Si, Eu, Tu, Ot, Ei, Bt, Ti, Sr, Iu, yu, vr, Nt, yr, xr, Ii, Zl, vo, go, Jl, Ql, ea, ta, Tr, Ir, bo, ia, $e, Ve, xe, So, ra, Xn, wr, Te, Zn, Dr, na, xu, Fe, st, sa, oa, Eo, la, wu, Du, Ru, Lu, ot, aa, yi, Jn, To, Io, yo, Qn, Rr, es, ua, ha, da, fa, ft, wo, Lr, qe, xi, Do, ma, ts2, Ye, kr, ba, Ar, va, _e, Cr, Bh, be, Nh, Fh, Hh, Oo, Wh, Uh, No, Kh, zh, ss, os10, wa, mt, Mr, Di, pt, Gh, Y, Da, ls, Wt, He, Q, Pr, lt, Uo, Or, cs, Ri, Br, Nr, Fr, Ca, Ut, Kt, Wr, Ur, Ma, Ko, zo, us, zr, hs, ds, Kr, zt, Gt, Gr, We, at, Li, bt, b, Ai, fs8, $t, ue, he, de, J, ps, j, U, z, ve, $r, Vr, ct, Vt, Yr, ms, _s, Le, jr, jo, ki, Xr, Na, Yt, jt, Zr, bs, vs, Jr, gs, Qr, Xt, en, tn, Mi, Pi, Oi, Ss, Fa, Zo, Zt, Wa, Ua, Es, Bi, Ts, rn, Is, ys, Jt, nn, Qt, xs, on, Ds, Ya, ja, Xa, Za, Ja, ei, Hi, Wi, re, St, Ki, tl, il, Ui, Qa, ti, Rs, ln, ec, tc, ii, ic, zi, B, X, an, Ls, Ze, un, cn, ne, Je, cl, $i, hn, ks, Cs, ni, si, nc, dn, ul, hl, li, dl, Ps, fl, ai, Os, ac, se, fn, Ae, pn, Vi, uc, ci, qi, mn, pe, Yi, _n, ji, Xi, Fs, ke, hc, bn, dc, fc, mc, ut, _l, vl, gl, vn, Zi, _c, El, bc, gn, ui, Tl, Sn, gc, ee, En, Us, yl, Tn, Ks, Sc, In, xl, wl, Tt, hi, yn, xn, wn, Ji, Dn, Rn, Ln, Ic, Ue, Dl;
9678
+ var zs, Rl, Ll, M, S, Gs, mi, $s, _i, er, tr, ir, we, De, rt, q, js, Hn, Fn, F, rr, ge, Zs, xt, nr, H, sr, Js, Be, wt, nt, ae, Dt, ce, Qs, or, Re, lr, Wn, Bl, Un, bi, ar, Rt, cr, ro, so, At, lo, ao, oo, ur, zn, Wl, dt, hr, dr, Ee, D, ye, fe, kt, G, Ct, zl, mr, Gl, fo, $l, $, Mt, $n, po, br, Vn, gi, qn, Yn, Vl, Pt, ql, Yl, _r, v, jn, gr, Si, Eu, Tu, Ot, Ei, Bt, Ti, Sr, Iu, yu, vr, Nt, yr, xr, Ii, Zl, vo, go, Jl, Ql, ea, ta, Tr, Ir, bo, ia, $e, Ve, xe, So, ra, Xn, wr, Te, Zn, Dr, na, xu, Fe, st, sa, oa, Eo, la, wu, Du, Ru, Lu, ot, aa, yi, Jn, To, Io, yo, Qn, Rr, es, ua, ha, da, fa, ft, wo, Lr, qe, xi, Do, ma, ts2, Ye, kr, ba, Ar, va, _e, Cr, Bh, be, Nh, Fh, Hh, Oo, Wh, Uh, No, Kh, zh, ss, os10, wa, mt, Mr, Di, pt, Gh, Y, Da, ls, Wt, He, Q, Pr, lt, Uo, Or, cs, Ri, Br, Nr, Fr, Ca, Ut, Kt, Wr, Ur, Ma, Ko, zo, us, zr, hs, ds, Kr, zt, Gt, Gr, We, at, Li, bt, b, Ai, fs7, $t, ue, he, de, J, ps, j, U, z, ve, $r, Vr, ct, Vt, Yr, ms, _s, Le, jr, jo, ki, Xr, Na, Yt, jt, Zr, bs, vs, Jr, gs, Qr, Xt, en, tn, Mi, Pi, Oi, Ss, Fa, Zo, Zt, Wa, Ua, Es, Bi, Ts, rn, Is, ys, Jt, nn, Qt, xs, on, Ds, Ya, ja, Xa, Za, Ja, ei, Hi, Wi, re, St, Ki, tl, il, Ui, Qa, ti, Rs, ln, ec, tc, ii, ic, zi, B, X, an, Ls, Ze, un, cn, ne, Je, cl, $i, hn, ks, Cs, ni, si, nc, dn, ul, hl, li, dl, Ps, fl, ai, Os, ac, se, fn, Ae, pn, Vi, uc, ci, qi, mn, pe, Yi, _n, ji, Xi, Fs, ke, hc, bn, dc, fc, mc, ut, _l, vl, gl, vn, Zi, _c, El, bc, gn, ui, Tl, Sn, gc, ee, En, Us, yl, Tn, Ks, Sc, In, xl, wl, Tt, hi, yn, xn, wn, Ji, Dn, Rn, Ln, Ic, Ue, Dl;
10000
9679
  var init_xterm = __esm({
10001
9680
  "../../oss/node_modules/@xterm/xterm/lib/xterm.mjs"() {
10002
9681
  "use strict";
@@ -13271,7 +12950,7 @@ ${h.join(`
13271
12950
  ((E) => (E.NUL = "\0", E.SOH = "", E.STX = "", E.ETX = "", E.EOT = "", E.ENQ = "", E.ACK = "", E.BEL = "\x07", E.BS = "\b", E.HT = " ", E.LF = `
13272
12951
  `, E.VT = "\v", E.FF = "\f", E.CR = "\r", E.SO = "", E.SI = "", E.DLE = "", E.DC1 = "", E.DC2 = "", E.DC3 = "", E.DC4 = "", E.NAK = "", E.SYN = "", E.ETB = "", E.CAN = "", E.EM = "", E.SUB = "", E.ESC = "\x1B", E.FS = "", E.GS = "", E.RS = "", E.US = "", E.SP = " ", E.DEL = "\x7F"))(b ||= {});
13273
12952
  ((g) => (g.PAD = "\x80", g.HOP = "\x81", g.BPH = "\x82", g.NBH = "\x83", g.IND = "\x84", g.NEL = "\x85", g.SSA = "\x86", g.ESA = "\x87", g.HTS = "\x88", g.HTJ = "\x89", g.VTS = "\x8A", g.PLD = "\x8B", g.PLU = "\x8C", g.RI = "\x8D", g.SS2 = "\x8E", g.SS3 = "\x8F", g.DCS = "\x90", g.PU1 = "\x91", g.PU2 = "\x92", g.STS = "\x93", g.CCH = "\x94", g.MW = "\x95", g.SPA = "\x96", g.EPA = "\x97", g.SOS = "\x98", g.SGCI = "\x99", g.SCI = "\x9A", g.CSI = "\x9B", g.ST = "\x9C", g.OSC = "\x9D", g.PM = "\x9E", g.APC = "\x9F"))(Ai ||= {});
13274
- ((t) => t.ST = `${b.ESC}\\`)(fs8 ||= {});
12953
+ ((t) => t.ST = `${b.ESC}\\`)(fs7 ||= {});
13275
12954
  $t = class {
13276
12955
  constructor(t, e, i, r, n, o) {
13277
12956
  this._textarea = t;
@@ -17700,7 +17379,7 @@ ${h.join(`
17700
17379
  switch (i.type) {
17701
17380
  case 0:
17702
17381
  let o = U.toColorRGB(r === "ansi" ? this._themeService.colors.ansi[i.index] : this._themeService.colors[r]);
17703
- this.coreService.triggerDataEvent(`${b.ESC}]${n};${ml(o)}${fs8.ST}`);
17382
+ this.coreService.triggerDataEvent(`${b.ESC}]${n};${ml(o)}${fs7.ST}`);
17704
17383
  break;
17705
17384
  case 1:
17706
17385
  if (r === "ansi") this._themeService.modifyColors((l) => l.ansi[i.index] = j.toColor(...i.color));
@@ -18541,94 +18220,45 @@ function getSessionMessageUpdatedAt(session) {
18541
18220
  if (!lastMessage) return 0;
18542
18221
  return parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt) || 0;
18543
18222
  }
18223
+ function getSessionCompletionMarker(session) {
18224
+ const lastMessage = session.activeChat?.messages?.at?.(-1);
18225
+ if (!lastMessage) return "";
18226
+ const role = typeof lastMessage.role === "string" ? lastMessage.role : "";
18227
+ if (role === "user" || role === "human") return "";
18228
+ if (typeof lastMessage._turnKey === "string" && lastMessage._turnKey) return `turn:${lastMessage._turnKey}`;
18229
+ if (typeof lastMessage.id === "string" && lastMessage.id) return `id:${lastMessage.id}`;
18230
+ if (typeof lastMessage.index === "number" && Number.isFinite(lastMessage.index)) return `idx:${lastMessage.index}`;
18231
+ const timestamp = parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt);
18232
+ return timestamp > 0 ? `ts:${timestamp}` : "";
18233
+ }
18544
18234
  function getSessionLastUsedAt(session) {
18545
18235
  return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
18546
18236
  }
18547
- function getSessionKind(session) {
18548
- return session.transport === "cdp-page" || session.transport === "cdp-webview" ? "ide" : session.transport === "acp" ? "acp" : "cli";
18549
- }
18550
18237
  function getLastMessageRole(session) {
18551
18238
  const role = session.activeChat?.messages?.at?.(-1)?.role;
18552
18239
  return typeof role === "string" ? role : "";
18553
18240
  }
18554
- function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole) {
18241
+ function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole, completionMarker, seenCompletionMarker) {
18555
18242
  if (status === "waiting_approval") {
18556
18243
  return { unread: false, inboxBucket: "needs_attention" };
18557
18244
  }
18558
18245
  if (status === "generating" || status === "starting") {
18559
18246
  return { unread: false, inboxBucket: "working" };
18560
18247
  }
18561
- const unread = hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
18248
+ const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
18562
18249
  return { unread, inboxBucket: unread ? "task_complete" : "idle" };
18563
18250
  }
18564
- function buildRecentSessions(sessions, recentActivity, readState) {
18565
- const visibleKeys = /* @__PURE__ */ new Set();
18566
- const hiddenKeys = /* @__PURE__ */ new Set();
18567
- const live = sessions.filter((session) => !session.surfaceHidden && session.status !== "stopped").map((session) => {
18568
- const kind = getSessionKind(session);
18569
- const recentKey = buildRecentActivityKey({
18570
- kind,
18571
- providerType: session.providerType,
18572
- workspace: session.workspace
18573
- });
18574
- const lastSeenAt = readState[recentKey] || 0;
18575
- const lastUsedAt = getSessionLastUsedAt(session);
18576
- const { unread, inboxBucket } = getUnreadState(
18577
- getSessionMessageUpdatedAt(session) > 0,
18578
- session.status,
18579
- lastUsedAt,
18580
- lastSeenAt,
18581
- getLastMessageRole(session)
18582
- );
18583
- return {
18584
- id: session.id,
18585
- recentKey,
18586
- sessionId: session.id,
18587
- providerType: session.providerType,
18588
- providerName: session.providerName,
18589
- kind,
18590
- title: session.activeChat?.title || session.title || session.providerName,
18591
- workspace: session.workspace,
18592
- currentModel: session.currentModel,
18593
- status: session.status,
18594
- lastUsedAt,
18595
- unread,
18596
- lastSeenAt,
18597
- inboxBucket,
18598
- surfaceHidden: false
18599
- };
18600
- });
18601
- for (const item of live) {
18602
- visibleKeys.add(`${item.kind}:${item.providerType}:${item.workspace || ""}`);
18603
- }
18604
- for (const session of sessions) {
18605
- if (!session.surfaceHidden) continue;
18606
- hiddenKeys.add(`${getSessionKind(session)}:${session.providerType}:${session.workspace || ""}`);
18607
- }
18608
- const persisted = recentActivity.filter((item) => {
18609
- const key = `${item.kind}:${item.providerType}:${item.workspace || ""}`;
18610
- return !visibleKeys.has(key) && !hiddenKeys.has(key);
18611
- }).map((item) => {
18612
- const lastSeenAt = readState[item.id] || 0;
18613
- const unread = item.lastUsedAt > lastSeenAt;
18614
- return {
18615
- id: item.id,
18616
- recentKey: item.id,
18617
- sessionId: item.sessionId || null,
18618
- providerType: item.providerType,
18619
- providerName: item.providerName,
18620
- kind: item.kind,
18621
- title: item.title || item.providerName,
18622
- workspace: item.workspace,
18623
- currentModel: item.currentModel,
18624
- lastUsedAt: item.lastUsedAt,
18625
- unread,
18626
- lastSeenAt,
18627
- inboxBucket: unread ? "task_complete" : "idle",
18628
- surfaceHidden: false
18629
- };
18630
- });
18631
- return [...live, ...persisted].sort((a, b2) => b2.lastUsedAt - a.lastUsedAt).slice(0, 12);
18251
+ function buildRecentLaunches(recentActivity) {
18252
+ return recentActivity.map((item) => ({
18253
+ id: item.id,
18254
+ providerType: item.providerType,
18255
+ providerName: item.providerName,
18256
+ kind: item.kind,
18257
+ title: item.title || item.providerName,
18258
+ workspace: item.workspace,
18259
+ currentModel: item.currentModel,
18260
+ lastLaunchedAt: item.lastUsedAt
18261
+ })).sort((a, b2) => b2.lastLaunchedAt - a.lastLaunchedAt).slice(0, 12);
18632
18262
  }
18633
18263
  function buildStatusSnapshot(options) {
18634
18264
  const cfg = loadConfig();
@@ -18639,27 +18269,29 @@ function buildStatusSnapshot(options) {
18639
18269
  options.allStates,
18640
18270
  options.cdpManagers
18641
18271
  );
18642
- const readState = cfg.recentSessionReads || {};
18643
18272
  for (const session of sessions) {
18644
- const kind = getSessionKind(session);
18645
- const recentKey = buildRecentActivityKey({
18646
- kind,
18647
- providerType: session.providerType,
18648
- workspace: session.workspace
18649
- });
18650
- const lastSeenAt = getRecentSessionSeenAt(cfg, recentKey);
18273
+ const lastSeenAt = getSessionSeenAt(cfg, session.id);
18274
+ const seenCompletionMarker = getSessionSeenMarker(cfg, session.id);
18651
18275
  const lastUsedAt = getSessionLastUsedAt(session);
18276
+ const completionMarker = getSessionCompletionMarker(session);
18652
18277
  const { unread, inboxBucket } = session.surfaceHidden ? { unread: false, inboxBucket: "idle" } : getUnreadState(
18653
18278
  getSessionMessageUpdatedAt(session) > 0,
18654
18279
  session.status,
18655
18280
  lastUsedAt,
18656
18281
  lastSeenAt,
18657
- getLastMessageRole(session)
18282
+ getLastMessageRole(session),
18283
+ completionMarker,
18284
+ seenCompletionMarker
18658
18285
  );
18659
- session.recentKey = recentKey;
18660
18286
  session.lastSeenAt = lastSeenAt;
18661
18287
  session.unread = unread;
18662
18288
  session.inboxBucket = inboxBucket;
18289
+ if (READ_DEBUG_ENABLED && (session.unread || session.inboxBucket !== "idle" || session.providerType.includes("codex"))) {
18290
+ LOG.info(
18291
+ "RecentRead",
18292
+ `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)}`
18293
+ );
18294
+ }
18663
18295
  }
18664
18296
  const terminalBackend = getTerminalBackendRuntimeStatus();
18665
18297
  return {
@@ -18686,12 +18318,12 @@ function buildStatusSnapshot(options) {
18686
18318
  workspaces: wsState.workspaces,
18687
18319
  defaultWorkspaceId: wsState.defaultWorkspaceId,
18688
18320
  defaultWorkspacePath: wsState.defaultWorkspacePath,
18689
- recentSessions: buildRecentSessions(sessions, recentActivity, readState),
18321
+ recentLaunches: buildRecentLaunches(recentActivity),
18690
18322
  terminalBackend,
18691
18323
  availableProviders: buildAvailableProviders(options.providerLoader)
18692
18324
  };
18693
18325
  }
18694
- var os11;
18326
+ var os11, READ_DEBUG_ENABLED;
18695
18327
  var init_snapshot = __esm({
18696
18328
  "../../oss/packages/daemon-core/src/status/snapshot.ts"() {
18697
18329
  "use strict";
@@ -18701,7 +18333,350 @@ var init_snapshot = __esm({
18701
18333
  init_workspaces();
18702
18334
  init_host_memory();
18703
18335
  init_terminal_screen();
18336
+ init_logger();
18704
18337
  init_builders();
18338
+ READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
18339
+ }
18340
+ });
18341
+
18342
+ // ../../oss/packages/daemon-core/src/commands/router.ts
18343
+ var fs8, CHAT_COMMANDS, READ_DEBUG_ENABLED2, DaemonCommandRouter;
18344
+ var init_router = __esm({
18345
+ "../../oss/packages/daemon-core/src/commands/router.ts"() {
18346
+ "use strict";
18347
+ init_manager();
18348
+ init_setup();
18349
+ init_launch();
18350
+ init_config();
18351
+ init_workspaces();
18352
+ init_recent_activity();
18353
+ init_ide_detector();
18354
+ init_logger();
18355
+ init_command_log();
18356
+ init_logger();
18357
+ init_builders();
18358
+ init_snapshot();
18359
+ fs8 = __toESM(require("fs"));
18360
+ CHAT_COMMANDS = [
18361
+ "send_chat",
18362
+ "new_chat",
18363
+ "switch_chat",
18364
+ "set_mode",
18365
+ "change_model"
18366
+ ];
18367
+ READ_DEBUG_ENABLED2 = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
18368
+ DaemonCommandRouter = class {
18369
+ deps;
18370
+ constructor(deps) {
18371
+ this.deps = deps;
18372
+ }
18373
+ /**
18374
+ * Unified command routing.
18375
+ * Returns result for all commands:
18376
+ * 1. Daemon-level commands (launch_ide, stop_ide, etc.)
18377
+ * 2. CLI commands (launch_cli, stop_cli, agent_command)
18378
+ * 3. DaemonCommandHandler delegation (CDP/agent-stream/file commands)
18379
+ *
18380
+ * @param cmd Command name
18381
+ * @param args Command arguments
18382
+ * @param source Log source ('ws' | 'p2p' | 'standalone' | etc.)
18383
+ */
18384
+ async execute(cmd, args, source = "unknown") {
18385
+ const cmdStart = Date.now();
18386
+ try {
18387
+ const daemonResult = await this.executeDaemonCommand(cmd, args);
18388
+ if (daemonResult) {
18389
+ logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source, args, success: daemonResult.success, durationMs: Date.now() - cmdStart });
18390
+ return daemonResult;
18391
+ }
18392
+ const handlerResult = await this.deps.commandHandler.handle(cmd, args);
18393
+ logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source, args, success: handlerResult.success, durationMs: Date.now() - cmdStart });
18394
+ if (CHAT_COMMANDS.includes(cmd) && this.deps.onPostChatCommand) {
18395
+ this.deps.onPostChatCommand();
18396
+ }
18397
+ return handlerResult;
18398
+ } catch (e) {
18399
+ logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source, args, success: false, error: e.message, durationMs: Date.now() - cmdStart });
18400
+ throw e;
18401
+ }
18402
+ }
18403
+ // ─── Daemon-level command core ───────────────────
18404
+ /**
18405
+ * Daemon-level command execution (IDE start/stop/restart, CLI, detect, logs).
18406
+ * Returns null if not handled at this level → caller delegates to CommandHandler.
18407
+ */
18408
+ async executeDaemonCommand(cmd, args) {
18409
+ switch (cmd) {
18410
+ // ─── CLI / ACP commands ───
18411
+ case "launch_cli":
18412
+ case "stop_cli":
18413
+ case "agent_command": {
18414
+ return this.deps.cliManager.handleCliCommand(cmd, args);
18415
+ }
18416
+ // ─── Logs ───
18417
+ case "get_logs": {
18418
+ const count = parseInt(args?.count) || parseInt(args?.lines) || 100;
18419
+ const minLevel = args?.minLevel || "info";
18420
+ const sinceTs = args?.since || 0;
18421
+ try {
18422
+ let logs = getRecentLogs(count, minLevel);
18423
+ if (sinceTs > 0) {
18424
+ logs = logs.filter((l) => l.ts > sinceTs);
18425
+ }
18426
+ if (logs.length > 0) {
18427
+ return { success: true, logs, totalBuffered: logs.length };
18428
+ }
18429
+ if (fs8.existsSync(LOG_PATH)) {
18430
+ const content = fs8.readFileSync(LOG_PATH, "utf-8");
18431
+ const allLines = content.split("\n");
18432
+ const recent = allLines.slice(-count).join("\n");
18433
+ return { success: true, logs: recent, totalLines: allLines.length };
18434
+ }
18435
+ return { success: true, logs: [], totalBuffered: 0 };
18436
+ } catch (e) {
18437
+ return { success: false, error: e.message };
18438
+ }
18439
+ }
18440
+ // ─── restart_session: IDE / CLI / ACP unified ───
18441
+ case "restart_session": {
18442
+ const targetType = args?.cliType || args?.agentType || args?.ideType;
18443
+ if (!targetType) throw new Error("cliType or ideType required");
18444
+ const isIde = this.deps.cdpManagers.has(targetType) || this.deps.providerLoader.getMeta(targetType)?.category === "ide";
18445
+ if (isIde) {
18446
+ await this.stopIde(targetType, true);
18447
+ const launchResult = await this.executeDaemonCommand("launch_ide", { ideType: targetType, enableCdp: true, workspace: args?.workspace });
18448
+ return { success: true, restarted: true, ideType: targetType, launch: launchResult };
18449
+ }
18450
+ return this.deps.cliManager.handleCliCommand(cmd, args);
18451
+ }
18452
+ // ─── IDE stop ───
18453
+ case "stop_ide": {
18454
+ const ideType = args?.ideType;
18455
+ if (!ideType) throw new Error("ideType required");
18456
+ const killProcess = args?.killProcess !== false;
18457
+ await this.stopIde(ideType, killProcess);
18458
+ return { success: true, ideType, stopped: true, processKilled: killProcess };
18459
+ }
18460
+ // ─── IDE restart ───
18461
+ case "restart_ide": {
18462
+ const ideType = args?.ideType;
18463
+ if (!ideType) throw new Error("ideType required");
18464
+ await this.stopIde(ideType, true);
18465
+ const launchResult = await this.executeDaemonCommand("launch_ide", { ideType, enableCdp: true, workspace: args?.workspace });
18466
+ return { success: true, ideType, restarted: true, launch: launchResult };
18467
+ }
18468
+ // ─── IDE launch + CDP connect ───
18469
+ case "launch_ide": {
18470
+ const ideKey = args?.ideId || args?.ideType;
18471
+ const resolvedWorkspace = resolveIdeLaunchWorkspace(
18472
+ {
18473
+ workspace: args?.workspace,
18474
+ workspaceId: args?.workspaceId,
18475
+ useDefaultWorkspace: args?.useDefaultWorkspace
18476
+ },
18477
+ loadConfig()
18478
+ );
18479
+ const launchArgs = {
18480
+ ideId: ideKey,
18481
+ workspace: resolvedWorkspace,
18482
+ newWindow: args?.newWindow
18483
+ };
18484
+ LOG.info("LaunchIDE", `target=${ideKey || "auto"}`);
18485
+ const result = await launchWithCdp(launchArgs);
18486
+ if (result.success && result.port && result.ideId && !this.deps.cdpManagers.has(result.ideId)) {
18487
+ const logFn = this.deps.getCdpLogFn ? this.deps.getCdpLogFn(result.ideId) : LOG.forComponent(`CDP:${result.ideId}`).asLogFn();
18488
+ const provider = this.deps.providerLoader.getMeta(result.ideId);
18489
+ const manager = new DaemonCdpManager(result.port, logFn, void 0, provider?.targetFilter);
18490
+ const connected = await manager.connect();
18491
+ if (connected) {
18492
+ registerExtensionProviders(this.deps.providerLoader, manager, result.ideId);
18493
+ this.deps.cdpManagers.set(result.ideId, manager);
18494
+ LOG.info("CDP", `Connected: ${result.ideId} (port ${result.port})`);
18495
+ LOG.info("CDP", `${this.deps.cdpManagers.size} IDE(s) connected`);
18496
+ this.deps.onCdpManagerCreated?.(result.ideId, manager);
18497
+ }
18498
+ }
18499
+ this.deps.onIdeConnected?.();
18500
+ if (result.success && resolvedWorkspace) {
18501
+ try {
18502
+ const next = appendRecentActivity(loadConfig(), {
18503
+ kind: "ide",
18504
+ providerType: result.ideId || ideKey,
18505
+ providerName: result.ideId || ideKey,
18506
+ workspace: resolvedWorkspace,
18507
+ title: result.ideId || ideKey
18508
+ });
18509
+ saveConfig(next);
18510
+ } catch {
18511
+ }
18512
+ } else if (result.success && (result.ideId || ideKey)) {
18513
+ try {
18514
+ saveConfig(appendRecentActivity(loadConfig(), {
18515
+ kind: "ide",
18516
+ providerType: result.ideId || ideKey,
18517
+ providerName: result.ideId || ideKey,
18518
+ title: result.ideId || ideKey
18519
+ }));
18520
+ } catch {
18521
+ }
18522
+ }
18523
+ return { success: result.success, ...result };
18524
+ }
18525
+ // ─── Detect IDEs ───
18526
+ case "detect_ides": {
18527
+ const results = await detectIDEs();
18528
+ this.deps.detectedIdes.value = results;
18529
+ return { success: true, detectedInfo: results };
18530
+ }
18531
+ // ─── Set User Name ───
18532
+ case "set_user_name": {
18533
+ const name = args?.userName;
18534
+ if (!name || typeof name !== "string") throw new Error("userName required");
18535
+ updateConfig({ userName: name });
18536
+ return { success: true, userName: name };
18537
+ }
18538
+ case "mark_session_seen": {
18539
+ const sessionId = args?.sessionId;
18540
+ if (!sessionId || typeof sessionId !== "string") {
18541
+ return { success: false, error: "sessionId is required" };
18542
+ }
18543
+ const currentConfig = loadConfig();
18544
+ const prevSeenAt = currentConfig.sessionReads?.[sessionId] || 0;
18545
+ const sessionEntries = buildSessionEntries(
18546
+ this.deps.instanceManager.collectAllStates(),
18547
+ this.deps.cdpManagers
18548
+ );
18549
+ const targetSession = sessionEntries.find((entry) => entry.id === sessionId);
18550
+ const completionMarker = targetSession ? getSessionCompletionMarker(targetSession) : "";
18551
+ const next = markSessionSeen(
18552
+ currentConfig,
18553
+ sessionId,
18554
+ typeof args?.seenAt === "number" ? args.seenAt : Date.now(),
18555
+ completionMarker
18556
+ );
18557
+ if (READ_DEBUG_ENABLED2) {
18558
+ LOG.info("RecentRead", `mark_session_seen sessionId=${sessionId} seenAt=${String(args?.seenAt || "")} prevSeenAt=${String(prevSeenAt)} nextSeenAt=${String(next.sessionReads?.[sessionId] || 0)} marker=${completionMarker || "-"}`);
18559
+ }
18560
+ saveConfig(next);
18561
+ this.deps.onStatusChange?.();
18562
+ return {
18563
+ success: true,
18564
+ sessionId,
18565
+ seenAt: next.sessionReads?.[sessionId] || Date.now(),
18566
+ completionMarker
18567
+ };
18568
+ }
18569
+ // ─── Daemon Self-Upgrade ───
18570
+ case "daemon_upgrade": {
18571
+ LOG.info("Upgrade", "Remote upgrade requested from dashboard");
18572
+ try {
18573
+ const { execSync: execSync7 } = await import("child_process");
18574
+ const isStandalone = this.deps.packageName === "@adhdev/daemon-standalone" || process.argv[1]?.includes("daemon-standalone");
18575
+ const pkgName = isStandalone ? "@adhdev/daemon-standalone" : "adhdev";
18576
+ const latest = execSync7(`npm view ${pkgName} version`, { encoding: "utf-8", timeout: 1e4 }).trim();
18577
+ LOG.info("Upgrade", `Latest ${pkgName}: v${latest}`);
18578
+ execSync7(`npm install -g ${pkgName}@latest --force`, {
18579
+ encoding: "utf-8",
18580
+ timeout: 12e4,
18581
+ stdio: ["pipe", "pipe", "pipe"]
18582
+ });
18583
+ LOG.info("Upgrade", `\u2705 Upgraded to v${latest}`);
18584
+ setTimeout(() => {
18585
+ LOG.info("Upgrade", "Restarting daemon with new version...");
18586
+ try {
18587
+ const path18 = require("path");
18588
+ const fs16 = require("fs");
18589
+ const pidFile = path18.join(process.env.HOME || process.env.USERPROFILE || "", ".adhdev", "daemon.pid");
18590
+ if (fs16.existsSync(pidFile)) fs16.unlinkSync(pidFile);
18591
+ } catch {
18592
+ }
18593
+ const { spawn: spawn4 } = require("child_process");
18594
+ const child = spawn4(process.execPath, process.argv.slice(1), {
18595
+ detached: true,
18596
+ stdio: "ignore",
18597
+ env: { ...process.env }
18598
+ });
18599
+ child.unref();
18600
+ process.exit(0);
18601
+ }, 3e3);
18602
+ return { success: true, upgraded: true, version: latest };
18603
+ } catch (e) {
18604
+ LOG.error("Upgrade", `Failed: ${e.message}`);
18605
+ return { success: false, error: e.message };
18606
+ }
18607
+ }
18608
+ // ─── Machine Settings ───
18609
+ case "set_machine_nickname": {
18610
+ const nickname = args?.nickname;
18611
+ updateConfig({ machineNickname: nickname || null });
18612
+ return { success: true };
18613
+ }
18614
+ default:
18615
+ break;
18616
+ }
18617
+ return null;
18618
+ }
18619
+ /**
18620
+ * IDE stop: CDP disconnect + InstanceManager cleanup + optionally kill OS process
18621
+ */
18622
+ async stopIde(ideType, killProcess = false) {
18623
+ const cdpKeysToRemove = [];
18624
+ for (const key of this.deps.cdpManagers.keys()) {
18625
+ if (key === ideType || key.startsWith(`${ideType}_`)) {
18626
+ cdpKeysToRemove.push(key);
18627
+ }
18628
+ }
18629
+ for (const key of cdpKeysToRemove) {
18630
+ const cdp = this.deps.cdpManagers.get(key);
18631
+ if (cdp) {
18632
+ try {
18633
+ cdp.disconnect();
18634
+ } catch {
18635
+ }
18636
+ this.deps.cdpManagers.delete(key);
18637
+ this.deps.sessionRegistry.unregisterByManagerKey(key);
18638
+ LOG.info("StopIDE", `CDP disconnected: ${key}`);
18639
+ }
18640
+ }
18641
+ const keysToRemove = [];
18642
+ for (const key of this.deps.instanceManager.listInstanceIds()) {
18643
+ if (key === `ide:${ideType}` || typeof key === "string" && key.startsWith(`ide:${ideType}_`)) {
18644
+ keysToRemove.push(key);
18645
+ }
18646
+ }
18647
+ for (const instanceKey of keysToRemove) {
18648
+ const ideInstance = this.deps.instanceManager.getInstance(instanceKey);
18649
+ if (ideInstance) {
18650
+ this.deps.instanceManager.removeInstance(instanceKey);
18651
+ LOG.info("StopIDE", `Instance removed: ${instanceKey}`);
18652
+ }
18653
+ }
18654
+ if (keysToRemove.length === 0) {
18655
+ const instanceKey = `ide:${ideType}`;
18656
+ const ideInstance = this.deps.instanceManager.getInstance(instanceKey);
18657
+ if (ideInstance) {
18658
+ this.deps.instanceManager.removeInstance(instanceKey);
18659
+ LOG.info("StopIDE", `Instance removed: ${instanceKey}`);
18660
+ }
18661
+ }
18662
+ if (killProcess) {
18663
+ const running = isIdeRunning(ideType);
18664
+ if (running) {
18665
+ LOG.info("StopIDE", `Killing IDE process: ${ideType}`);
18666
+ const killed = await killIdeProcess(ideType);
18667
+ if (killed) {
18668
+ LOG.info("StopIDE", `\u2705 Process killed: ${ideType}`);
18669
+ } else {
18670
+ LOG.warn("StopIDE", `\u26A0 Could not kill process: ${ideType} (may need manual intervention)`);
18671
+ }
18672
+ } else {
18673
+ LOG.info("StopIDE", `Process not running: ${ideType}`);
18674
+ }
18675
+ }
18676
+ this.deps.onStatusChange?.();
18677
+ LOG.info("StopIDE", `IDE stopped: ${ideType} (processKill=${killProcess})`);
18678
+ }
18679
+ };
18705
18680
  }
18706
18681
  });
18707
18682
 
@@ -18860,7 +18835,7 @@ var init_reporter = __esm({
18860
18835
  currentModel: session.currentModel,
18861
18836
  currentPlan: session.currentPlan,
18862
18837
  currentAutoApprove: session.currentAutoApprove,
18863
- recentKey: session.recentKey,
18838
+ lastUpdated: session.lastUpdated,
18864
18839
  unread: session.unread,
18865
18840
  lastSeenAt: session.lastSeenAt,
18866
18841
  inboxBucket: session.inboxBucket,
@@ -45685,7 +45660,7 @@ var init_adhdev_daemon = __esm({
45685
45660
  fs15 = __toESM(require("fs"));
45686
45661
  path17 = __toESM(require("path"));
45687
45662
  import_chalk2 = __toESM(require("chalk"));
45688
- pkgVersion = "0.7.39";
45663
+ pkgVersion = "0.7.40";
45689
45664
  if (pkgVersion === "unknown") {
45690
45665
  try {
45691
45666
  const possiblePaths = [