@adhdev/daemon-core 0.9.82-rc.546 → 0.9.82-rc.548

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-core",
3
- "version": "0.9.82-rc.546",
3
+ "version": "0.9.82-rc.548",
4
4
  "description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -47,8 +47,8 @@
47
47
  "author": "vilmire",
48
48
  "license": "AGPL-3.0-or-later",
49
49
  "dependencies": {
50
- "@adhdev/mesh-shared": "0.9.82-rc.546",
51
- "@adhdev/session-host-core": "0.9.82-rc.546",
50
+ "@adhdev/mesh-shared": "0.9.82-rc.548",
51
+ "@adhdev/session-host-core": "0.9.82-rc.548",
52
52
  "@agentclientprotocol/sdk": "^0.16.1",
53
53
  "ajv": "^8.20.0",
54
54
  "ajv-formats": "^3.0.1",
@@ -14,10 +14,60 @@ import { loadState } from '../../config/state-store.js';
14
14
  import { getRecentActivity } from '../../config/recent-activity.js';
15
15
  import { getSavedProviderSessions } from '../../config/saved-sessions.js';
16
16
  import { listProviderHistorySessions } from '../../config/chat-history.js';
17
- import { buildMeshWorkerRelayStamp } from '../../mesh/mesh-events-utils.js';
17
+ import { buildMeshWorkerRelayStamp, readNonEmptyString } from '../../mesh/mesh-events-utils.js';
18
+ import { LOG } from '../../logging/logger.js';
18
19
  import { readStringValue } from '../router.js';
19
20
  import type { MedFamilyContext, MedFamilyHandler } from './types.js';
20
21
 
22
+ /**
23
+ * MESH-WORKER-PREFS Fix B: when a mesh WORKER session's per-conversation Hide/Mute is toggled
24
+ * (set_conversation_prefs, forwarded to the worker daemon by the coordinator's
25
+ * MESH_FORWARDABLE_SESSION_COMMANDS router), the worker updates its own live-session
26
+ * userHidden/userMuted but the COORDINATOR's mirror of that session (adhdev-daemon
27
+ * meshOwnedSessions) is only refreshed by a `mesh_forward_event` carrying `sessionSettings`.
28
+ * Without one the mirror stays stale, so when the coordinator re-emits the session metadata to
29
+ * the dashboard the old surfaceHidden/muted comes back and the toggle reverts after the 8s
30
+ * optimistic overlay expires. Push a best-effort `mesh_forward_event` to the coordinator daemon
31
+ * with the fresh prefs so its mirror updates immediately. Fire-and-forget: the coordinator's
32
+ * mesh_forward_event command consumer calls updateMeshOwnedSession(args) BEFORE routing, so the
33
+ * mirror is refreshed even though the (non coordinator-event) event name is otherwise ignored;
34
+ * a self-addressed or failed dispatch is harmless (the local status snapshot already fired).
35
+ */
36
+ function forwardConversationPrefsToCoordinator(
37
+ ctx: MedFamilyContext,
38
+ sessionId: string,
39
+ patch: Record<string, unknown>,
40
+ ): void {
41
+ const dispatch = ctx.deps.dispatchMeshCommand;
42
+ if (!dispatch) return;
43
+ let settings: Record<string, unknown> = {};
44
+ try {
45
+ const state = ctx.deps.instanceManager.getInstance(sessionId)?.getState?.();
46
+ if (state?.settings && typeof state.settings === 'object') {
47
+ settings = state.settings as Record<string, unknown>;
48
+ }
49
+ } catch { /* best-effort — no session settings, nothing to forward */ }
50
+
51
+ const coordinatorDaemonId = readNonEmptyString(settings.meshCoordinatorDaemonId);
52
+ const meshId = readNonEmptyString(settings.meshNodeFor);
53
+ // A non-delegated (non-mesh) session has no coordinator anchor — nothing to mirror.
54
+ if (!coordinatorDaemonId || !meshId) return;
55
+ const nodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.meshLastNodeId);
56
+
57
+ // sessionSettings mirrors the exact keys updateMeshOwnedSession merges onto the mirror's
58
+ // settings (userHidden / userMuted). The coordinator's mirror resolver reads these to derive
59
+ // surfaceHidden/muted, so the dashboard sees the fresh value on the next metadata flush.
60
+ const payload: Record<string, unknown> = {
61
+ event: 'session:settings_changed',
62
+ meshId,
63
+ targetSessionId: sessionId,
64
+ ...(nodeId ? { nodeId } : {}),
65
+ sessionSettings: { ...patch },
66
+ };
67
+ Promise.resolve(dispatch(coordinatorDaemonId, 'mesh_forward_event', payload))
68
+ .catch((e: any) => LOG.warn('Mesh', `[Mesh] set_conversation_prefs mirror forward to coordinator ${coordinatorDaemonId.slice(0, 12)} failed: ${e?.message || e}`));
69
+ }
70
+
21
71
  export const cliAgentHandlers: Record<string, MedFamilyHandler> = {
22
72
  launch_cli: async (ctx: MedFamilyContext, args: any) => {
23
73
  // The coordinator routing anchor (meshCoordinatorDaemonId) is stamped
@@ -90,6 +140,10 @@ export const cliAgentHandlers: Record<string, MedFamilyHandler> = {
90
140
  // surfaceHidden/muted immediately (cloud path). The standalone server has a
91
141
  // parallel broadcast gate keyed on the command name (see daemon-standalone).
92
142
  ctx.deps.onStatusChange?.();
143
+ // MESH-WORKER-PREFS Fix B: if this is a mesh worker session, mirror the fresh prefs onto
144
+ // the coordinator so its stale meshOwnedSessions copy can't revert the toggle when it
145
+ // re-emits the dashboard metadata. Best-effort / no-op for non-mesh sessions.
146
+ forwardConversationPrefsToCoordinator(ctx, sessionId, patch);
93
147
  return { success: true, sessionId, ...patch };
94
148
  },
95
149