@adhdev/daemon-core 0.9.82-rc.420 → 0.9.82-rc.422

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
@@ -384,10 +384,10 @@ function readInjected(value) {
384
384
  }
385
385
  function getDaemonBuildInfo() {
386
386
  if (cached) return cached;
387
- const commit = readInjected(true ? "bd19cb0fbe1e16db1d8d2fcd8c2c871aae3ce33b" : void 0) ?? "unknown";
388
- const commitShort = readInjected(true ? "bd19cb0f" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
389
- const version = readInjected(true ? "0.9.82-rc.420" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
390
- const builtAt = readInjected(true ? "2026-06-28T19:41:31.696Z" : void 0);
387
+ const commit = readInjected(true ? "308e099c65d2de2491f3db46913f9ced6aa3992c" : void 0) ?? "unknown";
388
+ const commitShort = readInjected(true ? "308e099c" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
389
+ const version = readInjected(true ? "0.9.82-rc.422" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
390
+ const builtAt = readInjected(true ? "2026-06-29T05:26:31.350Z" : void 0);
391
391
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
392
392
  return cached;
393
393
  }
@@ -3680,21 +3680,6 @@ var init_async_batch_writer = __esm({
3680
3680
  });
3681
3681
 
3682
3682
  // src/logging/logger.ts
3683
- var logger_exports = {};
3684
- __export(logger_exports, {
3685
- LOG: () => LOG,
3686
- LOG_DIR_PATH: () => LOG_DIR_PATH,
3687
- LOG_PATH: () => LOG_PATH,
3688
- daemonLog: () => daemonLog,
3689
- getCurrentDaemonLogPath: () => getCurrentDaemonLogPath,
3690
- getDaemonLogDir: () => getDaemonLogDir,
3691
- getLogBufferSize: () => getLogBufferSize,
3692
- getLogLevel: () => getLogLevel,
3693
- getLogPath: () => getLogPath,
3694
- getRecentLogs: () => getRecentLogs,
3695
- installGlobalInterceptor: () => installGlobalInterceptor,
3696
- setLogLevel: () => setLogLevel
3697
- });
3698
3683
  import * as fs4 from "fs";
3699
3684
  import * as path9 from "path";
3700
3685
  import * as os3 from "os";
@@ -3769,9 +3754,6 @@ function getRecentLogs(count = 50, minLevel = "info") {
3769
3754
  const filtered = ringBuffer.filter((e) => LEVEL_NUM[e.level] >= minNum);
3770
3755
  return filtered.slice(-count);
3771
3756
  }
3772
- function getLogBufferSize() {
3773
- return ringBuffer.length;
3774
- }
3775
3757
  function ts() {
3776
3758
  return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
3777
3759
  }
@@ -3851,10 +3833,7 @@ function installGlobalInterceptor() {
3851
3833
  writeToFile(`Log file: ${currentLogFile}`);
3852
3834
  writeToFile(`Log level: ${currentLevel}`);
3853
3835
  }
3854
- function getLogPath() {
3855
- return currentLogFile;
3856
- }
3857
- var LEVEL_NUM, LEVEL_LABEL, currentLevel, ADHDEV_HOME, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH, LOG_DIR_PATH;
3836
+ var LEVEL_NUM, LEVEL_LABEL, currentLevel, ADHDEV_HOME, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH;
3858
3837
  var init_logger = __esm({
3859
3838
  "src/logging/logger.ts"() {
3860
3839
  "use strict";
@@ -3913,7 +3892,6 @@ var init_logger = __esm({
3913
3892
  };
3914
3893
  interceptorInstalled = false;
3915
3894
  LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
3916
- LOG_DIR_PATH = LOG_DIR;
3917
3895
  }
3918
3896
  });
3919
3897
 
@@ -12524,6 +12502,23 @@ function liveSessionCountForNode(components, meshId, nodeId) {
12524
12502
  return !isTerminalSessionStatus(status);
12525
12503
  }).length;
12526
12504
  }
12505
+ function nodeHasLiveSessionPendingClaim(components, meshId, nodeId) {
12506
+ const busySessionIds = new Set(
12507
+ getQueue(meshId, { status: ["assigned"] }).filter((task) => daemonIdsEquivalent(task.assignedNodeId, nodeId)).map((task) => readNonEmptyString2(task.assignedSessionId)).filter(Boolean)
12508
+ );
12509
+ return components.instanceManager.getByCategory("cli").some((inst) => {
12510
+ const state = inst.getState();
12511
+ const settings = state.settings || {};
12512
+ if (readNonEmptyString2(settings.meshNodeFor) !== meshId) return false;
12513
+ const instNodeId = readNonEmptyString2(settings.meshNodeId) || readNonEmptyString2(settings.nodeId);
12514
+ if (!daemonIdsEquivalent(instNodeId, nodeId)) return false;
12515
+ const status = readNonEmptyString2(state.status).toLowerCase();
12516
+ if (isTerminalSessionStatus(status)) return false;
12517
+ const sessionId = readNonEmptyString2(state.instanceId);
12518
+ if (sessionId && busySessionIds.has(sessionId)) return false;
12519
+ return true;
12520
+ });
12521
+ }
12527
12522
  function recordAutoLaunchEvent(meshId, args) {
12528
12523
  const dedupKey = `${meshId}:${args.taskId}`;
12529
12524
  const currentSig = `${args.phase}|${args.reason || ""}`;
@@ -12709,6 +12704,10 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
12709
12704
  sweepExpiredCooldowns();
12710
12705
  continue;
12711
12706
  }
12707
+ if (nodeHasLiveSessionPendingClaim(components, meshId, nodeId)) {
12708
+ markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_has_live_session_pending_claim", nodeId });
12709
+ continue;
12710
+ }
12712
12711
  if (!isTaskReadonly(task) && nodeHasActiveAssignment(meshId, nodeId)) {
12713
12712
  markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_has_active_assignment", nodeId });
12714
12713
  continue;
@@ -16553,6 +16552,62 @@ function ackUnresolvedDelegateForwardByFingerprint(coordinatorDaemonId, eventNam
16553
16552
  );
16554
16553
  if (match) ackUnresolvedDelegateForward(match.id);
16555
16554
  }
16555
+ function flushPendingForMeshIdleCoordinators(components, meshId) {
16556
+ try {
16557
+ const store = MeshRuntimeStore.getInstance();
16558
+ if (store.pendingEventCount(meshId) === 0) return;
16559
+ } catch {
16560
+ }
16561
+ const idleCoordinators = [];
16562
+ try {
16563
+ for (const inst of components.instanceManager.getByCategory("cli")) {
16564
+ const state = inst.getState();
16565
+ const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
16566
+ if (readNonEmptyString2(settings.meshCoordinatorFor) !== meshId) continue;
16567
+ const status = readNonEmptyString2(state.status).toLowerCase();
16568
+ const modalParked = typeof inst.isModalParked === "function" ? inst.isModalParked() === true : status === "waiting_choice" || status === "waiting_approval";
16569
+ if (status === "idle" && !modalParked) {
16570
+ idleCoordinators.push({ instance: inst, sessionId: readNonEmptyString2(state.instanceId) });
16571
+ }
16572
+ }
16573
+ } catch {
16574
+ return;
16575
+ }
16576
+ if (idleCoordinators.length === 0) return;
16577
+ const drainDaemonIds = resolveCoordinatorDrainDaemonIds(components);
16578
+ let pendingEvents;
16579
+ try {
16580
+ pendingEvents = drainPendingMeshCoordinatorEvents(meshId, drainDaemonIds.length > 0 ? drainDaemonIds : void 0);
16581
+ } catch (e) {
16582
+ LOG.warn("MeshEvents", `Event-driven coordinator drain failed for mesh ${meshId}: ${e?.message || e}`);
16583
+ return;
16584
+ }
16585
+ if (pendingEvents.length === 0) return;
16586
+ let delivered = 0;
16587
+ for (const pending of pendingEvents) {
16588
+ const wantSession = readNonEmptyString2(pending.targetCoordinatorSessionId);
16589
+ const targets = wantSession ? idleCoordinators.filter((c) => c.sessionId === wantSession) : idleCoordinators;
16590
+ if (targets.length === 0 || !pending.coordinatorMessage) {
16591
+ try {
16592
+ queuePendingMeshCoordinatorEvent(pending);
16593
+ } catch {
16594
+ }
16595
+ continue;
16596
+ }
16597
+ const message = pending.coordinatorMessage;
16598
+ const force = shouldForceInjectMeshEvent(pending.event);
16599
+ for (const c of targets) {
16600
+ c.instance.onEvent("send_message", {
16601
+ input: { text: message, textFallback: message },
16602
+ ...force ? { force: true } : {}
16603
+ });
16604
+ delivered++;
16605
+ }
16606
+ }
16607
+ if (delivered > 0) {
16608
+ LOG.info("MeshEvents", `Event-driven drain delivered ${delivered} pending event(s) to ${idleCoordinators.length} idle coordinator(s) for mesh ${meshId}`);
16609
+ }
16610
+ }
16556
16611
  function setupMeshEventForwarding(components) {
16557
16612
  components.instanceManager.onEvent((event) => {
16558
16613
  if (event.event === "agent:ready" || event.event === "agent:generating_completed") {
@@ -16624,6 +16679,7 @@ function setupMeshEventForwarding(components) {
16624
16679
  event: event.event,
16625
16680
  metadataEvent: event
16626
16681
  });
16682
+ flushPendingForMeshIdleCoordinators(components, routing.meshId);
16627
16683
  });
16628
16684
  }
16629
16685
  var REMOTE_IDLE_SESSION_TTL_MS, meshByWorkspaceCache, MESH_WORKSPACE_CACHE_TTL_MS, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, RECENT_COMPLETION_FINGERPRINT_TTL_MS, RECONCILED_COMPLETION_SOURCES, coordinatorForwardLanes;
@@ -16744,7 +16800,7 @@ function findLiveCoordinators(components) {
16744
16800
  const meshId = readNonEmptyString2(settings.meshCoordinatorFor);
16745
16801
  if (!meshId) continue;
16746
16802
  const status = readNonEmptyString2(state.status).toLowerCase();
16747
- const modalParked = status === "waiting_choice" || status === "waiting_approval";
16803
+ const modalParked = typeof inst.isModalParked === "function" ? inst.isModalParked() === true : status === "waiting_choice" || status === "waiting_approval";
16748
16804
  const sessionId = readNonEmptyString2(state.instanceId);
16749
16805
  const stateKey = `${meshId}::${sessionId || "?"}`;
16750
16806
  const prevParked = coordinatorModalParkState.get(stateKey);
@@ -40637,10 +40693,27 @@ var CliProviderInstance = class _CliProviderInstance {
40637
40693
  return null;
40638
40694
  }
40639
40695
  if (adapterStatus.status === "waiting_approval" && (!this.autoApproveEffectivelyActive(adapterStatus.status) || this.autoApproveMaskStalled())) {
40696
+ if (this.isTransientToolConsent()) {
40697
+ return null;
40698
+ }
40640
40699
  return "waiting_approval";
40641
40700
  }
40642
40701
  return null;
40643
40702
  }
40703
+ /**
40704
+ * NOTIF-HELD-DRAIN: true when this `waiting_approval` is a routine, transient tool-consent
40705
+ * of an autonomously-progressing mesh session rather than a genuine human-await modal —
40706
+ * i.e. it is a mesh coordinator/worker session, a turn is actively in flight
40707
+ * (hasAdapterPendingResponse), and no human is attending it by hand. Such a consent is
40708
+ * driven to resolution by the harness/operator as part of the in-flight turn, so holding
40709
+ * the mesh's completion events behind it (modal_parked) is the false-positive that stalls
40710
+ * delivery. Narrow by design: manual attendance or a non-progressing session falls through
40711
+ * to the genuine-modal classification.
40712
+ */
40713
+ isTransientToolConsent(now = Date.now()) {
40714
+ const isAutonomousMeshSession = this.isMeshWorkerSession() || !!this.settings.meshCoordinatorFor;
40715
+ return isAutonomousMeshSession && this.hasAdapterPendingResponse() && !this.manualAttendance.isAttended(now);
40716
+ }
40644
40717
  /** True when this session is parked on a modal awaiting a human answer. */
40645
40718
  isModalParked() {
40646
40719
  return this.resolveModalParkStatus() !== null;
@@ -44521,8 +44594,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
44521
44594
  const meshContext = args?.meshContext;
44522
44595
  if (meshContext && typeof meshContext === "object" && typeof meshContext.meshId === "string" && meshContext.meshId) {
44523
44596
  const targetInstanceId = key2;
44597
+ let stampResult;
44524
44598
  try {
44525
- this.deps.getInstanceManager()?.attachMeshAssignmentToInstance(targetInstanceId, {
44599
+ stampResult = this.deps.getInstanceManager()?.attachMeshAssignmentToInstance(targetInstanceId, {
44526
44600
  meshId: meshContext.meshId,
44527
44601
  ...typeof meshContext.nodeId === "string" && meshContext.nodeId ? { nodeId: meshContext.nodeId } : {},
44528
44602
  ...typeof meshContext.taskId === "string" && meshContext.taskId ? { taskId: meshContext.taskId } : {},
@@ -44530,6 +44604,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
44530
44604
  });
44531
44605
  } catch {
44532
44606
  }
44607
+ if (stampResult && stampResult.stamped === false && stampResult.reason === "task_already_stamped_on_live_instance") {
44608
+ throw new Error(`Refusing duplicate mesh dispatch: task ${meshContext.taskId} is already being worked by a live session on this daemon`);
44609
+ }
44533
44610
  }
44534
44611
  const input = normalizeInputEnvelope(args?.input ? { input: args.input } : args);
44535
44612
  const provider = this.providerLoader.resolve(agentType) || this.providerLoader.getMeta(agentType);
@@ -58137,25 +58214,54 @@ var ProviderInstanceManager = class {
58137
58214
  }
58138
58215
  /** Stamp a mesh assignment on a single instance (used by mesh_send_task
58139
58216
  * --direct so the worker's completion event has a coordinator routing
58140
- * marker in state.settings). Returns true if the instance existed and
58141
- * the stamp was applied. */
58217
+ * marker in state.settings). Returns `{ stamped: true }` when the stamp was
58218
+ * applied, or `{ stamped: false, reason }` when it was refused — the instance
58219
+ * was missing / has no attach method, or the DOUBLE-DISPATCH idempotence guard
58220
+ * fired (the same task is already running on another live session here). */
58142
58221
  attachMeshAssignmentToInstance(instanceId, assignment) {
58143
58222
  const inst = this.instances.get(instanceId);
58144
58223
  if (!inst || typeof inst.attachMeshAssignment !== "function") {
58145
- try {
58146
- const { LOG: LOG2 } = (init_logger(), __toCommonJS(logger_exports));
58147
- LOG2.warn?.("MeshDispatch", `attachMeshAssignment skipped: instance ${instanceId} ${inst ? "has no attach method" : "not found"}`);
58148
- } catch {
58224
+ LOG.warn("MeshDispatch", `attachMeshAssignment skipped: instance ${instanceId} ${inst ? "has no attach method" : "not found"}`);
58225
+ return { stamped: false, reason: inst ? "instance_has_no_attach_method" : "instance_not_found" };
58226
+ }
58227
+ if (assignment.taskId) {
58228
+ const conflict = this.findLiveWorkingTaskHolder(assignment.meshId, assignment.taskId, instanceId);
58229
+ if (conflict) {
58230
+ LOG.warn("MeshDispatch", `attachMeshAssignment refused: task ${assignment.taskId} (mesh ${assignment.meshId}) is already being worked by live session ${conflict} \u2014 skipping duplicate stamp on ${instanceId}`);
58231
+ return { stamped: false, reason: "task_already_stamped_on_live_instance" };
58149
58232
  }
58150
- return false;
58151
58233
  }
58152
58234
  inst.attachMeshAssignment(assignment);
58153
- try {
58154
- const { LOG: LOG2 } = (init_logger(), __toCommonJS(logger_exports));
58155
- LOG2.info?.("MeshDispatch", `stamped mesh assignment on ${instanceId}: mesh=${assignment.meshId} node=${assignment.nodeId || ""} task=${assignment.taskId || ""} coordinator=${assignment.coordinatorDaemonId || ""}`);
58156
- } catch {
58235
+ LOG.info("MeshDispatch", `stamped mesh assignment on ${instanceId}: mesh=${assignment.meshId} node=${assignment.nodeId || ""} task=${assignment.taskId || ""} coordinator=${assignment.coordinatorDaemonId || ""}`);
58236
+ return { stamped: true };
58237
+ }
58238
+ /**
58239
+ * DOUBLE-DISPATCH support: the id of another LIVE, actively-working instance that already
58240
+ * holds (meshId, taskId), or null. "Live working" = stamped with this exact mesh+task AND
58241
+ * currently mid-turn / booting toward it (generating / waiting on approval-or-choice /
58242
+ * starting) — NOT idle, stopped, or errored. A stale/dead/idle holder is deliberately
58243
+ * ignored so a legitimate re-dispatch (e.g. after a dispatch failure) is never blocked.
58244
+ * The instance being stamped (excludeInstanceId) is skipped so re-stamping the same
58245
+ * session stays idempotent. O(n) over instances — the count is small.
58246
+ */
58247
+ findLiveWorkingTaskHolder(meshId, taskId, excludeInstanceId) {
58248
+ const working = /* @__PURE__ */ new Set(["generating", "waiting_approval", "waiting_choice", "starting", "streaming", "working", "no_progress", "long_generating"]);
58249
+ for (const [id, inst] of this.instances) {
58250
+ if (id === excludeInstanceId) continue;
58251
+ let state;
58252
+ try {
58253
+ state = inst.getState();
58254
+ } catch {
58255
+ continue;
58256
+ }
58257
+ const settings = state.settings || {};
58258
+ if (settings.meshNodeFor !== meshId) continue;
58259
+ if (settings.meshActiveTaskId !== taskId) continue;
58260
+ const status = (typeof state.status === "string" ? state.status : "").toLowerCase();
58261
+ const chatStatus = (typeof state.activeChat?.status === "string" ? state.activeChat.status : "").toLowerCase();
58262
+ if (working.has(status) || working.has(chatStatus)) return id;
58157
58263
  }
58158
- return true;
58264
+ return null;
58159
58265
  }
58160
58266
  /** Clear a mesh assignment after the dispatched task reaches a terminal
58161
58267
  * state (generating_completed / stopped / failed). */
@@ -64860,6 +64966,7 @@ export {
64860
64966
  isSetupComplete,
64861
64967
  isTaskReadonly,
64862
64968
  isUserFacingChatMessage,
64969
+ isWeakCompletionEvidence,
64863
64970
  killIdeProcess,
64864
64971
  launchIDE,
64865
64972
  launchWithCdp,