@adhdev/daemon-standalone 0.9.82-rc.274 → 0.9.82-rc.275

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
@@ -29983,10 +29983,10 @@ var require_dist3 = __commonJS({
29983
29983
  }
29984
29984
  function getDaemonBuildInfo() {
29985
29985
  if (cached2) return cached2;
29986
- const commit = readInjected(true ? "89d1ac61612c1dfe7fac53be61ec5dbfa67d00b2" : void 0) ?? "unknown";
29987
- const commitShort = readInjected(true ? "89d1ac61" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
29988
- const version2 = readInjected(true ? "0.9.82-rc.274" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
29989
- const builtAt = readInjected(true ? "2026-06-15T07:05:20.920Z" : void 0);
29986
+ const commit = readInjected(true ? "080b607ef221e44126942d9d52eaf547b4e92550" : void 0) ?? "unknown";
29987
+ const commitShort = readInjected(true ? "080b607e" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
29988
+ const version2 = readInjected(true ? "0.9.82-rc.275" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
29989
+ const builtAt = readInjected(true ? "2026-06-15T08:25:07.224Z" : void 0);
29990
29990
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
29991
29991
  return cached2;
29992
29992
  }
@@ -34007,12 +34007,33 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
34007
34007
  this.maybeCheckpointWal();
34008
34008
  return result.changes > 0;
34009
34009
  }
34010
- drainPendingEvents(meshId, coordinatorDaemonId) {
34010
+ /**
34011
+ * Drain undrained pending events for a mesh, atomically marking them drained.
34012
+ * When `opts.onlyEvents` is supplied, ONLY rows whose `event` is in that set are
34013
+ * drained — the rest stay queued (drained=0) for a later drain. This is how the
34014
+ * reconcile loop force-drains terminal/force-inject events into a *generating*
34015
+ * coordinator while leaving non-force progress events for the coordinator's next
34016
+ * idle transition. Filtering happens inside the same transaction as the
34017
+ * drained=1 marking, so force-drain + a concurrent full drain can never both
34018
+ * consume the same row.
34019
+ */
34020
+ drainPendingEvents(meshId, coordinatorDaemonId, opts) {
34011
34021
  return this.transaction(() => {
34012
- const whereClause = coordinatorDaemonId ? `WHERE mesh_id = ? AND drained = 0 AND (coordinator_daemon_id IS NULL OR coordinator_daemon_id = ?)` : `WHERE mesh_id = ? AND drained = 0`;
34013
- const params = coordinatorDaemonId ? [meshId, coordinatorDaemonId] : [meshId];
34022
+ const onlyEvents = opts?.onlyEvents;
34023
+ if (onlyEvents && onlyEvents.size === 0) return [];
34024
+ const eventList = onlyEvents ? [...onlyEvents] : [];
34025
+ const clauses = ["mesh_id = ?", "drained = 0"];
34026
+ const params = [meshId];
34027
+ if (coordinatorDaemonId) {
34028
+ clauses.push("(coordinator_daemon_id IS NULL OR coordinator_daemon_id = ?)");
34029
+ params.push(coordinatorDaemonId);
34030
+ }
34031
+ if (eventList.length > 0) {
34032
+ clauses.push(`event IN (${eventList.map(() => "?").join(",")})`);
34033
+ params.push(...eventList);
34034
+ }
34014
34035
  const rows = this.db.prepare(
34015
- `SELECT id, event, payload FROM mesh_pending_events ${whereClause} ORDER BY queued_at ASC LIMIT 100`
34036
+ `SELECT id, event, payload FROM mesh_pending_events WHERE ${clauses.join(" AND ")} ORDER BY queued_at ASC LIMIT 100`
34016
34037
  ).all(...params);
34017
34038
  if (rows.length === 0) return [];
34018
34039
  const ids = rows.map((r) => r.id);
@@ -36286,8 +36307,57 @@ Next step: ${nextStep}`;
36286
36307
  return null;
36287
36308
  }
36288
36309
  }
36289
- function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
36310
+ function selectiveDrainFile(path39, predicate) {
36311
+ const tmpPath = `${path39}.draining`;
36312
+ try {
36313
+ (0, import_fs8.renameSync)(path39, tmpPath);
36314
+ } catch {
36315
+ return [];
36316
+ }
36317
+ let content;
36318
+ try {
36319
+ content = (0, import_fs8.readFileSync)(tmpPath, "utf-8");
36320
+ } catch {
36321
+ try {
36322
+ (0, import_fs8.unlinkSync)(tmpPath);
36323
+ } catch {
36324
+ }
36325
+ return [];
36326
+ }
36327
+ const consumed = [];
36328
+ const keptLines = [];
36329
+ for (const line of content.split("\n")) {
36330
+ if (!line) continue;
36331
+ let parsed;
36332
+ try {
36333
+ parsed = JSON.parse(line);
36334
+ } catch {
36335
+ parsed = void 0;
36336
+ }
36337
+ if (parsed && predicate(parsed)) {
36338
+ consumed.push(parsed);
36339
+ } else {
36340
+ keptLines.push(line);
36341
+ }
36342
+ }
36343
+ try {
36344
+ if (keptLines.length > 0) {
36345
+ (0, import_fs8.writeFileSync)(path39, keptLines.join("\n") + "\n", "utf-8");
36346
+ }
36347
+ (0, import_fs8.unlinkSync)(tmpPath);
36348
+ } catch {
36349
+ try {
36350
+ if ((0, import_fs8.existsSync)(tmpPath) && !(0, import_fs8.existsSync)(path39)) (0, import_fs8.renameSync)(tmpPath, path39);
36351
+ } catch {
36352
+ }
36353
+ return [];
36354
+ }
36355
+ return consumed;
36356
+ }
36357
+ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId, opts) {
36290
36358
  if (!meshId) return [];
36359
+ const onlyEvents = opts?.onlyEvents;
36360
+ const matchesFilter = (eventName) => !onlyEvents || onlyEvents.has(eventName);
36291
36361
  const merged = [];
36292
36362
  const seenFingerprints = /* @__PURE__ */ new Set();
36293
36363
  const pushUnique = (event) => {
@@ -36301,7 +36371,7 @@ Next step: ${nextStep}`;
36301
36371
  try {
36302
36372
  const store = MeshRuntimeStore.getInstance();
36303
36373
  if (store.pendingEventCount(meshId) > 0) {
36304
- for (const row of store.drainPendingEvents(meshId, coordinatorDaemonId)) {
36374
+ for (const row of store.drainPendingEvents(meshId, coordinatorDaemonId, onlyEvents ? { onlyEvents } : void 0)) {
36305
36375
  const event = row.payload;
36306
36376
  if (event) pushUnique(event);
36307
36377
  }
@@ -36310,6 +36380,14 @@ Next step: ${nextStep}`;
36310
36380
  }
36311
36381
  const paths = coordinatorDaemonId ? [getPendingEventsPath(meshId, coordinatorDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
36312
36382
  for (const path39 of paths) {
36383
+ const isSharedFile = coordinatorDaemonId && path39 === getPendingEventsPath(meshId);
36384
+ const targets = (e) => !isSharedFile || !e.targetCoordinatorDaemonId || e.targetCoordinatorDaemonId === coordinatorDaemonId;
36385
+ if (onlyEvents) {
36386
+ for (const event of selectiveDrainFile(path39, (e) => targets(e) && matchesFilter(e.event))) {
36387
+ pushUnique(event);
36388
+ }
36389
+ continue;
36390
+ }
36313
36391
  const content = atomicDrainFile(path39);
36314
36392
  if (!content) continue;
36315
36393
  const parsed = content.split("\n").filter(Boolean).flatMap((line) => {
@@ -36319,7 +36397,7 @@ Next step: ${nextStep}`;
36319
36397
  return [];
36320
36398
  }
36321
36399
  });
36322
- const filtered = coordinatorDaemonId && path39 === getPendingEventsPath(meshId) ? parsed.filter((e) => !e.targetCoordinatorDaemonId || e.targetCoordinatorDaemonId === coordinatorDaemonId) : parsed;
36400
+ const filtered = isSharedFile ? parsed.filter(targets) : parsed;
36323
36401
  for (const event of filtered) pushUnique(event);
36324
36402
  }
36325
36403
  if (merged.length === 0) return [];
@@ -38353,7 +38431,9 @@ Next step: ${nextStep}`;
38353
38431
  }
38354
38432
  }
38355
38433
  const idleCoordinators = meshCoordinators.filter((c) => c.idle);
38356
- if (idleCoordinators.length === 0) continue;
38434
+ const generatingCoordinators = meshCoordinators.filter((c) => !c.idle);
38435
+ const targetCoordinators = idleCoordinators.length > 0 ? idleCoordinators : generatingCoordinators;
38436
+ const forceOnly = idleCoordinators.length === 0;
38357
38437
  if (store) {
38358
38438
  try {
38359
38439
  if (store.pendingEventCount(meshId) === 0) continue;
@@ -38362,15 +38442,20 @@ Next step: ${nextStep}`;
38362
38442
  }
38363
38443
  let pendingEvents = [];
38364
38444
  try {
38365
- pendingEvents = drainPendingMeshCoordinatorEvents(meshId, localDaemonId);
38445
+ pendingEvents = drainPendingMeshCoordinatorEvents(
38446
+ meshId,
38447
+ localDaemonId,
38448
+ forceOnly ? { onlyEvents: MESH_FORCE_INJECT_EVENTS } : void 0
38449
+ );
38366
38450
  } catch (e) {
38367
38451
  LOG2.warn("MeshReconcile", `Drain failed for mesh ${meshId}: ${e?.message || e}`);
38368
38452
  continue;
38369
38453
  }
38370
38454
  if (pendingEvents.length === 0) continue;
38371
- LOG2.info("MeshReconcile", `Reconcile inject: ${pendingEvents.length} pending event(s) \u2192 ${idleCoordinators.length} idle coordinator(s) for mesh ${meshId}`);
38455
+ const mode = forceOnly ? "force-drain \u2192 generating" : "inject \u2192 idle";
38456
+ LOG2.info("MeshReconcile", `Reconcile ${mode}: ${pendingEvents.length} pending event(s) \u2192 ${targetCoordinators.length} coordinator(s) for mesh ${meshId}`);
38372
38457
  for (const pending of pendingEvents) {
38373
- for (const c of idleCoordinators) {
38458
+ for (const c of targetCoordinators) {
38374
38459
  injectPendingIntoCoordinator(c.instance, pending);
38375
38460
  }
38376
38461
  }