@adhdev/daemon-core 0.9.82-rc.356 → 0.9.82-rc.357

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.mjs CHANGED
@@ -311,10 +311,10 @@ function readInjected(value) {
311
311
  }
312
312
  function getDaemonBuildInfo() {
313
313
  if (cached) return cached;
314
- const commit = readInjected(true ? "91500e054cf2b6258f6041f90c18be03ad05a8ad" : void 0) ?? "unknown";
315
- const commitShort = readInjected(true ? "91500e05" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
316
- const version = readInjected(true ? "0.9.82-rc.356" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
317
- const builtAt = readInjected(true ? "2026-06-22T22:47:29.082Z" : void 0);
314
+ const commit = readInjected(true ? "37b9d1d9e10336707dbc0861a96d5bcc55cc015e" : void 0) ?? "unknown";
315
+ const commitShort = readInjected(true ? "37b9d1d9" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
316
+ const version = readInjected(true ? "0.9.82-rc.357" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
317
+ const builtAt = readInjected(true ? "2026-06-23T00:25:21.599Z" : void 0);
318
318
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
319
319
  return cached;
320
320
  }
@@ -12670,8 +12670,22 @@ function sweepExpiredRemoteIdleSessions() {
12670
12670
  }
12671
12671
  function getMeshWithCache(components, meshId) {
12672
12672
  const localMesh = getMesh(meshId);
12673
- if (localMesh) return localMesh;
12674
- return components.router?.getCachedInlineMesh(meshId);
12673
+ const cachedMesh = components.router?.getCachedInlineMesh(meshId);
12674
+ if (!localMesh) return cachedMesh;
12675
+ if (!cachedMesh) return localMesh;
12676
+ return mergeInlineCacheOnlyNodes(localMesh, cachedMesh);
12677
+ }
12678
+ function mergeInlineCacheOnlyNodes(localMesh, cachedMesh) {
12679
+ const localNodes = Array.isArray(localMesh?.nodes) ? localMesh.nodes : [];
12680
+ const cachedNodes = Array.isArray(cachedMesh?.nodes) ? cachedMesh.nodes : [];
12681
+ if (!cachedNodes.length) return localMesh;
12682
+ const cacheOnly = cachedNodes.filter((cachedNode) => {
12683
+ const cachedId = readMeshNodeId(cachedNode);
12684
+ if (!cachedId) return false;
12685
+ return !localNodes.some((localNode) => meshNodeIdMatches(localNode, cachedId));
12686
+ });
12687
+ if (!cacheOnly.length) return localMesh;
12688
+ return { ...localMesh, nodes: [...localNodes, ...cacheOnly] };
12675
12689
  }
12676
12690
  function isIntentionalCleanupStopMetadata(event) {
12677
12691
  return event.intentional === true || event.intentionalStop === true || event.operatorCleanup === true || event.reason === "operator_cleanup" || event.stopReason === "operator_cleanup" || event.cleanupReason === "operator_cleanup" || event.source === "mesh_cleanup_sessions" || event.source === "mesh_remove_node";
@@ -14008,6 +14022,76 @@ function injectMeshSystemMessage(components, args) {
14008
14022
  }
14009
14023
  return { success: true, forwarded: 0 };
14010
14024
  }
14025
+ function buildRelayMetadataEvent(payload) {
14026
+ const relayModalMessage = readNonEmptyString2(payload.modalMessage);
14027
+ const relayModalButtons = Array.isArray(payload.modalButtons) ? payload.modalButtons.filter((b) => typeof b === "string" && b.trim().length > 0) : null;
14028
+ return {
14029
+ // Preserve the dispatch task id across the machine boundary. The `received` trace
14030
+ // stage reads payload.taskId; without mirroring it here the rebuilt metadataEvent
14031
+ // loses it, so injectMeshSystemMessage's traceCtx.taskId and the
14032
+ // updateDirectDispatchStatus(eventTaskId) call go undefined — the EvtTrace
14033
+ // queued/surfaced stages show task=- and the direct-dispatch ledger falls back to a
14034
+ // session_id match (which can flip a sibling row). The local in-process forward path
14035
+ // keeps event.taskId/meshActiveTaskId for free; this mirrors it for the remote relay.
14036
+ // Same taskId/meshActiveTaskId ordering the local unroutable trace uses.
14037
+ taskId: readNonEmptyString2(payload.taskId) || readNonEmptyString2(payload.meshActiveTaskId),
14038
+ targetSessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId) || readNonEmptyString2(payload.instanceId),
14039
+ providerType: readNonEmptyString2(payload.providerType),
14040
+ providerSessionId: readNonEmptyString2(payload.providerSessionId),
14041
+ // Preserve the originating coordinator SESSION id across the machine boundary so
14042
+ // the completion routes back to the exact coordinator session (multi-coordinator).
14043
+ // buildForwardPayloadFromPending spreads the worker event's metadata, so the id
14044
+ // arrives as payload.meshCoordinatorSessionId; the top-level targetCoordinatorSessionId
14045
+ // is also accepted as a fallback. injectMeshSystemMessage re-derives the routing
14046
+ // anchors from this. Absent → daemon-level fallback (version-skew safe).
14047
+ meshCoordinatorSessionId: readNonEmptyString2(payload.meshCoordinatorSessionId) || readNonEmptyString2(payload.targetCoordinatorSessionId),
14048
+ // Carry the session identity fields the worker provider event emits so the
14049
+ // coordinator's mirror (updateMeshOwnedSession) gets a real workspace/title/
14050
+ // settings. Without these the remote-relay hop reconstructs metadataEvent with
14051
+ // an empty workspace, and the dashboard flaps to the generic
14052
+ // "Terminal (Mesh Node)" title (and degrades the provider label) between live
14053
+ // events and the periodic get_status_metadata snapshot. The local in-process
14054
+ // forward path (onMeshCoordinatorEventForwarded) already preserves these; this
14055
+ // mirrors them for the remote-only relay path.
14056
+ workspace: readNonEmptyString2(payload.workspace) || readNonEmptyString2(payload.workspaceName),
14057
+ workspaceName: readNonEmptyString2(payload.workspaceName) || readNonEmptyString2(payload.workspace),
14058
+ sessionTitle: readNonEmptyString2(payload.sessionTitle),
14059
+ sessionStatus: readNonEmptyString2(payload.sessionStatus),
14060
+ sessionChatStatus: readNonEmptyString2(payload.sessionChatStatus),
14061
+ providerName: readNonEmptyString2(payload.providerName),
14062
+ ...payload.sessionSettings && typeof payload.sessionSettings === "object" && !Array.isArray(payload.sessionSettings) ? { sessionSettings: payload.sessionSettings } : {},
14063
+ finalSummary: readNonEmptyString2(payload.finalSummary) || readNonEmptyString2(payload.summary),
14064
+ // T2: carry the worker's status-snapshot last-message preview across the machine
14065
+ // boundary so a summary-less completion still surfaces the assistant reply in the
14066
+ // coordinator's inbox mirror. resolveMeshSurfacedSessionPreview reads these
14067
+ // (assistant-role only) when finalSummary is absent.
14068
+ lastMessagePreview: readNonEmptyString2(payload.lastMessagePreview),
14069
+ lastMessageRole: readNonEmptyString2(payload.lastMessageRole),
14070
+ ...payload.lastMessageAt !== void 0 ? { lastMessageAt: payload.lastMessageAt } : {},
14071
+ jobId: readNonEmptyString2(payload.jobId),
14072
+ interactionId: readNonEmptyString2(payload.interactionId),
14073
+ status: readNonEmptyString2(payload.status),
14074
+ targetDaemonId: readNonEmptyString2(payload.targetDaemonId),
14075
+ startedAt: readNonEmptyString2(payload.startedAt),
14076
+ completedAt: readNonEmptyString2(payload.completedAt),
14077
+ retryOfJobId: readNonEmptyString2(payload.retryOfJobId),
14078
+ ...relayModalMessage ? { modalMessage: relayModalMessage } : {},
14079
+ ...relayModalButtons && relayModalButtons.length > 0 ? { modalButtons: relayModalButtons } : {},
14080
+ ...payload.result && typeof payload.result === "object" && !Array.isArray(payload.result) ? { result: payload.result } : {},
14081
+ ...payload.completionDiagnostic && typeof payload.completionDiagnostic === "object" && !Array.isArray(payload.completionDiagnostic) ? { completionDiagnostic: payload.completionDiagnostic } : {},
14082
+ ...payload.workerResult && typeof payload.workerResult === "object" && !Array.isArray(payload.workerResult) ? { workerResult: payload.workerResult } : {},
14083
+ ...payload.meshWorkerResult && typeof payload.meshWorkerResult === "object" && !Array.isArray(payload.meshWorkerResult) ? { meshWorkerResult: payload.meshWorkerResult } : {},
14084
+ ...payload.structuredResult && typeof payload.structuredResult === "object" && !Array.isArray(payload.structuredResult) ? { structuredResult: payload.structuredResult } : {},
14085
+ ...payload.timestamp !== void 0 ? { timestamp: payload.timestamp } : {},
14086
+ intentional: payload.intentional === true,
14087
+ intentionalStop: payload.intentionalStop === true,
14088
+ operatorCleanup: payload.operatorCleanup === true,
14089
+ reason: readNonEmptyString2(payload.reason),
14090
+ stopReason: readNonEmptyString2(payload.stopReason),
14091
+ cleanupReason: readNonEmptyString2(payload.cleanupReason),
14092
+ source: readNonEmptyString2(payload.source)
14093
+ };
14094
+ }
14011
14095
  function handleMeshForwardEvent(components, payload) {
14012
14096
  const eventName = readNonEmptyString2(payload.event);
14013
14097
  if (!isMeshCoordinatorEvent(eventName)) {
@@ -14033,70 +14117,12 @@ function handleMeshForwardEvent(components, payload) {
14033
14117
  event: eventName
14034
14118
  });
14035
14119
  const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
14036
- const relayModalMessage = readNonEmptyString2(payload.modalMessage);
14037
- const relayModalButtons = Array.isArray(payload.modalButtons) ? payload.modalButtons.filter((b) => typeof b === "string" && b.trim().length > 0) : null;
14038
14120
  return injectMeshSystemMessage(components, {
14039
14121
  meshId,
14040
14122
  nodeId,
14041
14123
  nodeLabel,
14042
14124
  event: eventName,
14043
- metadataEvent: {
14044
- targetSessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId) || readNonEmptyString2(payload.instanceId),
14045
- providerType: readNonEmptyString2(payload.providerType),
14046
- providerSessionId: readNonEmptyString2(payload.providerSessionId),
14047
- // Preserve the originating coordinator SESSION id across the machine boundary so
14048
- // the completion routes back to the exact coordinator session (multi-coordinator).
14049
- // buildForwardPayloadFromPending spreads the worker event's metadata, so the id
14050
- // arrives as payload.meshCoordinatorSessionId; the top-level targetCoordinatorSessionId
14051
- // is also accepted as a fallback. injectMeshSystemMessage re-derives the routing
14052
- // anchors from this. Absent → daemon-level fallback (version-skew safe).
14053
- meshCoordinatorSessionId: readNonEmptyString2(payload.meshCoordinatorSessionId) || readNonEmptyString2(payload.targetCoordinatorSessionId),
14054
- // Carry the session identity fields the worker provider event emits so the
14055
- // coordinator's mirror (updateMeshOwnedSession) gets a real workspace/title/
14056
- // settings. Without these the remote-relay hop reconstructs metadataEvent with
14057
- // an empty workspace, and the dashboard flaps to the generic
14058
- // "Terminal (Mesh Node)" title (and degrades the provider label) between live
14059
- // events and the periodic get_status_metadata snapshot. The local in-process
14060
- // forward path (onMeshCoordinatorEventForwarded) already preserves these; this
14061
- // mirrors them for the remote-only relay path.
14062
- workspace: readNonEmptyString2(payload.workspace) || readNonEmptyString2(payload.workspaceName),
14063
- workspaceName: readNonEmptyString2(payload.workspaceName) || readNonEmptyString2(payload.workspace),
14064
- sessionTitle: readNonEmptyString2(payload.sessionTitle),
14065
- sessionStatus: readNonEmptyString2(payload.sessionStatus),
14066
- sessionChatStatus: readNonEmptyString2(payload.sessionChatStatus),
14067
- providerName: readNonEmptyString2(payload.providerName),
14068
- ...payload.sessionSettings && typeof payload.sessionSettings === "object" && !Array.isArray(payload.sessionSettings) ? { sessionSettings: payload.sessionSettings } : {},
14069
- finalSummary: readNonEmptyString2(payload.finalSummary) || readNonEmptyString2(payload.summary),
14070
- // T2: carry the worker's status-snapshot last-message preview across the machine
14071
- // boundary so a summary-less completion still surfaces the assistant reply in the
14072
- // coordinator's inbox mirror. resolveMeshSurfacedSessionPreview reads these
14073
- // (assistant-role only) when finalSummary is absent.
14074
- lastMessagePreview: readNonEmptyString2(payload.lastMessagePreview),
14075
- lastMessageRole: readNonEmptyString2(payload.lastMessageRole),
14076
- ...payload.lastMessageAt !== void 0 ? { lastMessageAt: payload.lastMessageAt } : {},
14077
- jobId: readNonEmptyString2(payload.jobId),
14078
- interactionId: readNonEmptyString2(payload.interactionId),
14079
- status: readNonEmptyString2(payload.status),
14080
- targetDaemonId: readNonEmptyString2(payload.targetDaemonId),
14081
- startedAt: readNonEmptyString2(payload.startedAt),
14082
- completedAt: readNonEmptyString2(payload.completedAt),
14083
- retryOfJobId: readNonEmptyString2(payload.retryOfJobId),
14084
- ...relayModalMessage ? { modalMessage: relayModalMessage } : {},
14085
- ...relayModalButtons && relayModalButtons.length > 0 ? { modalButtons: relayModalButtons } : {},
14086
- ...payload.result && typeof payload.result === "object" && !Array.isArray(payload.result) ? { result: payload.result } : {},
14087
- ...payload.completionDiagnostic && typeof payload.completionDiagnostic === "object" && !Array.isArray(payload.completionDiagnostic) ? { completionDiagnostic: payload.completionDiagnostic } : {},
14088
- ...payload.workerResult && typeof payload.workerResult === "object" && !Array.isArray(payload.workerResult) ? { workerResult: payload.workerResult } : {},
14089
- ...payload.meshWorkerResult && typeof payload.meshWorkerResult === "object" && !Array.isArray(payload.meshWorkerResult) ? { meshWorkerResult: payload.meshWorkerResult } : {},
14090
- ...payload.structuredResult && typeof payload.structuredResult === "object" && !Array.isArray(payload.structuredResult) ? { structuredResult: payload.structuredResult } : {},
14091
- ...payload.timestamp !== void 0 ? { timestamp: payload.timestamp } : {},
14092
- intentional: payload.intentional === true,
14093
- intentionalStop: payload.intentionalStop === true,
14094
- operatorCleanup: payload.operatorCleanup === true,
14095
- reason: readNonEmptyString2(payload.reason),
14096
- stopReason: readNonEmptyString2(payload.stopReason),
14097
- cleanupReason: readNonEmptyString2(payload.cleanupReason),
14098
- source: readNonEmptyString2(payload.source)
14099
- }
14125
+ metadataEvent: buildRelayMetadataEvent(payload)
14100
14126
  });
14101
14127
  }
14102
14128
  function forwardUnresolvedDelegateEvent(components, routing, event) {
@@ -19802,6 +19828,11 @@ function statusForState(state) {
19802
19828
  if (state.id === "busy" || state.id === "generating") return "generating";
19803
19829
  return "idle";
19804
19830
  }
19831
+ function modalKindForState(state) {
19832
+ if (state.modal_kind) return state.modal_kind;
19833
+ if (state.modal) return "approval";
19834
+ return null;
19835
+ }
19805
19836
  var init_fsm_types = __esm({
19806
19837
  "src/providers/spec/fsm-types.ts"() {
19807
19838
  "use strict";
@@ -33330,7 +33361,12 @@ var FsmDriver = class {
33330
33361
  this.emit({
33331
33362
  kind: "state_changed",
33332
33363
  state: next.state,
33333
- modal: next.modal ? { title: next.modal.title, buttons: next.modal.buttons.map((b) => ({ index: b.index, label: b.label })) } : null,
33364
+ // kind is the SEMANTIC modal class (approval vs picker/confirm)
33365
+ // derived from the FSM state, NOT from the parsed buttons — the
33366
+ // status field already collapsed it to 'approval' so the modal is
33367
+ // surfaced. The auto-approve worker needs the distinction back to
33368
+ // avoid answering a /model picker on the user's behalf.
33369
+ modal: next.modal ? { title: next.modal.title, buttons: next.modal.buttons.map((b) => ({ index: b.index, label: b.label })), kind: modalKindForState(state) } : null,
33334
33370
  controls: next.controls.map((c) => ({ id: c.id, label: c.label, action_type: c.actionType }))
33335
33371
  });
33336
33372
  this.fireNotifications(state.id, title);
@@ -34750,7 +34786,9 @@ var SpecCliAdapter = class _SpecCliAdapter {
34750
34786
  messages: [],
34751
34787
  // Surface buttons when we have them; an approval state with no parsed
34752
34788
  // modal this frame still stays waiting_approval (no activeModal yet).
34753
- activeModal: modal ? { message: modal.title ?? state.label, buttons: modal.buttons.map((b) => b.label) } : null,
34789
+ // `kind` carries the semantic modal class through to the auto-approve
34790
+ // gate so a /model picker (kind='picker') is never auto-answered.
34791
+ activeModal: modal ? { message: modal.title ?? state.label, buttons: modal.buttons.map((b) => b.label), kind: modal.kind ?? null } : null,
34754
34792
  activeInteractivePrompt: this.activeInteractivePrompt,
34755
34793
  ...sessionFields
34756
34794
  };
@@ -36717,8 +36755,12 @@ var CliProviderInstance = class _CliProviderInstance {
36717
36755
  if (!modal || buttons.length === 0) {
36718
36756
  return autoApproveActive;
36719
36757
  }
36720
- const { index: buttonIndex, label: buttonLabel } = pickAutoApprovalButton(buttons);
36721
- if (buttonIndex < 0) {
36758
+ const modalKind = typeof modal?.kind === "string" ? modal.kind : "approval";
36759
+ if (modalKind !== "approval") {
36760
+ return autoApproveActive;
36761
+ }
36762
+ const { index: buttonIndex, label: buttonLabel } = pickApprovalButton(buttons, this.provider);
36763
+ if (buttonIndex < 0 || !hasNegativeApprovalOption(buttons)) {
36722
36764
  return autoApproveActive;
36723
36765
  }
36724
36766
  const modalSignature = [