@adhdev/daemon-core 0.9.82-rc.441 → 0.9.82-rc.443
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/high-family/types.d.ts +4 -0
- package/dist/commands/router.d.ts +4 -0
- package/dist/index.js +249 -53
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +249 -53
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-node-identity.d.ts +15 -0
- package/dist/mesh/mesh-reconcile-loop.d.ts +15 -1
- package/dist/providers/chat-message-normalization.d.ts +1 -0
- package/dist/providers/cli-provider-instance.d.ts +1 -0
- package/package.json +2 -2
- package/src/commands/chat-commands-read.ts +41 -0
- package/src/commands/high-family/mesh-events.ts +11 -2
- package/src/commands/high-family/mesh-status.ts +102 -9
- package/src/commands/high-family/types.ts +5 -1
- package/src/commands/router.ts +19 -2
- package/src/mesh/mesh-node-identity.ts +106 -18
- package/src/mesh/mesh-reconcile-loop.ts +22 -1
- package/src/providers/chat-message-normalization.ts +1 -1
- package/src/providers/cli-provider-instance.ts +95 -8
- package/src/providers/spec/native-history-executor.ts +52 -21
package/dist/index.mjs
CHANGED
|
@@ -404,10 +404,10 @@ function readInjected(value) {
|
|
|
404
404
|
}
|
|
405
405
|
function getDaemonBuildInfo() {
|
|
406
406
|
if (cached) return cached;
|
|
407
|
-
const commit = readInjected(true ? "
|
|
408
|
-
const commitShort = readInjected(true ? "
|
|
409
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
410
|
-
const builtAt = readInjected(true ? "2026-07-
|
|
407
|
+
const commit = readInjected(true ? "21c6fe269d621db0b4841be14c111d4d656d6996" : void 0) ?? "unknown";
|
|
408
|
+
const commitShort = readInjected(true ? "21c6fe26" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
409
|
+
const version = readInjected(true ? "0.9.82-rc.443" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
410
|
+
const builtAt = readInjected(true ? "2026-07-01T10:41:15.424Z" : void 0);
|
|
411
411
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
412
412
|
return cached;
|
|
413
413
|
}
|
|
@@ -17195,7 +17195,7 @@ function resolveCoordinatorDrainDeliverability(components, meshId) {
|
|
|
17195
17195
|
holdForReconcile: !hasIdle
|
|
17196
17196
|
};
|
|
17197
17197
|
}
|
|
17198
|
-
function shouldHoldPendingDrainForBusyLocalCoordinator(components, meshId, requestedCoordinatorDaemonId) {
|
|
17198
|
+
function shouldHoldPendingDrainForBusyLocalCoordinator(components, meshId, requestedCoordinatorDaemonId, callerIsSelfCoordinatorInboxRead) {
|
|
17199
17199
|
if (!meshId) return false;
|
|
17200
17200
|
const deliverability = resolveCoordinatorDrainDeliverability(components, meshId);
|
|
17201
17201
|
if (!deliverability.holdForReconcile) return false;
|
|
@@ -17205,7 +17205,10 @@ function shouldHoldPendingDrainForBusyLocalCoordinator(components, meshId, reque
|
|
|
17205
17205
|
readNonEmptyString2(components.statusInstanceId),
|
|
17206
17206
|
readNonEmptyString2(loadConfig().machineId)
|
|
17207
17207
|
]);
|
|
17208
|
-
|
|
17208
|
+
const targetsLocalCoordinator = localIds.some((id) => daemonIdsEquivalent(id, requested));
|
|
17209
|
+
if (!targetsLocalCoordinator) return false;
|
|
17210
|
+
if (callerIsSelfCoordinatorInboxRead) return false;
|
|
17211
|
+
return true;
|
|
17209
17212
|
}
|
|
17210
17213
|
function injectPendingIntoCoordinator(coordinator, pending) {
|
|
17211
17214
|
if (!coordinator) return;
|
|
@@ -32038,6 +32041,26 @@ async function handleReadChat(h, args) {
|
|
|
32038
32041
|
ptyStatusApprovalOnly: false
|
|
32039
32042
|
});
|
|
32040
32043
|
if (supportsNative && !decision.nativeSelected) {
|
|
32044
|
+
if (safeMapping && historyMessages.length > 0) {
|
|
32045
|
+
LOG.debug("Command", `[read_chat] native-only content preserved despite pty-parser selection target=${String(args?.targetSessionId || "")} provider=${agentStr} rows=${historyMessages.length} cause=${decision.decision.transition.cause}`);
|
|
32046
|
+
return buildReadChatCommandResult({
|
|
32047
|
+
messages: historyMessages,
|
|
32048
|
+
status: "idle",
|
|
32049
|
+
messageSource: {
|
|
32050
|
+
...decision.messageSource,
|
|
32051
|
+
nativeOnlyContentPreserved: true,
|
|
32052
|
+
returnedMessageCount: historyMessages.length
|
|
32053
|
+
},
|
|
32054
|
+
transcriptProvenance: {
|
|
32055
|
+
...decision.messageSource,
|
|
32056
|
+
nativeOnlyContentPreserved: true
|
|
32057
|
+
},
|
|
32058
|
+
...typeof history?.title === "string" ? { title: history.title } : {},
|
|
32059
|
+
...historyProviderSessionId ? { providerSessionId: historyProviderSessionId } : {},
|
|
32060
|
+
...provider?.historyBehavior?.transcriptAuthority === "provider" || provider?.historyBehavior?.transcriptAuthority === "daemon" ? { transcriptAuthority: (provider?.historyBehavior).transcriptAuthority } : {},
|
|
32061
|
+
coverage: "tail"
|
|
32062
|
+
}, args, h);
|
|
32063
|
+
}
|
|
32041
32064
|
LOG.debug("Command", `[read_chat] soft pending: no live adapter and native history not safely mappable target=${String(args?.targetSessionId || "")} provider=${agentStr} reason=native_history_not_safely_available`);
|
|
32042
32065
|
return {
|
|
32043
32066
|
success: true,
|
|
@@ -38731,10 +38754,17 @@ function executeSqlite(src, input) {
|
|
|
38731
38754
|
}
|
|
38732
38755
|
try {
|
|
38733
38756
|
const requested = input.providerSessionId || "";
|
|
38734
|
-
|
|
38735
|
-
|
|
38736
|
-
|
|
38737
|
-
|
|
38757
|
+
const resolveMessagesFor = (sessionId2) => {
|
|
38758
|
+
if (!sessionId2) return null;
|
|
38759
|
+
let rows;
|
|
38760
|
+
try {
|
|
38761
|
+
rows = db.prepare(src.message_query).all(sessionId2);
|
|
38762
|
+
} catch {
|
|
38763
|
+
return null;
|
|
38764
|
+
}
|
|
38765
|
+
return rows && rows.length > 0 ? rows : null;
|
|
38766
|
+
};
|
|
38767
|
+
const resolveNewestSessionId = () => {
|
|
38738
38768
|
let sessionRow;
|
|
38739
38769
|
try {
|
|
38740
38770
|
const sessionFloorSeconds = typeof input.sessionStartedAtMs === "number" ? Math.floor(input.sessionStartedAtMs / 1e3) : 0;
|
|
@@ -38745,14 +38775,27 @@ function executeSqlite(src, input) {
|
|
|
38745
38775
|
sessionRow = stmt.get();
|
|
38746
38776
|
}
|
|
38747
38777
|
} catch {
|
|
38748
|
-
return
|
|
38778
|
+
return "";
|
|
38749
38779
|
}
|
|
38750
|
-
if (!sessionRow) return
|
|
38780
|
+
if (!sessionRow) return "";
|
|
38751
38781
|
const sessionIdRaw = Object.values(sessionRow)[0];
|
|
38752
|
-
|
|
38782
|
+
return sessionIdRaw == null ? "" : String(sessionIdRaw);
|
|
38783
|
+
};
|
|
38784
|
+
let sessionId;
|
|
38785
|
+
let messageRows;
|
|
38786
|
+
if (requested) {
|
|
38787
|
+
messageRows = resolveMessagesFor(requested);
|
|
38788
|
+
if (messageRows) {
|
|
38789
|
+
sessionId = requested;
|
|
38790
|
+
} else {
|
|
38791
|
+
sessionId = resolveNewestSessionId();
|
|
38792
|
+
messageRows = resolveMessagesFor(sessionId);
|
|
38793
|
+
}
|
|
38794
|
+
} else {
|
|
38795
|
+
sessionId = resolveNewestSessionId();
|
|
38796
|
+
messageRows = resolveMessagesFor(sessionId);
|
|
38753
38797
|
}
|
|
38754
38798
|
if (!sessionId) return null;
|
|
38755
|
-
const messageRows = db.prepare(src.message_query).all(sessionId);
|
|
38756
38799
|
if (!messageRows || messageRows.length === 0) return null;
|
|
38757
38800
|
const mtime = safeMtimeMs(resolved);
|
|
38758
38801
|
const messages = [];
|
|
@@ -40619,6 +40662,15 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
40619
40662
|
// first sets it; the other becomes a no-op.
|
|
40620
40663
|
agentReadyEmitted = false;
|
|
40621
40664
|
generatingStartedAt = 0;
|
|
40665
|
+
// FALSE-IDLE continuity epoch: monotonically bumped on EVERY entry into a busy
|
|
40666
|
+
// phase (→generating or →waiting_approval). The completedDebouncePending snapshots
|
|
40667
|
+
// this value at arm time (busyEpochAtArm); the flush guard requires it UNCHANGED
|
|
40668
|
+
// — proving the session did not re-enter a busy phase (a momentary busy→idle blip
|
|
40669
|
+
// in an inter-approval valley) between arming the debounce and flushing it. A
|
|
40670
|
+
// single point-sample of status at flush time cannot see a generating phase that
|
|
40671
|
+
// opened AND closed within the settle window; the epoch can. See
|
|
40672
|
+
// flushCompletedDebounceIfFinalized.
|
|
40673
|
+
busyEpoch = 0;
|
|
40622
40674
|
// GENERATING-BOUNDARY (R4b): the per-turn taskId for which a startup-grace
|
|
40623
40675
|
// started+completed pair was already synthesized. Both fast-collapse callers
|
|
40624
40676
|
// (starting→idle transition AND the idle-stayed no-status-change poll) route
|
|
@@ -41285,13 +41337,17 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
41285
41337
|
}
|
|
41286
41338
|
this.applyProviderResponse(parsed.payload, { phase: "immediate" });
|
|
41287
41339
|
}
|
|
41288
|
-
completionHasFinalAssistantMessage(messages) {
|
|
41340
|
+
completionHasFinalAssistantMessage(messages, turnStartedAt) {
|
|
41289
41341
|
const visibleMessages = (Array.isArray(messages) ? messages : []).filter((message) => isUserFacingChatMessage(message));
|
|
41290
41342
|
const lastVisible = visibleMessages[visibleMessages.length - 1];
|
|
41291
41343
|
const role = typeof lastVisible?.role === "string" ? lastVisible.role.trim().toLowerCase() : "";
|
|
41292
41344
|
const content = lastVisible ? flattenContent(lastVisible.content).trim() : "";
|
|
41293
41345
|
if (role !== "assistant" || !content) return false;
|
|
41294
41346
|
if (looksLikeActiveApprovalPromptText(content)) return false;
|
|
41347
|
+
if (typeof turnStartedAt === "number" && Number.isFinite(turnStartedAt) && turnStartedAt > 0) {
|
|
41348
|
+
const ts2 = readChatMessageTimestampMs(lastVisible);
|
|
41349
|
+
if (typeof ts2 === "number" && ts2 < turnStartedAt) return false;
|
|
41350
|
+
}
|
|
41295
41351
|
return true;
|
|
41296
41352
|
}
|
|
41297
41353
|
buildExternalTranscriptProbe(messages, sourcePath, sourceMtimeMs) {
|
|
@@ -41354,8 +41410,8 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
41354
41410
|
);
|
|
41355
41411
|
return restoredHistory.messages;
|
|
41356
41412
|
}
|
|
41357
|
-
completionFinalAssistantEvidence(parsedMessages) {
|
|
41358
|
-
if (this.completionHasFinalAssistantMessage(parsedMessages)) {
|
|
41413
|
+
completionFinalAssistantEvidence(parsedMessages, turnStartedAt) {
|
|
41414
|
+
if (this.completionHasFinalAssistantMessage(parsedMessages, turnStartedAt)) {
|
|
41359
41415
|
return {
|
|
41360
41416
|
present: true,
|
|
41361
41417
|
messages: Array.isArray(parsedMessages) ? parsedMessages : [],
|
|
@@ -41365,7 +41421,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
41365
41421
|
const externalMessages = this.readExternalCompletionMessages();
|
|
41366
41422
|
if (externalMessages) {
|
|
41367
41423
|
return {
|
|
41368
|
-
present: this.completionHasFinalAssistantMessage(externalMessages),
|
|
41424
|
+
present: this.completionHasFinalAssistantMessage(externalMessages, turnStartedAt),
|
|
41369
41425
|
messages: externalMessages,
|
|
41370
41426
|
source: "external-native"
|
|
41371
41427
|
};
|
|
@@ -41378,8 +41434,9 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
41378
41434
|
}
|
|
41379
41435
|
completionFinalSummary(parsedMessages, turnStartedAt) {
|
|
41380
41436
|
const adapterOwnsMessagesElsewhere = this.adapter?.chatMessagesOwnedExternally === true;
|
|
41381
|
-
const parsedSummary =
|
|
41382
|
-
this.completionHasFinalAssistantMessage(parsedMessages) ? Array.isArray(parsedMessages) ? parsedMessages : [] : []
|
|
41437
|
+
const parsedSummary = extractFinalSummaryFromMessagesAfter(
|
|
41438
|
+
this.completionHasFinalAssistantMessage(parsedMessages, turnStartedAt) ? Array.isArray(parsedMessages) ? parsedMessages : [] : [],
|
|
41439
|
+
turnStartedAt
|
|
41383
41440
|
);
|
|
41384
41441
|
if (adapterOwnsMessagesElsewhere) {
|
|
41385
41442
|
const externalMessages = this.readExternalCompletionMessages();
|
|
@@ -41484,7 +41541,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
41484
41541
|
}
|
|
41485
41542
|
if (parsed?.activeModal || parsed?.modal) return { reason: "parsed_modal_active", terminal: true };
|
|
41486
41543
|
const adapterOwnsMessagesElsewhere = this.adapter?.chatMessagesOwnedExternally === true;
|
|
41487
|
-
const finalAssistantEvidence = this.completionFinalAssistantEvidence(parsed?.messages);
|
|
41544
|
+
const finalAssistantEvidence = this.completionFinalAssistantEvidence(parsed?.messages, pending.turnStartedAt);
|
|
41488
41545
|
const allowMissingAssistantTimeout = !!(this.settings.meshNodeFor || this.settings.meshActiveTaskId || this.settings.launchedByCoordinator);
|
|
41489
41546
|
LOG.debug("CLI", `[${this.type}] finalAssistantEvidence: present=${finalAssistantEvidence.present} source=${finalAssistantEvidence.source} adapterOwnsMessagesElsewhere=${adapterOwnsMessagesElsewhere} parsedStatus=${parsedStatus}`);
|
|
41490
41547
|
if (!finalAssistantEvidence.present) {
|
|
@@ -41625,6 +41682,19 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
41625
41682
|
this.completedDebounceTimer = null;
|
|
41626
41683
|
return;
|
|
41627
41684
|
}
|
|
41685
|
+
if (typeof pending.busyEpochAtArm === "number" && this.busyEpoch !== pending.busyEpochAtArm) {
|
|
41686
|
+
LOG.info("CLI", `[${this.type}] cancelled pending completed (busy re-entry during settle: epoch ${pending.busyEpochAtArm}\u2192${this.busyEpoch})`);
|
|
41687
|
+
this.completedDebouncePending = null;
|
|
41688
|
+
this.completedDebounceTimer = null;
|
|
41689
|
+
return;
|
|
41690
|
+
}
|
|
41691
|
+
const latestOutputAt = typeof latestStatus?.lastOutputAt === "number" ? latestStatus.lastOutputAt : void 0;
|
|
41692
|
+
if (typeof pending.lastOutputAtArm === "number" && typeof latestOutputAt === "number" && latestOutputAt > pending.lastOutputAtArm) {
|
|
41693
|
+
LOG.info("CLI", `[${this.type}] cancelled pending completed (new PTY output during settle: ${pending.lastOutputAtArm}\u2192${latestOutputAt})`);
|
|
41694
|
+
this.completedDebouncePending = null;
|
|
41695
|
+
this.completedDebounceTimer = null;
|
|
41696
|
+
return;
|
|
41697
|
+
}
|
|
41628
41698
|
const block2 = this.getCompletedFinalizationBlock(latestVisibleStatus, pending);
|
|
41629
41699
|
if (block2) {
|
|
41630
41700
|
const blockReason = block2.reason;
|
|
@@ -41927,6 +41997,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
41927
41997
|
this.completedDebouncePending = null;
|
|
41928
41998
|
}
|
|
41929
41999
|
if (!this.generatingStartedAt) this.generatingStartedAt = now;
|
|
42000
|
+
this.busyEpoch++;
|
|
41930
42001
|
if (this.generatingDebounceTimer) clearTimeout(this.generatingDebounceTimer);
|
|
41931
42002
|
this.generatingDebouncePending = { chatTitle, timestamp: now };
|
|
41932
42003
|
this.generatingDebounceTimer = setTimeout(() => {
|
|
@@ -41952,6 +42023,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
41952
42023
|
}
|
|
41953
42024
|
this.completedDebouncePending = null;
|
|
41954
42025
|
if (!this.generatingStartedAt) this.generatingStartedAt = now;
|
|
42026
|
+
this.busyEpoch++;
|
|
41955
42027
|
const modal = adapterStatus.activeModal;
|
|
41956
42028
|
LOG.info("CLI", `[${this.type}] approval modal: "${modal?.message?.slice(0, 80) ?? "none"}"`);
|
|
41957
42029
|
const approvalEntrySeq = typeof adapterStatus?.approvalEntrySeq === "number" ? adapterStatus.approvalEntrySeq : 0;
|
|
@@ -42050,7 +42122,13 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
42050
42122
|
const engineTurnStart = typeof this.adapter?.currentTurnStartedAt === "number" && Number.isFinite(this.adapter.currentTurnStartedAt) ? this.adapter.currentTurnStartedAt : 0;
|
|
42051
42123
|
const turnStartedAt = engineTurnStart || this.generatingStartedAt || 0;
|
|
42052
42124
|
return turnStartedAt ? { turnStartedAt } : {};
|
|
42053
|
-
})()
|
|
42125
|
+
})(),
|
|
42126
|
+
// FALSE-IDLE continuity: snapshot the busy epoch + raw PTY output
|
|
42127
|
+
// clock at arm time so the flush guard can prove the session stayed
|
|
42128
|
+
// continuously idle (no busy re-entry, no new PTY output) through the
|
|
42129
|
+
// settle window rather than merely reading 'idle' once at flush.
|
|
42130
|
+
busyEpochAtArm: this.busyEpoch,
|
|
42131
|
+
...typeof adapterStatus?.lastOutputAt === "number" && Number.isFinite(adapterStatus.lastOutputAt) ? { lastOutputAtArm: adapterStatus.lastOutputAt } : {}
|
|
42054
42132
|
};
|
|
42055
42133
|
const ownsExternalHistory = !!this.adapter?.chatMessagesOwnedExternally;
|
|
42056
42134
|
const meshWorkerSession = this.isMeshWorkerSession();
|
|
@@ -50863,12 +50941,13 @@ var meshEventsHandlers = {
|
|
|
50863
50941
|
get_pending_mesh_events: async (ctx, args) => {
|
|
50864
50942
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
50865
50943
|
const coordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : void 0;
|
|
50944
|
+
const selfCoordinatorInboxRead = args?.selfCoordinatorInboxRead === true;
|
|
50866
50945
|
const hasLiveCliCoordinator = meshId ? resolveCoordinatorDrainDeliverability(ctx.deps, meshId).hasLiveCliCoordinator : false;
|
|
50867
|
-
if (meshId && shouldHoldPendingDrainForBusyLocalCoordinator(ctx.deps, meshId, coordinatorDaemonId)) {
|
|
50946
|
+
if (meshId && shouldHoldPendingDrainForBusyLocalCoordinator(ctx.deps, meshId, coordinatorDaemonId, selfCoordinatorInboxRead)) {
|
|
50868
50947
|
return { success: true, events: [], heldForBusyLocalCoordinator: true, hasLiveCliCoordinator };
|
|
50869
50948
|
}
|
|
50870
50949
|
const events = drainPendingMeshCoordinatorEvents(meshId || void 0, coordinatorDaemonId);
|
|
50871
|
-
return { success: true, events, hasLiveCliCoordinator };
|
|
50950
|
+
return { success: true, events, hasLiveCliCoordinator, ...selfCoordinatorInboxRead ? { surfacedForSelfCoordinator: true } : {} };
|
|
50872
50951
|
},
|
|
50873
50952
|
interactive_prompt_response: async (ctx, args) => {
|
|
50874
50953
|
const sessionId = typeof args?.targetSessionId === "string" && args.targetSessionId.trim() ? args.targetSessionId.trim() : typeof args?.sessionId === "string" && args.sessionId.trim() ? args.sessionId.trim() : "";
|
|
@@ -51506,6 +51585,7 @@ var meshStatusHandlers = {
|
|
|
51506
51585
|
mesh_status: async (ctx, args) => {
|
|
51507
51586
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
51508
51587
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
51588
|
+
const startedAtMs = Date.now();
|
|
51509
51589
|
try {
|
|
51510
51590
|
const meshRecord = await ctx.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
51511
51591
|
const mesh = meshRecord?.mesh;
|
|
@@ -51523,10 +51603,38 @@ var meshStatusHandlers = {
|
|
|
51523
51603
|
meshId,
|
|
51524
51604
|
command: "mesh_status",
|
|
51525
51605
|
refreshRequested,
|
|
51606
|
+
durationMs: Date.now() - startedAtMs,
|
|
51526
51607
|
summary: summarizeRepoMeshStatusDebug(cachedStatus)
|
|
51527
51608
|
});
|
|
51528
51609
|
return cachedStatus;
|
|
51529
51610
|
}
|
|
51611
|
+
const staleStatus = ctx.getCachedAggregateMeshStatus(meshId, mesh, {
|
|
51612
|
+
requireDirectPeerTruth: args?.requireDirectPeerTruth === true,
|
|
51613
|
+
allowStalePending: true
|
|
51614
|
+
});
|
|
51615
|
+
if (staleStatus) {
|
|
51616
|
+
if (!ctx.swrRefreshInFlight.has(meshId)) {
|
|
51617
|
+
ctx.swrRefreshInFlight.add(meshId);
|
|
51618
|
+
void Promise.resolve().then(() => ctx.execute("mesh_status", {
|
|
51619
|
+
meshId,
|
|
51620
|
+
inlineMesh: args?.inlineMesh,
|
|
51621
|
+
coordinatorDaemonId: args?.coordinatorDaemonId,
|
|
51622
|
+
requireDirectPeerTruth: args?.requireDirectPeerTruth === true,
|
|
51623
|
+
refresh: true
|
|
51624
|
+
}, "mesh_status_swr_freshen")).catch(() => {
|
|
51625
|
+
}).finally(() => {
|
|
51626
|
+
ctx.swrRefreshInFlight.delete(meshId);
|
|
51627
|
+
});
|
|
51628
|
+
}
|
|
51629
|
+
logRepoMeshStatusDebug("return_stale_swr", {
|
|
51630
|
+
meshId,
|
|
51631
|
+
command: "mesh_status",
|
|
51632
|
+
refreshRequested,
|
|
51633
|
+
durationMs: Date.now() - startedAtMs,
|
|
51634
|
+
summary: summarizeRepoMeshStatusDebug(staleStatus)
|
|
51635
|
+
});
|
|
51636
|
+
return staleStatus;
|
|
51637
|
+
}
|
|
51530
51638
|
}
|
|
51531
51639
|
const refreshReason = refreshRequested ? "explicit_refresh" : pendingCoordinatorEventCount > 0 ? "pending_coordinator_events" : hadAggregateCache ? "stale_pending_cache_refresh" : "cold_cache_miss";
|
|
51532
51640
|
const { getMeshQueueStats: getMeshQueueStats2, getQueue: getQueue2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
@@ -51607,8 +51715,7 @@ var meshStatusHandlers = {
|
|
|
51607
51715
|
);
|
|
51608
51716
|
const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? selectedCoordinatorNodeId : void 0;
|
|
51609
51717
|
const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
51610
|
-
const
|
|
51611
|
-
for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
|
|
51718
|
+
const renderMeshNode = async (nodeIndex, node) => {
|
|
51612
51719
|
const nodeId = normalizeMeshNodeId(node) ?? "";
|
|
51613
51720
|
const daemonId = readStringValue(node.daemonId);
|
|
51614
51721
|
const nodeMachineId = readMeshNodeMachineId(node);
|
|
@@ -51763,19 +51870,19 @@ var meshStatusHandlers = {
|
|
|
51763
51870
|
)) {
|
|
51764
51871
|
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
51765
51872
|
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
|
|
51766
|
-
|
|
51767
|
-
continue;
|
|
51873
|
+
return status;
|
|
51768
51874
|
}
|
|
51769
51875
|
if (meshRecord?.source === "inline_cache" && !isSelfNode) {
|
|
51770
51876
|
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
51771
51877
|
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
|
|
51772
|
-
|
|
51773
|
-
continue;
|
|
51878
|
+
return status;
|
|
51774
51879
|
}
|
|
51775
51880
|
}
|
|
51776
51881
|
} else {
|
|
51777
51882
|
try {
|
|
51778
|
-
const
|
|
51883
|
+
const runLocalProbe = () => getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
51884
|
+
const gitStatus = await meshGitProbeCache.probeLocal(workspace, runLocalProbe);
|
|
51885
|
+
if (!gitStatus) throw new Error("local_git_probe_unavailable");
|
|
51779
51886
|
status.git = gitStatus;
|
|
51780
51887
|
status[MESH_NODE_LIVE_TRUTH_MARKER] = true;
|
|
51781
51888
|
const reporter = recordInlineMeshDirectGitTruth(node, gitStatus, "selected_coordinator_local_git");
|
|
@@ -51797,8 +51904,38 @@ var meshStatusHandlers = {
|
|
|
51797
51904
|
}
|
|
51798
51905
|
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
51799
51906
|
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
|
|
51800
|
-
|
|
51801
|
-
}
|
|
51907
|
+
return status;
|
|
51908
|
+
};
|
|
51909
|
+
const meshNodeEntries = [...(mesh.nodes || []).entries()];
|
|
51910
|
+
const settledNodeStatuses = await Promise.allSettled(
|
|
51911
|
+
meshNodeEntries.map(([nodeIndex, node]) => renderMeshNode(nodeIndex, node))
|
|
51912
|
+
);
|
|
51913
|
+
const nodeStatuses = settledNodeStatuses.map((settled, i) => {
|
|
51914
|
+
if (settled.status === "fulfilled") return settled.value;
|
|
51915
|
+
const [nodeIndex, node] = meshNodeEntries[i];
|
|
51916
|
+
const nodeId = normalizeMeshNodeId(node) ?? "";
|
|
51917
|
+
const daemonId = readStringValue(node.daemonId);
|
|
51918
|
+
const fallback = {
|
|
51919
|
+
nodeId,
|
|
51920
|
+
machineLabel: buildMeshNodeDisplayLabel(node, nodeId, readProviderPriorityFromPolicy(node.policy)),
|
|
51921
|
+
workspace: node.workspace,
|
|
51922
|
+
repoRoot: node.repoRoot,
|
|
51923
|
+
isLocalWorktree: node.isLocalWorktree,
|
|
51924
|
+
worktreeBranch: node.worktreeBranch,
|
|
51925
|
+
daemonId,
|
|
51926
|
+
machineId: readMeshNodeMachineId(node) || node.machineId,
|
|
51927
|
+
health: "unknown",
|
|
51928
|
+
providers: node.providers || [],
|
|
51929
|
+
activeSessions: [],
|
|
51930
|
+
activeSessionDetails: [],
|
|
51931
|
+
launchReady: false,
|
|
51932
|
+
error: settled.reason instanceof Error ? settled.reason.message : "node render failed"
|
|
51933
|
+
};
|
|
51934
|
+
applyCachedInlineMeshNodeStatus(fallback, node);
|
|
51935
|
+
applyInlineMeshBranchConvergence(mesh, node, fallback);
|
|
51936
|
+
finalizeMeshNodeStatus({ status: fallback, node, daemonId, isSelfNode: false, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
|
|
51937
|
+
return fallback;
|
|
51938
|
+
});
|
|
51802
51939
|
const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : ctx.deps.statusInstanceId || void 0;
|
|
51803
51940
|
const pendingCoordinatorEvents = getPendingMeshCoordinatorEvents(meshId, callerCoordinatorDaemonId);
|
|
51804
51941
|
const unroutableDeliveries = getRecentUnroutableDeliveries();
|
|
@@ -51914,6 +52051,7 @@ var meshStatusHandlers = {
|
|
|
51914
52051
|
refreshReason,
|
|
51915
52052
|
meshSource: meshRecord.source,
|
|
51916
52053
|
directTruth,
|
|
52054
|
+
durationMs: Date.now() - startedAtMs,
|
|
51917
52055
|
summary: summarizeRepoMeshStatusDebug(returnedStatus)
|
|
51918
52056
|
});
|
|
51919
52057
|
return returnedStatus;
|
|
@@ -53114,7 +53252,7 @@ var MESH_DIRECT_PROBE_TIMEOUT_MS = readMeshTimeoutEnvMs("MESH_DIRECT_PROBE_TIMEO
|
|
|
53114
53252
|
var MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS = readMeshTimeoutEnvMs("MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS", 25e3);
|
|
53115
53253
|
var MESH_DIRECT_PROBE_CONNECT_TIMEOUT_MS = MESH_CONNECT_TIMEOUT_MS;
|
|
53116
53254
|
var MESH_DIRECT_PROBE_REUSE_MS = readMeshTimeoutEnvMs("MESH_DIRECT_PROBE_REUSE_MS", 12e3);
|
|
53117
|
-
var MeshGitProbeCache = class {
|
|
53255
|
+
var MeshGitProbeCache = class _MeshGitProbeCache {
|
|
53118
53256
|
constructor(reuseMs, now = Date.now) {
|
|
53119
53257
|
this.reuseMs = reuseMs;
|
|
53120
53258
|
this.now = now;
|
|
@@ -53124,6 +53262,23 @@ var MeshGitProbeCache = class {
|
|
|
53124
53262
|
key(daemonId, workspace) {
|
|
53125
53263
|
return `${daemonId}::${workspace}`;
|
|
53126
53264
|
}
|
|
53265
|
+
/**
|
|
53266
|
+
* Local (same-machine) git_status dedup. The bootstrap direct-truth hydrate
|
|
53267
|
+
* and the per-node render loop both call getGitRepoStatus(refreshUpstream:true)
|
|
53268
|
+
* for the same local workspace within one mesh_status call. Each such probe
|
|
53269
|
+
* fans out ~13-15 git subprocesses, and because the two passes are separated by
|
|
53270
|
+
* the render/hydrate work of every OTHER node they routinely straddle the
|
|
53271
|
+
* getGitRepoStatus 1.5s TTL, so the second pass re-shells the whole ~14-process
|
|
53272
|
+
* collection. Routing both through this cache (namespaced under a reserved
|
|
53273
|
+
* daemon id so it never collides with a remote-peer key) collapses them to one
|
|
53274
|
+
* collection per workspace per request, and reuses it across the reuse window
|
|
53275
|
+
* so the dashboard auto-retry loop can't restart a fresh local probe seconds
|
|
53276
|
+
* apart either.
|
|
53277
|
+
*/
|
|
53278
|
+
static LOCAL_PROBE_DAEMON_ID = "__local_git__";
|
|
53279
|
+
async probeLocal(workspace, probe) {
|
|
53280
|
+
return this.probe(_MeshGitProbeCache.LOCAL_PROBE_DAEMON_ID, workspace, probe);
|
|
53281
|
+
}
|
|
53127
53282
|
/**
|
|
53128
53283
|
* Run `probe` for this peer, but reuse a fresh recent result or an in-flight
|
|
53129
53284
|
* probe for the same key when one is available. `probe` is only invoked when
|
|
@@ -53234,7 +53389,7 @@ async function hydrateInlineMeshDirectTruth(args) {
|
|
|
53234
53389
|
let standingEvidenceCount = 0;
|
|
53235
53390
|
const unavailableNodeIds = [];
|
|
53236
53391
|
const deadNodeIds = [];
|
|
53237
|
-
|
|
53392
|
+
const classifyNode = async (nodeIndex, node) => {
|
|
53238
53393
|
const nodeId = normalizeMeshNodeId(node) || `node_${nodeIndex}`;
|
|
53239
53394
|
const workspace = readStringValue(node?.workspace);
|
|
53240
53395
|
const daemonId = readStringValue(node?.daemonId);
|
|
@@ -53247,38 +53402,33 @@ async function hydrateInlineMeshDirectTruth(args) {
|
|
|
53247
53402
|
daemonId && (daemonIdsEquivalent(daemonId, args.localMachineId) || daemonIdsEquivalent(daemonId, args.statusInstanceId))
|
|
53248
53403
|
);
|
|
53249
53404
|
if ((isSelfNode || isSelfDaemonNode) && isDeadLocalWorktreeNode(node)) {
|
|
53250
|
-
|
|
53251
|
-
continue;
|
|
53405
|
+
return { kind: "dead", nodeId };
|
|
53252
53406
|
}
|
|
53253
53407
|
if (!workspace) {
|
|
53254
|
-
|
|
53255
|
-
continue;
|
|
53408
|
+
return !isSelfNode && daemonId ? { kind: "unavailable", nodeId } : { kind: "skip" };
|
|
53256
53409
|
}
|
|
53257
53410
|
if (fs29.existsSync(workspace)) {
|
|
53258
53411
|
try {
|
|
53259
|
-
const
|
|
53412
|
+
const runLocalProbe = () => getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
53413
|
+
const localGit = args.probeCache ? await args.probeCache.probeLocal(workspace, runLocalProbe) : await runLocalProbe();
|
|
53260
53414
|
if (localGit?.isGitRepo) {
|
|
53261
53415
|
const reporter = recordInlineMeshDirectGitTruth(node, localGit, "selected_coordinator_local_git");
|
|
53262
53416
|
persistNodeReporterPlatform(args.meshSource, args.mesh, nodeId, reporter);
|
|
53263
|
-
|
|
53264
|
-
continue;
|
|
53417
|
+
return { kind: "local" };
|
|
53265
53418
|
}
|
|
53266
53419
|
} catch {
|
|
53267
53420
|
}
|
|
53268
53421
|
}
|
|
53269
53422
|
const standingGit = buildInlineMeshTransitGitStatus(node);
|
|
53270
53423
|
if (standingGit) {
|
|
53271
|
-
|
|
53272
|
-
continue;
|
|
53424
|
+
return { kind: "standing" };
|
|
53273
53425
|
}
|
|
53274
53426
|
if (!args.probeRemotePeers) {
|
|
53275
|
-
|
|
53427
|
+
return { kind: "skip" };
|
|
53276
53428
|
}
|
|
53277
53429
|
if (!daemonId || !args.dispatchMeshCommand) {
|
|
53278
|
-
|
|
53279
|
-
continue;
|
|
53430
|
+
return !isSelfNode ? { kind: "unavailable", nodeId } : { kind: "skip" };
|
|
53280
53431
|
}
|
|
53281
|
-
peerAttemptedCount += 1;
|
|
53282
53432
|
const runProbe = () => probeRemoteMeshGitStatusWithRetry({
|
|
53283
53433
|
dispatchMeshCommand: args.dispatchMeshCommand,
|
|
53284
53434
|
daemonId,
|
|
@@ -53292,11 +53442,52 @@ async function hydrateInlineMeshDirectTruth(args) {
|
|
|
53292
53442
|
if (remoteGit) {
|
|
53293
53443
|
const reporter = recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
|
|
53294
53444
|
persistNodeReporterPlatform(args.meshSource, args.mesh, nodeId, reporter);
|
|
53295
|
-
|
|
53296
|
-
continue;
|
|
53445
|
+
return { kind: "peerConfirmed" };
|
|
53297
53446
|
}
|
|
53298
|
-
|
|
53299
|
-
}
|
|
53447
|
+
return { kind: "peerUnavailable", nodeId };
|
|
53448
|
+
};
|
|
53449
|
+
const nodeEntries = [...nodes.entries()];
|
|
53450
|
+
const settledResults = await Promise.allSettled(
|
|
53451
|
+
nodeEntries.map(([nodeIndex, node]) => classifyNode(nodeIndex, node))
|
|
53452
|
+
);
|
|
53453
|
+
settledResults.forEach((settled, i) => {
|
|
53454
|
+
const [nodeIndex, node] = nodeEntries[i];
|
|
53455
|
+
const result = settled.status === "fulfilled" ? settled.value : (() => {
|
|
53456
|
+
const nodeId = normalizeMeshNodeId(node) || `node_${nodeIndex}`;
|
|
53457
|
+
const daemonId = readStringValue(node?.daemonId);
|
|
53458
|
+
const isSelfNode = Boolean(
|
|
53459
|
+
nodeId && selectedCoordinatorNodeId && nodeId === selectedCoordinatorNodeId
|
|
53460
|
+
) || Boolean(
|
|
53461
|
+
daemonId && (daemonIdsEquivalent(daemonId, args.localMachineId) || daemonIdsEquivalent(daemonId, args.statusInstanceId))
|
|
53462
|
+
);
|
|
53463
|
+
return !isSelfNode && daemonId ? { kind: "unavailable", nodeId } : { kind: "skip" };
|
|
53464
|
+
})();
|
|
53465
|
+
switch (result.kind) {
|
|
53466
|
+
case "dead":
|
|
53467
|
+
deadNodeIds.push(result.nodeId);
|
|
53468
|
+
break;
|
|
53469
|
+
case "unavailable":
|
|
53470
|
+
unavailableNodeIds.push(result.nodeId);
|
|
53471
|
+
break;
|
|
53472
|
+
case "local":
|
|
53473
|
+
localConfirmedCount += 1;
|
|
53474
|
+
break;
|
|
53475
|
+
case "standing":
|
|
53476
|
+
standingEvidenceCount += 1;
|
|
53477
|
+
break;
|
|
53478
|
+
case "peerConfirmed":
|
|
53479
|
+
peerAttemptedCount += 1;
|
|
53480
|
+
peerConfirmedCount += 1;
|
|
53481
|
+
break;
|
|
53482
|
+
case "peerUnavailable":
|
|
53483
|
+
peerAttemptedCount += 1;
|
|
53484
|
+
unavailableNodeIds.push(result.nodeId);
|
|
53485
|
+
break;
|
|
53486
|
+
case "skip":
|
|
53487
|
+
default:
|
|
53488
|
+
break;
|
|
53489
|
+
}
|
|
53490
|
+
});
|
|
53300
53491
|
return {
|
|
53301
53492
|
directEvidenceCount: localConfirmedCount + peerConfirmedCount + standingEvidenceCount,
|
|
53302
53493
|
localConfirmedCount,
|
|
@@ -54667,6 +54858,10 @@ var DaemonCommandRouter = class {
|
|
|
54667
54858
|
* Spans separate mesh_status/get_mesh calls so the dashboard auto-retry
|
|
54668
54859
|
* loop cannot storm a slow peer with back-to-back refreshUpstream probes. */
|
|
54669
54860
|
meshGitProbeCache = new MeshGitProbeCache(MESH_DIRECT_PROBE_REUSE_MS);
|
|
54861
|
+
/** Meshes with a background SWR freshen (async mesh_status refresh) already in
|
|
54862
|
+
* flight — so a burst of interactive detail-opens serves the cached snapshot
|
|
54863
|
+
* and coalesces onto ONE background refresh instead of storming the peers. */
|
|
54864
|
+
swrRefreshInFlight = /* @__PURE__ */ new Set();
|
|
54670
54865
|
/** In-memory async Refinery jobs keyed by meshId:nodeId to reject/return duplicate in-flight requests. */
|
|
54671
54866
|
runningRefineJobs = /* @__PURE__ */ new Map();
|
|
54672
54867
|
/** Terminal async Refinery jobs preserve a clear answer after the worktree node has been removed. */
|
|
@@ -54770,7 +54965,7 @@ var DaemonCommandRouter = class {
|
|
|
54770
54965
|
if (cached3.queueRevision !== getMeshQueueRevision(meshId)) return null;
|
|
54771
54966
|
let snapshot = this.cloneJsonValue(cached3.snapshot);
|
|
54772
54967
|
snapshot = this.hydrateCachedAggregateMeshStatusFromInline(snapshot, mesh, options);
|
|
54773
|
-
if (shouldRefreshStalePendingAggregate(snapshot, options)) return null;
|
|
54968
|
+
if (!options?.allowStalePending && shouldRefreshStalePendingAggregate(snapshot, options)) return null;
|
|
54774
54969
|
const ageMs = Math.max(0, Date.now() - cached3.builtAt);
|
|
54775
54970
|
const sourceOfTruth = snapshot.sourceOfTruth && typeof snapshot.sourceOfTruth === "object" ? snapshot.sourceOfTruth : {};
|
|
54776
54971
|
snapshot.sourceOfTruth = {
|
|
@@ -55000,6 +55195,7 @@ var DaemonCommandRouter = class {
|
|
|
55000
55195
|
rememberAggregateMeshStatus: this.rememberAggregateMeshStatus.bind(this),
|
|
55001
55196
|
execute: this.execute.bind(this),
|
|
55002
55197
|
aggregateMeshStatusCache: this.aggregateMeshStatusCache,
|
|
55198
|
+
swrRefreshInFlight: this.swrRefreshInFlight,
|
|
55003
55199
|
runningRefineJobs: this.runningRefineJobs,
|
|
55004
55200
|
inlineMeshCache: this.inlineMeshCache,
|
|
55005
55201
|
meshGitProbeCache: this.meshGitProbeCache
|