@adhdev/daemon-core 0.9.82-rc.494 → 0.9.82-rc.496
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/commands/router-refine.d.ts +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +127 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +122 -11
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-idle-reminder.d.ts +68 -0
- package/dist/mesh/mesh-runtime-store.d.ts +17 -0
- package/dist/repo-mesh-types.d.ts +10 -0
- package/package.json +3 -3
- package/src/commands/router-refine.ts +2 -2
- package/src/index.ts +1 -0
- package/src/mesh/coordinator-prompt.ts +0 -1
- package/src/mesh/mesh-event-forwarding.ts +12 -0
- package/src/mesh/mesh-idle-reminder.ts +153 -0
- package/src/mesh/mesh-reconcile-loop.ts +15 -2
- package/src/mesh/mesh-remote-event-pull.ts +8 -1
- package/src/mesh/mesh-runtime-store.ts +26 -0
- package/src/mesh/p2p-relay-failure.ts +2 -2
- package/src/repo-mesh-types.ts +13 -0
package/dist/index.mjs
CHANGED
|
@@ -170,7 +170,10 @@ var init_repo_mesh_types = __esm({
|
|
|
170
170
|
// auto-launched sessions are cleaned — see RepoMeshMagiSessionCleanupMode.
|
|
171
171
|
magiSessionCleanup: "stop_and_delete",
|
|
172
172
|
autoFastForward: { enabled: true },
|
|
173
|
-
maxTaskRetries: 1
|
|
173
|
+
maxTaskRetries: 1,
|
|
174
|
+
// Nudge the coordinator when the mesh is fully idle but active missions linger,
|
|
175
|
+
// so a mission is never left drifting in `active` after its work is really done.
|
|
176
|
+
idleActiveMissionReminder: true
|
|
174
177
|
};
|
|
175
178
|
SESSION_CLEANUP_MODES = /* @__PURE__ */ new Set([
|
|
176
179
|
"preserve",
|
|
@@ -409,10 +412,10 @@ function readInjected(value) {
|
|
|
409
412
|
}
|
|
410
413
|
function getDaemonBuildInfo() {
|
|
411
414
|
if (cached) return cached;
|
|
412
|
-
const commit = readInjected(true ? "
|
|
413
|
-
const commitShort = readInjected(true ? "
|
|
414
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
415
|
-
const builtAt = readInjected(true ? "2026-07-
|
|
415
|
+
const commit = readInjected(true ? "bafa66a406e7efc123493af30c0779646ea02c5c" : void 0) ?? "unknown";
|
|
416
|
+
const commitShort = readInjected(true ? "bafa66a4" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
417
|
+
const version = readInjected(true ? "0.9.82-rc.496" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
418
|
+
const builtAt = readInjected(true ? "2026-07-11T16:11:16.059Z" : void 0);
|
|
416
419
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
417
420
|
return cached;
|
|
418
421
|
}
|
|
@@ -2924,7 +2927,6 @@ var init_dist = __esm({
|
|
|
2924
2927
|
"mesh_forget_note",
|
|
2925
2928
|
"mesh_reconcile_ledger",
|
|
2926
2929
|
"mesh_requeue_held_events",
|
|
2927
|
-
"mesh_wait_events",
|
|
2928
2930
|
"mesh_mission_upsert",
|
|
2929
2931
|
"mesh_mission_list",
|
|
2930
2932
|
"mesh_review_inbox",
|
|
@@ -3938,7 +3940,6 @@ var init_coordinator_prompt = __esm({
|
|
|
3938
3940
|
| \`mesh_ledger_query\` | Read-only ledger query along the kind/time/node axes (complement to task-axis mesh_task_history): filter by kind, since, node, tail \u2014 answer "what happened on node X / what failed since T" without scanning transcripts |
|
|
3939
3941
|
| \`mesh_reconcile_ledger\` | Reconcile daemon-local ledgers over P2P \u2014 import missing entries from remote nodes into the coordinator local ledger |
|
|
3940
3942
|
| \`mesh_requeue_held_events\` | Restore recoverable held coordinator events (T6 quarantine / pending-trim) back to the pending queue; lossless, no double-requeue |
|
|
3941
|
-
| \`mesh_wait_events\` | Long-poll blocking wait for coordinator events (worker completions/approvals/nudges) up to timeoutMs \u2014 drains immediately if any are pending, else blocks until they arrive. Use this instead of busy-polling mesh_status/mesh_view_queue after dispatching work |
|
|
3942
3943
|
| \`mesh_review_inbox\` | List local worktree nodes needing human review \u2014 merge candidates and Refinery-blocked results with evidence/diff summaries |
|
|
3943
3944
|
| \`mesh_record_note\` | Record a durable, provider-neutral operating note (provider quirk / pattern to avoid / recovery lesson). Future coordinators see it under "## Operating Notes" at launch |
|
|
3944
3945
|
| \`mesh_forget_note\` | Retract a stale/wrong operating note by note_id or exact text so it stops riding into future coordinators' prompts (append-only tombstone; history preserved) |
|
|
@@ -6492,6 +6493,13 @@ var init_mesh_runtime_store = __esm({
|
|
|
6492
6493
|
db;
|
|
6493
6494
|
dbPath;
|
|
6494
6495
|
migratedMeshIds = /* @__PURE__ */ new Set();
|
|
6496
|
+
// Idle-active-mission-reminder debounce (mesh-idle-reminder.ts). In-memory only:
|
|
6497
|
+
// this is a spam guard for a best-effort coordinator nudge, so a daemon restart
|
|
6498
|
+
// resetting it (at most one extra reminder) is harmless — no SQLite persistence
|
|
6499
|
+
// is warranted. Keyed by meshId; the value records when the last reminder fired
|
|
6500
|
+
// and the hash of the active-mission id set it named, so a changed mission set
|
|
6501
|
+
// re-fires before the time window elapses.
|
|
6502
|
+
idleReminderState = /* @__PURE__ */ new Map();
|
|
6495
6503
|
fingerprintSweepCounter = 0;
|
|
6496
6504
|
walWriteCounter = 0;
|
|
6497
6505
|
// Independent cadence for the tool-call-log sweep. Must NOT share walWriteCounter:
|
|
@@ -8087,6 +8095,22 @@ var init_mesh_runtime_store = __esm({
|
|
|
8087
8095
|
"UPDATE mesh_missions SET close_candidate_emitted_at = ? WHERE mesh_id = ? AND id = ?"
|
|
8088
8096
|
).run(emittedAt, meshId, missionId).changes;
|
|
8089
8097
|
}
|
|
8098
|
+
/**
|
|
8099
|
+
* Read the last idle-active-mission-reminder debounce marker for a mesh, or null if
|
|
8100
|
+
* none has fired this process. In-memory only (see idleReminderState) — best-effort
|
|
8101
|
+
* spam guard for a coordinator nudge, intentionally not SQLite-backed.
|
|
8102
|
+
*/
|
|
8103
|
+
getIdleReminderState(meshId) {
|
|
8104
|
+
return this.idleReminderState.get(meshId) ?? null;
|
|
8105
|
+
}
|
|
8106
|
+
/** Record that an idle-active-mission reminder just fired for a mesh (debounce marker). */
|
|
8107
|
+
setIdleReminderState(meshId, state) {
|
|
8108
|
+
this.idleReminderState.set(meshId, state);
|
|
8109
|
+
}
|
|
8110
|
+
/** Clear the idle-reminder debounce marker for a mesh — mesh deletion / test cleanup. */
|
|
8111
|
+
clearIdleReminderState(meshId) {
|
|
8112
|
+
this.idleReminderState.delete(meshId);
|
|
8113
|
+
}
|
|
8090
8114
|
/** Remove all missions for a mesh — mesh deletion / test cleanup. */
|
|
8091
8115
|
clearMissionsForMesh(meshId) {
|
|
8092
8116
|
return this.db.prepare("DELETE FROM mesh_missions WHERE mesh_id = ?").run(meshId).changes;
|
|
@@ -12594,6 +12618,72 @@ var init_mesh_active_work = __esm({
|
|
|
12594
12618
|
}
|
|
12595
12619
|
});
|
|
12596
12620
|
|
|
12621
|
+
// src/mesh/mesh-idle-reminder.ts
|
|
12622
|
+
function missionSetHash(missions) {
|
|
12623
|
+
return missions.map((m) => m.id).sort().join(",");
|
|
12624
|
+
}
|
|
12625
|
+
function shouldFireIdleReminder(last, hash, now, debounceMs = IDLE_REMINDER_DEBOUNCE_MS) {
|
|
12626
|
+
if (!last) return true;
|
|
12627
|
+
if (now - last.emittedAt > debounceMs) return true;
|
|
12628
|
+
return hash !== last.missionSetHash;
|
|
12629
|
+
}
|
|
12630
|
+
function buildIdleReminderMessage(missions) {
|
|
12631
|
+
const shown = missions.slice(0, MISSION_LIST_CAP);
|
|
12632
|
+
const lines = shown.map((m) => `- ${m.title} (${m.id})`);
|
|
12633
|
+
const overflow = missions.length - shown.length;
|
|
12634
|
+
if (overflow > 0) lines.push(`- \u2026and ${overflow} more`);
|
|
12635
|
+
return `[System] Coordinator idle with ${missions.length} active mission(s):
|
|
12636
|
+
${lines.join("\n")}
|
|
12637
|
+
The mesh has no work in flight. For each mission, decide its outcome: continue it (enqueue/dispatch the remaining work) or close it with mesh_mission_upsert(mission_id, status: "completed" | "abandoned"). Do not leave a finished mission in 'active'. This is a one-time reminder.`;
|
|
12638
|
+
}
|
|
12639
|
+
function maybeInjectIdleActiveMissionReminder(meshId, coordinator, policy, now = Date.now()) {
|
|
12640
|
+
try {
|
|
12641
|
+
if (!coordinator) return false;
|
|
12642
|
+
if (policy?.idleActiveMissionReminder === false) return false;
|
|
12643
|
+
const activeMissions = getMeshMissions(meshId, ["active"]);
|
|
12644
|
+
if (activeMissions.length === 0) return false;
|
|
12645
|
+
const summary = buildMeshActiveWork({
|
|
12646
|
+
meshId,
|
|
12647
|
+
queue: getQueue(meshId),
|
|
12648
|
+
directDispatches: getActiveDirectDispatches(meshId),
|
|
12649
|
+
ledgerEntries: readLedgerEntries(meshId, { tail: 200 }),
|
|
12650
|
+
now
|
|
12651
|
+
}).summary;
|
|
12652
|
+
if (summary.totalActiveCount !== 0 || summary.generatingCount !== 0) return false;
|
|
12653
|
+
const store = MeshRuntimeStore.getInstance();
|
|
12654
|
+
const hash = missionSetHash(activeMissions);
|
|
12655
|
+
const last = store.getIdleReminderState(meshId);
|
|
12656
|
+
if (!shouldFireIdleReminder(last, hash, now)) return false;
|
|
12657
|
+
const message = buildIdleReminderMessage(activeMissions);
|
|
12658
|
+
coordinator.onEvent("send_message", {
|
|
12659
|
+
input: { text: message, textFallback: message }
|
|
12660
|
+
});
|
|
12661
|
+
store.setIdleReminderState(meshId, { emittedAt: now, missionSetHash: hash });
|
|
12662
|
+
LOG.info(
|
|
12663
|
+
"MeshIdleReminder",
|
|
12664
|
+
`Injected idle reminder for mesh ${meshId} (${activeMissions.length} active mission(s), fully idle)`
|
|
12665
|
+
);
|
|
12666
|
+
return true;
|
|
12667
|
+
} catch (e) {
|
|
12668
|
+
LOG.warn("MeshIdleReminder", `maybeInjectIdleActiveMissionReminder failed for mesh ${meshId}: ${e?.message || e}`);
|
|
12669
|
+
return false;
|
|
12670
|
+
}
|
|
12671
|
+
}
|
|
12672
|
+
var IDLE_REMINDER_DEBOUNCE_MS, MISSION_LIST_CAP;
|
|
12673
|
+
var init_mesh_idle_reminder = __esm({
|
|
12674
|
+
"src/mesh/mesh-idle-reminder.ts"() {
|
|
12675
|
+
"use strict";
|
|
12676
|
+
init_logger();
|
|
12677
|
+
init_mesh_runtime_store();
|
|
12678
|
+
init_mesh_missions();
|
|
12679
|
+
init_mesh_work_queue();
|
|
12680
|
+
init_mesh_ledger();
|
|
12681
|
+
init_mesh_active_work();
|
|
12682
|
+
IDLE_REMINDER_DEBOUNCE_MS = 3e5;
|
|
12683
|
+
MISSION_LIST_CAP = 10;
|
|
12684
|
+
}
|
|
12685
|
+
});
|
|
12686
|
+
|
|
12597
12687
|
// src/mesh/mesh-magi-status.ts
|
|
12598
12688
|
var mesh_magi_status_exports = {};
|
|
12599
12689
|
__export(mesh_magi_status_exports, {
|
|
@@ -20480,6 +20570,12 @@ function setupMeshEventForwarding(components) {
|
|
|
20480
20570
|
...forcePending ? { force: true } : {}
|
|
20481
20571
|
});
|
|
20482
20572
|
}
|
|
20573
|
+
} else {
|
|
20574
|
+
maybeInjectIdleActiveMissionReminder(
|
|
20575
|
+
coordinatorMeshId,
|
|
20576
|
+
flushSource,
|
|
20577
|
+
getMesh(coordinatorMeshId)?.policy
|
|
20578
|
+
);
|
|
20483
20579
|
}
|
|
20484
20580
|
} catch (e) {
|
|
20485
20581
|
LOG.warn("MeshEvents", `Failed to auto-flush pending coordinator events: ${e?.message || e}`);
|
|
@@ -20539,6 +20635,7 @@ var init_mesh_event_forwarding = __esm({
|
|
|
20539
20635
|
init_mesh_work_queue();
|
|
20540
20636
|
init_mesh_delivery_policy();
|
|
20541
20637
|
init_mesh_runtime_store();
|
|
20638
|
+
init_mesh_idle_reminder();
|
|
20542
20639
|
init_mesh_events_pending();
|
|
20543
20640
|
init_mesh_routing();
|
|
20544
20641
|
init_mesh_host_ownership();
|
|
@@ -20873,7 +20970,7 @@ async function collectLiveNodesWithSessions(components, mesh, selfIds, localDaem
|
|
|
20873
20970
|
let statusResult;
|
|
20874
20971
|
try {
|
|
20875
20972
|
if (isLocalNode) {
|
|
20876
|
-
statusResult = await components.
|
|
20973
|
+
statusResult = await components.router.execute("get_status_metadata", {}, "mesh");
|
|
20877
20974
|
} else if (dispatchMeshCommand) {
|
|
20878
20975
|
statusResult = await dispatchMeshCommand(nodeDaemonId, "get_status_metadata", {});
|
|
20879
20976
|
} else {
|
|
@@ -21840,7 +21937,14 @@ async function runMeshReconcileTick(components) {
|
|
|
21840
21937
|
}
|
|
21841
21938
|
if (store) {
|
|
21842
21939
|
try {
|
|
21843
|
-
if (store.pendingEventCount(meshId) === 0)
|
|
21940
|
+
if (store.pendingEventCount(meshId) === 0) {
|
|
21941
|
+
maybeInjectIdleActiveMissionReminder(
|
|
21942
|
+
meshId,
|
|
21943
|
+
targetCoordinators[0].instance,
|
|
21944
|
+
getMesh(meshId)?.policy
|
|
21945
|
+
);
|
|
21946
|
+
continue;
|
|
21947
|
+
}
|
|
21844
21948
|
} catch {
|
|
21845
21949
|
}
|
|
21846
21950
|
}
|
|
@@ -22014,6 +22118,7 @@ var init_mesh_reconcile_loop = __esm({
|
|
|
22014
22118
|
"use strict";
|
|
22015
22119
|
init_config();
|
|
22016
22120
|
init_mesh_config();
|
|
22121
|
+
init_mesh_idle_reminder();
|
|
22017
22122
|
init_logger();
|
|
22018
22123
|
init_mesh_events_pending();
|
|
22019
22124
|
init_mesh_ledger();
|
|
@@ -29259,6 +29364,7 @@ function buildMeshLedgerReconciliationEvidence(meshId, replicas) {
|
|
|
29259
29364
|
// src/index.ts
|
|
29260
29365
|
init_mesh_work_queue();
|
|
29261
29366
|
init_mesh_active_work();
|
|
29367
|
+
init_mesh_idle_reminder();
|
|
29262
29368
|
init_mesh_refine_status();
|
|
29263
29369
|
init_mesh_magi_status();
|
|
29264
29370
|
init_mesh_scheduling_runtime();
|
|
@@ -29269,8 +29375,8 @@ init_mesh_events_utils();
|
|
|
29269
29375
|
init_mesh_delivery_policy();
|
|
29270
29376
|
|
|
29271
29377
|
// src/mesh/p2p-relay-failure.ts
|
|
29272
|
-
var NO_FALLBACK_REASON = "
|
|
29273
|
-
var P2P_NEXT_ACTION = "
|
|
29378
|
+
var NO_FALLBACK_REASON = "This mesh operation needs a live peer-to-peer connection to the node, which is not open right now. This is often transient \u2014 the peer may be connecting, slow via TURN relay, or briefly offline. Wait a moment and retry, or re-establish the node's connection. Mesh commands use P2P only by design \u2014 there is no cloud/WS relay fallback.";
|
|
29379
|
+
var P2P_NEXT_ACTION = "The peer connection is recoverable. Wait a moment for the connection to establish (especially over TURN relay), then retry. If the node remains unreachable, check that the target daemon is running and online, then re-establish its connection.";
|
|
29274
29380
|
var NON_P2P_NEXT_ACTION = "Inspect the provider/command error and fix the underlying logic or configuration before retrying.";
|
|
29275
29381
|
function messageFromError(error) {
|
|
29276
29382
|
if (error instanceof Error) return error.message;
|
|
@@ -70359,6 +70465,7 @@ export {
|
|
|
70359
70465
|
GOAL_PREVIEW_MAX,
|
|
70360
70466
|
GitCommandError,
|
|
70361
70467
|
GitWorkspaceMonitor,
|
|
70468
|
+
IDLE_REMINDER_DEBOUNCE_MS,
|
|
70362
70469
|
IdeProviderInstance,
|
|
70363
70470
|
InMemoryGitSnapshotStore,
|
|
70364
70471
|
LOG,
|
|
@@ -70419,6 +70526,7 @@ export {
|
|
|
70419
70526
|
buildClaudeInteractiveToolResult,
|
|
70420
70527
|
buildCompactStaleDirectWorkSummary,
|
|
70421
70528
|
buildCoordinatorSystemPrompt,
|
|
70529
|
+
buildIdleReminderMessage,
|
|
70422
70530
|
buildIpcStatusHttpResponse,
|
|
70423
70531
|
buildMachineInfo,
|
|
70424
70532
|
buildMeshActiveWork,
|
|
@@ -70593,11 +70701,13 @@ export {
|
|
|
70593
70701
|
markSessionDeliveriesTerminal,
|
|
70594
70702
|
markSetupComplete,
|
|
70595
70703
|
markStaleDirectDispatches,
|
|
70704
|
+
maybeInjectIdleActiveMissionReminder,
|
|
70596
70705
|
maybeRunDaemonUpgradeHelperFromEnv,
|
|
70597
70706
|
mergeAndNormalizePolicy,
|
|
70598
70707
|
meshNodeIdMatches,
|
|
70599
70708
|
meshTaskNotBeforeReady,
|
|
70600
70709
|
meshTaskPriorityRank,
|
|
70710
|
+
missionSetHash,
|
|
70601
70711
|
namedKeyToAnsi,
|
|
70602
70712
|
namedKeysToAnsi,
|
|
70603
70713
|
nodeSatisfiesRequiredTags,
|
|
@@ -70694,6 +70804,7 @@ export {
|
|
|
70694
70804
|
setupIdeInstance,
|
|
70695
70805
|
shouldAutoRestoreHostedSessionsOnStartup,
|
|
70696
70806
|
shouldCollectTraceCategory,
|
|
70807
|
+
shouldFireIdleReminder,
|
|
70697
70808
|
shutdownDaemonComponents,
|
|
70698
70809
|
spawnDetachedDaemonUpgradeHelper,
|
|
70699
70810
|
startDaemonDevSupport,
|