@adhdev/daemon-core 0.9.82-rc.274 → 0.9.82-rc.276
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/boot/daemon-lifecycle.d.ts +1 -0
- package/dist/index.js +148 -25
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +148 -25
- 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 +15 -3
- package/dist/mesh/mesh-runtime-store.d.ts +14 -2
- package/package.json +2 -2
- package/src/boot/daemon-lifecycle.ts +9 -0
- package/src/mesh/mesh-events-coordinator.ts +21 -3
- package/src/mesh/mesh-events-pending.ts +128 -17
- package/src/mesh/mesh-reconcile-loop.ts +56 -14
- package/src/mesh/mesh-runtime-store.ts +50 -12
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 ? "746fc68e4c297b988b76207bb8c63ab6062a38e1" : void 0) ?? "unknown";
|
|
279
|
+
const commitShort = readInjected(true ? "746fc68e" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
280
|
+
const version = readInjected(true ? "0.9.82-rc.276" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
281
|
+
const builtAt = readInjected(true ? "2026-06-15T09:29:09.895Z" : void 0);
|
|
282
282
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
283
283
|
return cached;
|
|
284
284
|
}
|
|
@@ -4264,12 +4264,34 @@ 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 daemonIds = (Array.isArray(coordinatorDaemonId) ? coordinatorDaemonId : coordinatorDaemonId ? [coordinatorDaemonId] : []).filter((id) => typeof id === "string" && id.length > 0);
|
|
4283
|
+
const clauses = ["mesh_id = ?", "drained = 0"];
|
|
4284
|
+
const params = [meshId];
|
|
4285
|
+
if (daemonIds.length > 0) {
|
|
4286
|
+
clauses.push(`(coordinator_daemon_id IS NULL OR coordinator_daemon_id IN (${daemonIds.map(() => "?").join(",")}))`);
|
|
4287
|
+
params.push(...daemonIds);
|
|
4288
|
+
}
|
|
4289
|
+
if (eventList.length > 0) {
|
|
4290
|
+
clauses.push(`event IN (${eventList.map(() => "?").join(",")})`);
|
|
4291
|
+
params.push(...eventList);
|
|
4292
|
+
}
|
|
4271
4293
|
const rows = this.db.prepare(
|
|
4272
|
-
`SELECT id, event, payload FROM mesh_pending_events ${
|
|
4294
|
+
`SELECT id, event, payload FROM mesh_pending_events WHERE ${clauses.join(" AND ")} ORDER BY queued_at ASC LIMIT 100`
|
|
4273
4295
|
).all(...params);
|
|
4274
4296
|
if (rows.length === 0) return [];
|
|
4275
4297
|
const ids = rows.map((r) => r.id);
|
|
@@ -4292,8 +4314,9 @@ var init_mesh_runtime_store = __esm({
|
|
|
4292
4314
|
}
|
|
4293
4315
|
/** Non-destructive peek — returns undrained events without marking them drained. */
|
|
4294
4316
|
peekPendingEvents(meshId, coordinatorDaemonId) {
|
|
4295
|
-
const
|
|
4296
|
-
const
|
|
4317
|
+
const daemonIds = (Array.isArray(coordinatorDaemonId) ? coordinatorDaemonId : coordinatorDaemonId ? [coordinatorDaemonId] : []).filter((id) => typeof id === "string" && id.length > 0);
|
|
4318
|
+
const whereClause = daemonIds.length > 0 ? `WHERE mesh_id = ? AND drained = 0 AND (coordinator_daemon_id IS NULL OR coordinator_daemon_id IN (${daemonIds.map(() => "?").join(",")}))` : `WHERE mesh_id = ? AND drained = 0`;
|
|
4319
|
+
const params = daemonIds.length > 0 ? [meshId, ...daemonIds] : [meshId];
|
|
4297
4320
|
const rows = this.db.prepare(
|
|
4298
4321
|
`SELECT id, event, payload FROM mesh_pending_events ${whereClause} ORDER BY queued_at ASC LIMIT 100`
|
|
4299
4322
|
).all(...params);
|
|
@@ -6333,6 +6356,19 @@ var init_mesh_events_utils = __esm({
|
|
|
6333
6356
|
});
|
|
6334
6357
|
|
|
6335
6358
|
// src/mesh/mesh-events-pending.ts
|
|
6359
|
+
function normalizeCoordinatorDaemonIds(coordinatorDaemonId) {
|
|
6360
|
+
const raw = Array.isArray(coordinatorDaemonId) ? coordinatorDaemonId : coordinatorDaemonId != null ? [coordinatorDaemonId] : [];
|
|
6361
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6362
|
+
const out = [];
|
|
6363
|
+
for (const id of raw) {
|
|
6364
|
+
if (typeof id !== "string") continue;
|
|
6365
|
+
const trimmed = id.trim();
|
|
6366
|
+
if (!trimmed || seen.has(trimmed)) continue;
|
|
6367
|
+
seen.add(trimmed);
|
|
6368
|
+
out.push(trimmed);
|
|
6369
|
+
}
|
|
6370
|
+
return out;
|
|
6371
|
+
}
|
|
6336
6372
|
function readRefineJobId2(event) {
|
|
6337
6373
|
const metadata = readRecord3(event.metadataEvent) || event;
|
|
6338
6374
|
const result = readRecord3(metadata.result);
|
|
@@ -6387,7 +6423,9 @@ function getPendingEventsPath(meshId, coordinatorDaemonId) {
|
|
|
6387
6423
|
}
|
|
6388
6424
|
function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
|
|
6389
6425
|
if (!meshId) return [];
|
|
6390
|
-
const
|
|
6426
|
+
const daemonIds = normalizeCoordinatorDaemonIds(coordinatorDaemonId);
|
|
6427
|
+
const primaryDaemonId = daemonIds[0];
|
|
6428
|
+
const paths = primaryDaemonId ? [getPendingEventsPath(meshId, primaryDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
|
|
6391
6429
|
const events = [];
|
|
6392
6430
|
for (const path39 of paths) {
|
|
6393
6431
|
if (!(0, import_fs8.existsSync)(path39)) continue;
|
|
@@ -6400,7 +6438,7 @@ function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
|
|
|
6400
6438
|
return [];
|
|
6401
6439
|
}
|
|
6402
6440
|
});
|
|
6403
|
-
const filtered =
|
|
6441
|
+
const filtered = primaryDaemonId && path39 === getPendingEventsPath(meshId) ? parsed.filter((e) => !e.targetCoordinatorDaemonId || daemonIds.includes(e.targetCoordinatorDaemonId)) : parsed;
|
|
6404
6442
|
events.push(...filtered);
|
|
6405
6443
|
} catch {
|
|
6406
6444
|
}
|
|
@@ -6529,8 +6567,59 @@ function atomicDrainFile(path39) {
|
|
|
6529
6567
|
return null;
|
|
6530
6568
|
}
|
|
6531
6569
|
}
|
|
6532
|
-
function
|
|
6570
|
+
function selectiveDrainFile(path39, predicate) {
|
|
6571
|
+
const tmpPath = `${path39}.draining`;
|
|
6572
|
+
try {
|
|
6573
|
+
(0, import_fs8.renameSync)(path39, tmpPath);
|
|
6574
|
+
} catch {
|
|
6575
|
+
return [];
|
|
6576
|
+
}
|
|
6577
|
+
let content;
|
|
6578
|
+
try {
|
|
6579
|
+
content = (0, import_fs8.readFileSync)(tmpPath, "utf-8");
|
|
6580
|
+
} catch {
|
|
6581
|
+
try {
|
|
6582
|
+
(0, import_fs8.unlinkSync)(tmpPath);
|
|
6583
|
+
} catch {
|
|
6584
|
+
}
|
|
6585
|
+
return [];
|
|
6586
|
+
}
|
|
6587
|
+
const consumed = [];
|
|
6588
|
+
const keptLines = [];
|
|
6589
|
+
for (const line of content.split("\n")) {
|
|
6590
|
+
if (!line) continue;
|
|
6591
|
+
let parsed;
|
|
6592
|
+
try {
|
|
6593
|
+
parsed = JSON.parse(line);
|
|
6594
|
+
} catch {
|
|
6595
|
+
parsed = void 0;
|
|
6596
|
+
}
|
|
6597
|
+
if (parsed && predicate(parsed)) {
|
|
6598
|
+
consumed.push(parsed);
|
|
6599
|
+
} else {
|
|
6600
|
+
keptLines.push(line);
|
|
6601
|
+
}
|
|
6602
|
+
}
|
|
6603
|
+
try {
|
|
6604
|
+
if (keptLines.length > 0) {
|
|
6605
|
+
(0, import_fs8.writeFileSync)(path39, keptLines.join("\n") + "\n", "utf-8");
|
|
6606
|
+
}
|
|
6607
|
+
(0, import_fs8.unlinkSync)(tmpPath);
|
|
6608
|
+
} catch {
|
|
6609
|
+
try {
|
|
6610
|
+
if ((0, import_fs8.existsSync)(tmpPath) && !(0, import_fs8.existsSync)(path39)) (0, import_fs8.renameSync)(tmpPath, path39);
|
|
6611
|
+
} catch {
|
|
6612
|
+
}
|
|
6613
|
+
return [];
|
|
6614
|
+
}
|
|
6615
|
+
return consumed;
|
|
6616
|
+
}
|
|
6617
|
+
function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId, opts) {
|
|
6533
6618
|
if (!meshId) return [];
|
|
6619
|
+
const daemonIds = normalizeCoordinatorDaemonIds(coordinatorDaemonId);
|
|
6620
|
+
const primaryDaemonId = daemonIds[0];
|
|
6621
|
+
const onlyEvents = opts?.onlyEvents;
|
|
6622
|
+
const matchesFilter = (eventName) => !onlyEvents || onlyEvents.has(eventName);
|
|
6534
6623
|
const merged = [];
|
|
6535
6624
|
const seenFingerprints = /* @__PURE__ */ new Set();
|
|
6536
6625
|
const pushUnique = (event) => {
|
|
@@ -6544,15 +6633,23 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
|
6544
6633
|
try {
|
|
6545
6634
|
const store = MeshRuntimeStore.getInstance();
|
|
6546
6635
|
if (store.pendingEventCount(meshId) > 0) {
|
|
6547
|
-
for (const row of store.drainPendingEvents(meshId,
|
|
6636
|
+
for (const row of store.drainPendingEvents(meshId, daemonIds.length > 0 ? daemonIds : void 0, onlyEvents ? { onlyEvents } : void 0)) {
|
|
6548
6637
|
const event = row.payload;
|
|
6549
6638
|
if (event) pushUnique(event);
|
|
6550
6639
|
}
|
|
6551
6640
|
}
|
|
6552
6641
|
} catch {
|
|
6553
6642
|
}
|
|
6554
|
-
const paths =
|
|
6643
|
+
const paths = primaryDaemonId ? [getPendingEventsPath(meshId, primaryDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
|
|
6555
6644
|
for (const path39 of paths) {
|
|
6645
|
+
const isSharedFile = !!primaryDaemonId && path39 === getPendingEventsPath(meshId);
|
|
6646
|
+
const targets = (e) => !isSharedFile || !e.targetCoordinatorDaemonId || daemonIds.includes(e.targetCoordinatorDaemonId);
|
|
6647
|
+
if (onlyEvents) {
|
|
6648
|
+
for (const event of selectiveDrainFile(path39, (e) => targets(e) && matchesFilter(e.event))) {
|
|
6649
|
+
pushUnique(event);
|
|
6650
|
+
}
|
|
6651
|
+
continue;
|
|
6652
|
+
}
|
|
6556
6653
|
const content = atomicDrainFile(path39);
|
|
6557
6654
|
if (!content) continue;
|
|
6558
6655
|
const parsed = content.split("\n").filter(Boolean).flatMap((line) => {
|
|
@@ -6562,7 +6659,7 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
|
6562
6659
|
return [];
|
|
6563
6660
|
}
|
|
6564
6661
|
});
|
|
6565
|
-
const filtered =
|
|
6662
|
+
const filtered = isSharedFile ? parsed.filter(targets) : parsed;
|
|
6566
6663
|
for (const event of filtered) pushUnique(event);
|
|
6567
6664
|
}
|
|
6568
6665
|
if (merged.length === 0) return [];
|
|
@@ -6570,6 +6667,7 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
|
6570
6667
|
}
|
|
6571
6668
|
function getPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
6572
6669
|
if (!meshId) return [];
|
|
6670
|
+
const daemonIds = normalizeCoordinatorDaemonIds(coordinatorDaemonId);
|
|
6573
6671
|
const merged = [];
|
|
6574
6672
|
const seenFingerprints = /* @__PURE__ */ new Set();
|
|
6575
6673
|
const pushUnique = (event) => {
|
|
@@ -6583,14 +6681,14 @@ function getPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
|
6583
6681
|
try {
|
|
6584
6682
|
const store = MeshRuntimeStore.getInstance();
|
|
6585
6683
|
if (store.pendingEventCount(meshId) > 0) {
|
|
6586
|
-
for (const row of store.peekPendingEvents(meshId,
|
|
6684
|
+
for (const row of store.peekPendingEvents(meshId, daemonIds.length > 0 ? daemonIds : void 0)) {
|
|
6587
6685
|
const event = row.payload;
|
|
6588
6686
|
if (event) pushUnique(event);
|
|
6589
6687
|
}
|
|
6590
6688
|
}
|
|
6591
6689
|
} catch {
|
|
6592
6690
|
}
|
|
6593
|
-
for (const event of readPendingMeshCoordinatorEventsFromDisk(meshId,
|
|
6691
|
+
for (const event of readPendingMeshCoordinatorEventsFromDisk(meshId, daemonIds)) {
|
|
6594
6692
|
pushUnique(event);
|
|
6595
6693
|
}
|
|
6596
6694
|
return reconcilePendingMeshCoordinatorEvents(meshId, merged);
|
|
@@ -7292,6 +7390,14 @@ var init_mesh_routing = __esm({
|
|
|
7292
7390
|
});
|
|
7293
7391
|
|
|
7294
7392
|
// src/mesh/mesh-events-coordinator.ts
|
|
7393
|
+
function resolveCoordinatorDrainDaemonIds(components) {
|
|
7394
|
+
const ids = /* @__PURE__ */ new Set();
|
|
7395
|
+
const statusInstanceId = readNonEmptyString2(components.statusInstanceId);
|
|
7396
|
+
if (statusInstanceId) ids.add(statusInstanceId);
|
|
7397
|
+
const machineId = readNonEmptyString2(loadConfig().machineId);
|
|
7398
|
+
if (machineId) ids.add(machineId);
|
|
7399
|
+
return [...ids];
|
|
7400
|
+
}
|
|
7295
7401
|
function getCachedMeshByWorkspace(workspace) {
|
|
7296
7402
|
const now = Date.now();
|
|
7297
7403
|
const cached2 = meshByWorkspaceCache.get(workspace);
|
|
@@ -8416,8 +8522,8 @@ function setupMeshEventForwarding(components) {
|
|
|
8416
8522
|
const status = readNonEmptyString2(flushState.status).toLowerCase();
|
|
8417
8523
|
if (status === "idle") {
|
|
8418
8524
|
try {
|
|
8419
|
-
const
|
|
8420
|
-
const pendingEvents = drainPendingMeshCoordinatorEvents(coordinatorMeshId,
|
|
8525
|
+
const drainDaemonIds = resolveCoordinatorDrainDaemonIds(components);
|
|
8526
|
+
const pendingEvents = drainPendingMeshCoordinatorEvents(coordinatorMeshId, drainDaemonIds.length > 0 ? drainDaemonIds : void 0);
|
|
8421
8527
|
if (pendingEvents.length > 0) {
|
|
8422
8528
|
LOG.info("MeshEvents", `Auto-flushing ${pendingEvents.length} pending coordinator event(s) for mesh ${coordinatorMeshId} on coordinator idle`);
|
|
8423
8529
|
for (const pending of pendingEvents) {
|
|
@@ -8533,6 +8639,14 @@ function resolveReconcileIntervalMs() {
|
|
|
8533
8639
|
}
|
|
8534
8640
|
return DEFAULT_RECONCILE_INTERVAL_MS;
|
|
8535
8641
|
}
|
|
8642
|
+
function resolveCoordinatorDaemonIds(components) {
|
|
8643
|
+
const ids = /* @__PURE__ */ new Set();
|
|
8644
|
+
const statusInstanceId = readNonEmptyString2(components.statusInstanceId);
|
|
8645
|
+
if (statusInstanceId) ids.add(statusInstanceId);
|
|
8646
|
+
const machineId = readNonEmptyString2(loadConfig().machineId);
|
|
8647
|
+
if (machineId) ids.add(machineId);
|
|
8648
|
+
return [...ids];
|
|
8649
|
+
}
|
|
8536
8650
|
function findLiveCoordinators(components) {
|
|
8537
8651
|
const out = [];
|
|
8538
8652
|
for (const inst of components.instanceManager.getByCategory("cli")) {
|
|
@@ -8565,6 +8679,7 @@ async function runMeshReconcileTick(components) {
|
|
|
8565
8679
|
else byMesh.set(c.meshId, [c]);
|
|
8566
8680
|
}
|
|
8567
8681
|
const localDaemonId = readNonEmptyString2(loadConfig().machineId) || void 0;
|
|
8682
|
+
const drainDaemonIds = resolveCoordinatorDaemonIds(components);
|
|
8568
8683
|
const dispatchMeshCommand = components.dispatchMeshCommand;
|
|
8569
8684
|
const store = (() => {
|
|
8570
8685
|
try {
|
|
@@ -8582,7 +8697,9 @@ async function runMeshReconcileTick(components) {
|
|
|
8582
8697
|
}
|
|
8583
8698
|
}
|
|
8584
8699
|
const idleCoordinators = meshCoordinators.filter((c) => c.idle);
|
|
8585
|
-
|
|
8700
|
+
const generatingCoordinators = meshCoordinators.filter((c) => !c.idle);
|
|
8701
|
+
const targetCoordinators = idleCoordinators.length > 0 ? idleCoordinators : generatingCoordinators;
|
|
8702
|
+
const forceOnly = idleCoordinators.length === 0;
|
|
8586
8703
|
if (store) {
|
|
8587
8704
|
try {
|
|
8588
8705
|
if (store.pendingEventCount(meshId) === 0) continue;
|
|
@@ -8591,15 +8708,20 @@ async function runMeshReconcileTick(components) {
|
|
|
8591
8708
|
}
|
|
8592
8709
|
let pendingEvents = [];
|
|
8593
8710
|
try {
|
|
8594
|
-
pendingEvents = drainPendingMeshCoordinatorEvents(
|
|
8711
|
+
pendingEvents = drainPendingMeshCoordinatorEvents(
|
|
8712
|
+
meshId,
|
|
8713
|
+
drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId,
|
|
8714
|
+
forceOnly ? { onlyEvents: MESH_FORCE_INJECT_EVENTS } : void 0
|
|
8715
|
+
);
|
|
8595
8716
|
} catch (e) {
|
|
8596
8717
|
LOG.warn("MeshReconcile", `Drain failed for mesh ${meshId}: ${e?.message || e}`);
|
|
8597
8718
|
continue;
|
|
8598
8719
|
}
|
|
8599
8720
|
if (pendingEvents.length === 0) continue;
|
|
8600
|
-
|
|
8721
|
+
const mode = forceOnly ? "force-drain \u2192 generating" : "inject \u2192 idle";
|
|
8722
|
+
LOG.info("MeshReconcile", `Reconcile ${mode}: ${pendingEvents.length} pending event(s) \u2192 ${targetCoordinators.length} coordinator(s) for mesh ${meshId}`);
|
|
8601
8723
|
for (const pending of pendingEvents) {
|
|
8602
|
-
for (const c of
|
|
8724
|
+
for (const c of targetCoordinators) {
|
|
8603
8725
|
injectPendingIntoCoordinator(c.instance, pending);
|
|
8604
8726
|
}
|
|
8605
8727
|
}
|
|
@@ -55697,7 +55819,8 @@ async function initDaemonComponents(config) {
|
|
|
55697
55819
|
detectedIdes: detectedIdesRef,
|
|
55698
55820
|
refreshProviderAvailability,
|
|
55699
55821
|
dispatchMeshCommand: config.dispatchMeshCommand,
|
|
55700
|
-
onMeshCoordinatorEventForwarded: config.onMeshCoordinatorEventForwarded
|
|
55822
|
+
onMeshCoordinatorEventForwarded: config.onMeshCoordinatorEventForwarded,
|
|
55823
|
+
statusInstanceId: config.statusInstanceId
|
|
55701
55824
|
};
|
|
55702
55825
|
setupMeshEventForwarding(components);
|
|
55703
55826
|
components.meshReconcileLoop = setupMeshReconcileLoop(components);
|