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/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;
@@ -8636,337 +8646,6 @@ var init_command_log = __esm({
8636
8646
  }
8637
8647
  });
8638
8648
 
8639
- // ../../oss/packages/daemon-core/src/commands/router.ts
8640
- var fs7, CHAT_COMMANDS, DaemonCommandRouter;
8641
- var init_router = __esm({
8642
- "../../oss/packages/daemon-core/src/commands/router.ts"() {
8643
- "use strict";
8644
- init_manager();
8645
- init_setup();
8646
- init_launch();
8647
- init_config();
8648
- init_workspaces();
8649
- init_recent_activity();
8650
- init_ide_detector();
8651
- init_logger();
8652
- init_command_log();
8653
- init_logger();
8654
- fs7 = __toESM(require("fs"));
8655
- CHAT_COMMANDS = [
8656
- "send_chat",
8657
- "new_chat",
8658
- "switch_chat",
8659
- "set_mode",
8660
- "change_model"
8661
- ];
8662
- DaemonCommandRouter = class {
8663
- deps;
8664
- constructor(deps) {
8665
- this.deps = deps;
8666
- }
8667
- /**
8668
- * Unified command routing.
8669
- * Returns result for all commands:
8670
- * 1. Daemon-level commands (launch_ide, stop_ide, etc.)
8671
- * 2. CLI commands (launch_cli, stop_cli, agent_command)
8672
- * 3. DaemonCommandHandler delegation (CDP/agent-stream/file commands)
8673
- *
8674
- * @param cmd Command name
8675
- * @param args Command arguments
8676
- * @param source Log source ('ws' | 'p2p' | 'standalone' | etc.)
8677
- */
8678
- async execute(cmd, args, source = "unknown") {
8679
- const cmdStart = Date.now();
8680
- try {
8681
- const daemonResult = await this.executeDaemonCommand(cmd, args);
8682
- if (daemonResult) {
8683
- logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source, args, success: daemonResult.success, durationMs: Date.now() - cmdStart });
8684
- return daemonResult;
8685
- }
8686
- const handlerResult = await this.deps.commandHandler.handle(cmd, args);
8687
- logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source, args, success: handlerResult.success, durationMs: Date.now() - cmdStart });
8688
- if (CHAT_COMMANDS.includes(cmd) && this.deps.onPostChatCommand) {
8689
- this.deps.onPostChatCommand();
8690
- }
8691
- return handlerResult;
8692
- } catch (e) {
8693
- logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source, args, success: false, error: e.message, durationMs: Date.now() - cmdStart });
8694
- throw e;
8695
- }
8696
- }
8697
- // ─── Daemon-level command core ───────────────────
8698
- /**
8699
- * Daemon-level command execution (IDE start/stop/restart, CLI, detect, logs).
8700
- * Returns null if not handled at this level → caller delegates to CommandHandler.
8701
- */
8702
- async executeDaemonCommand(cmd, args) {
8703
- switch (cmd) {
8704
- // ─── CLI / ACP commands ───
8705
- case "launch_cli":
8706
- case "stop_cli":
8707
- case "agent_command": {
8708
- return this.deps.cliManager.handleCliCommand(cmd, args);
8709
- }
8710
- // ─── Logs ───
8711
- case "get_logs": {
8712
- const count = parseInt(args?.count) || parseInt(args?.lines) || 100;
8713
- const minLevel = args?.minLevel || "info";
8714
- const sinceTs = args?.since || 0;
8715
- try {
8716
- let logs = getRecentLogs(count, minLevel);
8717
- if (sinceTs > 0) {
8718
- logs = logs.filter((l) => l.ts > sinceTs);
8719
- }
8720
- if (logs.length > 0) {
8721
- return { success: true, logs, totalBuffered: logs.length };
8722
- }
8723
- if (fs7.existsSync(LOG_PATH)) {
8724
- const content = fs7.readFileSync(LOG_PATH, "utf-8");
8725
- const allLines = content.split("\n");
8726
- const recent = allLines.slice(-count).join("\n");
8727
- return { success: true, logs: recent, totalLines: allLines.length };
8728
- }
8729
- return { success: true, logs: [], totalBuffered: 0 };
8730
- } catch (e) {
8731
- return { success: false, error: e.message };
8732
- }
8733
- }
8734
- // ─── restart_session: IDE / CLI / ACP unified ───
8735
- case "restart_session": {
8736
- const targetType = args?.cliType || args?.agentType || args?.ideType;
8737
- if (!targetType) throw new Error("cliType or ideType required");
8738
- const isIde = this.deps.cdpManagers.has(targetType) || this.deps.providerLoader.getMeta(targetType)?.category === "ide";
8739
- if (isIde) {
8740
- await this.stopIde(targetType, true);
8741
- const launchResult = await this.executeDaemonCommand("launch_ide", { ideType: targetType, enableCdp: true, workspace: args?.workspace });
8742
- return { success: true, restarted: true, ideType: targetType, launch: launchResult };
8743
- }
8744
- return this.deps.cliManager.handleCliCommand(cmd, args);
8745
- }
8746
- // ─── IDE stop ───
8747
- case "stop_ide": {
8748
- const ideType = args?.ideType;
8749
- if (!ideType) throw new Error("ideType required");
8750
- const killProcess = args?.killProcess !== false;
8751
- await this.stopIde(ideType, killProcess);
8752
- return { success: true, ideType, stopped: true, processKilled: killProcess };
8753
- }
8754
- // ─── IDE restart ───
8755
- case "restart_ide": {
8756
- const ideType = args?.ideType;
8757
- if (!ideType) throw new Error("ideType required");
8758
- await this.stopIde(ideType, true);
8759
- const launchResult = await this.executeDaemonCommand("launch_ide", { ideType, enableCdp: true, workspace: args?.workspace });
8760
- return { success: true, ideType, restarted: true, launch: launchResult };
8761
- }
8762
- // ─── IDE launch + CDP connect ───
8763
- case "launch_ide": {
8764
- const ideKey = args?.ideId || args?.ideType;
8765
- const resolvedWorkspace = resolveIdeLaunchWorkspace(
8766
- {
8767
- workspace: args?.workspace,
8768
- workspaceId: args?.workspaceId,
8769
- useDefaultWorkspace: args?.useDefaultWorkspace
8770
- },
8771
- loadConfig()
8772
- );
8773
- const launchArgs = {
8774
- ideId: ideKey,
8775
- workspace: resolvedWorkspace,
8776
- newWindow: args?.newWindow
8777
- };
8778
- LOG.info("LaunchIDE", `target=${ideKey || "auto"}`);
8779
- const result = await launchWithCdp(launchArgs);
8780
- if (result.success && result.port && result.ideId && !this.deps.cdpManagers.has(result.ideId)) {
8781
- const logFn = this.deps.getCdpLogFn ? this.deps.getCdpLogFn(result.ideId) : LOG.forComponent(`CDP:${result.ideId}`).asLogFn();
8782
- const provider = this.deps.providerLoader.getMeta(result.ideId);
8783
- const manager = new DaemonCdpManager(result.port, logFn, void 0, provider?.targetFilter);
8784
- const connected = await manager.connect();
8785
- if (connected) {
8786
- registerExtensionProviders(this.deps.providerLoader, manager, result.ideId);
8787
- this.deps.cdpManagers.set(result.ideId, manager);
8788
- LOG.info("CDP", `Connected: ${result.ideId} (port ${result.port})`);
8789
- LOG.info("CDP", `${this.deps.cdpManagers.size} IDE(s) connected`);
8790
- this.deps.onCdpManagerCreated?.(result.ideId, manager);
8791
- }
8792
- }
8793
- this.deps.onIdeConnected?.();
8794
- if (result.success && resolvedWorkspace) {
8795
- try {
8796
- const next = appendRecentActivity(loadConfig(), {
8797
- kind: "ide",
8798
- providerType: result.ideId || ideKey,
8799
- providerName: result.ideId || ideKey,
8800
- workspace: resolvedWorkspace,
8801
- title: result.ideId || ideKey
8802
- });
8803
- saveConfig(next);
8804
- } catch {
8805
- }
8806
- } else if (result.success && (result.ideId || ideKey)) {
8807
- try {
8808
- saveConfig(appendRecentActivity(loadConfig(), {
8809
- kind: "ide",
8810
- providerType: result.ideId || ideKey,
8811
- providerName: result.ideId || ideKey,
8812
- title: result.ideId || ideKey
8813
- }));
8814
- } catch {
8815
- }
8816
- }
8817
- return { success: result.success, ...result };
8818
- }
8819
- // ─── Detect IDEs ───
8820
- case "detect_ides": {
8821
- const results = await detectIDEs();
8822
- this.deps.detectedIdes.value = results;
8823
- return { success: true, detectedInfo: results };
8824
- }
8825
- // ─── Set User Name ───
8826
- case "set_user_name": {
8827
- const name = args?.userName;
8828
- if (!name || typeof name !== "string") throw new Error("userName required");
8829
- updateConfig({ userName: name });
8830
- return { success: true, userName: name };
8831
- }
8832
- case "mark_recent_seen": {
8833
- const kind = args?.kind;
8834
- const providerType = args?.providerType;
8835
- if (!kind || !providerType) {
8836
- return { success: false, error: "kind and providerType are required" };
8837
- }
8838
- const recentKey = args?.recentKey || buildRecentActivityKey({
8839
- kind,
8840
- providerType,
8841
- workspace: args?.workspace || null
8842
- });
8843
- const next = markRecentSessionSeen(
8844
- loadConfig(),
8845
- recentKey,
8846
- typeof args?.seenAt === "number" ? args.seenAt : Date.now()
8847
- );
8848
- saveConfig(next);
8849
- this.deps.onStatusChange?.();
8850
- return {
8851
- success: true,
8852
- recentKey,
8853
- seenAt: next.recentSessionReads?.[recentKey] || Date.now()
8854
- };
8855
- }
8856
- // ─── Daemon Self-Upgrade ───
8857
- case "daemon_upgrade": {
8858
- LOG.info("Upgrade", "Remote upgrade requested from dashboard");
8859
- try {
8860
- const { execSync: execSync6 } = await import("child_process");
8861
- const isStandalone = this.deps.packageName === "@adhdev/daemon-standalone" || process.argv[1]?.includes("daemon-standalone");
8862
- const pkgName = isStandalone ? "@adhdev/daemon-standalone" : "adhdev";
8863
- const latest = execSync6(`npm view ${pkgName} version`, { encoding: "utf-8", timeout: 1e4 }).trim();
8864
- LOG.info("Upgrade", `Latest ${pkgName}: v${latest}`);
8865
- execSync6(`npm install -g ${pkgName}@latest --force`, {
8866
- encoding: "utf-8",
8867
- timeout: 12e4,
8868
- stdio: ["pipe", "pipe", "pipe"]
8869
- });
8870
- LOG.info("Upgrade", `\u2705 Upgraded to v${latest}`);
8871
- setTimeout(() => {
8872
- LOG.info("Upgrade", "Restarting daemon with new version...");
8873
- try {
8874
- const path18 = require("path");
8875
- const fs16 = require("fs");
8876
- const pidFile = path18.join(process.env.HOME || process.env.USERPROFILE || "", ".adhdev", "daemon.pid");
8877
- if (fs16.existsSync(pidFile)) fs16.unlinkSync(pidFile);
8878
- } catch {
8879
- }
8880
- const { spawn: spawn4 } = require("child_process");
8881
- const child = spawn4(process.execPath, process.argv.slice(1), {
8882
- detached: true,
8883
- stdio: "ignore",
8884
- env: { ...process.env }
8885
- });
8886
- child.unref();
8887
- process.exit(0);
8888
- }, 3e3);
8889
- return { success: true, upgraded: true, version: latest };
8890
- } catch (e) {
8891
- LOG.error("Upgrade", `Failed: ${e.message}`);
8892
- return { success: false, error: e.message };
8893
- }
8894
- }
8895
- // ─── Machine Settings ───
8896
- case "set_machine_nickname": {
8897
- const nickname = args?.nickname;
8898
- updateConfig({ machineNickname: nickname || null });
8899
- return { success: true };
8900
- }
8901
- default:
8902
- break;
8903
- }
8904
- return null;
8905
- }
8906
- /**
8907
- * IDE stop: CDP disconnect + InstanceManager cleanup + optionally kill OS process
8908
- */
8909
- async stopIde(ideType, killProcess = false) {
8910
- const cdpKeysToRemove = [];
8911
- for (const key of this.deps.cdpManagers.keys()) {
8912
- if (key === ideType || key.startsWith(`${ideType}_`)) {
8913
- cdpKeysToRemove.push(key);
8914
- }
8915
- }
8916
- for (const key of cdpKeysToRemove) {
8917
- const cdp = this.deps.cdpManagers.get(key);
8918
- if (cdp) {
8919
- try {
8920
- cdp.disconnect();
8921
- } catch {
8922
- }
8923
- this.deps.cdpManagers.delete(key);
8924
- this.deps.sessionRegistry.unregisterByManagerKey(key);
8925
- LOG.info("StopIDE", `CDP disconnected: ${key}`);
8926
- }
8927
- }
8928
- const keysToRemove = [];
8929
- for (const key of this.deps.instanceManager.listInstanceIds()) {
8930
- if (key === `ide:${ideType}` || typeof key === "string" && key.startsWith(`ide:${ideType}_`)) {
8931
- keysToRemove.push(key);
8932
- }
8933
- }
8934
- for (const instanceKey of keysToRemove) {
8935
- const ideInstance = this.deps.instanceManager.getInstance(instanceKey);
8936
- if (ideInstance) {
8937
- this.deps.instanceManager.removeInstance(instanceKey);
8938
- LOG.info("StopIDE", `Instance removed: ${instanceKey}`);
8939
- }
8940
- }
8941
- if (keysToRemove.length === 0) {
8942
- const instanceKey = `ide:${ideType}`;
8943
- const ideInstance = this.deps.instanceManager.getInstance(instanceKey);
8944
- if (ideInstance) {
8945
- this.deps.instanceManager.removeInstance(instanceKey);
8946
- LOG.info("StopIDE", `Instance removed: ${instanceKey}`);
8947
- }
8948
- }
8949
- if (killProcess) {
8950
- const running = isIdeRunning(ideType);
8951
- if (running) {
8952
- LOG.info("StopIDE", `Killing IDE process: ${ideType}`);
8953
- const killed = await killIdeProcess(ideType);
8954
- if (killed) {
8955
- LOG.info("StopIDE", `\u2705 Process killed: ${ideType}`);
8956
- } else {
8957
- LOG.warn("StopIDE", `\u26A0 Could not kill process: ${ideType} (may need manual intervention)`);
8958
- }
8959
- } else {
8960
- LOG.info("StopIDE", `Process not running: ${ideType}`);
8961
- }
8962
- }
8963
- this.deps.onStatusChange?.();
8964
- LOG.info("StopIDE", `IDE stopped: ${ideType} (processKill=${killProcess})`);
8965
- }
8966
- };
8967
- }
8968
- });
8969
-
8970
8649
  // ../../oss/packages/daemon-core/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts
