@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.mjs
CHANGED
|
@@ -270,10 +270,10 @@ function readInjected(value) {
|
|
|
270
270
|
}
|
|
271
271
|
function getDaemonBuildInfo() {
|
|
272
272
|
if (cached) return cached;
|
|
273
|
-
const commit = readInjected(true ? "
|
|
274
|
-
const commitShort = readInjected(true ? "
|
|
275
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
276
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
273
|
+
const commit = readInjected(true ? "746fc68e4c297b988b76207bb8c63ab6062a38e1" : void 0) ?? "unknown";
|
|
274
|
+
const commitShort = readInjected(true ? "746fc68e" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
275
|
+
const version = readInjected(true ? "0.9.82-rc.276" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
276
|
+
const builtAt = readInjected(true ? "2026-06-15T09:29:09.895Z" : void 0);
|
|
277
277
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
278
278
|
return cached;
|
|
279
279
|
}
|
|
@@ -4258,12 +4258,34 @@ var init_mesh_runtime_store = __esm({
|
|
|
4258
4258
|
this.maybeCheckpointWal();
|
|
4259
4259
|
return result.changes > 0;
|
|
4260
4260
|
}
|
|
4261
|
-
|
|
4261
|
+
/**
|
|
4262
|
+
* Drain undrained pending events for a mesh, atomically marking them drained.
|
|
4263
|
+
* When `opts.onlyEvents` is supplied, ONLY rows whose `event` is in that set are
|
|
4264
|
+
* drained — the rest stay queued (drained=0) for a later drain. This is how the
|
|
4265
|
+
* reconcile loop force-drains terminal/force-inject events into a *generating*
|
|
4266
|
+
* coordinator while leaving non-force progress events for the coordinator's next
|
|
4267
|
+
* idle transition. Filtering happens inside the same transaction as the
|
|
4268
|
+
* drained=1 marking, so force-drain + a concurrent full drain can never both
|
|
4269
|
+
* consume the same row.
|
|
4270
|
+
*/
|
|
4271
|
+
drainPendingEvents(meshId, coordinatorDaemonId, opts) {
|
|
4262
4272
|
return this.transaction(() => {
|
|
4263
|
-
const
|
|
4264
|
-
|
|
4273
|
+
const onlyEvents = opts?.onlyEvents;
|
|
4274
|
+
if (onlyEvents && onlyEvents.size === 0) return [];
|
|
4275
|
+
const eventList = onlyEvents ? [...onlyEvents] : [];
|
|
4276
|
+
const daemonIds = (Array.isArray(coordinatorDaemonId) ? coordinatorDaemonId : coordinatorDaemonId ? [coordinatorDaemonId] : []).filter((id) => typeof id === "string" && id.length > 0);
|
|
4277
|
+
const clauses = ["mesh_id = ?", "drained = 0"];
|
|
4278
|
+
const params = [meshId];
|
|
4279
|
+
if (daemonIds.length > 0) {
|
|
4280
|
+
clauses.push(`(coordinator_daemon_id IS NULL OR coordinator_daemon_id IN (${daemonIds.map(() => "?").join(",")}))`);
|
|
4281
|
+
params.push(...daemonIds);
|
|
4282
|
+
}
|
|
4283
|
+
if (eventList.length > 0) {
|
|
4284
|
+
clauses.push(`event IN (${eventList.map(() => "?").join(",")})`);
|
|
4285
|
+
params.push(...eventList);
|
|
4286
|
+
}
|
|
4265
4287
|
const rows = this.db.prepare(
|
|
4266
|
-
`SELECT id, event, payload FROM mesh_pending_events ${
|
|
4288
|
+
`SELECT id, event, payload FROM mesh_pending_events WHERE ${clauses.join(" AND ")} ORDER BY queued_at ASC LIMIT 100`
|
|
4267
4289
|
).all(...params);
|
|
4268
4290
|
if (rows.length === 0) return [];
|
|
4269
4291
|
const ids = rows.map((r) => r.id);
|
|
@@ -4286,8 +4308,9 @@ var init_mesh_runtime_store = __esm({
|
|
|
4286
4308
|
}
|
|
4287
4309
|
/** Non-destructive peek — returns undrained events without marking them drained. */
|
|
4288
4310
|
peekPendingEvents(meshId, coordinatorDaemonId) {
|
|
4289
|
-
const
|
|
4290
|
-
const
|
|
4311
|
+
const daemonIds = (Array.isArray(coordinatorDaemonId) ? coordinatorDaemonId : coordinatorDaemonId ? [coordinatorDaemonId] : []).filter((id) => typeof id === "string" && id.length > 0);
|
|
4312
|
+
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`;
|
|
4313
|
+
const params = daemonIds.length > 0 ? [meshId, ...daemonIds] : [meshId];
|
|
4291
4314
|
const rows = this.db.prepare(
|
|
4292
4315
|
`SELECT id, event, payload FROM mesh_pending_events ${whereClause} ORDER BY queued_at ASC LIMIT 100`
|
|
4293
4316
|
).all(...params);
|
|
@@ -6330,6 +6353,19 @@ var init_mesh_events_utils = __esm({
|
|
|
6330
6353
|
import { appendFileSync as appendFileSync2, existsSync as existsSync12, readFileSync as readFileSync10, renameSync as renameSync4, statSync as statSync5, unlinkSync as unlinkSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
6331
6354
|
import { join as join13 } from "path";
|
|
6332
6355
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
6356
|
+
function normalizeCoordinatorDaemonIds(coordinatorDaemonId) {
|
|
6357
|
+
const raw = Array.isArray(coordinatorDaemonId) ? coordinatorDaemonId : coordinatorDaemonId != null ? [coordinatorDaemonId] : [];
|
|
6358
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6359
|
+
const out = [];
|
|
6360
|
+
for (const id of raw) {
|
|
6361
|
+
if (typeof id !== "string") continue;
|
|
6362
|
+
const trimmed = id.trim();
|
|
6363
|
+
if (!trimmed || seen.has(trimmed)) continue;
|
|
6364
|
+
seen.add(trimmed);
|
|
6365
|
+
out.push(trimmed);
|
|
6366
|
+
}
|
|
6367
|
+
return out;
|
|
6368
|
+
}
|
|
6333
6369
|
function readRefineJobId2(event) {
|
|
6334
6370
|
const metadata = readRecord3(event.metadataEvent) || event;
|
|
6335
6371
|
const result = readRecord3(metadata.result);
|
|
@@ -6384,7 +6420,9 @@ function getPendingEventsPath(meshId, coordinatorDaemonId) {
|
|
|
6384
6420
|
}
|
|
6385
6421
|
function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
|
|
6386
6422
|
if (!meshId) return [];
|
|
6387
|
-
const
|
|
6423
|
+
const daemonIds = normalizeCoordinatorDaemonIds(coordinatorDaemonId);
|
|
6424
|
+
const primaryDaemonId = daemonIds[0];
|
|
6425
|
+
const paths = primaryDaemonId ? [getPendingEventsPath(meshId, primaryDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
|
|
6388
6426
|
const events = [];
|
|
6389
6427
|
for (const path39 of paths) {
|
|
6390
6428
|
if (!existsSync12(path39)) continue;
|
|
@@ -6397,7 +6435,7 @@ function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
|
|
|
6397
6435
|
return [];
|
|
6398
6436
|
}
|
|
6399
6437
|
});
|
|
6400
|
-
const filtered =
|
|
6438
|
+
const filtered = primaryDaemonId && path39 === getPendingEventsPath(meshId) ? parsed.filter((e) => !e.targetCoordinatorDaemonId || daemonIds.includes(e.targetCoordinatorDaemonId)) : parsed;
|
|
6401
6439
|
events.push(...filtered);
|
|
6402
6440
|
} catch {
|
|
6403
6441
|
}
|
|
@@ -6526,8 +6564,59 @@ function atomicDrainFile(path39) {
|
|
|
6526
6564
|
return null;
|
|
6527
6565
|
}
|
|
6528
6566
|
}
|
|
6529
|
-
function
|
|
6567
|
+
function selectiveDrainFile(path39, predicate) {
|
|
6568
|
+
const tmpPath = `${path39}.draining`;
|
|
6569
|
+
try {
|
|
6570
|
+
renameSync4(path39, tmpPath);
|
|
6571
|
+
} catch {
|
|
6572
|
+
return [];
|
|
6573
|
+
}
|
|
6574
|
+
let content;
|
|
6575
|
+
try {
|
|
6576
|
+
content = readFileSync10(tmpPath, "utf-8");
|
|
6577
|
+
} catch {
|
|
6578
|
+
try {
|
|
6579
|
+
unlinkSync2(tmpPath);
|
|
6580
|
+
} catch {
|
|
6581
|
+
}
|
|
6582
|
+
return [];
|
|
6583
|
+
}
|
|
6584
|
+
const consumed = [];
|
|
6585
|
+
const keptLines = [];
|
|
6586
|
+
for (const line of content.split("\n")) {
|
|
6587
|
+
if (!line) continue;
|
|
6588
|
+
let parsed;
|
|
6589
|
+
try {
|
|
6590
|
+
parsed = JSON.parse(line);
|
|
6591
|
+
} catch {
|
|
6592
|
+
parsed = void 0;
|
|
6593
|
+
}
|
|
6594
|
+
if (parsed && predicate(parsed)) {
|
|
6595
|
+
consumed.push(parsed);
|
|
6596
|
+
} else {
|
|
6597
|
+
keptLines.push(line);
|
|
6598
|
+
}
|
|
6599
|
+
}
|
|
6600
|
+
try {
|
|
6601
|
+
if (keptLines.length > 0) {
|
|
6602
|
+
writeFileSync6(path39, keptLines.join("\n") + "\n", "utf-8");
|
|
6603
|
+
}
|
|
6604
|
+
unlinkSync2(tmpPath);
|
|
6605
|
+
} catch {
|
|
6606
|
+
try {
|
|
6607
|
+
if (existsSync12(tmpPath) && !existsSync12(path39)) renameSync4(tmpPath, path39);
|
|
6608
|
+
} catch {
|
|
6609
|
+
}
|
|
6610
|
+
return [];
|
|
6611
|
+
}
|
|
6612
|
+
return consumed;
|
|
6613
|
+
}
|
|
6614
|
+
function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId, opts) {
|
|
6530
6615
|
if (!meshId) return [];
|
|
6616
|
+
const daemonIds = normalizeCoordinatorDaemonIds(coordinatorDaemonId);
|
|
6617
|
+
const primaryDaemonId = daemonIds[0];
|
|
6618
|
+
const onlyEvents = opts?.onlyEvents;
|
|
6619
|
+
const matchesFilter = (eventName) => !onlyEvents || onlyEvents.has(eventName);
|
|
6531
6620
|
const merged = [];
|
|
6532
6621
|
const seenFingerprints = /* @__PURE__ */ new Set();
|
|
6533
6622
|
const pushUnique = (event) => {
|
|
@@ -6541,15 +6630,23 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
|
6541
6630
|
try {
|
|
6542
6631
|
const store = MeshRuntimeStore.getInstance();
|
|
6543
6632
|
if (store.pendingEventCount(meshId) > 0) {
|
|
6544
|
-
for (const row of store.drainPendingEvents(meshId,
|
|
6633
|
+
for (const row of store.drainPendingEvents(meshId, daemonIds.length > 0 ? daemonIds : void 0, onlyEvents ? { onlyEvents } : void 0)) {
|
|
6545
6634
|
const event = row.payload;
|
|
6546
6635
|
if (event) pushUnique(event);
|
|
6547
6636
|
}
|
|
6548
6637
|
}
|
|
6549
6638
|
} catch {
|
|
6550
6639
|
}
|
|
6551
|
-
const paths =
|
|
6640
|
+
const paths = primaryDaemonId ? [getPendingEventsPath(meshId, primaryDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
|
|
6552
6641
|
for (const path39 of paths) {
|
|
6642
|
+
const isSharedFile = !!primaryDaemonId && path39 === getPendingEventsPath(meshId);
|
|
6643
|
+
const targets = (e) => !isSharedFile || !e.targetCoordinatorDaemonId || daemonIds.includes(e.targetCoordinatorDaemonId);
|
|
6644
|
+
if (onlyEvents) {
|
|
6645
|
+
for (const event of selectiveDrainFile(path39, (e) => targets(e) && matchesFilter(e.event))) {
|
|
6646
|
+
pushUnique(event);
|
|
6647
|
+
}
|
|
6648
|
+
continue;
|
|
6649
|
+
}
|
|
6553
6650
|
const content = atomicDrainFile(path39);
|
|
6554
6651
|
if (!content) continue;
|
|
6555
6652
|
const parsed = content.split("\n").filter(Boolean).flatMap((line) => {
|
|
@@ -6559,7 +6656,7 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
|
6559
6656
|
return [];
|
|
6560
6657
|
}
|
|
6561
6658
|
});
|
|
6562
|
-
const filtered =
|
|
6659
|
+
const filtered = isSharedFile ? parsed.filter(targets) : parsed;
|
|
6563
6660
|
for (const event of filtered) pushUnique(event);
|
|
6564
6661
|
}
|
|
6565
6662
|
if (merged.length === 0) return [];
|
|
@@ -6567,6 +6664,7 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
|
6567
6664
|
}
|
|
6568
6665
|
function getPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
6569
6666
|
if (!meshId) return [];
|
|
6667
|
+
const daemonIds = normalizeCoordinatorDaemonIds(coordinatorDaemonId);
|
|
6570
6668
|
const merged = [];
|
|
6571
6669
|
const seenFingerprints = /* @__PURE__ */ new Set();
|
|
6572
6670
|
const pushUnique = (event) => {
|
|
@@ -6580,14 +6678,14 @@ function getPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
|
6580
6678
|
try {
|
|
6581
6679
|
const store = MeshRuntimeStore.getInstance();
|
|
6582
6680
|
if (store.pendingEventCount(meshId) > 0) {
|
|
6583
|
-
for (const row of store.peekPendingEvents(meshId,
|
|
6681
|
+
for (const row of store.peekPendingEvents(meshId, daemonIds.length > 0 ? daemonIds : void 0)) {
|
|
6584
6682
|
const event = row.payload;
|
|
6585
6683
|
if (event) pushUnique(event);
|
|
6586
6684
|
}
|
|
6587
6685
|
}
|
|
6588
6686
|
} catch {
|
|
6589
6687
|
}
|
|
6590
|
-
for (const event of readPendingMeshCoordinatorEventsFromDisk(meshId,
|
|
6688
|
+
for (const event of readPendingMeshCoordinatorEventsFromDisk(meshId, daemonIds)) {
|
|
6591
6689
|
pushUnique(event);
|
|
6592
6690
|
}
|
|
6593
6691
|
return reconcilePendingMeshCoordinatorEvents(meshId, merged);
|
|
@@ -7286,6 +7384,14 @@ var init_mesh_routing = __esm({
|
|
|
7286
7384
|
|
|
7287
7385
|
// src/mesh/mesh-events-coordinator.ts
|
|
7288
7386
|
import { existsSync as existsSync14 } from "fs";
|
|
7387
|
+
function resolveCoordinatorDrainDaemonIds(components) {
|
|
7388
|
+
const ids = /* @__PURE__ */ new Set();
|
|
7389
|
+
const statusInstanceId = readNonEmptyString2(components.statusInstanceId);
|
|
7390
|
+
if (statusInstanceId) ids.add(statusInstanceId);
|
|
7391
|
+
const machineId = readNonEmptyString2(loadConfig().machineId);
|
|
7392
|
+
if (machineId) ids.add(machineId);
|
|
7393
|
+
return [...ids];
|
|
7394
|
+
}
|
|
7289
7395
|
function getCachedMeshByWorkspace(workspace) {
|
|
7290
7396
|
const now = Date.now();
|
|
7291
7397
|
const cached2 = meshByWorkspaceCache.get(workspace);
|
|
@@ -8410,8 +8516,8 @@ function setupMeshEventForwarding(components) {
|
|
|
8410
8516
|
const status = readNonEmptyString2(flushState.status).toLowerCase();
|
|
8411
8517
|
if (status === "idle") {
|
|
8412
8518
|
try {
|
|
8413
|
-
const
|
|
8414
|
-
const pendingEvents = drainPendingMeshCoordinatorEvents(coordinatorMeshId,
|
|
8519
|
+
const drainDaemonIds = resolveCoordinatorDrainDaemonIds(components);
|
|
8520
|
+
const pendingEvents = drainPendingMeshCoordinatorEvents(coordinatorMeshId, drainDaemonIds.length > 0 ? drainDaemonIds : void 0);
|
|
8415
8521
|
if (pendingEvents.length > 0) {
|
|
8416
8522
|
LOG.info("MeshEvents", `Auto-flushing ${pendingEvents.length} pending coordinator event(s) for mesh ${coordinatorMeshId} on coordinator idle`);
|
|
8417
8523
|
for (const pending of pendingEvents) {
|
|
@@ -8526,6 +8632,14 @@ function resolveReconcileIntervalMs() {
|
|
|
8526
8632
|
}
|
|
8527
8633
|
return DEFAULT_RECONCILE_INTERVAL_MS;
|
|
8528
8634
|
}
|
|
8635
|
+
function resolveCoordinatorDaemonIds(components) {
|
|
8636
|
+
const ids = /* @__PURE__ */ new Set();
|
|
8637
|
+
const statusInstanceId = readNonEmptyString2(components.statusInstanceId);
|
|
8638
|
+
if (statusInstanceId) ids.add(statusInstanceId);
|
|
8639
|
+
const machineId = readNonEmptyString2(loadConfig().machineId);
|
|
8640
|
+
if (machineId) ids.add(machineId);
|
|
8641
|
+
return [...ids];
|
|
8642
|
+
}
|
|
8529
8643
|
function findLiveCoordinators(components) {
|
|
8530
8644
|
const out = [];
|
|
8531
8645
|
for (const inst of components.instanceManager.getByCategory("cli")) {
|
|
@@ -8558,6 +8672,7 @@ async function runMeshReconcileTick(components) {
|
|
|
8558
8672
|
else byMesh.set(c.meshId, [c]);
|
|
8559
8673
|
}
|
|
8560
8674
|
const localDaemonId = readNonEmptyString2(loadConfig().machineId) || void 0;
|
|
8675
|
+
const drainDaemonIds = resolveCoordinatorDaemonIds(components);
|
|
8561
8676
|
const dispatchMeshCommand = components.dispatchMeshCommand;
|
|
8562
8677
|
const store = (() => {
|
|
8563
8678
|
try {
|
|
@@ -8575,7 +8690,9 @@ async function runMeshReconcileTick(components) {
|
|
|
8575
8690
|
}
|
|
8576
8691
|
}
|
|
8577
8692
|
const idleCoordinators = meshCoordinators.filter((c) => c.idle);
|
|
8578
|
-
|
|
8693
|
+
const generatingCoordinators = meshCoordinators.filter((c) => !c.idle);
|
|
8694
|
+
const targetCoordinators = idleCoordinators.length > 0 ? idleCoordinators : generatingCoordinators;
|
|
8695
|
+
const forceOnly = idleCoordinators.length === 0;
|
|
8579
8696
|
if (store) {
|
|
8580
8697
|
try {
|
|
8581
8698
|
if (store.pendingEventCount(meshId) === 0) continue;
|
|
@@ -8584,15 +8701,20 @@ async function runMeshReconcileTick(components) {
|
|
|
8584
8701
|
}
|
|
8585
8702
|
let pendingEvents = [];
|
|
8586
8703
|
try {
|
|
8587
|
-
pendingEvents = drainPendingMeshCoordinatorEvents(
|
|
8704
|
+
pendingEvents = drainPendingMeshCoordinatorEvents(
|
|
8705
|
+
meshId,
|
|
8706
|
+
drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId,
|
|
8707
|
+
forceOnly ? { onlyEvents: MESH_FORCE_INJECT_EVENTS } : void 0
|
|
8708
|
+
);
|
|
8588
8709
|
} catch (e) {
|
|
8589
8710
|
LOG.warn("MeshReconcile", `Drain failed for mesh ${meshId}: ${e?.message || e}`);
|
|
8590
8711
|
continue;
|
|
8591
8712
|
}
|
|
8592
8713
|
if (pendingEvents.length === 0) continue;
|
|
8593
|
-
|
|
8714
|
+
const mode = forceOnly ? "force-drain \u2192 generating" : "inject \u2192 idle";
|
|
8715
|
+
LOG.info("MeshReconcile", `Reconcile ${mode}: ${pendingEvents.length} pending event(s) \u2192 ${targetCoordinators.length} coordinator(s) for mesh ${meshId}`);
|
|
8594
8716
|
for (const pending of pendingEvents) {
|
|
8595
|
-
for (const c of
|
|
8717
|
+
for (const c of targetCoordinators) {
|
|
8596
8718
|
injectPendingIntoCoordinator(c.instance, pending);
|
|
8597
8719
|
}
|
|
8598
8720
|
}
|
|
@@ -55368,7 +55490,8 @@ async function initDaemonComponents(config) {
|
|
|
55368
55490
|
detectedIdes: detectedIdesRef,
|
|
55369
55491
|
refreshProviderAvailability,
|
|
55370
55492
|
dispatchMeshCommand: config.dispatchMeshCommand,
|
|
55371
|
-
onMeshCoordinatorEventForwarded: config.onMeshCoordinatorEventForwarded
|
|
55493
|
+
onMeshCoordinatorEventForwarded: config.onMeshCoordinatorEventForwarded,
|
|
55494
|
+
statusInstanceId: config.statusInstanceId
|
|
55372
55495
|
};
|
|
55373
55496
|
setupMeshEventForwarding(components);
|
|
55374
55497
|
components.meshReconcileLoop = setupMeshReconcileLoop(components);
|