@adhdev/daemon-core 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 +100 -15
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +100 -15
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-events-coordinator.d.ts +1 -0
- package/dist/mesh/mesh-events-pending.d.ts +14 -2
- package/dist/mesh/mesh-runtime-store.d.ts +13 -1
- package/package.json +2 -2
- package/src/mesh/mesh-events-coordinator.ts +1 -1
- package/src/mesh/mesh-events-pending.ts +84 -6
- package/src/mesh/mesh-reconcile-loop.ts +34 -14
- package/src/mesh/mesh-runtime-store.ts +33 -8
package/dist/index.js
CHANGED
|
@@ -275,10 +275,10 @@ function readInjected(value) {
|
|
|
275
275
|
}
|
|
276
276
|
function getDaemonBuildInfo() {
|
|
277
277
|
if (cached) return cached;
|
|
278
|
-
const commit = readInjected(true ? "
|
|
279
|
-
const commitShort = readInjected(true ? "
|
|
280
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
281
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
278
|
+
const commit = readInjected(true ? "080b607ef221e44126942d9d52eaf547b4e92550" : void 0) ?? "unknown";
|
|
279
|
+
const commitShort = readInjected(true ? "080b607e" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
280
|
+
const version = readInjected(true ? "0.9.82-rc.275" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
281
|
+
const builtAt = readInjected(true ? "2026-06-15T08:24:26.468Z" : void 0);
|
|
282
282
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
283
283
|
return cached;
|
|
284
284
|
}
|
|
@@ -4264,12 +4264,33 @@ var init_mesh_runtime_store = __esm({
|
|
|
4264
4264
|
this.maybeCheckpointWal();
|
|
4265
4265
|
return result.changes > 0;
|
|
4266
4266
|
}
|
|
4267
|
-
|
|
4267
|
+
/**
|
|
4268
|
+
* Drain undrained pending events for a mesh, atomically marking them drained.
|
|
4269
|
+
* When `opts.onlyEvents` is supplied, ONLY rows whose `event` is in that set are
|
|
4270
|
+
* drained — the rest stay queued (drained=0) for a later drain. This is how the
|
|
4271
|
+
* reconcile loop force-drains terminal/force-inject events into a *generating*
|
|
4272
|
+
* coordinator while leaving non-force progress events for the coordinator's next
|
|
4273
|
+
* idle transition. Filtering happens inside the same transaction as the
|
|
4274
|
+
* drained=1 marking, so force-drain + a concurrent full drain can never both
|
|
4275
|
+
* consume the same row.
|
|
4276
|
+
*/
|
|
4277
|
+
drainPendingEvents(meshId, coordinatorDaemonId, opts) {
|
|
4268
4278
|
return this.transaction(() => {
|
|
4269
|
-
const
|
|
4270
|
-
|
|
4279
|
+
const onlyEvents = opts?.onlyEvents;
|
|
4280
|
+
if (onlyEvents && onlyEvents.size === 0) return [];
|
|
4281
|
+
const eventList = onlyEvents ? [...onlyEvents] : [];
|
|
4282
|
+
const clauses = ["mesh_id = ?", "drained = 0"];
|
|
4283
|
+
const params = [meshId];
|
|
4284
|
+
if (coordinatorDaemonId) {
|
|
4285
|
+
clauses.push("(coordinator_daemon_id IS NULL OR coordinator_daemon_id = ?)");
|
|
4286
|
+
params.push(coordinatorDaemonId);
|
|
4287
|
+
}
|
|
4288
|
+
if (eventList.length > 0) {
|
|
4289
|
+
clauses.push(`event IN (${eventList.map(() => "?").join(",")})`);
|
|
4290
|
+
params.push(...eventList);
|
|
4291
|
+
}
|
|
4271
4292
|
const rows = this.db.prepare(
|
|
4272
|
-
`SELECT id, event, payload FROM mesh_pending_events ${
|
|
4293
|
+
`SELECT id, event, payload FROM mesh_pending_events WHERE ${clauses.join(" AND ")} ORDER BY queued_at ASC LIMIT 100`
|
|
4273
4294
|
).all(...params);
|
|
4274
4295
|
if (rows.length === 0) return [];
|
|
4275
4296
|
const ids = rows.map((r) => r.id);
|
|
@@ -6529,8 +6550,57 @@ function atomicDrainFile(path39) {
|
|
|
6529
6550
|
return null;
|
|
6530
6551
|
}
|
|
6531
6552
|
}
|
|
6532
|
-
function
|
|
6553
|
+
function selectiveDrainFile(path39, predicate) {
|
|
6554
|
+
const tmpPath = `${path39}.draining`;
|
|
6555
|
+
try {
|
|
6556
|
+
(0, import_fs8.renameSync)(path39, tmpPath);
|
|
6557
|
+
} catch {
|
|
6558
|
+
return [];
|
|
6559
|
+
}
|
|
6560
|
+
let content;
|
|
6561
|
+
try {
|
|
6562
|
+
content = (0, import_fs8.readFileSync)(tmpPath, "utf-8");
|
|
6563
|
+
} catch {
|
|
6564
|
+
try {
|
|
6565
|
+
(0, import_fs8.unlinkSync)(tmpPath);
|
|
6566
|
+
} catch {
|
|
6567
|
+
}
|
|
6568
|
+
return [];
|
|
6569
|
+
}
|
|
6570
|
+
const consumed = [];
|
|
6571
|
+
const keptLines = [];
|
|
6572
|
+
for (const line of content.split("\n")) {
|
|
6573
|
+
if (!line) continue;
|
|
6574
|
+
let parsed;
|
|
6575
|
+
try {
|
|
6576
|
+
parsed = JSON.parse(line);
|
|
6577
|
+
} catch {
|
|
6578
|
+
parsed = void 0;
|
|
6579
|
+
}
|
|
6580
|
+
if (parsed && predicate(parsed)) {
|
|
6581
|
+
consumed.push(parsed);
|
|
6582
|
+
} else {
|
|
6583
|
+
keptLines.push(line);
|
|
6584
|
+
}
|
|
6585
|
+
}
|
|
6586
|
+
try {
|
|
6587
|
+
if (keptLines.length > 0) {
|
|
6588
|
+
(0, import_fs8.writeFileSync)(path39, keptLines.join("\n") + "\n", "utf-8");
|
|
6589
|
+
}
|
|
6590
|
+
(0, import_fs8.unlinkSync)(tmpPath);
|
|
6591
|
+
} catch {
|
|
6592
|
+
try {
|
|
6593
|
+
if ((0, import_fs8.existsSync)(tmpPath) && !(0, import_fs8.existsSync)(path39)) (0, import_fs8.renameSync)(tmpPath, path39);
|
|
6594
|
+
} catch {
|
|
6595
|
+
}
|
|
6596
|
+
return [];
|
|
6597
|
+
}
|
|
6598
|
+
return consumed;
|
|
6599
|
+
}
|
|
6600
|
+
function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId, opts) {
|
|
6533
6601
|
if (!meshId) return [];
|
|
6602
|
+
const onlyEvents = opts?.onlyEvents;
|
|
6603
|
+
const matchesFilter = (eventName) => !onlyEvents || onlyEvents.has(eventName);
|
|
6534
6604
|
const merged = [];
|
|
6535
6605
|
const seenFingerprints = /* @__PURE__ */ new Set();
|
|
6536
6606
|
const pushUnique = (event) => {
|
|
@@ -6544,7 +6614,7 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
|
6544
6614
|
try {
|
|
6545
6615
|
const store = MeshRuntimeStore.getInstance();
|
|
6546
6616
|
if (store.pendingEventCount(meshId) > 0) {
|
|
6547
|
-
for (const row of store.drainPendingEvents(meshId, coordinatorDaemonId)) {
|
|
6617
|
+
for (const row of store.drainPendingEvents(meshId, coordinatorDaemonId, onlyEvents ? { onlyEvents } : void 0)) {
|
|
6548
6618
|
const event = row.payload;
|
|
6549
6619
|
if (event) pushUnique(event);
|
|
6550
6620
|
}
|
|
@@ -6553,6 +6623,14 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
|
6553
6623
|
}
|
|
6554
6624
|
const paths = coordinatorDaemonId ? [getPendingEventsPath(meshId, coordinatorDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
|
|
6555
6625
|
for (const path39 of paths) {
|
|
6626
|
+
const isSharedFile = coordinatorDaemonId && path39 === getPendingEventsPath(meshId);
|
|
6627
|
+
const targets = (e) => !isSharedFile || !e.targetCoordinatorDaemonId || e.targetCoordinatorDaemonId === coordinatorDaemonId;
|
|
6628
|
+
if (onlyEvents) {
|
|
6629
|
+
for (const event of selectiveDrainFile(path39, (e) => targets(e) && matchesFilter(e.event))) {
|
|
6630
|
+
pushUnique(event);
|
|
6631
|
+
}
|
|
6632
|
+
continue;
|
|
6633
|
+
}
|
|
6556
6634
|
const content = atomicDrainFile(path39);
|
|
6557
6635
|
if (!content) continue;
|
|
6558
6636
|
const parsed = content.split("\n").filter(Boolean).flatMap((line) => {
|
|
@@ -6562,7 +6640,7 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
|
6562
6640
|
return [];
|
|
6563
6641
|
}
|
|
6564
6642
|
});
|
|
6565
|
-
const filtered =
|
|
6643
|
+
const filtered = isSharedFile ? parsed.filter(targets) : parsed;
|
|
6566
6644
|
for (const event of filtered) pushUnique(event);
|
|
6567
6645
|
}
|
|
6568
6646
|
if (merged.length === 0) return [];
|
|
@@ -8582,7 +8660,9 @@ async function runMeshReconcileTick(components) {
|
|
|
8582
8660
|
}
|
|
8583
8661
|
}
|
|
8584
8662
|
const idleCoordinators = meshCoordinators.filter((c) => c.idle);
|
|
8585
|
-
|
|
8663
|
+
const generatingCoordinators = meshCoordinators.filter((c) => !c.idle);
|
|
8664
|
+
const targetCoordinators = idleCoordinators.length > 0 ? idleCoordinators : generatingCoordinators;
|
|
8665
|
+
const forceOnly = idleCoordinators.length === 0;
|
|
8586
8666
|
if (store) {
|
|
8587
8667
|
try {
|
|
8588
8668
|
if (store.pendingEventCount(meshId) === 0) continue;
|
|
@@ -8591,15 +8671,20 @@ async function runMeshReconcileTick(components) {
|
|
|
8591
8671
|
}
|
|
8592
8672
|
let pendingEvents = [];
|
|
8593
8673
|
try {
|
|
8594
|
-
pendingEvents = drainPendingMeshCoordinatorEvents(
|
|
8674
|
+
pendingEvents = drainPendingMeshCoordinatorEvents(
|
|
8675
|
+
meshId,
|
|
8676
|
+
localDaemonId,
|
|
8677
|
+
forceOnly ? { onlyEvents: MESH_FORCE_INJECT_EVENTS } : void 0
|
|
8678
|
+
);
|
|
8595
8679
|
} catch (e) {
|
|
8596
8680
|
LOG.warn("MeshReconcile", `Drain failed for mesh ${meshId}: ${e?.message || e}`);
|
|
8597
8681
|
continue;
|
|
8598
8682
|
}
|
|
8599
8683
|
if (pendingEvents.length === 0) continue;
|
|
8600
|
-
|
|
8684
|
+
const mode = forceOnly ? "force-drain \u2192 generating" : "inject \u2192 idle";
|
|
8685
|
+
LOG.info("MeshReconcile", `Reconcile ${mode}: ${pendingEvents.length} pending event(s) \u2192 ${targetCoordinators.length} coordinator(s) for mesh ${meshId}`);
|
|
8601
8686
|
for (const pending of pendingEvents) {
|
|
8602
|
-
for (const c of
|
|
8687
|
+
for (const c of targetCoordinators) {
|
|
8603
8688
|
injectPendingIntoCoordinator(c.instance, pending);
|
|
8604
8689
|
}
|
|
8605
8690
|
}
|