@adhdev/daemon-standalone 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
@@ -18114,8 +18114,8 @@ function watch(paths, options = {}) {
18114
18114
  var fs6 = __toESM(require("fs"), 1);
18115
18115
  var path8 = __toESM(require("path"), 1);
18116
18116
  var os9 = __toESM(require("os"), 1);
18117
- var fs7 = __toESM(require("fs"), 1);
18118
18117
  var os10 = __toESM(require("os"), 1);
18118
+ var fs7 = __toESM(require("fs"), 1);
18119
18119
  var os13 = __toESM(require("os"), 1);
18120
18120
  var path10 = __toESM(require("path"), 1);
18121
18121
  var crypto4 = __toESM(require("crypto"), 1);
@@ -18435,7 +18435,8 @@ var init_config = __esm2({
18435
18435
  workspaces: [],
18436
18436
  defaultWorkspaceId: null,
18437
18437
  recentActivity: [],
18438
- recentSessionReads: {},
18438
+ sessionReads: {},
18439
+ sessionReadMarkers: {},
18439
18440
  machineNickname: null,
18440
18441
  machineId: void 0,
18441
18442
  machineSecret: null,
@@ -20297,18 +20298,27 @@ function appendRecentActivity(config2, entry) {
20297
20298
  function getRecentActivity(config2, limit = 20) {
20298
20299
  return [...config2.recentActivity || []].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, limit);
20299
20300
  }
20300
- function getRecentSessionSeenAt(config2, recentKey) {
20301
- return config2.recentSessionReads?.[recentKey] || 0;
20301
+ function getSessionSeenAt(config2, sessionId) {
20302
+ return config2.sessionReads?.[sessionId] || 0;
20302
20303
  }
20303
- function markRecentSessionSeen(config2, recentKey, seenAt = Date.now()) {
20304
- const prev = config2.recentSessionReads || {};
20305
- const nextSeenAt = Math.max(prev[recentKey] || 0, seenAt);
20304
+ function getSessionSeenMarker(config2, sessionId) {
20305
+ return config2.sessionReadMarkers?.[sessionId] || "";
20306
+ }
20307
+ function markSessionSeen(config2, sessionId, seenAt = Date.now(), completionMarker) {
20308
+ const prev = config2.sessionReads || {};
20309
+ const nextSeenAt = Math.max(prev[sessionId] || 0, seenAt);
20310
+ const prevMarkers = config2.sessionReadMarkers || {};
20311
+ const nextMarker = typeof completionMarker === "string" ? completionMarker : "";
20306
20312
  return {
20307
20313
  ...config2,
20308
- recentSessionReads: {
20314
+ sessionReads: {
20309
20315
  ...prev,
20310
- [recentKey]: nextSeenAt
20311
- }
20316
+ [sessionId]: nextSeenAt
20317
+ },
20318
+ sessionReadMarkers: nextMarker ? {
20319
+ ...prevMarkers,
20320
+ [sessionId]: nextMarker
20321
+ } : prevMarkers
20312
20322
  };
20313
20323
  }
20314
20324
  var BUILTIN_IDE_DEFINITIONS = [];
@@ -26363,6 +26373,144 @@ function logCommand(entry) {
26363
26373
  }
26364
26374
  cleanOldFiles();
26365
26375
  init_logger();
26376
+ init_config();
26377
+ init_terminal_screen();
26378
+ init_logger();
26379
+ var READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
26380
+ function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
26381
+ return detectedIdes.filter((ide) => ide.installed !== false).map((ide) => ({
26382
+ id: ide.id,
26383
+ type: ide.id,
26384
+ name: ide.displayName || ide.name || ide.id,
26385
+ running: isCdpConnected(cdpManagers, ide.id),
26386
+ ...ide.path ? { path: ide.path } : {}
26387
+ }));
26388
+ }
26389
+ function buildAvailableProviders(providerLoader) {
26390
+ return providerLoader.getAll().map((provider) => ({
26391
+ type: provider.type,
26392
+ name: provider.displayName || provider.type,
26393
+ displayName: provider.displayName || provider.type,
26394
+ icon: provider.icon || "\u{1F4BB}",
26395
+ category: provider.category
26396
+ }));
26397
+ }
26398
+ function parseMessageTime(value) {
26399
+ if (typeof value === "number" && Number.isFinite(value)) return value;
26400
+ if (typeof value === "string") {
26401
+ const parsed = Date.parse(value);
26402
+ if (Number.isFinite(parsed)) return parsed;
26403
+ }
26404
+ return 0;
26405
+ }
26406
+ function getSessionMessageUpdatedAt(session) {
26407
+ const lastMessage = session.activeChat?.messages?.at?.(-1);
26408
+ if (!lastMessage) return 0;
26409
+ return parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt) || 0;
26410
+ }
26411
+ function getSessionCompletionMarker(session) {
26412
+ const lastMessage = session.activeChat?.messages?.at?.(-1);
26413
+ if (!lastMessage) return "";
26414
+ const role = typeof lastMessage.role === "string" ? lastMessage.role : "";
26415
+ if (role === "user" || role === "human") return "";
26416
+ if (typeof lastMessage._turnKey === "string" && lastMessage._turnKey) return `turn:${lastMessage._turnKey}`;
26417
+ if (typeof lastMessage.id === "string" && lastMessage.id) return `id:${lastMessage.id}`;
26418
+ if (typeof lastMessage.index === "number" && Number.isFinite(lastMessage.index)) return `idx:${lastMessage.index}`;
26419
+ const timestamp = parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt);
26420
+ return timestamp > 0 ? `ts:${timestamp}` : "";
26421
+ }
26422
+ function getSessionLastUsedAt(session) {
26423
+ return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
26424
+ }
26425
+ function getLastMessageRole(session) {
26426
+ const role = session.activeChat?.messages?.at?.(-1)?.role;
26427
+ return typeof role === "string" ? role : "";
26428
+ }
26429
+ function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole, completionMarker, seenCompletionMarker) {
26430
+ if (status === "waiting_approval") {
26431
+ return { unread: false, inboxBucket: "needs_attention" };
26432
+ }
26433
+ if (status === "generating" || status === "starting") {
26434
+ return { unread: false, inboxBucket: "working" };
26435
+ }
26436
+ const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
26437
+ return { unread, inboxBucket: unread ? "task_complete" : "idle" };
26438
+ }
26439
+ function buildRecentLaunches(recentActivity) {
26440
+ return recentActivity.map((item) => ({
26441
+ id: item.id,
26442
+ providerType: item.providerType,
26443
+ providerName: item.providerName,
26444
+ kind: item.kind,
26445
+ title: item.title || item.providerName,
26446
+ workspace: item.workspace,
26447
+ currentModel: item.currentModel,
26448
+ lastLaunchedAt: item.lastUsedAt
26449
+ })).sort((a, b) => b.lastLaunchedAt - a.lastLaunchedAt).slice(0, 12);
26450
+ }
26451
+ function buildStatusSnapshot(options) {
26452
+ const cfg = loadConfig();
26453
+ const wsState = getWorkspaceState(cfg);
26454
+ const memSnap = getHostMemorySnapshot();
26455
+ const recentActivity = getRecentActivity(cfg, 20);
26456
+ const sessions = buildSessionEntries(
26457
+ options.allStates,
26458
+ options.cdpManagers
26459
+ );
26460
+ for (const session of sessions) {
26461
+ const lastSeenAt = getSessionSeenAt(cfg, session.id);
26462
+ const seenCompletionMarker = getSessionSeenMarker(cfg, session.id);
26463
+ const lastUsedAt = getSessionLastUsedAt(session);
26464
+ const completionMarker = getSessionCompletionMarker(session);
26465
+ const { unread, inboxBucket } = session.surfaceHidden ? { unread: false, inboxBucket: "idle" } : getUnreadState(
26466
+ getSessionMessageUpdatedAt(session) > 0,
26467
+ session.status,
26468
+ lastUsedAt,
26469
+ lastSeenAt,
26470
+ getLastMessageRole(session),
26471
+ completionMarker,
26472
+ seenCompletionMarker
26473
+ );
26474
+ session.lastSeenAt = lastSeenAt;
26475
+ session.unread = unread;
26476
+ session.inboxBucket = inboxBucket;
26477
+ if (READ_DEBUG_ENABLED && (session.unread || session.inboxBucket !== "idle" || session.providerType.includes("codex"))) {
26478
+ LOG.info(
26479
+ "RecentRead",
26480
+ `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)}`
26481
+ );
26482
+ }
26483
+ }
26484
+ const terminalBackend = getTerminalBackendRuntimeStatus();
26485
+ return {
26486
+ instanceId: options.instanceId,
26487
+ version: options.version,
26488
+ daemonMode: options.daemonMode,
26489
+ machine: {
26490
+ hostname: os10.hostname(),
26491
+ platform: os10.platform(),
26492
+ arch: os10.arch(),
26493
+ cpus: os10.cpus().length,
26494
+ totalMem: memSnap.totalMem,
26495
+ freeMem: memSnap.freeMem,
26496
+ availableMem: memSnap.availableMem,
26497
+ loadavg: os10.loadavg(),
26498
+ uptime: os10.uptime(),
26499
+ release: os10.release()
26500
+ },
26501
+ machineNickname: options.machineNickname ?? cfg.machineNickname ?? null,
26502
+ timestamp: options.timestamp ?? Date.now(),
26503
+ detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
26504
+ ...options.p2p ? { p2p: options.p2p } : {},
26505
+ sessions,
26506
+ workspaces: wsState.workspaces,
26507
+ defaultWorkspaceId: wsState.defaultWorkspaceId,
26508
+ defaultWorkspacePath: wsState.defaultWorkspacePath,
26509
+ recentLaunches: buildRecentLaunches(recentActivity),
26510
+ terminalBackend,
26511
+ availableProviders: buildAvailableProviders(options.providerLoader)
26512
+ };
26513
+ }
26366
26514
  var CHAT_COMMANDS = [
26367
26515
  "send_chat",
26368
26516
  "new_chat",
@@ -26370,6 +26518,7 @@ var CHAT_COMMANDS = [
26370
26518
  "set_mode",
26371
26519
  "change_model"
26372
26520
  ];
26521
+ var READ_DEBUG_ENABLED2 = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
26373
26522
  var DaemonCommandRouter = class {
26374
26523
  deps;
26375
26524
  constructor(deps) {
@@ -26540,28 +26689,35 @@ var DaemonCommandRouter = class {
26540
26689
  updateConfig({ userName: name });
26541
26690
  return { success: true, userName: name };
26542
26691
  }
26543
- case "mark_recent_seen": {
26544
- const kind = args?.kind;
26545
- const providerType = args?.providerType;
26546
- if (!kind || !providerType) {
26547
- return { success: false, error: "kind and providerType are required" };
26692
+ case "mark_session_seen": {
26693
+ const sessionId = args?.sessionId;
26694
+ if (!sessionId || typeof sessionId !== "string") {
26695
+ return { success: false, error: "sessionId is required" };
26548
26696
  }
26549
- const recentKey = args?.recentKey || buildRecentActivityKey({
26550
- kind,
26551
- providerType,
26552
- workspace: args?.workspace || null
26553
- });
26554
- const next = markRecentSessionSeen(
26555
- loadConfig(),
26556
- recentKey,
26557
- typeof args?.seenAt === "number" ? args.seenAt : Date.now()
26697
+ const currentConfig = loadConfig();
26698
+ const prevSeenAt = currentConfig.sessionReads?.[sessionId] || 0;
26699
+ const sessionEntries = buildSessionEntries(
26700
+ this.deps.instanceManager.collectAllStates(),
26701
+ this.deps.cdpManagers
26702
+ );
26703
+ const targetSession = sessionEntries.find((entry) => entry.id === sessionId);
26704
+ const completionMarker = targetSession ? getSessionCompletionMarker(targetSession) : "";
26705
+ const next = markSessionSeen(
26706
+ currentConfig,
26707
+ sessionId,
26708
+ typeof args?.seenAt === "number" ? args.seenAt : Date.now(),
26709
+ completionMarker
26558
26710
  );
26711
+ if (READ_DEBUG_ENABLED2) {
26712
+ LOG.info("RecentRead", `mark_session_seen sessionId=${sessionId} seenAt=${String(args?.seenAt || "")} prevSeenAt=${String(prevSeenAt)} nextSeenAt=${String(next.sessionReads?.[sessionId] || 0)} marker=${completionMarker || "-"}`);
26713
+ }
26559
26714
  saveConfig(next);
26560
26715
  this.deps.onStatusChange?.();
26561
26716
  return {
26562
26717
  success: true,
26563
- recentKey,
26564
- seenAt: next.recentSessionReads?.[recentKey] || Date.now()
26718
+ sessionId,
26719
+ seenAt: next.sessionReads?.[sessionId] || Date.now(),
26720
+ completionMarker
26565
26721
  };
26566
26722
  }
26567
26723
  // ─── Daemon Self-Upgrade ───
@@ -26676,189 +26832,6 @@ var DaemonCommandRouter = class {
26676
26832
  }
26677
26833
  };
26678
26834
  init_logger();
26679
- init_config();
26680
- init_terminal_screen();
26681
- function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
26682
- return detectedIdes.filter((ide) => ide.installed !== false).map((ide) => ({
26683
- id: ide.id,
26684
- type: ide.id,
26685
- name: ide.displayName || ide.name || ide.id,
26686
- running: isCdpConnected(cdpManagers, ide.id),
26687
- ...ide.path ? { path: ide.path } : {}
26688
- }));
26689
- }
26690
- function buildAvailableProviders(providerLoader) {
26691
- return providerLoader.getAll().map((provider) => ({
26692
- type: provider.type,
26693
- name: provider.displayName || provider.type,
26694
- displayName: provider.displayName || provider.type,
26695
- icon: provider.icon || "\u{1F4BB}",
26696
- category: provider.category
26697
- }));
26698
- }
26699
- function parseMessageTime(value) {
26700
- if (typeof value === "number" && Number.isFinite(value)) return value;
26701
- if (typeof value === "string") {
26702
- const parsed = Date.parse(value);
26703
- if (Number.isFinite(parsed)) return parsed;
26704
- }
26705
- return 0;
26706
- }
26707
- function getSessionMessageUpdatedAt(session) {
26708
- const lastMessage = session.activeChat?.messages?.at?.(-1);
26709
- if (!lastMessage) return 0;
26710
- return parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt) || 0;
26711
- }
26712
- function getSessionLastUsedAt(session) {
26713
- return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
26714
- }
26715
- function getSessionKind(session) {
26716
- return session.transport === "cdp-page" || session.transport === "cdp-webview" ? "ide" : session.transport === "acp" ? "acp" : "cli";
26717
- }
26718
- function getLastMessageRole(session) {
26719
- const role = session.activeChat?.messages?.at?.(-1)?.role;
26720
- return typeof role === "string" ? role : "";
26721
- }
26722
- function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole) {
26723
- if (status === "waiting_approval") {
26724
- return { unread: false, inboxBucket: "needs_attention" };
26725
- }
26726
- if (status === "generating" || status === "starting") {
26727
- return { unread: false, inboxBucket: "working" };
26728
- }
26729
- const unread = hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
26730
- return { unread, inboxBucket: unread ? "task_complete" : "idle" };
26731
- }
26732
- function buildRecentSessions(sessions, recentActivity, readState) {
26733
- const visibleKeys = /* @__PURE__ */ new Set();
26734
- const hiddenKeys = /* @__PURE__ */ new Set();
26735
- const live = sessions.filter((session) => !session.surfaceHidden && session.status !== "stopped").map((session) => {
26736
- const kind = getSessionKind(session);
26737
- const recentKey = buildRecentActivityKey({
26738
- kind,
26739
- providerType: session.providerType,
26740
- workspace: session.workspace
26741
- });
26742
- const lastSeenAt = readState[recentKey] || 0;
26743
- const lastUsedAt = getSessionLastUsedAt(session);
26744
- const { unread, inboxBucket } = getUnreadState(
26745
- getSessionMessageUpdatedAt(session) > 0,
26746
- session.status,
26747
- lastUsedAt,
26748
- lastSeenAt,
26749
- getLastMessageRole(session)
26750
- );
26751
- return {
26752
- id: session.id,
26753
- recentKey,
26754
- sessionId: session.id,
26755
- providerType: session.providerType,
26756
- providerName: session.providerName,
26757
- kind,
26758
- title: session.activeChat?.title || session.title || session.providerName,
26759
- workspace: session.workspace,
26760
- currentModel: session.currentModel,
26761
- status: session.status,
26762
- lastUsedAt,
26763
- unread,
26764
- lastSeenAt,
26765
- inboxBucket,
26766
- surfaceHidden: false
26767
- };
26768
- });
26769
- for (const item of live) {
26770
- visibleKeys.add(`${item.kind}:${item.providerType}:${item.workspace || ""}`);
26771
- }
26772
- for (const session of sessions) {
26773
- if (!session.surfaceHidden) continue;
26774
- hiddenKeys.add(`${getSessionKind(session)}:${session.providerType}:${session.workspace || ""}`);
26775
- }
26776
- const persisted = recentActivity.filter((item) => {
26777
- const key = `${item.kind}:${item.providerType}:${item.workspace || ""}`;
26778
- return !visibleKeys.has(key) && !hiddenKeys.has(key);
26779
- }).map((item) => {
26780
- const lastSeenAt = readState[item.id] || 0;
26781
- const unread = item.lastUsedAt > lastSeenAt;
26782
- return {
26783
- id: item.id,
26784
- recentKey: item.id,
26785
- sessionId: item.sessionId || null,
26786
- providerType: item.providerType,
26787
- providerName: item.providerName,
26788
- kind: item.kind,
26789
- title: item.title || item.providerName,
26790
- workspace: item.workspace,
26791
- currentModel: item.currentModel,
26792
- lastUsedAt: item.lastUsedAt,
26793
- unread,
26794
- lastSeenAt,
26795
- inboxBucket: unread ? "task_complete" : "idle",
26796
- surfaceHidden: false
26797
- };
26798
- });
26799
- return [...live, ...persisted].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, 12);
26800
- }
26801
- function buildStatusSnapshot(options) {
26802
- const cfg = loadConfig();
26803
- const wsState = getWorkspaceState(cfg);
26804
- const memSnap = getHostMemorySnapshot();
26805
- const recentActivity = getRecentActivity(cfg, 20);
26806
- const sessions = buildSessionEntries(
26807
- options.allStates,
26808
- options.cdpManagers
26809
- );
26810
- const readState = cfg.recentSessionReads || {};
26811
- for (const session of sessions) {
26812
- const kind = getSessionKind(session);
26813
- const recentKey = buildRecentActivityKey({
26814
- kind,
26815
- providerType: session.providerType,
26816
- workspace: session.workspace
26817
- });
26818
- const lastSeenAt = getRecentSessionSeenAt(cfg, recentKey);
26819
- const lastUsedAt = getSessionLastUsedAt(session);
26820
- const { unread, inboxBucket } = session.surfaceHidden ? { unread: false, inboxBucket: "idle" } : getUnreadState(
26821
- getSessionMessageUpdatedAt(session) > 0,
26822
- session.status,
26823
- lastUsedAt,
26824
- lastSeenAt,
26825
- getLastMessageRole(session)
26826
- );
26827
- session.recentKey = recentKey;
26828
- session.lastSeenAt = lastSeenAt;
26829
- session.unread = unread;
26830
- session.inboxBucket = inboxBucket;
26831
- }
26832
- const terminalBackend = getTerminalBackendRuntimeStatus();
26833
- return {
26834
- instanceId: options.instanceId,
26835
- version: options.version,
26836
- daemonMode: options.daemonMode,
26837
- machine: {
26838
- hostname: os10.hostname(),
26839
- platform: os10.platform(),
26840
- arch: os10.arch(),
26841
- cpus: os10.cpus().length,
26842
- totalMem: memSnap.totalMem,
26843
- freeMem: memSnap.freeMem,
26844
- availableMem: memSnap.availableMem,
26845
- loadavg: os10.loadavg(),
26846
- uptime: os10.uptime(),
26847
- release: os10.release()
26848
- },
26849
- machineNickname: options.machineNickname ?? cfg.machineNickname ?? null,
26850
- timestamp: options.timestamp ?? Date.now(),
26851
- detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
26852
- ...options.p2p ? { p2p: options.p2p } : {},
26853
- sessions,
26854
- workspaces: wsState.workspaces,
26855
- defaultWorkspaceId: wsState.defaultWorkspaceId,
26856
- defaultWorkspacePath: wsState.defaultWorkspacePath,
26857
- recentSessions: buildRecentSessions(sessions, recentActivity, readState),
26858
- terminalBackend,
26859
- availableProviders: buildAvailableProviders(options.providerLoader)
26860
- };
26861
- }
26862
26835
  init_logger();
26863
26836
  init_provider_cli_adapter();
26864
26837
  init_config();