@adhdev/daemon-standalone 0.9.82-rc.374 → 0.9.82-rc.376
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 +309 -56
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/vendor/mcp-server/index.js +47 -0
- package/vendor/mcp-server/index.js.map +1 -1
package/dist/index.js
CHANGED
|
@@ -30036,10 +30036,10 @@ var require_dist3 = __commonJS({
|
|
|
30036
30036
|
}
|
|
30037
30037
|
function getDaemonBuildInfo() {
|
|
30038
30038
|
if (cached2) return cached2;
|
|
30039
|
-
const commit = readInjected(true ? "
|
|
30040
|
-
const commitShort = readInjected(true ? "
|
|
30041
|
-
const version2 = readInjected(true ? "0.9.82-rc.
|
|
30042
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
30039
|
+
const commit = readInjected(true ? "5f02f35175e6b8b9d8c70d2232438b332cd18d84" : void 0) ?? "unknown";
|
|
30040
|
+
const commitShort = readInjected(true ? "5f02f351" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
30041
|
+
const version2 = readInjected(true ? "0.9.82-rc.376" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
30042
|
+
const builtAt = readInjected(true ? "2026-06-25T03:48:42.404Z" : void 0);
|
|
30043
30043
|
cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
|
|
30044
30044
|
return cached2;
|
|
30045
30045
|
}
|
|
@@ -32771,6 +32771,10 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
|
|
|
32771
32771
|
if (ctx.missionSection?.trim()) {
|
|
32772
32772
|
sections.push(ctx.missionSection.trim());
|
|
32773
32773
|
}
|
|
32774
|
+
const recentActivity = buildRecentActivitySection(ctx.recentActivity);
|
|
32775
|
+
if (recentActivity) sections.push(recentActivity);
|
|
32776
|
+
const operatingNotes = buildOperatingNotesSection(ctx.operatingNotes);
|
|
32777
|
+
if (operatingNotes) sections.push(operatingNotes);
|
|
32774
32778
|
sections.push(buildPolicySection({ ...DEFAULT_MESH_POLICY, ...mesh.policy || {} }));
|
|
32775
32779
|
sections.push(TOOLS_SECTION);
|
|
32776
32780
|
sections.push(TOOL_EXPOSURE_PREFLIGHT_SECTION);
|
|
@@ -32802,6 +32806,8 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
|
|
|
32802
32806
|
cliType: coordinatorCliType || "",
|
|
32803
32807
|
nodes: nodesSection,
|
|
32804
32808
|
mission: ctx.missionSection?.trim() || "",
|
|
32809
|
+
recentActivity: buildRecentActivitySection(ctx.recentActivity) || "",
|
|
32810
|
+
operatingNotes: buildOperatingNotesSection(ctx.operatingNotes) || "",
|
|
32805
32811
|
policy: buildPolicySection({ ...DEFAULT_MESH_POLICY, ...mesh.policy || {} }),
|
|
32806
32812
|
tools: TOOLS_SECTION,
|
|
32807
32813
|
workflow: WORKFLOW_SECTION,
|
|
@@ -32873,6 +32879,56 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
|
|
|
32873
32879
|
if (lines.length === 1) return lines[0];
|
|
32874
32880
|
return [lines[0], ...lines.slice(1).map((l) => pad + l)].join("\n");
|
|
32875
32881
|
}
|
|
32882
|
+
function buildRecentActivitySection(activity) {
|
|
32883
|
+
if (!activity) return "";
|
|
32884
|
+
const failures = Array.isArray(activity.recentFailures) ? activity.recentFailures : [];
|
|
32885
|
+
const pending = Number.isFinite(activity.pendingTasks) ? Number(activity.pendingTasks) : 0;
|
|
32886
|
+
const assigned = Number.isFinite(activity.assignedTasks) ? Number(activity.assignedTasks) : 0;
|
|
32887
|
+
const stalled = Number.isFinite(activity.stalledTasks) ? Number(activity.stalledTasks) : 0;
|
|
32888
|
+
const recentFailureCount = Number.isFinite(activity.recentFailureCount) ? Number(activity.recentFailureCount) : failures.length;
|
|
32889
|
+
if (failures.length === 0 && pending === 0 && assigned === 0 && stalled === 0 && recentFailureCount === 0) {
|
|
32890
|
+
return "";
|
|
32891
|
+
}
|
|
32892
|
+
const lines = ["## Recent Activity", ""];
|
|
32893
|
+
lines.push("A snapshot of this mesh's recent ledger/queue state at launch. Use it to decide what needs attention first; call `mesh_task_history` / `mesh_view_queue` for full detail.");
|
|
32894
|
+
lines.push("");
|
|
32895
|
+
const counts = [];
|
|
32896
|
+
if (pending > 0) counts.push(`**${pending}** pending`);
|
|
32897
|
+
if (assigned > 0) counts.push(`**${assigned}** assigned`);
|
|
32898
|
+
if (stalled > 0) counts.push(`**${stalled}** stalled`);
|
|
32899
|
+
if (recentFailureCount > 0) counts.push(`**${recentFailureCount}** failed in the last 30 min`);
|
|
32900
|
+
if (counts.length) lines.push(`- Queue/ledger: ${counts.join(", ")}.`);
|
|
32901
|
+
if (activity.lastActivityAt) lines.push(`- Last ledger activity: ${activity.lastActivityAt}.`);
|
|
32902
|
+
if (failures.length > 0) {
|
|
32903
|
+
const recent = failures.slice(-5).reverse();
|
|
32904
|
+
lines.push("", "Recent failures (newest first):");
|
|
32905
|
+
for (const f of recent) {
|
|
32906
|
+
const when = f.timestamp ? `${f.timestamp} ` : "";
|
|
32907
|
+
const node = f.nodeId ? `node \`${f.nodeId}\`` : "unknown node";
|
|
32908
|
+
const summary = (f.summary || "").trim();
|
|
32909
|
+
lines.push(`- ${when}${node}${summary ? ` \u2014 ${summary}` : ""}`);
|
|
32910
|
+
}
|
|
32911
|
+
lines.push("", "_Check `mesh_task_history` before retrying; repeated failures on the same node mean reassign or escalate, not retry._");
|
|
32912
|
+
}
|
|
32913
|
+
return lines.join("\n");
|
|
32914
|
+
}
|
|
32915
|
+
function buildOperatingNotesSection(notes) {
|
|
32916
|
+
const valid = Array.isArray(notes) ? notes.filter((n) => n && typeof n.text === "string" && n.text.trim()) : [];
|
|
32917
|
+
if (valid.length === 0) return "";
|
|
32918
|
+
const categoryLabel = {
|
|
32919
|
+
provider_quirk: "provider quirk",
|
|
32920
|
+
pattern_to_avoid: "pattern to avoid",
|
|
32921
|
+
recovery_lesson: "recovery lesson"
|
|
32922
|
+
};
|
|
32923
|
+
const lines = ["## Operating Notes", ""];
|
|
32924
|
+
lines.push("Lessons earlier coordinators on this mesh recorded via `mesh_record_note`. Treat them as accumulated operating knowledge \u2014 apply them. When you learn a durable lesson (a provider quirk, a pattern to avoid, a recovery lesson), record it with `mesh_record_note` so future coordinators inherit it.");
|
|
32925
|
+
lines.push("");
|
|
32926
|
+
for (const n of valid) {
|
|
32927
|
+
const cat = n.category && categoryLabel[n.category] ? `[${categoryLabel[n.category]}] ` : "";
|
|
32928
|
+
lines.push(`- ${cat}${n.text.trim()}`);
|
|
32929
|
+
}
|
|
32930
|
+
return lines.join("\n");
|
|
32931
|
+
}
|
|
32876
32932
|
function buildPolicySection(policy) {
|
|
32877
32933
|
const rules = [];
|
|
32878
32934
|
if (policy.requirePreTaskCheckpoint) rules.push("- Create a git checkpoint **before** starting each task");
|
|
@@ -32941,6 +32997,7 @@ ${rules.join("\n")}`;
|
|
|
32941
32997
|
| \`mesh_read_chat\` | Read recent chat messages from a delegated agent session |
|
|
32942
32998
|
| \`mesh_read_debug\` | Collect a daemon-side chat/parser debug bundle for a session |
|
|
32943
32999
|
| \`mesh_task_history\` | Read the task ledger \u2014 dispatches, completions, failures. Use to understand what has been done before deciding next steps |
|
|
33000
|
+
| \`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 |
|
|
32944
33001
|
| \`mesh_git_status\` | Check git status on a specific node |
|
|
32945
33002
|
| \`mesh_read_node_logs\` | Fetch a remote node's daemon log tail directly over P2P (grep/since/byte-bounded, secrets redacted) \u2014 no session/PowerShell needed to debug a node's daemon |
|
|
32946
33003
|
| \`mesh_fast_forward_node\` | Safely dry-run or explicitly execute an obvious clean fast-forward without launching an agent session |
|
|
@@ -42724,6 +42781,18 @@ ${cleanBody}`;
|
|
|
42724
42781
|
const diag = readRecord4(payload.completionDiagnostic);
|
|
42725
42782
|
return diag?.finalAssistantPresent === false || diag?.blockReason === "missing_final_assistant";
|
|
42726
42783
|
}
|
|
42784
|
+
function supersedesTruncatedTerminalSummary(args) {
|
|
42785
|
+
if (!args.terminalTaskId || !args.eventTaskId || args.terminalTaskId !== args.eventTaskId) return false;
|
|
42786
|
+
if (!isGenuineCompletionEvidence(args.metadataEvent)) return false;
|
|
42787
|
+
const terminalSummary = readNonEmptyString2(args.terminalPayload.finalSummary);
|
|
42788
|
+
const eventSummary = readNonEmptyString2(args.metadataEvent.finalSummary);
|
|
42789
|
+
if (!eventSummary) return false;
|
|
42790
|
+
if (terminalSummary === eventSummary) return false;
|
|
42791
|
+
if (isWeakTerminalLedgerPayload(args.terminalPayload)) return false;
|
|
42792
|
+
if (!terminalSummary) return true;
|
|
42793
|
+
if (eventSummary.startsWith(terminalSummary)) return true;
|
|
42794
|
+
return eventSummary.length > terminalSummary.length + 32;
|
|
42795
|
+
}
|
|
42727
42796
|
function resolveActiveDirectDispatchTaskId(meshId, sessionId) {
|
|
42728
42797
|
try {
|
|
42729
42798
|
const matches = getActiveDirectDispatches(meshId).filter((d) => d.sessionId === sessionId);
|
|
@@ -43640,7 +43709,13 @@ ${cleanBody}`;
|
|
|
43640
43709
|
const terminalTaskId = readNonEmptyString2(terminal.payload.taskId);
|
|
43641
43710
|
const eventTaskId = readNonEmptyString2(args.metadataEvent.taskId);
|
|
43642
43711
|
const distinctTaskCompletion = !!eventTaskId && !!terminalTaskId && eventTaskId !== terminalTaskId;
|
|
43643
|
-
|
|
43712
|
+
const supersedesTruncatedTerminal = supersedesTruncatedTerminalSummary({
|
|
43713
|
+
terminalPayload: terminal.payload,
|
|
43714
|
+
metadataEvent: args.metadataEvent,
|
|
43715
|
+
terminalTaskId,
|
|
43716
|
+
eventTaskId
|
|
43717
|
+
});
|
|
43718
|
+
if (!newDispatchAfterTerminal && !supersedesWeakTerminal && !distinctTaskCompletion && !supersedesTruncatedTerminal) {
|
|
43644
43719
|
const terminalProviderSessionId = readNonEmptyString2(terminal.payload.providerSessionId);
|
|
43645
43720
|
const terminalFinalSummary = readNonEmptyString2(terminal.payload.finalSummary);
|
|
43646
43721
|
const eventProviderSessionId = readNonEmptyString2(args.metadataEvent.providerSessionId);
|
|
@@ -44435,6 +44510,16 @@ ${cleanBody}`;
|
|
|
44435
44510
|
const status = readNonEmptyString2(state.status).toLowerCase();
|
|
44436
44511
|
const modalParked = status === "waiting_choice" || status === "waiting_approval";
|
|
44437
44512
|
const sessionId = readNonEmptyString2(state.instanceId);
|
|
44513
|
+
const stateKey = `${meshId}::${sessionId || "?"}`;
|
|
44514
|
+
const prevParked = coordinatorModalParkState.get(stateKey);
|
|
44515
|
+
if (prevParked !== modalParked) {
|
|
44516
|
+
coordinatorModalParkState.set(stateKey, modalParked);
|
|
44517
|
+
if (modalParked) {
|
|
44518
|
+
LOG2.info("MeshReconcile", `Coordinator ${sessionId || "?"} (mesh ${meshId}) entered modal-park (status=${status}) \u2014 terminal events for it will be held until the modal is answered`);
|
|
44519
|
+
} else if (prevParked === true) {
|
|
44520
|
+
LOG2.info("MeshReconcile", `Coordinator ${sessionId || "?"} (mesh ${meshId}) left modal-park (status=${status}) \u2014 held events will drain on this/next tick`);
|
|
44521
|
+
}
|
|
44522
|
+
}
|
|
44438
44523
|
out.push({ meshId, instance: inst, sessionId, idle: status === "idle", modalParked });
|
|
44439
44524
|
}
|
|
44440
44525
|
return out;
|
|
@@ -44628,7 +44713,55 @@ ${cleanBody}`;
|
|
|
44628
44713
|
const forceOnly = idleCoordinators.length === 0;
|
|
44629
44714
|
if (targetCoordinators.length === 0) {
|
|
44630
44715
|
if (modalParkedCoordinators.length > 0) {
|
|
44631
|
-
|
|
44716
|
+
const liveSessionIds = new Set(
|
|
44717
|
+
meshCoordinators.map((c) => readNonEmptyString2(c.sessionId)).filter(Boolean)
|
|
44718
|
+
);
|
|
44719
|
+
let orphanEscaped = 0;
|
|
44720
|
+
const hasPendingForOrphanPeek = !store || (() => {
|
|
44721
|
+
try {
|
|
44722
|
+
return store.pendingEventCount(meshId) > 0;
|
|
44723
|
+
} catch {
|
|
44724
|
+
return true;
|
|
44725
|
+
}
|
|
44726
|
+
})();
|
|
44727
|
+
if (hasPendingForOrphanPeek) {
|
|
44728
|
+
let peeked = [];
|
|
44729
|
+
try {
|
|
44730
|
+
peeked = getPendingMeshCoordinatorEvents(meshId, drainDaemonIds.length > 0 ? drainDaemonIds : void 0);
|
|
44731
|
+
} catch {
|
|
44732
|
+
peeked = [];
|
|
44733
|
+
}
|
|
44734
|
+
const isOrphan = (e) => {
|
|
44735
|
+
const want = readNonEmptyString2(e.targetCoordinatorSessionId);
|
|
44736
|
+
return !!want && !liveSessionIds.has(want);
|
|
44737
|
+
};
|
|
44738
|
+
const orphanEventNames = new Set(peeked.filter(isOrphan).map((e) => e.event));
|
|
44739
|
+
if (orphanEventNames.size > 0) {
|
|
44740
|
+
let drained = [];
|
|
44741
|
+
try {
|
|
44742
|
+
drained = drainPendingMeshCoordinatorEvents(
|
|
44743
|
+
meshId,
|
|
44744
|
+
drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId,
|
|
44745
|
+
{ onlyEvents: orphanEventNames }
|
|
44746
|
+
);
|
|
44747
|
+
} catch (e) {
|
|
44748
|
+
LOG2.warn("MeshReconcile", `Orphan-escape drain failed for mesh ${meshId}: ${e?.message || e}`);
|
|
44749
|
+
drained = [];
|
|
44750
|
+
}
|
|
44751
|
+
for (const pending of drained) {
|
|
44752
|
+
if (isOrphan(pending)) {
|
|
44753
|
+
holdOrExpireStrictUnmatchedEvent(pending, readNonEmptyString2(pending.targetCoordinatorSessionId), meshId);
|
|
44754
|
+
orphanEscaped++;
|
|
44755
|
+
} else {
|
|
44756
|
+
try {
|
|
44757
|
+
queuePendingMeshCoordinatorEvent(pending);
|
|
44758
|
+
} catch {
|
|
44759
|
+
}
|
|
44760
|
+
}
|
|
44761
|
+
}
|
|
44762
|
+
}
|
|
44763
|
+
}
|
|
44764
|
+
LOG2.info("MeshReconcile", `Reconcile skip \u2192 modal-parked: holding pending event(s) for mesh ${meshId} (${modalParkedCoordinators.length} coordinator(s) awaiting a modal answer; events left queued${orphanEscaped > 0 ? `; ${orphanEscaped} orphan-targeted event(s) routed to strict-route TTL` : ""})`);
|
|
44632
44765
|
let hasPending = true;
|
|
44633
44766
|
if (store) {
|
|
44634
44767
|
try {
|
|
@@ -44899,6 +45032,19 @@ ${cleanBody}`;
|
|
|
44899
45032
|
const messages = Array.isArray(payload.messages) ? payload.messages : [];
|
|
44900
45033
|
const evidence = extractFinalAssistantSummaryEvidence(messages);
|
|
44901
45034
|
if (!evidence.finalSummary) continue;
|
|
45035
|
+
const dispatchedAtMs = Date.parse(readNonEmptyString2(dispatch.dispatchedAt));
|
|
45036
|
+
const transcriptAtMs = Date.parse(evidence.transcriptMessageAt ?? "");
|
|
45037
|
+
if (Number.isFinite(dispatchedAtMs) && Number.isFinite(transcriptAtMs) && transcriptAtMs < dispatchedAtMs) {
|
|
45038
|
+
LOG2.info("MeshReconcile", `Stale-summary guard: skipping transcript reconcile for task ${taskId} on node ${nodeId} (mesh ${mesh.id}) \u2014 final assistant message (${evidence.transcriptMessageAt}) predates this task's dispatch (${dispatch.dispatchedAt}); it is a prior task's summary`);
|
|
45039
|
+
traceMeshEventDrop("reconcile_stale_summary_before_dispatch", {
|
|
45040
|
+
taskId,
|
|
45041
|
+
sessionId,
|
|
45042
|
+
nodeId,
|
|
45043
|
+
meshId: mesh.id,
|
|
45044
|
+
event: "agent:generating_completed"
|
|
45045
|
+
}, `transcriptAt=${evidence.transcriptMessageAt} < dispatchedAt=${dispatch.dispatchedAt}`);
|
|
45046
|
+
continue;
|
|
45047
|
+
}
|
|
44902
45048
|
const providerSessionId = readNonEmptyString2(payload.providerSessionId);
|
|
44903
45049
|
const coordinatorDaemonId = selfIds.find((id) => !!id);
|
|
44904
45050
|
try {
|
|
@@ -45028,6 +45174,7 @@ ${cleanBody}`;
|
|
|
45028
45174
|
}
|
|
45029
45175
|
var DEFAULT_RECONCILE_INTERVAL_MS;
|
|
45030
45176
|
var DEFAULT_AUTO_PRUNE_MIN_AGE_MS;
|
|
45177
|
+
var coordinatorModalParkState;
|
|
45031
45178
|
var heldEventLedgerRecorded;
|
|
45032
45179
|
var ASSIGNED_STRANDED_DEADLINE_MS;
|
|
45033
45180
|
var STRICT_SESSION_MATCH_TTL_MS;
|
|
@@ -45054,6 +45201,7 @@ ${cleanBody}`;
|
|
|
45054
45201
|
init_chat_message_normalization();
|
|
45055
45202
|
DEFAULT_RECONCILE_INTERVAL_MS = 4e3;
|
|
45056
45203
|
DEFAULT_AUTO_PRUNE_MIN_AGE_MS = 24 * 60 * 6e4;
|
|
45204
|
+
coordinatorModalParkState = /* @__PURE__ */ new Map();
|
|
45057
45205
|
heldEventLedgerRecorded = /* @__PURE__ */ new Set();
|
|
45058
45206
|
ASSIGNED_STRANDED_DEADLINE_MS = 5 * 6e4;
|
|
45059
45207
|
STRICT_SESSION_MATCH_TTL_MS = 6e4;
|
|
@@ -67800,6 +67948,8 @@ ${body}
|
|
|
67800
67948
|
}
|
|
67801
67949
|
var COMPLETED_FINALIZATION_RETRY_MS = 1e3;
|
|
67802
67950
|
var COMPLETED_FINALIZATION_MAX_WAIT_MS = 3e4;
|
|
67951
|
+
var NATIVE_HISTORY_MESH_IDLE_SETTLE_MS = 1500;
|
|
67952
|
+
var USER_INPUT_ACK_DEDUP_WINDOW_MS = 6e4;
|
|
67803
67953
|
var TERMINAL_MESH_EVENTS = /* @__PURE__ */ new Set([
|
|
67804
67954
|
"agent:generating_completed",
|
|
67805
67955
|
"agent:stopped",
|
|
@@ -68071,6 +68221,14 @@ ${body}
|
|
|
68071
68221
|
runtimeMessages = [];
|
|
68072
68222
|
lastPersistedHistoryMessages = [];
|
|
68073
68223
|
lastAcknowledgedUserInputAt = 0;
|
|
68224
|
+
// TASKBUBBLE-DUP: per-content last-ack timestamps so the same dispatched
|
|
68225
|
+
// prompt acked twice in quick succession (the worker buffers the first
|
|
68226
|
+
// send during bootstrap/busy, then a redelivery — dispatch-confirm-timeout
|
|
68227
|
+
// requeue or a reconcile re-dispatch — fires a SECOND send_chat before the
|
|
68228
|
+
// outbound queue drains) collapses to ONE user bubble. Keyed on the trimmed
|
|
68229
|
+
// content; an entry older than USER_INPUT_ACK_DEDUP_WINDOW_MS is treated as
|
|
68230
|
+
// a fresh, intentional resend and is NOT suppressed.
|
|
68231
|
+
recentUserInputAcks = /* @__PURE__ */ new Map();
|
|
68074
68232
|
lastNativeSourceCanonicalCheckAt = 0;
|
|
68075
68233
|
lastNativeSourceCanonicalCacheKey = void 0;
|
|
68076
68234
|
cachedSqliteDb = null;
|
|
@@ -68505,6 +68663,15 @@ ${body}
|
|
|
68505
68663
|
const content = typeof input === "string" ? input.trim() : buildCliStructuredInputPrompt(input).trim();
|
|
68506
68664
|
if (!content) return;
|
|
68507
68665
|
const receivedAt = Date.now();
|
|
68666
|
+
const ackContentKey = shortHash(`${this.instanceId}:${content}`, 24);
|
|
68667
|
+
const lastAckAt = this.recentUserInputAcks.get(ackContentKey);
|
|
68668
|
+
if (lastAckAt !== void 0 && receivedAt - lastAckAt <= USER_INPUT_ACK_DEDUP_WINDOW_MS) {
|
|
68669
|
+
this.recentUserInputAcks.set(ackContentKey, receivedAt);
|
|
68670
|
+
this.pruneRecentUserInputAcks(receivedAt);
|
|
68671
|
+
return;
|
|
68672
|
+
}
|
|
68673
|
+
this.recentUserInputAcks.set(ackContentKey, receivedAt);
|
|
68674
|
+
this.pruneRecentUserInputAcks(receivedAt);
|
|
68508
68675
|
this.lastAcknowledgedUserInputAt = receivedAt;
|
|
68509
68676
|
const dedupKey = `user_input_ack:${shortHash(`${this.instanceId}:${content}:${receivedAt}`, 24)}`;
|
|
68510
68677
|
this.appendRuntimeMessage(buildChatMessage({
|
|
@@ -68522,6 +68689,13 @@ ${body}
|
|
|
68522
68689
|
}
|
|
68523
68690
|
}), dedupKey);
|
|
68524
68691
|
}
|
|
68692
|
+
/** Drop user-input ack entries older than the dedup window so the map can't grow unbounded. */
|
|
68693
|
+
pruneRecentUserInputAcks(now) {
|
|
68694
|
+
if (this.recentUserInputAcks.size <= 1) return;
|
|
68695
|
+
for (const [key, at] of this.recentUserInputAcks) {
|
|
68696
|
+
if (now - at > USER_INPUT_ACK_DEDUP_WINDOW_MS) this.recentUserInputAcks.delete(key);
|
|
68697
|
+
}
|
|
68698
|
+
}
|
|
68525
68699
|
dispose() {
|
|
68526
68700
|
this.adapter.shutdown();
|
|
68527
68701
|
this.monitor.reset();
|
|
@@ -69211,8 +69385,9 @@ ${body}
|
|
|
69211
69385
|
previousStatus: this.lastStatus
|
|
69212
69386
|
};
|
|
69213
69387
|
const ownsExternalHistory = !!this.adapter?.chatMessagesOwnedExternally;
|
|
69214
|
-
const
|
|
69215
|
-
|
|
69388
|
+
const meshWorkerSession = this.isMeshWorkerSession();
|
|
69389
|
+
const flushDelay = ownsExternalHistory ? meshWorkerSession ? NATIVE_HISTORY_MESH_IDLE_SETTLE_MS : 0 : 3e3;
|
|
69390
|
+
LOG2.debug("CLI", `[${this.type}] set completedDebouncePending duration=${duration3}s ownsExternalHistory=${ownsExternalHistory} meshWorker=${meshWorkerSession} flushDelay=${flushDelay}ms generatingStartedAt=${this.generatingStartedAt}`);
|
|
69216
69391
|
this.scheduleCompletedDebounceFlush(flushDelay);
|
|
69217
69392
|
}
|
|
69218
69393
|
} else if (newStatus === "idle" && this.lastStatus === "starting") {
|
|
@@ -72257,11 +72432,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
72257
72432
|
}
|
|
72258
72433
|
}
|
|
72259
72434
|
}
|
|
72260
|
-
const agentResult = await ctx.deps.cliManager.handleCliCommand("agent_command", args);
|
|
72261
72435
|
const meshCtx = args?.meshContext;
|
|
72262
72436
|
const dispatchNodeId = readStringValue(meshCtx?.nodeId);
|
|
72263
72437
|
const dispatchMeshId = readStringValue(meshCtx?.meshId);
|
|
72264
|
-
|
|
72438
|
+
const isSendChat = args?.action === "send_chat";
|
|
72439
|
+
if (isSendChat && dispatchNodeId && dispatchMeshId) {
|
|
72265
72440
|
try {
|
|
72266
72441
|
const { getMesh: getMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
72267
72442
|
const meshObj = getMesh2(dispatchMeshId) ?? ctx.getCachedInlineMesh(dispatchMeshId);
|
|
@@ -72269,17 +72444,22 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
72269
72444
|
const bootstrapStatus = readStringValue(nodeObj?.worktreeBootstrap?.status);
|
|
72270
72445
|
if (bootstrapStatus === "running") {
|
|
72271
72446
|
return {
|
|
72272
|
-
success:
|
|
72273
|
-
|
|
72274
|
-
|
|
72275
|
-
|
|
72276
|
-
|
|
72447
|
+
success: false,
|
|
72448
|
+
recoverable: true,
|
|
72449
|
+
dispatched: false,
|
|
72450
|
+
code: "mesh_node_bootstrap_pending",
|
|
72451
|
+
reason: "bootstrap_still_running",
|
|
72452
|
+
nodeId: dispatchNodeId,
|
|
72453
|
+
meshId: dispatchMeshId,
|
|
72454
|
+
...readStringValue(meshCtx?.taskId) ? { taskId: readStringValue(meshCtx?.taskId) } : {},
|
|
72455
|
+
error: `Node '${dispatchNodeId}' worktree bootstrap is still running; a task injected now would land in the session input buffer before the provider is ready to consume it and be silently lost. Dispatch deferred.`,
|
|
72456
|
+
nextAction: "Wait for the worktree_bootstrap_complete event (or poll mesh_status until the node session is ready), then re-send the task with mesh_send_task. Alternatively use mesh_enqueue_task so the queue auto-assigns it once a ready session is available."
|
|
72277
72457
|
};
|
|
72278
72458
|
}
|
|
72279
72459
|
} catch {
|
|
72280
72460
|
}
|
|
72281
72461
|
}
|
|
72282
|
-
return
|
|
72462
|
+
return ctx.deps.cliManager.handleCliCommand("agent_command", args);
|
|
72283
72463
|
},
|
|
72284
72464
|
// ─── Logs ───
|
|
72285
72465
|
list_saved_sessions: async (ctx, args) => {
|
|
@@ -77361,49 +77541,72 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
77361
77541
|
};
|
|
77362
77542
|
},
|
|
77363
77543
|
fast_forward_mesh_node: async (ctx, args) => {
|
|
77364
|
-
const
|
|
77365
|
-
const
|
|
77366
|
-
|
|
77367
|
-
|
|
77368
|
-
|
|
77369
|
-
|
|
77370
|
-
|
|
77371
|
-
|
|
77372
|
-
|
|
77373
|
-
|
|
77374
|
-
if (
|
|
77375
|
-
|
|
77544
|
+
const workspaceForError = typeof args?.workspace === "string" ? args.workspace.trim() : "";
|
|
77545
|
+
const meshIdForError = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
77546
|
+
const nodeIdForError = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
77547
|
+
try {
|
|
77548
|
+
const meshId = meshIdForError;
|
|
77549
|
+
const nodeId = nodeIdForError;
|
|
77550
|
+
let workspace = workspaceForError;
|
|
77551
|
+
let submoduleIgnorePaths = Array.isArray(args?.submoduleIgnorePaths) ? args.submoduleIgnorePaths.filter((value) => typeof value === "string") : void 0;
|
|
77552
|
+
let nodeDaemonId;
|
|
77553
|
+
let allowAutoPublishSubmoduleMainCommits = false;
|
|
77554
|
+
if (meshId && nodeId) {
|
|
77555
|
+
const meshRecord = await ctx.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
77556
|
+
const mesh = meshRecord?.mesh;
|
|
77557
|
+
const node = mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
|
|
77558
|
+
if (!workspace) {
|
|
77559
|
+
workspace = typeof node?.workspace === "string" ? node.workspace.trim() : "";
|
|
77560
|
+
}
|
|
77561
|
+
if (!submoduleIgnorePaths && Array.isArray(node?.policy?.submoduleIgnorePaths)) {
|
|
77562
|
+
submoduleIgnorePaths = node.policy.submoduleIgnorePaths.filter((value) => typeof value === "string");
|
|
77563
|
+
}
|
|
77564
|
+
allowAutoPublishSubmoduleMainCommits = mesh?.policy?.allowAutoPublishSubmoduleMainCommits === true;
|
|
77565
|
+
nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
77376
77566
|
}
|
|
77377
|
-
|
|
77378
|
-
|
|
77567
|
+
const selfDaemonId = ctx.deps.statusInstanceId;
|
|
77568
|
+
const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
|
|
77569
|
+
if (isRemote && ctx.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
77570
|
+
const forwarded = await ctx.deps.dispatchMeshCommand(nodeDaemonId, "fast_forward_mesh_node", {
|
|
77571
|
+
...typeof args === "object" && args !== null ? args : {},
|
|
77572
|
+
workspace,
|
|
77573
|
+
_meshDirectDispatch: true
|
|
77574
|
+
});
|
|
77575
|
+
return forwarded ?? { success: false, error: "no response from remote node" };
|
|
77379
77576
|
}
|
|
77380
|
-
|
|
77381
|
-
|
|
77382
|
-
|
|
77383
|
-
const selfDaemonId = ctx.deps.statusInstanceId;
|
|
77384
|
-
const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
|
|
77385
|
-
if (isRemote && ctx.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
77386
|
-
const forwarded = await ctx.deps.dispatchMeshCommand(nodeDaemonId, "fast_forward_mesh_node", {
|
|
77387
|
-
...typeof args === "object" && args !== null ? args : {},
|
|
77577
|
+
const result = await fastForwardMeshNode({
|
|
77578
|
+
meshId: meshId || void 0,
|
|
77579
|
+
nodeId: nodeId || void 0,
|
|
77388
77580
|
workspace,
|
|
77389
|
-
|
|
77581
|
+
branch: typeof args?.branch === "string" ? args.branch : void 0,
|
|
77582
|
+
execute: args?.execute === true,
|
|
77583
|
+
dryRun: args?.dryRun === true,
|
|
77584
|
+
updateSubmodules: args?.updateSubmodules === true,
|
|
77585
|
+
submoduleIgnorePaths,
|
|
77586
|
+
mode: args?.mode === "push" ? "push" : "merge",
|
|
77587
|
+
pushSubmodules: args?.pushSubmodules === true,
|
|
77588
|
+
allowAutoPublishSubmoduleMainCommits
|
|
77390
77589
|
});
|
|
77391
|
-
return
|
|
77590
|
+
return result;
|
|
77591
|
+
} catch (e) {
|
|
77592
|
+
const errorMessage = e?.message || String(e);
|
|
77593
|
+
return {
|
|
77594
|
+
success: false,
|
|
77595
|
+
code: "fast_forward_safety_gate_error",
|
|
77596
|
+
...meshIdForError ? { meshId: meshIdForError } : {},
|
|
77597
|
+
...nodeIdForError ? { nodeId: nodeIdForError } : {},
|
|
77598
|
+
workspace: workspaceForError,
|
|
77599
|
+
mode: args?.mode === "push" ? "push" : "merge",
|
|
77600
|
+
allowed: false,
|
|
77601
|
+
willRun: false,
|
|
77602
|
+
executed: false,
|
|
77603
|
+
// Surface the throw as a blocking reason instead of an opaque IPC crash
|
|
77604
|
+
// so the coordinator gets the same structured shape a clean node returns.
|
|
77605
|
+
blockingReasons: ["fast_forward_safety_gate_error"],
|
|
77606
|
+
operationError: errorMessage,
|
|
77607
|
+
error: errorMessage
|
|
77608
|
+
};
|
|
77392
77609
|
}
|
|
77393
|
-
const result = await fastForwardMeshNode({
|
|
77394
|
-
meshId: meshId || void 0,
|
|
77395
|
-
nodeId: nodeId || void 0,
|
|
77396
|
-
workspace,
|
|
77397
|
-
branch: typeof args?.branch === "string" ? args.branch : void 0,
|
|
77398
|
-
execute: args?.execute === true,
|
|
77399
|
-
dryRun: args?.dryRun === true,
|
|
77400
|
-
updateSubmodules: args?.updateSubmodules === true,
|
|
77401
|
-
submoduleIgnorePaths,
|
|
77402
|
-
mode: args?.mode === "push" ? "push" : "merge",
|
|
77403
|
-
pushSubmodules: args?.pushSubmodules === true,
|
|
77404
|
-
allowAutoPublishSubmoduleMainCommits
|
|
77405
|
-
});
|
|
77406
|
-
return result;
|
|
77407
77610
|
},
|
|
77408
77611
|
refine_mesh_node: async (ctx, args) => {
|
|
77409
77612
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
@@ -77552,6 +77755,56 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
77552
77755
|
return "";
|
|
77553
77756
|
}
|
|
77554
77757
|
};
|
|
77758
|
+
const buildRecentActivityBestEffort = async (id) => {
|
|
77759
|
+
try {
|
|
77760
|
+
const { getLedgerSummary: getLedgerSummary2, readLedgerEntries: readLedgerEntries2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
77761
|
+
const { getMeshQueueStats: getMeshQueueStats2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
77762
|
+
const summary = getLedgerSummary2(id);
|
|
77763
|
+
const queue = getMeshQueueStats2(id);
|
|
77764
|
+
const failureEntries = readLedgerEntries2(id, { kind: ["task_failed"], tail: 5 });
|
|
77765
|
+
const recentFailures = failureEntries.map((e) => {
|
|
77766
|
+
const p = e.payload || {};
|
|
77767
|
+
const raw = typeof p.taskSummary === "string" ? p.taskSummary : typeof p.message === "string" ? p.message : typeof p.error === "string" ? p.error : "";
|
|
77768
|
+
const summaryText = raw.length > 160 ? `${raw.slice(0, 160)}\u2026` : raw;
|
|
77769
|
+
return {
|
|
77770
|
+
timestamp: e.timestamp,
|
|
77771
|
+
nodeId: e.nodeId,
|
|
77772
|
+
summary: summaryText
|
|
77773
|
+
};
|
|
77774
|
+
});
|
|
77775
|
+
return {
|
|
77776
|
+
recentFailures,
|
|
77777
|
+
recentFailureCount: summary.recentFailures,
|
|
77778
|
+
pendingTasks: queue.pending,
|
|
77779
|
+
assignedTasks: queue.assigned,
|
|
77780
|
+
stalledTasks: summary.taskStalled,
|
|
77781
|
+
lastActivityAt: summary.lastActivityAt
|
|
77782
|
+
};
|
|
77783
|
+
} catch {
|
|
77784
|
+
return void 0;
|
|
77785
|
+
}
|
|
77786
|
+
};
|
|
77787
|
+
const buildOperatingNotesBestEffort = async (id) => {
|
|
77788
|
+
try {
|
|
77789
|
+
const { readLedgerEntries: readLedgerEntries2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
77790
|
+
const noteEntries = readLedgerEntries2(id, { kind: ["coordinator_operating_note"], tail: 20 });
|
|
77791
|
+
const notes = noteEntries.map((e) => {
|
|
77792
|
+
const p = e.payload || {};
|
|
77793
|
+
const text = typeof p.text === "string" ? p.text.trim() : "";
|
|
77794
|
+
if (!text) return null;
|
|
77795
|
+
const category = p.category === "provider_quirk" || p.category === "pattern_to_avoid" || p.category === "recovery_lesson" ? p.category : void 0;
|
|
77796
|
+
return {
|
|
77797
|
+
text,
|
|
77798
|
+
category,
|
|
77799
|
+
createdAt: typeof p.createdAt === "string" ? p.createdAt : e.timestamp,
|
|
77800
|
+
sourceCoordinator: typeof p.sourceCoordinator === "string" ? p.sourceCoordinator : void 0
|
|
77801
|
+
};
|
|
77802
|
+
}).filter((n) => n !== null);
|
|
77803
|
+
return notes.length ? notes : void 0;
|
|
77804
|
+
} catch {
|
|
77805
|
+
return void 0;
|
|
77806
|
+
}
|
|
77807
|
+
};
|
|
77555
77808
|
let mesh;
|
|
77556
77809
|
if (args?.inlineMesh && typeof args.inlineMesh === "object") {
|
|
77557
77810
|
mesh = args.inlineMesh;
|
|
@@ -77642,7 +77895,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
77642
77895
|
if (coordinatorSetup.kind === "cli_command") {
|
|
77643
77896
|
let cliCmdSystemPrompt = "";
|
|
77644
77897
|
try {
|
|
77645
|
-
cliCmdSystemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id) });
|
|
77898
|
+
cliCmdSystemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id), recentActivity: await buildRecentActivityBestEffort(mesh.id), operatingNotes: await buildOperatingNotesBestEffort(mesh.id) });
|
|
77646
77899
|
} catch (error48) {
|
|
77647
77900
|
const message = error48?.message || String(error48);
|
|
77648
77901
|
LOG2.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
|
|
@@ -77819,7 +78072,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
77819
78072
|
}
|
|
77820
78073
|
let systemPrompt = "";
|
|
77821
78074
|
try {
|
|
77822
|
-
systemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id) });
|
|
78075
|
+
systemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id), recentActivity: await buildRecentActivityBestEffort(mesh.id), operatingNotes: await buildOperatingNotesBestEffort(mesh.id) });
|
|
77823
78076
|
} catch (error48) {
|
|
77824
78077
|
const message = error48?.message || String(error48);
|
|
77825
78078
|
LOG2.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
|