@adhdev/daemon-core 0.9.82-rc.384 → 0.9.82-rc.386

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.
@@ -26,6 +26,18 @@ export interface CliAdapterStatus {
26
26
  providerSessionId?: string;
27
27
  errorMessage?: string;
28
28
  errorReason?: string;
29
+ /**
30
+ * FSM-spec adapters only: true once the driver has observed its first
31
+ * non-initial idle state (the prompt is genuinely drawn — see
32
+ * FsmDriver.maybeMarkReady / readySeenOnce). Used by CliProviderInstance to
33
+ * re-arm the queue-claim `agent:ready` event on the first genuine ready,
34
+ * independent of the boot-time starting→idle one-shot. That one-shot is
35
+ * consumed too early for providers whose INITIAL FSM state already reports
36
+ * status 'idle' (e.g. antigravity-cli), so without this re-arm the worker
37
+ * never claims its queued task and the coordinator relaunch-loops. Absent
38
+ * (undefined) for non-FSM adapters — they keep the boot one-shot behavior.
39
+ */
40
+ fsmReadySeen?: boolean;
29
41
  }
30
42
  export interface AcpAdapterHandle {
31
43
  onEvent(event: string, data?: unknown): void;
@@ -58,6 +58,17 @@ export interface CliSessionStatus {
58
58
  errorMessage?: string;
59
59
  errorReason?: string;
60
60
  providerSessionId?: string;
61
+ /**
62
+ * Spec/FSM adapters only (SpecCliAdapter): true once the driver has observed
63
+ * its first non-initial idle state — the prompt is genuinely drawn. The
64
+ * legacy ProviderCliAdapter never sets it (undefined). CliProviderInstance
65
+ * uses it to re-arm the queue-claim agent:ready on the first genuine ready,
66
+ * independent of the boot-time starting→idle one-shot (which is consumed too
67
+ * early for specs whose initial state already reports status 'idle', e.g.
68
+ * antigravity-cli — without the re-arm the worker never claims its queued
69
+ * task and the coordinator relaunch-loops).
70
+ */
71
+ fsmReadySeen?: boolean;
61
72
  /**
62
73
  * Timestamp (ms) of the most recent raw PTY output chunk. Advances on every
63
74
  * byte the process emits, including tool/build output that produces no
package/dist/index.js CHANGED
@@ -383,10 +383,10 @@ function readInjected(value) {
383
383
  }
384
384
  function getDaemonBuildInfo() {
385
385
  if (cached) return cached;
386
- const commit = readInjected(true ? "6cca365bcea9757dd350c6bac460ca5a169a9280" : void 0) ?? "unknown";
387
- const commitShort = readInjected(true ? "6cca365b" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
388
- const version = readInjected(true ? "0.9.82-rc.384" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
389
- const builtAt = readInjected(true ? "2026-06-25T15:21:26.360Z" : void 0);
386
+ const commit = readInjected(true ? "fad1d175ca84a75f52bd0c1d88125fbb783ad241" : void 0) ?? "unknown";
387
+ const commitShort = readInjected(true ? "fad1d175" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
388
+ const version = readInjected(true ? "0.9.82-rc.386" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
389
+ const builtAt = readInjected(true ? "2026-06-26T00:12:44.100Z" : void 0);
390
390
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
391
391
  return cached;
392
392
  }
@@ -14972,6 +14972,32 @@ function findLiveCoordinators(components) {
14972
14972
  }
14973
14973
  return out;
14974
14974
  }
14975
+ function resolveCoordinatorDrainDeliverability(components, meshId) {
14976
+ const coordinators = findLiveCoordinators(components).filter((c) => c.meshId === meshId);
14977
+ if (coordinators.length === 0) {
14978
+ return { hasLiveCliCoordinator: false, deliverableNow: false, holdForReconcile: false };
14979
+ }
14980
+ const hasIdle = coordinators.some((c) => c.idle);
14981
+ return {
14982
+ hasLiveCliCoordinator: true,
14983
+ deliverableNow: hasIdle,
14984
+ // A live CLI coordinator exists but none is idle → the reconcile loop is
14985
+ // holding the events; the poll must not steal them.
14986
+ holdForReconcile: !hasIdle
14987
+ };
14988
+ }
14989
+ function shouldHoldPendingDrainForBusyLocalCoordinator(components, meshId, requestedCoordinatorDaemonId) {
14990
+ if (!meshId) return false;
14991
+ const deliverability = resolveCoordinatorDrainDeliverability(components, meshId);
14992
+ if (!deliverability.holdForReconcile) return false;
14993
+ const requested = readNonEmptyString2(requestedCoordinatorDaemonId);
14994
+ if (!requested) return true;
14995
+ const localIds = expandDaemonIdForms([
14996
+ readNonEmptyString2(components.statusInstanceId),
14997
+ readNonEmptyString2(loadConfig().machineId)
14998
+ ]);
14999
+ return localIds.some((id) => daemonIdsEquivalent(id, requested));
15000
+ }
14975
15001
  function injectPendingIntoCoordinator(coordinator, pending) {
14976
15002
  if (!coordinator || !pending.coordinatorMessage) return;
14977
15003
  const force = shouldForceInjectMeshEvent(pending.event);
@@ -15688,9 +15714,11 @@ __export(mesh_events_exports, {
15688
15714
  isMeshCoordinatorEvent: () => isMeshCoordinatorEvent,
15689
15715
  queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
15690
15716
  reconcileDirectDispatchCompletionFromTranscript: () => reconcileDirectDispatchCompletionFromTranscript,
15717
+ resolveCoordinatorDrainDeliverability: () => resolveCoordinatorDrainDeliverability,
15691
15718
  runMeshReconcileTick: () => runMeshReconcileTick,
15692
15719
  setupMeshEventForwarding: () => setupMeshEventForwarding,
15693
15720
  setupMeshReconcileLoop: () => setupMeshReconcileLoop,
15721
+ shouldHoldPendingDrainForBusyLocalCoordinator: () => shouldHoldPendingDrainForBusyLocalCoordinator,
15694
15722
  triggerMeshQueue: () => triggerMeshQueue,
15695
15723
  tryAssignQueueTask: () => tryAssignQueueTask
15696
15724
  });
@@ -36186,6 +36214,17 @@ var FsmDriver = class {
36186
36214
  hasIdleHoldPending() {
36187
36215
  return (this.lastFsmEval?.transitions ?? []).some((t) => !t.holdSatisfied && t.condResult);
36188
36216
  }
36217
+ /**
36218
+ * True once the machine has reached its first non-initial idle state (the
36219
+ * prompt is genuinely drawn — see maybeMarkReady). The cli-adapter surfaces
36220
+ * this on its idle status so CliProviderInstance can re-arm the queue-claim
36221
+ * agent:ready on the first genuine ready, independent of the boot-time
36222
+ * starting→idle one-shot (which is consumed too early for specs whose
36223
+ * initial state already reports idle).
36224
+ */
36225
+ hasSeenReady() {
36226
+ return this.readySeenOnce;
36227
+ }
36189
36228
  getCompletionIdleDebounceState() {
36190
36229
  const out = outgoingTransitions(this.spec, this.currentStateId);
36191
36230
  const toReady = this.lastFsmEval?.transitions.find((t, i) => {
@@ -37852,7 +37891,7 @@ var SpecCliAdapter = class _SpecCliAdapter {
37852
37891
  if (state.status === "generating") {
37853
37892
  return { status: "generating", messages: [], activeModal: null, activeInteractivePrompt: this.activeInteractivePrompt, ...sessionFields };
37854
37893
  }
37855
- return { status: "idle", messages: [], activeModal: null, activeInteractivePrompt: this.activeInteractivePrompt, ...sessionFields };
37894
+ return { status: "idle", messages: [], activeModal: null, activeInteractivePrompt: this.activeInteractivePrompt, fsmReadySeen: this.driver.hasSeenReady?.() ?? false, ...sessionFields };
37856
37895
  }
37857
37896
  maybeRefreshNativeHistory() {
37858
37897
  }
@@ -38897,6 +38936,14 @@ var CliProviderInstance = class _CliProviderInstance {
38897
38936
  context = null;
38898
38937
  events = [];
38899
38938
  lastStatus = "starting";
38939
+ // Idempotency guard for the queue-claim agent:ready event. agent:ready is the
38940
+ // sole signal the mesh coordinator's tryAssignQueueTask waits on to hand a
38941
+ // queued task to this worker. It is emitted in two places: the boot-time
38942
+ // starting→idle one-shot, and the readySeen re-arm below. This flag makes the
38943
+ // event fire AT MOST ONCE per session so a worker is never claimed twice and a
38944
+ // queued task is never double-dispatched/double-injected. Whichever path fires
38945
+ // first sets it; the other becomes a no-op.
38946
+ agentReadyEmitted = false;
38900
38947
  generatingStartedAt = 0;
38901
38948
  settings = {};
38902
38949
  monitor;
@@ -39977,6 +40024,17 @@ var CliProviderInstance = class _CliProviderInstance {
39977
40024
  } catch {
39978
40025
  }
39979
40026
  }
40027
+ /**
40028
+ * Emit the queue-claim agent:ready event at most once per session. Both the
40029
+ * boot-time starting→idle one-shot and the fsmReadySeen re-arm call this; the
40030
+ * agentReadyEmitted guard ensures the second caller is a no-op so a worker is
40031
+ * never claimed twice and a queued task is never double-dispatched.
40032
+ */
40033
+ emitAgentReadyOnce(chatTitle, now) {
40034
+ if (this.agentReadyEmitted) return;
40035
+ this.agentReadyEmitted = true;
40036
+ this.pushEvent({ event: "agent:ready", chatTitle, timestamp: now });
40037
+ }
39980
40038
  detectStatusTransition() {
39981
40039
  const now = Date.now();
39982
40040
  const adapterStatus = this.adapter.getStatus({ allowParse: false });
@@ -40129,7 +40187,7 @@ var CliProviderInstance = class _CliProviderInstance {
40129
40187
  this.scheduleCompletedDebounceFlush(flushDelay);
40130
40188
  }
40131
40189
  } else if (newStatus === "idle" && this.lastStatus === "starting") {
40132
- this.pushEvent({ event: "agent:ready", chatTitle, timestamp: now });
40190
+ this.emitAgentReadyOnce(chatTitle, now);
40133
40191
  } else if (newStatus === "error") {
40134
40192
  if (this.generatingDebounceTimer) {
40135
40193
  clearTimeout(this.generatingDebounceTimer);
@@ -40168,6 +40226,9 @@ var CliProviderInstance = class _CliProviderInstance {
40168
40226
  }
40169
40227
  this.lastStatus = newStatus;
40170
40228
  }
40229
+ if (newStatus === "idle" && adapterStatus.fsmReadySeen === true && !this.agentReadyEmitted) {
40230
+ this.emitAgentReadyOnce(chatTitle, now);
40231
+ }
40171
40232
  this.applyProviderResponse(parsedStatus, {
40172
40233
  phase: newStatus === "idle" && (previousStatus === "generating" || previousStatus === "waiting_approval") ? "turn_completed" : "immediate"
40173
40234
  });
@@ -48514,9 +48575,12 @@ var meshEventsHandlers = {
48514
48575
  mesh_forward_event: async (ctx, args) => {
48515
48576
  return handleMeshForwardEvent({ instanceManager: ctx.deps.instanceManager }, args);
48516
48577
  },
48517
- get_pending_mesh_events: async (_ctx, args) => {
48578
+ get_pending_mesh_events: async (ctx, args) => {
48518
48579
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
48519
48580
  const coordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : void 0;
48581
+ if (meshId && shouldHoldPendingDrainForBusyLocalCoordinator(ctx.deps, meshId, coordinatorDaemonId)) {
48582
+ return { success: true, events: [], heldForBusyLocalCoordinator: true };
48583
+ }
48520
48584
  const events = drainPendingMeshCoordinatorEvents(meshId || void 0, coordinatorDaemonId);
48521
48585
  return { success: true, events };
48522
48586
  },