8971
8650
  function isModuleNotFoundError(error48, ref) {
8972
8651
  if (!(error48 instanceof Error)) return false;
@@ -9794,7 +9473,7 @@ function Ec(s15, t) {
9794
9473
  function Tc(s15) {
9795
9474
  return s15.keyCode === 16 || s15.keyCode === 17 || s15.keyCode === 18;
9796
9475
  }
9797
- 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;
9476
+ 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;
9798
9477
  var init_xterm = __esm({
9799
9478
  "../../oss/node_modules/@xterm/xterm/lib/xterm.mjs"() {
9800
9479
  "use strict";
@@ -13069,7 +12748,7 @@ ${h.join(`
13069
12748
  ((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 = `
13070
12749
  `, 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 ||= {});
13071
12750
  ((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 ||= {});
13072
- ((t) => t.ST = `${b.ESC}\\`)(fs8 ||= {});
12751
+ ((t) => t.ST = `${b.ESC}\\`)(fs7 ||= {});
13073
12752
  $t = class {
13074
12753
  constructor(t, e, i, r, n, o) {
13075
12754
  this._textarea = t;
@@ -17498,7 +17177,7 @@ ${h.join(`
17498
17177
  switch (i.type) {
17499
17178
  case 0:
17500
17179
  let o = U.toColorRGB(r === "ansi" ? this._themeService.colors.ansi[i.index] : this._themeService.colors[r]);
17501
- this.coreService.triggerDataEvent(`${b.ESC}]${n};${ml(o)}${fs8.ST}`);
17180
+ this.coreService.triggerDataEvent(`${b.ESC}]${n};${ml(o)}${fs7.ST}`);
17502
17181
  break;
17503
17182
  case 1:
17504
17183
  if (r === "ansi") this._themeService.modifyColors((l) => l.ansi[i.index] = j.toColor(...i.color));
@@ -18339,94 +18018,45 @@ function getSessionMessageUpdatedAt(session) {
18339
18018
  if (!lastMessage) return 0;
18340
18019
  return parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt) || 0;
18341
18020
  }
18021
+ function getSessionCompletionMarker(session) {
18022
+ const lastMessage = session.activeChat?.messages?.at?.(-1);
18023
+ if (!lastMessage) return "";
18024
+ const role = typeof lastMessage.role === "string" ? lastMessage.role : "";
18025
+ if (role === "user" || role === "human") return "";
18026
+ if (typeof lastMessage._turnKey === "string" && lastMessage._turnKey) return `turn:${lastMessage._turnKey}`;
18027
+ if (typeof lastMessage.id === "string" && lastMessage.id) return `id:${lastMessage.id}`;
18028
+ if (typeof lastMessage.index === "number" && Number.isFinite(lastMessage.index)) return `idx:${lastMessage.index}`;
18029
+ const timestamp = parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt);
18030
+ return timestamp > 0 ? `ts:${timestamp}` : "";
18031
+ }
18342
18032
  function getSessionLastUsedAt(session) {
18343
18033
  return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
18344
18034
  }
18345
- function getSessionKind(session) {
18346
- return session.transport === "cdp-page" || session.transport === "cdp-webview" ? "ide" : session.transport === "acp" ? "acp" : "cli";
18347
- }
18348
18035
  function getLastMessageRole(session) {
18349
18036
  const role = session.activeChat?.messages?.at?.(-1)?.role;
18350
18037
  return typeof role === "string" ? role : "";
18351
18038
  }
18352
- function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole) {
18039
+ function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole, completionMarker, seenCompletionMarker) {
18353
18040
  if (status === "waiting_approval") {
18354
18041
  return { unread: false, inboxBucket: "needs_attention" };
18355
18042
  }
18356
18043
  if (status === "generating" || status === "starting") {
18357
18044
  return { unread: false, inboxBucket: "working" };
18358
18045
  }
18359
- const unread = hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
18046
+ const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
18360
18047
  return { unread, inboxBucket: unread ? "task_complete" : "idle" };
18361
18048
  }
18362
- function buildRecentSessions(sessions, recentActivity, readState) {
18363
- const visibleKeys = /* @__PURE__ */ new Set();
18364
- const hiddenKeys = /* @__PURE__ */ new Set();
18365
- const live = sessions.filter((session) => !session.surfaceHidden && session.status !== "stopped").map((session) => {
18366
- const kind = getSessionKind(session);
18367
- const recentKey = buildRecentActivityKey({
18368
- kind,
18369
- providerType: session.providerType,
18370
- workspace: session.workspace
18371
- });
18372
- const lastSeenAt = readState[recentKey] || 0;
18373
- const lastUsedAt = getSessionLastUsedAt(session);
18374
- const { unread, inboxBucket } = getUnreadState(
18375
- getSessionMessageUpdatedAt(session) > 0,
18376
- session.status,
18377
- lastUsedAt,
18378
- lastSeenAt,
18379
- getLastMessageRole(session)
18380
- );
18381
- return {
18382
- id: session.id,
18383
- recentKey,
18384
- sessionId: session.id,
18385
- providerType: session.providerType,
18386
- providerName: session.providerName,
18387
- kind,
18388
- title: session.activeChat?.title || session.title || session.providerName,
18389
- workspace: session.workspace,
18390
- currentModel: session.currentModel,
18391
- status: session.status,
18392
- lastUsedAt,
18393
- unread,
18394
- lastSeenAt,
18395
- inboxBucket,
18396
- surfaceHidden: false
18397
- };
18398
- });
18399
- for (const item of live) {
18400
- visibleKeys.add(`${item.kind}:${item.providerType}:${item.workspace || ""}`);
18401
- }
18402
- for (const session of sessions) {
18403
- if (!session.surfaceHidden) continue;
18404
- hiddenKeys.add(`${getSessionKind(session)}:${session.providerType}:${session.workspace || ""}`);
18405
- }
18406
- const persisted = recentActivity.filter((item) => {
18407
- const key = `${item.kind}:${item.providerType}:${item.workspace || ""}`;
18408
- return !visibleKeys.has(key) && !hiddenKeys.has(key);
18409
- }).map((item) => {
18410
- const lastSeenAt = readState[item.id] || 0;
18411
- const unread = item.lastUsedAt > lastSeenAt;
18412
- return {
18413
- id: item.id,
18414
- recentKey: item.id,
18415
- sessionId: item.sessionId || null,
18416
- providerType: item.providerType,
18417
- providerName: item.providerName,
18418
- kind: item.kind,
18419
- title: item.title || item.providerName,
18420
- workspace: item.workspace,
18421
- currentModel: item.currentModel,
18422
- lastUsedAt: item.lastUsedAt,
18423
- unread,
18424
- lastSeenAt,
18425
- inboxBucket: unread ? "task_complete" : "idle",
18426
- surfaceHidden: false
18427
- };
18428
- });
18429
- return [...live, ...persisted].sort((a, b2) => b2.lastUsedAt - a.lastUsedAt).slice(0, 12);
18049
+ function buildRecentLaunches(recentActivity) {
18050
+ return recentActivity.map((item) => ({
18051
+ id: item.id,
18052
+ providerType: item.providerType,
18053
+ providerName: item.providerName,
18054
+ kind: item.kind,
18055
+ title: item.title || item.providerName,
18056
+ workspace: item.workspace,
18057
+ currentModel: item.currentModel,
18058
+ lastLaunchedAt: item.lastUsedAt
18059
+ })).sort((a, b2) => b2.lastLaunchedAt - a.lastLaunchedAt).slice(0, 12);
18430
18060
  }
18431
18061
  function buildStatusSnapshot(options) {
18432
18062
  const cfg = loadConfig();
@@ -18437,27 +18067,29 @@ function buildStatusSnapshot(options) {
18437
18067
  options.allStates,
18438
18068
  options.cdpManagers
18439
18069
  );
18440
- const readState = cfg.recentSessionReads || {};
18441
18070
  for (const session of sessions) {
18442
- const kind = getSessionKind(session);
18443
- const recentKey = buildRecentActivityKey({
18444
- kind,
18445
- providerType: session.providerType,
18446
- workspace: session.workspace
18447
- });
18448
- const lastSeenAt = getRecentSessionSeenAt(cfg, recentKey);
18071
+ const lastSeenAt = getSessionSeenAt(cfg, session.id);
18072
+ const seenCompletionMarker = getSessionSeenMarker(cfg, session.id);
18449
18073
  const lastUsedAt = getSessionLastUsedAt(session);
18074
+ const completionMarker = getSessionCompletionMarker(session);
18450
18075
  const { unread, inboxBucket } = session.surfaceHidden ? { unread: false, inboxBucket: "idle" } : getUnreadState(
18451
18076
  getSessionMessageUpdatedAt(session) > 0,
18452
18077
  session.status,
18453
18078
  lastUsedAt,
18454
18079
  lastSeenAt,
18455
- getLastMessageRole(session)
18080
+ getLastMessageRole(session),
18081
+ completionMarker,
18082
+ seenCompletionMarker
18456
18083
  );
18457
- session.recentKey = recentKey;
18458
18084
  session.lastSeenAt = lastSeenAt;
18459
18085
  session.unread = unread;
18460
18086
  session.inboxBucket = inboxBucket;
18087
+ if (READ_DEBUG_ENABLED && (session.unread || session.inboxBucket !== "idle" || session.providerType.includes("codex"))) {
18088
+ LOG.info(
18089
+ "RecentRead",
18090
+ `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)}`
18091
+ );
18092
+ }
18461
18093
  }
18462
18094
  const terminalBackend = getTerminalBackendRuntimeStatus();
18463
18095
  return {
@@ -18484,12 +18116,12 @@ function buildStatusSnapshot(options) {
18484
18116
  workspaces: wsState.workspaces,
18485
18117
  defaultWorkspaceId: wsState.defaultWorkspaceId,
18486
18118
  defaultWorkspacePath: wsState.defaultWorkspacePath,
18487
- recentSessions: buildRecentSessions(sessions, recentActivity, readState),
18119
+ recentLaunches: buildRecentLaunches(recentActivity),
18488
18120
  terminalBackend,
18489
18121
  availableProviders: buildAvailableProviders(options.providerLoader)
18490
18122
  };
18491
18123
  }
18492
- var os11;
18124
+ var os11, READ_DEBUG_ENABLED;
18493
18125
  var init_snapshot = __esm({
18494
18126
  "../../oss/packages/daemon-core/src/status/snapshot.ts"() {
18495
18127
  "use strict";
@@ -18499,7 +18131,350 @@ var init_snapshot = __esm({
18499
18131
  init_workspaces();
18500
18132
  init_host_memory();
18501
18133
  init_terminal_screen();
18134
+ init_logger();
18502
18135
  init_builders();
18136
+ READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
18137
+ }
18138
+ });
18139
+
18140
+ // ../../oss/packages/daemon-core/src/commands/router.ts
18141
+ var fs8, CHAT_COMMANDS, READ_DEBUG_ENABLED2, DaemonCommandRouter;
18142
+ var init_router = __esm({
18143
+ "../../oss/packages/daemon-core/src/commands/router.ts"() {
18144
+ "use strict";
18145
+ init_manager();
18146
+ init_setup();
18147
+ init_launch();
18148
+ init_config();
18149
+ init_workspaces();
18150
+ init_recent_activity();
18151
+ init_ide_detector();
18152
+ init_logger();
18153
+ init_command_log();
18154
+ init_logger();
18155
+ init_builders();
18156
+ init_snapshot();
18157
+ fs8 = __toESM(require("fs"));
18158
+ CHAT_COMMANDS = [
18159
+ "send_chat",
18160
+ "new_chat",
18161
+ "switch_chat",
18162
+ "set_mode",
18163
+ "change_model"
18164
+ ];
18165
+ READ_DEBUG_ENABLED2 = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
18166
+ DaemonCommandRouter = class {
18167
+ deps;
18168
+ constructor(deps) {
18169
+ this.deps = deps;
18170
+ }
18171
+ /**
18172
+ * Unified command routing.
18173
+ * Returns result for all commands:
18174
+ * 1. Daemon-level commands (launch_ide, stop_ide, etc.)
18175
+ * 2. CLI commands (launch_cli, stop_cli, agent_command)
18176
+ * 3. DaemonCommandHandler delegation (CDP/agent-stream/file commands)
18177
+ *
18178
+ * @param cmd Command name
18179
+ * @param args Command arguments
18180
+ * @param source Log source ('ws' | 'p2p' | 'standalone' | etc.)
18181
+ */
18182
+ async execute(cmd, args, source = "unknown") {
18183
+ const cmdStart = Date.now();
18184
+ try {
18185
+ const daemonResult = await this.executeDaemonCommand(cmd, args);
18186
+ if (daemonResult) {
18187
+ logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source, args, success: daemonResult.success, durationMs: Date.now() - cmdStart });
18188
+ return daemonResult;
18189
+ }
18190
+ const handlerResult = await this.deps.commandHandler.handle(cmd, args);
18191
+ logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source, args, success: handlerResult.success, durationMs: Date.now() - cmdStart });
18192
+ if (CHAT_COMMANDS.includes(cmd) && this.deps.onPostChatCommand) {
18193
+ this.deps.onPostChatCommand();
18194
+ }
18195
+ return handlerResult;
18196
+ } catch (e) {
18197
+ logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd, source, args, success: false, error: e.message, durationMs: Date.now() - cmdStart });
18198
+ throw e;
18199
+ }
18200
+ }
18201
+ // ─── Daemon-level command core ───────────────────
18202
+ /**
18203
+ * Daemon-level command execution (IDE start/stop/restart, CLI, detect, logs).
18204
+ * Returns null if not handled at this level → caller delegates to CommandHandler.
18205
+ */
18206
+ async executeDaemonCommand(cmd, args) {
18207
+ switch (cmd) {
18208
+ // ─── CLI / ACP commands ───
18209
+ case "launch_cli":
18210
+ case "stop_cli":
18211
+ case "agent_command": {
18212
+ return this.deps.cliManager.handleCliCommand(cmd, args);
18213
+ }
18214
+ // ─── Logs ───
18215
+ case "get_logs": {
18216
+ const count = parseInt(args?.count) || parseInt(args?.lines) || 100;
18217
+ const minLevel = args?.minLevel || "info";
18218
+ const sinceTs = args?.since || 0;
18219
+ try {
18220
+ let logs = getRecentLogs(count, minLevel);
18221
+ if (sinceTs > 0) {
18222
+ logs = logs.filter((l) => l.ts > sinceTs);
18223
+ }
18224
+ if (logs.length > 0) {
18225
+ return { success: true, logs, totalBuffered: logs.length };
18226
+ }
18227
+ if (fs8.existsSync(LOG_PATH)) {
18228
+ const content = fs8.readFileSync(LOG_PATH, "utf-8");
18229
+ const allLines = content.split("\n");
18230
+ const recent = allLines.slice(-count).join("\n");
18231
+ return { success: true, logs: recent, totalLines: allLines.length };
18232
+ }
18233
+ return { success: true, logs: [], totalBuffered: 0 };
18234
+ } catch (e) {
18235
+ return { success: false, error: e.message };
18236
+ }
18237
+ }
18238
+ // ─── restart_session: IDE / CLI / ACP unified ───
18239
+ case "restart_session": {
18240
+ const targetType = args?.cliType || args?.agentType || args?.ideType;
18241
+ if (!targetType) throw new Error("cliType or ideType required");
18242
+ const isIde = this.deps.cdpManagers.has(targetType) || this.deps.providerLoader.getMeta(targetType)?.category === "ide";
18243
+ if (isIde) {
18244
+ await this.stopIde(targetType, true);
18245
+ const launchResult = await this.executeDaemonCommand("launch_ide", { ideType: targetType, enableCdp: true, workspace: args?.workspace });
18246
+ return { success: true, restarted: true, ideType: targetType, launch: launchResult };
18247
+ }
18248
+ return this.deps.cliManager.handleCliCommand(cmd, args);
18249
+ }
18250
+ // ─── IDE stop ───
18251
+ case "stop_ide": {
18252
+ const ideType = args?.ideType;
18253
+ if (!ideType) throw new Error("ideType required");
18254
+ const killProcess = args?.killProcess !== false;
18255
+ await this.stopIde(ideType, killProcess);
18256
+ return { success: true, ideType, stopped: true, processKilled: killProcess };
18257
+ }
18258
+ // ─── IDE restart ───
18259
+ case "restart_ide": {
18260
+ const ideType = args?.ideType;
18261
+ if (!ideType) throw new Error("ideType required");
18262
+ await this.stopIde(ideType, true);
18263
+ const launchResult = await this.executeDaemonCommand("launch_ide", { ideType, enableCdp: true, workspace: args?.workspace });
18264
+ return { success: true, ideType, restarted: true, launch: launchResult };
18265
+ }
18266
+ // ─── IDE launch + CDP connect ───
18267
+ case "launch_ide": {
18268
+ const ideKey = args?.ideId || args?.ideType;
18269
+ const resolvedWorkspace = resolveIdeLaunchWorkspace(
18270
+ {
18271
+ workspace: args?.workspace,
18272
+ workspaceId: args?.workspaceId,
18273
+ useDefaultWorkspace: args?.useDefaultWorkspace
18274
+ },
18275
+ loadConfig()
18276
+ );
18277
+ const launchArgs = {
18278
+ ideId: ideKey,
18279
+ workspace: resolvedWorkspace,
18280
+ newWindow: args?.newWindow
18281
+ };
18282
+ LOG.info("LaunchIDE", `target=${ideKey || "auto"}`);
18283
+ const result = await launchWithCdp(launchArgs);
18284
+ if (result.success && result.port && result.ideId && !this.deps.cdpManagers.has(result.ideId)) {
18285
+ const logFn = this.deps.getCdpLogFn ? this.deps.getCdpLogFn(result.ideId) : LOG.forComponent(`CDP:${result.ideId}`).asLogFn();
18286
+ const provider = this.deps.providerLoader.getMeta(result.ideId);
18287
+ const manager = new DaemonCdpManager(result.port, logFn, void 0, provider?.targetFilter);
18288
+ const connected = await manager.connect();
18289
+ if (connected) {
18290
+ registerExtensionProviders(this.deps.providerLoader, manager, result.ideId);
18291
+ this.deps.cdpManagers.set(result.ideId, manager);
18292
+ LOG.info("CDP", `Connected: ${result.ideId} (port ${result.port})`);
18293
+ LOG.info("CDP", `${this.deps.cdpManagers.size} IDE(s) connected`);
18294
+ this.deps.onCdpManagerCreated?.(result.ideId, manager);
18295
+ }
18296
+ }
18297
+ this.deps.onIdeConnected?.();
18298
+ if (result.success && resolvedWorkspace) {
18299
+ try {
18300
+ const next = appendRecentActivity(loadConfig(), {
18301
+ kind: "ide",
18302
+ providerType: result.ideId || ideKey,
18303
+ providerName: result.ideId || ideKey,
18304
+ workspace: resolvedWorkspace,
18305
+ title: result.ideId || ideKey
18306
+ });
18307
+ saveConfig(next);
18308
+ } catch {
18309
+ }
18310
+ } else if (result.success && (result.ideId || ideKey)) {
18311
+ try {
18312
+ saveConfig(appendRecentActivity(loadConfig(), {
18313
+ kind: "ide",
18314
+ providerType: result.ideId || ideKey,
18315
+ providerName: result.ideId || ideKey,
18316
+ title: result.ideId || ideKey
18317
+ }));
18318
+ } catch {
18319
+ }
18320
+ }
18321
+ return { success: result.success, ...result };
18322
+ }
18323
+ // ─── Detect IDEs ───
18324
+ case "detect_ides": {
18325
+ const results = await detectIDEs();
18326
+ this.deps.detectedIdes.value = results;
18327
+ return { success: true, detectedInfo: results };
18328
+ }
18329
+ // ─── Set User Name ───
18330
+ case "set_user_name": {
18331
+ const name = args?.userName;
18332
+ if (!name || typeof name !== "string") throw new Error("userName required");
18333
+ updateConfig({ userName: name });
18334
+ return { success: true, userName: name };
18335
+ }
18336
+ case "mark_session_seen": {
18337
+ const sessionId = args?.sessionId;
18338
+ if (!sessionId || typeof sessionId !== "string") {
18339
+ return { success: false, error: "sessionId is required" };
18340
+ }
18341
+ const currentConfig = loadConfig();
18342
+ const prevSeenAt = currentConfig.sessionReads?.[sessionId] || 0;
18343
+ const sessionEntries = buildSessionEntries(
18344
+ this.deps.instanceManager.collectAllStates(),
18345
+ this.deps.cdpManagers
18346
+ );
18347
+ const targetSession = sessionEntries.find((entry) => entry.id === sessionId);
18348
+ const completionMarker = targetSession ? getSessionCompletionMarker(targetSession) : "";
18349
+ const next = markSessionSeen(
18350
+ currentConfig,
18351
+ sessionId,
18352
+ typeof args?.seenAt === "number" ? args.seenAt : Date.now(),
18353
+ completionMarker
18354
+ );
18355
+ if (READ_DEBUG_ENABLED2) {
18356
+ LOG.info("RecentRead", `mark_session_seen sessionId=${sessionId} seenAt=${String(args?.seenAt || "")} prevSeenAt=${String(prevSeenAt)} nextSeenAt=${String(next.sessionReads?.[sessionId] || 0)} marker=${completionMarker || "-"}`);
18357
+ }
18358
+ saveConfig(next);
18359
+ this.deps.onStatusChange?.();
18360
+ return {
18361
+ success: true,
18362
+ sessionId,
18363
+ seenAt: next.sessionReads?.[sessionId] || Date.now(),
18364
+ completionMarker
18365
+ };
18366
+ }
18367
+ // ─── Daemon Self-Upgrade ───
18368
+ case "daemon_upgrade": {
18369
+ LOG.info("Upgrade", "Remote upgrade requested from dashboard");
18370
+ try {
18371
+ const { execSync: execSync6 } = await import("child_process");
18372
+ const isStandalone = this.deps.packageName === "@adhdev/daemon-standalone" || process.argv[1]?.includes("daemon-standalone");
18373
+ const pkgName = isStandalone ? "@adhdev/daemon-standalone" : "adhdev";
18374
+ const latest = execSync6(`npm view ${pkgName} version`, { encoding: "utf-8", timeout: 1e4 }).trim();
18375
+ LOG.info("Upgrade", `Latest ${pkgName}: v${latest}`);
18376
+ execSync6(`npm install -g ${pkgName}@latest --force`, {
18377
+ encoding: "utf-8",
18378
+ timeout: 12e4,
18379
+ stdio: ["pipe", "pipe", "pipe"]
18380
+ });
18381
+ LOG.info("Upgrade", `\u2705 Upgraded to v${latest}`);
18382
+ setTimeout(() => {
18383
+ LOG.info("Upgrade", "Restarting daemon with new version...");
18384
+ try {
18385
+ const path18 = require("path");
18386
+ const fs16 = require("fs");
18387
+ const pidFile = path18.join(process.env.HOME || process.env.USERPROFILE || "", ".adhdev", "daemon.pid");
18388
+ if (fs16.existsSync(pidFile)) fs16.unlinkSync(pidFile);
18389
+ } catch {
18390
+ }
18391
+ const { spawn: spawn4 } = require("child_process");
18392
+ const child = spawn4(process.execPath, process.argv.slice(1), {
18393
+ detached: true,
18394
+ stdio: "ignore",
18395
+ env: { ...process.env }
18396
+ });
18397
+ child.unref();
18398
+ process.exit(0);
18399
+ }, 3e3);
18400
+ return { success: true, upgraded: true, version: latest };
18401
+ } catch (e) {
18402
+ LOG.error("Upgrade", `Failed: ${e.message}`);
18403
+ return { success: false, error: e.message };
18404
+ }
18405
+ }
18406
+ // ─── Machine Settings ───
18407
+ case "set_machine_nickname": {
18408
+ const nickname = args?.nickname;
18409
+ updateConfig({ machineNickname: nickname || null });
18410
+ return { success: true };
18411
+ }
18412
+ default:
18413
+ break;
18414
+ }
18415
+ return null;
18416
+ }
18417
+ /**
18418
+ * IDE stop: CDP disconnect + InstanceManager cleanup + optionally kill OS process
18419
+ */
18420
+ async stopIde(ideType, killProcess = false) {
18421
+ const cdpKeysToRemove = [];
18422
+ for (const key of this.deps.cdpManagers.keys()) {
18423
+ if (key === ideType || key.startsWith(`${ideType}_`)) {
18424
+ cdpKeysToRemove.push(key);
18425
+ }
18426
+ }
18427
+ for (const key of cdpKeysToRemove) {
18428
+ const cdp = this.deps.cdpManagers.get(key);
18429
+ if (cdp) {
18430
+ try {
18431
+ cdp.disconnect();
18432
+ } catch {
18433
+ }
18434
+ this.deps.cdpManagers.delete(key);
18435
+ this.deps.sessionRegistry.unregisterByManagerKey(key);
18436
+ LOG.info("StopIDE", `CDP disconnected: ${key}`);
18437
+ }
18438
+ }
18439
+ const keysToRemove = [];
18440
+ for (const key of this.deps.instanceManager.listInstanceIds()) {
18441
+ if (key === `ide:${ideType}` || typeof key === "string" && key.startsWith(`ide:${ideType}_`)) {
18442
+ keysToRemove.push(key);
18443
+ }
18444
+ }
18445
+ for (const instanceKey of keysToRemove) {
18446
+ const ideInstance = this.deps.instanceManager.getInstance(instanceKey);
18447
+ if (ideInstance) {
18448
+ this.deps.instanceManager.removeInstance(instanceKey);
18449
+ LOG.info("StopIDE", `Instance removed: ${instanceKey}`);
18450
+ }
18451
+ }
18452
+ if (keysToRemove.length === 0) {
18453
+ const instanceKey = `ide:${ideType}`;
18454
+ const ideInstance = this.deps.instanceManager.getInstance(instanceKey);
18455
+ if (ideInstance) {
18456
+ this.deps.instanceManager.removeInstance(instanceKey);
18457
+ LOG.info("StopIDE", `Instance removed: ${instanceKey}`);
18458
+ }
18459
+ }
18460
+ if (killProcess) {
18461
+ const running = isIdeRunning(ideType);
18462
+ if (running) {
18463
+ LOG.info("StopIDE", `Killing IDE process: ${ideType}`);
18464
+ const killed = await killIdeProcess(ideType);
18465
+ if (killed) {
18466
+ LOG.info("StopIDE", `\u2705 Process killed: ${ideType}`);
18467
+ } else {
18468
+ LOG.warn("StopIDE", `\u26A0 Could not kill process: ${ideType} (may need manual intervention)`);
18469
+ }
18470
+ } else {
18471
+ LOG.info("StopIDE", `Process not running: ${ideType}`);
18472
+ }
18473
+ }
18474
+ this.deps.onStatusChange?.();
18475
+ LOG.info("StopIDE", `IDE stopped: ${ideType} (processKill=${killProcess})`);
18476
+ }
18477
+ };
18503
18478
  }
18504
18479
  });
18505
18480
 
@@ -18658,7 +18633,7 @@ var init_reporter = __esm({
18658
18633
  currentModel: session.currentModel,
18659
18634
  currentPlan: session.currentPlan,
18660
18635
  currentAutoApprove: session.currentAutoApprove,
18661
- recentKey: session.recentKey,
18636
+ lastUpdated: session.lastUpdated,
18662
18637
  unread: session.unread,
18663
18638
  lastSeenAt: session.lastSeenAt,
18664
18639
  inboxBucket: session.inboxBucket,
@@ -45166,7 +45141,7 @@ var init_adhdev_daemon = __esm({
45166
45141
  fs15 = __toESM(require("fs"));
45167
45142
  path17 = __toESM(require("path"));
45168
45143
  import_chalk2 = __toESM(require("chalk"));
45169
- pkgVersion = "0.7.39";
45144
+ pkgVersion = "0.7.40";
45170
45145
  if (pkgVersion === "unknown") {
45171
45146
  try {
45172
45147
  const possiblePaths = [