@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
|
@@ -34,6 +34,7 @@ export interface HighFamilyContext {
|
|
|
34
34
|
/** Bound `DaemonCommandRouter.getCachedAggregateMeshStatus`. */
|
|
35
35
|
getCachedAggregateMeshStatus: (meshId: string, mesh?: any, options?: {
|
|
36
36
|
requireDirectPeerTruth?: boolean;
|
|
37
|
+
allowStalePending?: boolean;
|
|
37
38
|
}) => any | null;
|
|
38
39
|
/** Bound `DaemonCommandRouter.rememberAggregateMeshStatus`. */
|
|
39
40
|
rememberAggregateMeshStatus: (meshId: string, snapshot: any, refreshReason: string) => any;
|
|
@@ -49,6 +50,9 @@ export interface HighFamilyContext {
|
|
|
49
50
|
snapshot: any;
|
|
50
51
|
queueRevision: string;
|
|
51
52
|
}>;
|
|
53
|
+
/** Meshes with a background SWR freshen already in flight — coalesces the
|
|
54
|
+
* async refresh a stale-serve interactive open kicks off. */
|
|
55
|
+
swrRefreshInFlight: Set<string>;
|
|
52
56
|
/** Router's running-refine-job table (surfaced as activeRefineJobs in mesh_status). */
|
|
53
57
|
runningRefineJobs: Map<string, MeshRefineJobHandle>;
|
|
54
58
|
/** Router's inline-mesh cache (launch_mesh_coordinator caches cloud inline mesh). */
|
|
@@ -116,6 +116,10 @@ export declare class DaemonCommandRouter {
|
|
|
116
116
|
* Spans separate mesh_status/get_mesh calls so the dashboard auto-retry
|
|
117
117
|
* loop cannot storm a slow peer with back-to-back refreshUpstream probes. */
|
|
118
118
|
private meshGitProbeCache;
|
|
119
|
+
/** Meshes with a background SWR freshen (async mesh_status refresh) already in
|
|
120
|
+
* flight — so a burst of interactive detail-opens serves the cached snapshot
|
|
121
|
+
* and coalesces onto ONE background refresh instead of storming the peers. */
|
|
122
|
+
private swrRefreshInFlight;
|
|
119
123
|
/** In-memory async Refinery jobs keyed by meshId:nodeId to reject/return duplicate in-flight requests. */
|
|
120
124
|
private runningRefineJobs;
|
|
121
125
|
/** Terminal async Refinery jobs preserve a clear answer after the worktree node has been removed. */
|
package/dist/index.js
CHANGED
|
@@ -409,10 +409,10 @@ function readInjected(value) {
|
|
|
409
409
|
}
|
|
410
410
|
function getDaemonBuildInfo() {
|
|
411
411
|
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-
|
|
412
|
+
const commit = readInjected(true ? "21c6fe269d621db0b4841be14c111d4d656d6996" : void 0) ?? "unknown";
|
|
413
|
+
const commitShort = readInjected(true ? "21c6fe26" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
414
|
+
const version = readInjected(true ? "0.9.82-rc.443" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
415
|
+
const builtAt = readInjected(true ? "2026-07-01T10:41:15.424Z" : void 0);
|
|
416
416
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
417
417
|
return cached;
|
|
418
418
|
}
|
|
@@ -17200,7 +17200,7 @@ function resolveCoordinatorDrainDeliverability(components, meshId) {
|
|
|
17200
17200
|
holdForReconcile: !hasIdle
|
|
17201
17201
|
};
|
|
17202
17202
|
}
|
|
17203
|
-
function shouldHoldPendingDrainForBusyLocalCoordinator(components, meshId, requestedCoordinatorDaemonId) {
|
|
17203
|
+
function shouldHoldPendingDrainForBusyLocalCoordinator(components, meshId, requestedCoordinatorDaemonId, callerIsSelfCoordinatorInboxRead) {
|
|
17204
17204
|
if (!meshId) return false;
|
|
17205
17205
|
const deliverability = resolveCoordinatorDrainDeliverability(components, meshId);
|
|
17206
17206
|
if (!deliverability.holdForReconcile) return false;
|
|
@@ -17210,7 +17210,10 @@ function shouldHoldPendingDrainForBusyLocalCoordinator(components, meshId, reque
|
|
|
17210
17210
|
readNonEmptyString2(components.statusInstanceId),
|
|
17211
17211
|
readNonEmptyString2(loadConfig().machineId)
|
|
17212
17212
|
]);
|
|
17213
|
-
|
|
17213
|
+
const targetsLocalCoordinator = localIds.some((id) => daemonIdsEquivalent(id, requested));
|
|
17214
|
+
if (!targetsLocalCoordinator) return false;
|
|
17215
|
+
if (callerIsSelfCoordinatorInboxRead) return false;
|
|
17216
|
+
return true;
|
|
17214
17217
|
}
|
|
17215
17218
|
function injectPendingIntoCoordinator(coordinator, pending) {
|
|
17216
17219
|
if (!coordinator) return;
|
|
@@ -32442,6 +32445,26 @@ async function handleReadChat(h, args) {
|
|
|
32442
32445
|
ptyStatusApprovalOnly: false
|
|
32443
32446
|
});
|
|
32444
32447
|
if (supportsNative && !decision.nativeSelected) {
|
|
32448
|
+
if (safeMapping && historyMessages.length > 0) {
|
|
32449
|
+
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}`);
|
|
32450
|
+
return buildReadChatCommandResult({
|
|
32451
|
+
messages: historyMessages,
|
|
32452
|
+
status: "idle",
|
|
32453
|
+
messageSource: {
|
|
32454
|
+
...decision.messageSource,
|
|
32455
|
+
nativeOnlyContentPreserved: true,
|
|
32456
|
+
returnedMessageCount: historyMessages.length
|
|
32457
|
+
},
|
|
32458
|
+
transcriptProvenance: {
|
|
32459
|
+
...decision.messageSource,
|
|
32460
|
+
nativeOnlyContentPreserved: true
|
|
32461
|
+
},
|
|
32462
|
+
...typeof history?.title === "string" ? { title: history.title } : {},
|
|
32463
|
+
...historyProviderSessionId ? { providerSessionId: historyProviderSessionId } : {},
|
|
32464
|
+
...provider?.historyBehavior?.transcriptAuthority === "provider" || provider?.historyBehavior?.transcriptAuthority === "daemon" ? { transcriptAuthority: (provider?.historyBehavior).transcriptAuthority } : {},
|
|
32465
|
+
coverage: "tail"
|
|
32466
|
+
}, args, h);
|
|
32467
|
+
}
|
|
32445
32468
|
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`);
|
|
32446
32469
|
return {
|
|
32447
32470
|
success: true,
|
|
@@ -39135,10 +39158,17 @@ function executeSqlite(src, input) {
|
|
|
39135
39158
|
}
|
|
39136
39159
|
try {
|
|
39137
39160
|
const requested = input.providerSessionId || "";
|
|
39138
|
-
|
|
39139
|
-
|
|
39140
|
-
|
|
39141
|
-
|
|
39161
|
+
const resolveMessagesFor = (sessionId2) => {
|
|
39162
|
+
if (!sessionId2) return null;
|
|
39163
|
+
let rows;
|
|
39164
|
+
try {
|
|
39165
|
+
rows = db.prepare(src.message_query).all(sessionId2);
|
|
39166
|
+
} catch {
|
|
39167
|
+
return null;
|
|
39168
|
+
}
|
|
39169
|
+
return rows && rows.length > 0 ? rows : null;
|
|
39170
|
+
};
|
|
39171
|
+
const resolveNewestSessionId = () => {
|
|
39142
39172
|
let sessionRow;
|
|
39143
39173
|
try {
|
|
39144
39174
|
const sessionFloorSeconds = typeof input.sessionStartedAtMs === "number" ? Math.floor(input.sessionStartedAtMs / 1e3) : 0;
|
|
@@ -39149,14 +39179,27 @@ function executeSqlite(src, input) {
|
|
|
39149
39179
|
sessionRow = stmt.get();
|
|
39150
39180
|
}
|
|
39151
39181
|
} catch {
|
|
39152
|
-
return
|
|
39182
|
+
return "";
|
|
39153
39183
|
}
|
|
39154
|
-
if (!sessionRow) return
|
|
39184
|
+
if (!sessionRow) return "";
|
|
39155
39185
|
const sessionIdRaw = Object.values(sessionRow)[0];
|
|
39156
|
-
|
|
39186
|
+
return sessionIdRaw == null ? "" : String(sessionIdRaw);
|
|
39187
|
+
};
|
|
39188
|
+
let sessionId;
|
|
39189
|
+
let messageRows;
|
|
39190
|
+
if (requested) {
|
|
39191
|
+
messageRows = resolveMessagesFor(requested);
|
|
39192
|
+
if (messageRows) {
|
|
39193
|
+
sessionId = requested;
|
|
39194
|
+
} else {
|
|
39195
|
+
sessionId = resolveNewestSessionId();
|
|
39196
|
+
messageRows = resolveMessagesFor(sessionId);
|
|
39197
|
+
}
|
|
39198
|
+
} else {
|
|
39199
|
+
sessionId = resolveNewestSessionId();
|
|
39200
|
+
messageRows = resolveMessagesFor(sessionId);
|
|
39157
39201
|
}
|
|
39158
39202
|
if (!sessionId) return null;
|
|
39159
|
-
const messageRows = db.prepare(src.message_query).all(sessionId);
|
|
39160
39203
|
if (!messageRows || messageRows.length === 0) return null;
|
|
39161
39204
|
const mtime = safeMtimeMs(resolved);
|
|
39162
39205
|
const messages = [];
|
|
@@ -41023,6 +41066,15 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
41023
41066
|
// first sets it; the other becomes a no-op.
|
|
41024
41067
|
agentReadyEmitted = false;
|
|
41025
41068
|
generatingStartedAt = 0;
|
|
41069
|
+
// FALSE-IDLE continuity epoch: monotonically bumped on EVERY entry into a busy
|
|
41070
|
+
// phase (→generating or →waiting_approval). The completedDebouncePending snapshots
|
|
41071
|
+
// this value at arm time (busyEpochAtArm); the flush guard requires it UNCHANGED
|
|
41072
|
+
// — proving the session did not re-enter a busy phase (a momentary busy→idle blip
|
|
41073
|
+
// in an inter-approval valley) between arming the debounce and flushing it. A
|
|
41074
|
+
// single point-sample of status at flush time cannot see a generating phase that
|
|
41075
|
+
// opened AND closed within the settle window; the epoch can. See
|
|
41076
|
+
// flushCompletedDebounceIfFinalized.
|
|
41077
|
+
busyEpoch = 0;
|
|
41026
41078
|
// GENERATING-BOUNDARY (R4b): the per-turn taskId for which a startup-grace
|
|
41027
41079
|
// started+completed pair was already synthesized. Both fast-collapse callers
|
|
41028
41080
|
// (starting→idle transition AND the idle-stayed no-status-change poll) route
|
|
@@ -41689,13 +41741,17 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
41689
41741
|
}
|
|
41690
41742
|
this.applyProviderResponse(parsed.payload, { phase: "immediate" });
|
|
41691
41743
|
}
|
|
41692
|
-
completionHasFinalAssistantMessage(messages) {
|
|
41744
|
+
completionHasFinalAssistantMessage(messages, turnStartedAt) {
|
|
41693
41745
|
const visibleMessages = (Array.isArray(messages) ? messages : []).filter((message) => isUserFacingChatMessage(message));
|
|
41694
41746
|
const lastVisible = visibleMessages[visibleMessages.length - 1];
|
|
41695
41747
|
const role = typeof lastVisible?.role === "string" ? lastVisible.role.trim().toLowerCase() : "";
|
|
41696
41748
|
const content = lastVisible ? flattenContent(lastVisible.content).trim() : "";
|
|
41697
41749
|
if (role !== "assistant" || !content) return false;
|
|
41698
41750
|
if (looksLikeActiveApprovalPromptText(content)) return false;
|
|
41751
|
+
if (typeof turnStartedAt === "number" && Number.isFinite(turnStartedAt) && turnStartedAt > 0) {
|
|
41752
|
+
const ts2 = readChatMessageTimestampMs(lastVisible);
|
|
41753
|
+
if (typeof ts2 === "number" && ts2 < turnStartedAt) return false;
|
|
41754
|
+
}
|
|
41699
41755
|
return true;
|
|
41700
41756
|
}
|
|
41701
41757
|
buildExternalTranscriptProbe(messages, sourcePath, sourceMtimeMs) {
|
|
@@ -41758,8 +41814,8 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
41758
41814
|
);
|
|
41759
41815
|
return restoredHistory.messages;
|
|
41760
41816
|
}
|
|
41761
|
-
completionFinalAssistantEvidence(parsedMessages) {
|
|
41762
|
-
if (this.completionHasFinalAssistantMessage(parsedMessages)) {
|
|
41817
|
+
completionFinalAssistantEvidence(parsedMessages, turnStartedAt) {
|
|
41818
|
+
if (this.completionHasFinalAssistantMessage(parsedMessages, turnStartedAt)) {
|
|
41763
41819
|
return {
|
|
41764
41820
|
present: true,
|
|
41765
41821
|
messages: Array.isArray(parsedMessages) ? parsedMessages : [],
|
|
@@ -41769,7 +41825,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
41769
41825
|
const externalMessages = this.readExternalCompletionMessages();
|
|
41770
41826
|
if (externalMessages) {
|
|
41771
41827
|
return {
|
|
41772
|
-
present: this.completionHasFinalAssistantMessage(externalMessages),
|
|
41828
|
+
present: this.completionHasFinalAssistantMessage(externalMessages, turnStartedAt),
|
|
41773
41829
|
messages: externalMessages,
|
|
41774
41830
|
source: "external-native"
|
|
41775
41831
|
};
|
|
@@ -41782,8 +41838,9 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
41782
41838
|
}
|
|
41783
41839
|
completionFinalSummary(parsedMessages, turnStartedAt) {
|
|
41784
41840
|
const adapterOwnsMessagesElsewhere = this.adapter?.chatMessagesOwnedExternally === true;
|
|
41785
|
-
const parsedSummary =
|
|
41786
|
-
this.completionHasFinalAssistantMessage(parsedMessages) ? Array.isArray(parsedMessages) ? parsedMessages : [] : []
|
|
41841
|
+
const parsedSummary = extractFinalSummaryFromMessagesAfter(
|
|
41842
|
+
this.completionHasFinalAssistantMessage(parsedMessages, turnStartedAt) ? Array.isArray(parsedMessages) ? parsedMessages : [] : [],
|
|
41843
|
+
turnStartedAt
|
|
41787
41844
|
);
|
|
41788
41845
|
if (adapterOwnsMessagesElsewhere) {
|
|
41789
41846
|
const externalMessages = this.readExternalCompletionMessages();
|
|
@@ -41888,7 +41945,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
41888
41945
|
}
|
|
41889
41946
|
if (parsed?.activeModal || parsed?.modal) return { reason: "parsed_modal_active", terminal: true };
|
|
41890
41947
|
const adapterOwnsMessagesElsewhere = this.adapter?.chatMessagesOwnedExternally === true;
|
|
41891
|
-
const finalAssistantEvidence = this.completionFinalAssistantEvidence(parsed?.messages);
|
|
41948
|
+
const finalAssistantEvidence = this.completionFinalAssistantEvidence(parsed?.messages, pending.turnStartedAt);
|
|
41892
41949
|
const allowMissingAssistantTimeout = !!(this.settings.meshNodeFor || this.settings.meshActiveTaskId || this.settings.launchedByCoordinator);
|
|
41893
41950
|
LOG.debug("CLI", `[${this.type}] finalAssistantEvidence: present=${finalAssistantEvidence.present} source=${finalAssistantEvidence.source} adapterOwnsMessagesElsewhere=${adapterOwnsMessagesElsewhere} parsedStatus=${parsedStatus}`);
|
|
41894
41951
|
if (!finalAssistantEvidence.present) {
|
|
@@ -42029,6 +42086,19 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
42029
42086
|
this.completedDebounceTimer = null;
|
|
42030
42087
|
return;
|
|
42031
42088
|
}
|
|
42089
|
+
if (typeof pending.busyEpochAtArm === "number" && this.busyEpoch !== pending.busyEpochAtArm) {
|
|
42090
|
+
LOG.info("CLI", `[${this.type}] cancelled pending completed (busy re-entry during settle: epoch ${pending.busyEpochAtArm}\u2192${this.busyEpoch})`);
|
|
42091
|
+
this.completedDebouncePending = null;
|
|
42092
|
+
this.completedDebounceTimer = null;
|
|
42093
|
+
return;
|
|
42094
|
+
}
|
|
42095
|
+
const latestOutputAt = typeof latestStatus?.lastOutputAt === "number" ? latestStatus.lastOutputAt : void 0;
|
|
42096
|
+
if (typeof pending.lastOutputAtArm === "number" && typeof latestOutputAt === "number" && latestOutputAt > pending.lastOutputAtArm) {
|
|
42097
|
+
LOG.info("CLI", `[${this.type}] cancelled pending completed (new PTY output during settle: ${pending.lastOutputAtArm}\u2192${latestOutputAt})`);
|
|
42098
|
+
this.completedDebouncePending = null;
|
|
42099
|
+
this.completedDebounceTimer = null;
|
|
42100
|
+
return;
|
|
42101
|
+
}
|
|
42032
42102
|
const block2 = this.getCompletedFinalizationBlock(latestVisibleStatus, pending);
|
|
42033
42103
|
if (block2) {
|
|
42034
42104
|
const blockReason = block2.reason;
|
|
@@ -42331,6 +42401,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
42331
42401
|
this.completedDebouncePending = null;
|
|
42332
42402
|
}
|
|
42333
42403
|
if (!this.generatingStartedAt) this.generatingStartedAt = now;
|
|
42404
|
+
this.busyEpoch++;
|
|
42334
42405
|
if (this.generatingDebounceTimer) clearTimeout(this.generatingDebounceTimer);
|
|
42335
42406
|
this.generatingDebouncePending = { chatTitle, timestamp: now };
|
|
42336
42407
|
this.generatingDebounceTimer = setTimeout(() => {
|
|
@@ -42356,6 +42427,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
42356
42427
|
}
|
|
42357
42428
|
this.completedDebouncePending = null;
|
|
42358
42429
|
if (!this.generatingStartedAt) this.generatingStartedAt = now;
|
|
42430
|
+
this.busyEpoch++;
|
|
42359
42431
|
const modal = adapterStatus.activeModal;
|
|
42360
42432
|
LOG.info("CLI", `[${this.type}] approval modal: "${modal?.message?.slice(0, 80) ?? "none"}"`);
|
|
42361
42433
|
const approvalEntrySeq = typeof adapterStatus?.approvalEntrySeq === "number" ? adapterStatus.approvalEntrySeq : 0;
|
|
@@ -42454,7 +42526,13 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
42454
42526
|
const engineTurnStart = typeof this.adapter?.currentTurnStartedAt === "number" && Number.isFinite(this.adapter.currentTurnStartedAt) ? this.adapter.currentTurnStartedAt : 0;
|
|
42455
42527
|
const turnStartedAt = engineTurnStart || this.generatingStartedAt || 0;
|
|
42456
42528
|
return turnStartedAt ? { turnStartedAt } : {};
|
|
42457
|
-
})()
|
|
42529
|
+
})(),
|
|
42530
|
+
// FALSE-IDLE continuity: snapshot the busy epoch + raw PTY output
|
|
42531
|
+
// clock at arm time so the flush guard can prove the session stayed
|
|
42532
|
+
// continuously idle (no busy re-entry, no new PTY output) through the
|
|
42533
|
+
// settle window rather than merely reading 'idle' once at flush.
|
|
42534
|
+
busyEpochAtArm: this.busyEpoch,
|
|
42535
|
+
...typeof adapterStatus?.lastOutputAt === "number" && Number.isFinite(adapterStatus.lastOutputAt) ? { lastOutputAtArm: adapterStatus.lastOutputAt } : {}
|
|
42458
42536
|
};
|
|
42459
42537
|
const ownsExternalHistory = !!this.adapter?.chatMessagesOwnedExternally;
|
|
42460
42538
|
const meshWorkerSession = this.isMeshWorkerSession();
|
|
@@ -51262,12 +51340,13 @@ var meshEventsHandlers = {
|
|
|
51262
51340
|
get_pending_mesh_events: async (ctx, args) => {
|
|
51263
51341
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
51264
51342
|
const coordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : void 0;
|
|
51343
|
+
const selfCoordinatorInboxRead = args?.selfCoordinatorInboxRead === true;
|
|
51265
51344
|
const hasLiveCliCoordinator = meshId ? resolveCoordinatorDrainDeliverability(ctx.deps, meshId).hasLiveCliCoordinator : false;
|
|
51266
|
-
if (meshId && shouldHoldPendingDrainForBusyLocalCoordinator(ctx.deps, meshId, coordinatorDaemonId)) {
|
|
51345
|
+
if (meshId && shouldHoldPendingDrainForBusyLocalCoordinator(ctx.deps, meshId, coordinatorDaemonId, selfCoordinatorInboxRead)) {
|
|
51267
51346
|
return { success: true, events: [], heldForBusyLocalCoordinator: true, hasLiveCliCoordinator };
|
|
51268
51347
|
}
|
|
51269
51348
|
const events = drainPendingMeshCoordinatorEvents(meshId || void 0, coordinatorDaemonId);
|
|
51270
|
-
return { success: true, events, hasLiveCliCoordinator };
|
|
51349
|
+
return { success: true, events, hasLiveCliCoordinator, ...selfCoordinatorInboxRead ? { surfacedForSelfCoordinator: true } : {} };
|
|
51271
51350
|
},
|
|
51272
51351
|
interactive_prompt_response: async (ctx, args) => {
|
|
51273
51352
|
const sessionId = typeof args?.targetSessionId === "string" && args.targetSessionId.trim() ? args.targetSessionId.trim() : typeof args?.sessionId === "string" && args.sessionId.trim() ? args.sessionId.trim() : "";
|
|
@@ -51905,6 +51984,7 @@ var meshStatusHandlers = {
|
|
|
51905
51984
|
mesh_status: async (ctx, args) => {
|
|
51906
51985
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
51907
51986
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
51987
|
+
const startedAtMs = Date.now();
|
|
51908
51988
|
try {
|
|
51909
51989
|
const meshRecord = await ctx.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
51910
51990
|
const mesh = meshRecord?.mesh;
|
|
@@ -51922,10 +52002,38 @@ var meshStatusHandlers = {
|
|
|
51922
52002
|
meshId,
|
|
51923
52003
|
command: "mesh_status",
|
|
51924
52004
|
refreshRequested,
|
|
52005
|
+
durationMs: Date.now() - startedAtMs,
|
|
51925
52006
|
summary: summarizeRepoMeshStatusDebug(cachedStatus)
|
|
51926
52007
|
});
|
|
51927
52008
|
return cachedStatus;
|
|
51928
52009
|
}
|
|
52010
|
+
const staleStatus = ctx.getCachedAggregateMeshStatus(meshId, mesh, {
|
|
52011
|
+
requireDirectPeerTruth: args?.requireDirectPeerTruth === true,
|
|
52012
|
+
allowStalePending: true
|
|
52013
|
+
});
|
|
52014
|
+
if (staleStatus) {
|
|
52015
|
+
if (!ctx.swrRefreshInFlight.has(meshId)) {
|
|
52016
|
+
ctx.swrRefreshInFlight.add(meshId);
|
|
52017
|
+
void Promise.resolve().then(() => ctx.execute("mesh_status", {
|
|
52018
|
+
meshId,
|
|
52019
|
+
inlineMesh: args?.inlineMesh,
|
|
52020
|
+
coordinatorDaemonId: args?.coordinatorDaemonId,
|
|
52021
|
+
requireDirectPeerTruth: args?.requireDirectPeerTruth === true,
|
|
52022
|
+
refresh: true
|
|
52023
|
+
}, "mesh_status_swr_freshen")).catch(() => {
|
|
52024
|
+
}).finally(() => {
|
|
52025
|
+
ctx.swrRefreshInFlight.delete(meshId);
|
|
52026
|
+
});
|
|
52027
|
+
}
|
|
52028
|
+
logRepoMeshStatusDebug("return_stale_swr", {
|
|
52029
|
+
meshId,
|
|
52030
|
+
command: "mesh_status",
|
|
52031
|
+
refreshRequested,
|
|
52032
|
+
durationMs: Date.now() - startedAtMs,
|
|
52033
|
+
summary: summarizeRepoMeshStatusDebug(staleStatus)
|
|
52034
|
+
});
|
|
52035
|
+
return staleStatus;
|
|
52036
|
+
}
|
|
51929
52037
|
}
|
|
51930
52038
|
const refreshReason = refreshRequested ? "explicit_refresh" : pendingCoordinatorEventCount > 0 ? "pending_coordinator_events" : hadAggregateCache ? "stale_pending_cache_refresh" : "cold_cache_miss";
|
|
51931
52039
|
const { getMeshQueueStats: getMeshQueueStats2, getQueue: getQueue2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
@@ -52006,8 +52114,7 @@ var meshStatusHandlers = {
|
|
|
52006
52114
|
);
|
|
52007
52115
|
const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? selectedCoordinatorNodeId : void 0;
|
|
52008
52116
|
const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
52009
|
-
const
|
|
52010
|
-
for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
|
|
52117
|
+
const renderMeshNode = async (nodeIndex, node) => {
|
|
52011
52118
|
const nodeId = normalizeMeshNodeId(node) ?? "";
|
|
52012
52119
|
const daemonId = readStringValue(node.daemonId);
|
|
52013
52120
|
const nodeMachineId = readMeshNodeMachineId(node);
|
|
@@ -52162,19 +52269,19 @@ var meshStatusHandlers = {
|
|
|
52162
52269
|
)) {
|
|
52163
52270
|
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
52164
52271
|
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
|
|
52165
|
-
|
|
52166
|
-
continue;
|
|
52272
|
+
return status;
|
|
52167
52273
|
}
|
|
52168
52274
|
if (meshRecord?.source === "inline_cache" && !isSelfNode) {
|
|
52169
52275
|
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
52170
52276
|
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
|
|
52171
|
-
|
|
52172
|
-
continue;
|
|
52277
|
+
return status;
|
|
52173
52278
|
}
|
|
52174
52279
|
}
|
|
52175
52280
|
} else {
|
|
52176
52281
|
try {
|
|
52177
|
-
const
|
|
52282
|
+
const runLocalProbe = () => getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
52283
|
+
const gitStatus = await meshGitProbeCache.probeLocal(workspace, runLocalProbe);
|
|
52284
|
+
if (!gitStatus) throw new Error("local_git_probe_unavailable");
|
|
52178
52285
|
status.git = gitStatus;
|
|
52179
52286
|
status[MESH_NODE_LIVE_TRUTH_MARKER] = true;
|
|
52180
52287
|
const reporter = recordInlineMeshDirectGitTruth(node, gitStatus, "selected_coordinator_local_git");
|
|
@@ -52196,8 +52303,38 @@ var meshStatusHandlers = {
|
|
|
52196
52303
|
}
|
|
52197
52304
|
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
52198
52305
|
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
|
|
52199
|
-
|
|
52200
|
-
}
|
|
52306
|
+
return status;
|
|
52307
|
+
};
|
|
52308
|
+
const meshNodeEntries = [...(mesh.nodes || []).entries()];
|
|
52309
|
+
const settledNodeStatuses = await Promise.allSettled(
|
|
52310
|
+
meshNodeEntries.map(([nodeIndex, node]) => renderMeshNode(nodeIndex, node))
|
|
52311
|
+
);
|
|
52312
|
+
const nodeStatuses = settledNodeStatuses.map((settled, i) => {
|
|
52313
|
+
if (settled.status === "fulfilled") return settled.value;
|
|
52314
|
+
const [nodeIndex, node] = meshNodeEntries[i];
|
|
52315
|
+
const nodeId = normalizeMeshNodeId(node) ?? "";
|
|
52316
|
+
const daemonId = readStringValue(node.daemonId);
|
|
52317
|
+
const fallback = {
|
|
52318
|
+
nodeId,
|
|
52319
|
+
machineLabel: buildMeshNodeDisplayLabel(node, nodeId, readProviderPriorityFromPolicy(node.policy)),
|
|
52320
|
+
workspace: node.workspace,
|
|
52321
|
+
repoRoot: node.repoRoot,
|
|
52322
|
+
isLocalWorktree: node.isLocalWorktree,
|
|
52323
|
+
worktreeBranch: node.worktreeBranch,
|
|
52324
|
+
daemonId,
|
|
52325
|
+
machineId: readMeshNodeMachineId(node) || node.machineId,
|
|
52326
|
+
health: "unknown",
|
|
52327
|
+
providers: node.providers || [],
|
|
52328
|
+
activeSessions: [],
|
|
52329
|
+
activeSessionDetails: [],
|
|
52330
|
+
launchReady: false,
|
|
52331
|
+
error: settled.reason instanceof Error ? settled.reason.message : "node render failed"
|
|
52332
|
+
};
|
|
52333
|
+
applyCachedInlineMeshNodeStatus(fallback, node);
|
|
52334
|
+
applyInlineMeshBranchConvergence(mesh, node, fallback);
|
|
52335
|
+
finalizeMeshNodeStatus({ status: fallback, node, daemonId, isSelfNode: false, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
|
|
52336
|
+
return fallback;
|
|
52337
|
+
});
|
|
52201
52338
|
const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : ctx.deps.statusInstanceId || void 0;
|
|
52202
52339
|
const pendingCoordinatorEvents = getPendingMeshCoordinatorEvents(meshId, callerCoordinatorDaemonId);
|
|
52203
52340
|
const unroutableDeliveries = getRecentUnroutableDeliveries();
|
|
@@ -52313,6 +52450,7 @@ var meshStatusHandlers = {
|
|
|
52313
52450
|
refreshReason,
|
|
52314
52451
|
meshSource: meshRecord.source,
|
|
52315
52452
|
directTruth,
|
|
52453
|
+
durationMs: Date.now() - startedAtMs,
|
|
52316
52454
|
summary: summarizeRepoMeshStatusDebug(returnedStatus)
|
|
52317
52455
|
});
|
|
52318
52456
|
return returnedStatus;
|
|
@@ -53513,7 +53651,7 @@ var MESH_DIRECT_PROBE_TIMEOUT_MS = readMeshTimeoutEnvMs("MESH_DIRECT_PROBE_TIMEO
|
|
|
53513
53651
|
var MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS = readMeshTimeoutEnvMs("MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS", 25e3);
|
|
53514
53652
|
var MESH_DIRECT_PROBE_CONNECT_TIMEOUT_MS = MESH_CONNECT_TIMEOUT_MS;
|
|
53515
53653
|
var MESH_DIRECT_PROBE_REUSE_MS = readMeshTimeoutEnvMs("MESH_DIRECT_PROBE_REUSE_MS", 12e3);
|
|
53516
|
-
var MeshGitProbeCache = class {
|
|
53654
|
+
var MeshGitProbeCache = class _MeshGitProbeCache {
|
|
53517
53655
|
constructor(reuseMs, now = Date.now) {
|
|
53518
53656
|
this.reuseMs = reuseMs;
|
|
53519
53657
|
this.now = now;
|
|
@@ -53523,6 +53661,23 @@ var MeshGitProbeCache = class {
|
|
|
53523
53661
|
key(daemonId, workspace) {
|
|
53524
53662
|
return `${daemonId}::${workspace}`;
|
|
53525
53663
|
}
|
|
53664
|
+
/**
|
|
53665
|
+
* Local (same-machine) git_status dedup. The bootstrap direct-truth hydrate
|
|
53666
|
+
* and the per-node render loop both call getGitRepoStatus(refreshUpstream:true)
|
|
53667
|
+
* for the same local workspace within one mesh_status call. Each such probe
|
|
53668
|
+
* fans out ~13-15 git subprocesses, and because the two passes are separated by
|
|
53669
|
+
* the render/hydrate work of every OTHER node they routinely straddle the
|
|
53670
|
+
* getGitRepoStatus 1.5s TTL, so the second pass re-shells the whole ~14-process
|
|
53671
|
+
* collection. Routing both through this cache (namespaced under a reserved
|
|
53672
|
+
* daemon id so it never collides with a remote-peer key) collapses them to one
|
|
53673
|
+
* collection per workspace per request, and reuses it across the reuse window
|
|
53674
|
+
* so the dashboard auto-retry loop can't restart a fresh local probe seconds
|
|
53675
|
+
* apart either.
|
|
53676
|
+
*/
|
|
53677
|
+
static LOCAL_PROBE_DAEMON_ID = "__local_git__";
|
|
53678
|
+
async probeLocal(workspace, probe) {
|
|
53679
|
+
return this.probe(_MeshGitProbeCache.LOCAL_PROBE_DAEMON_ID, workspace, probe);
|
|
53680
|
+
}
|
|
53526
53681
|
/**
|
|
53527
53682
|
* Run `probe` for this peer, but reuse a fresh recent result or an in-flight
|
|
53528
53683
|
* probe for the same key when one is available. `probe` is only invoked when
|
|
@@ -53633,7 +53788,7 @@ async function hydrateInlineMeshDirectTruth(args) {
|
|
|
53633
53788
|
let standingEvidenceCount = 0;
|
|
53634
53789
|
const unavailableNodeIds = [];
|
|
53635
53790
|
const deadNodeIds = [];
|
|
53636
|
-
|
|
53791
|
+
const classifyNode = async (nodeIndex, node) => {
|
|
53637
53792
|
const nodeId = normalizeMeshNodeId(node) || `node_${nodeIndex}`;
|
|
53638
53793
|
const workspace = readStringValue(node?.workspace);
|
|
53639
53794
|
const daemonId = readStringValue(node?.daemonId);
|
|
@@ -53646,38 +53801,33 @@ async function hydrateInlineMeshDirectTruth(args) {
|
|
|
53646
53801
|
daemonId && (daemonIdsEquivalent(daemonId, args.localMachineId) || daemonIdsEquivalent(daemonId, args.statusInstanceId))
|
|
53647
53802
|
);
|
|
53648
53803
|
if ((isSelfNode || isSelfDaemonNode) && isDeadLocalWorktreeNode(node)) {
|
|
53649
|
-
|
|
53650
|
-
continue;
|
|
53804
|
+
return { kind: "dead", nodeId };
|
|
53651
53805
|
}
|
|
53652
53806
|
if (!workspace) {
|
|
53653
|
-
|
|
53654
|
-
continue;
|
|
53807
|
+
return !isSelfNode && daemonId ? { kind: "unavailable", nodeId } : { kind: "skip" };
|
|
53655
53808
|
}
|
|
53656
53809
|
if (fs29.existsSync(workspace)) {
|
|
53657
53810
|
try {
|
|
53658
|
-
const
|
|
53811
|
+
const runLocalProbe = () => getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
53812
|
+
const localGit = args.probeCache ? await args.probeCache.probeLocal(workspace, runLocalProbe) : await runLocalProbe();
|
|
53659
53813
|
if (localGit?.isGitRepo) {
|
|
53660
53814
|
const reporter = recordInlineMeshDirectGitTruth(node, localGit, "selected_coordinator_local_git");
|
|
53661
53815
|
persistNodeReporterPlatform(args.meshSource, args.mesh, nodeId, reporter);
|
|
53662
|
-
|
|
53663
|
-
continue;
|
|
53816
|
+
return { kind: "local" };
|
|
53664
53817
|
}
|
|
53665
53818
|
} catch {
|
|
53666
53819
|
}
|
|
53667
53820
|
}
|
|
53668
53821
|
const standingGit = buildInlineMeshTransitGitStatus(node);
|
|
53669
53822
|
if (standingGit) {
|
|
53670
|
-
|
|
53671
|
-
continue;
|
|
53823
|
+
return { kind: "standing" };
|
|
53672
53824
|
}
|
|
53673
53825
|
if (!args.probeRemotePeers) {
|
|
53674
|
-
|
|
53826
|
+
return { kind: "skip" };
|
|
53675
53827
|
}
|
|
53676
53828
|
if (!daemonId || !args.dispatchMeshCommand) {
|
|
53677
|
-
|
|
53678
|
-
continue;
|
|
53829
|
+
return !isSelfNode ? { kind: "unavailable", nodeId } : { kind: "skip" };
|
|
53679
53830
|
}
|
|
53680
|
-
peerAttemptedCount += 1;
|
|
53681
53831
|
const runProbe = () => probeRemoteMeshGitStatusWithRetry({
|
|
53682
53832
|
dispatchMeshCommand: args.dispatchMeshCommand,
|
|
53683
53833
|
daemonId,
|
|
@@ -53691,11 +53841,52 @@ async function hydrateInlineMeshDirectTruth(args) {
|
|
|
53691
53841
|
if (remoteGit) {
|
|
53692
53842
|
const reporter = recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
|
|
53693
53843
|
persistNodeReporterPlatform(args.meshSource, args.mesh, nodeId, reporter);
|
|
53694
|
-
|
|
53695
|
-
continue;
|
|
53844
|
+
return { kind: "peerConfirmed" };
|
|
53696
53845
|
}
|
|
53697
|
-
|
|
53698
|
-
}
|
|
53846
|
+
return { kind: "peerUnavailable", nodeId };
|
|
53847
|
+
};
|
|
53848
|
+
const nodeEntries = [...nodes.entries()];
|
|
53849
|
+
const settledResults = await Promise.allSettled(
|
|
53850
|
+
nodeEntries.map(([nodeIndex, node]) => classifyNode(nodeIndex, node))
|
|
53851
|
+
);
|
|
53852
|
+
settledResults.forEach((settled, i) => {
|
|
53853
|
+
const [nodeIndex, node] = nodeEntries[i];
|
|
53854
|
+
const result = settled.status === "fulfilled" ? settled.value : (() => {
|
|
53855
|
+
const nodeId = normalizeMeshNodeId(node) || `node_${nodeIndex}`;
|
|
53856
|
+
const daemonId = readStringValue(node?.daemonId);
|
|
53857
|
+
const isSelfNode = Boolean(
|
|
53858
|
+
nodeId && selectedCoordinatorNodeId && nodeId === selectedCoordinatorNodeId
|
|
53859
|
+
) || Boolean(
|
|
53860
|
+
daemonId && (daemonIdsEquivalent(daemonId, args.localMachineId) || daemonIdsEquivalent(daemonId, args.statusInstanceId))
|
|
53861
|
+
);
|
|
53862
|
+
return !isSelfNode && daemonId ? { kind: "unavailable", nodeId } : { kind: "skip" };
|
|
53863
|
+
})();
|
|
53864
|
+
switch (result.kind) {
|
|
53865
|
+
case "dead":
|
|
53866
|
+
deadNodeIds.push(result.nodeId);
|
|
53867
|
+
break;
|
|
53868
|
+
case "unavailable":
|
|
53869
|
+
unavailableNodeIds.push(result.nodeId);
|
|
53870
|
+
break;
|
|
53871
|
+
case "local":
|
|
53872
|
+
localConfirmedCount += 1;
|
|
53873
|
+
break;
|
|
53874
|
+
case "standing":
|
|
53875
|
+
standingEvidenceCount += 1;
|
|
53876
|
+
break;
|
|
53877
|
+
case "peerConfirmed":
|
|
53878
|
+
peerAttemptedCount += 1;
|
|
53879
|
+
peerConfirmedCount += 1;
|
|
53880
|
+
break;
|
|
53881
|
+
case "peerUnavailable":
|
|
53882
|
+
peerAttemptedCount += 1;
|
|
53883
|
+
unavailableNodeIds.push(result.nodeId);
|
|
53884
|
+
break;
|
|
53885
|
+
case "skip":
|
|
53886
|
+
default:
|
|
53887
|
+
break;
|
|
53888
|
+
}
|
|
53889
|
+
});
|
|
53699
53890
|
return {
|
|
53700
53891
|
directEvidenceCount: localConfirmedCount + peerConfirmedCount + standingEvidenceCount,
|
|
53701
53892
|
localConfirmedCount,
|
|
@@ -55066,6 +55257,10 @@ var DaemonCommandRouter = class {
|
|
|
55066
55257
|
* Spans separate mesh_status/get_mesh calls so the dashboard auto-retry
|
|
55067
55258
|
* loop cannot storm a slow peer with back-to-back refreshUpstream probes. */
|
|
55068
55259
|
meshGitProbeCache = new MeshGitProbeCache(MESH_DIRECT_PROBE_REUSE_MS);
|
|
55260
|
+
/** Meshes with a background SWR freshen (async mesh_status refresh) already in
|
|
55261
|
+
* flight — so a burst of interactive detail-opens serves the cached snapshot
|
|
55262
|
+
* and coalesces onto ONE background refresh instead of storming the peers. */
|
|
55263
|
+
swrRefreshInFlight = /* @__PURE__ */ new Set();
|
|
55069
55264
|
/** In-memory async Refinery jobs keyed by meshId:nodeId to reject/return duplicate in-flight requests. */
|
|
55070
55265
|
runningRefineJobs = /* @__PURE__ */ new Map();
|
|
55071
55266
|
/** Terminal async Refinery jobs preserve a clear answer after the worktree node has been removed. */
|
|
@@ -55169,7 +55364,7 @@ var DaemonCommandRouter = class {
|
|
|
55169
55364
|
if (cached3.queueRevision !== getMeshQueueRevision(meshId)) return null;
|
|
55170
55365
|
let snapshot = this.cloneJsonValue(cached3.snapshot);
|
|
55171
55366
|
snapshot = this.hydrateCachedAggregateMeshStatusFromInline(snapshot, mesh, options);
|
|
55172
|
-
if (shouldRefreshStalePendingAggregate(snapshot, options)) return null;
|
|
55367
|
+
if (!options?.allowStalePending && shouldRefreshStalePendingAggregate(snapshot, options)) return null;
|
|
55173
55368
|
const ageMs = Math.max(0, Date.now() - cached3.builtAt);
|
|
55174
55369
|
const sourceOfTruth = snapshot.sourceOfTruth && typeof snapshot.sourceOfTruth === "object" ? snapshot.sourceOfTruth : {};
|
|
55175
55370
|
snapshot.sourceOfTruth = {
|
|
@@ -55399,6 +55594,7 @@ var DaemonCommandRouter = class {
|
|
|
55399
55594
|
rememberAggregateMeshStatus: this.rememberAggregateMeshStatus.bind(this),
|
|
55400
55595
|
execute: this.execute.bind(this),
|
|
55401
55596
|
aggregateMeshStatusCache: this.aggregateMeshStatusCache,
|
|
55597
|
+
swrRefreshInFlight: this.swrRefreshInFlight,
|
|
55402
55598
|
runningRefineJobs: this.runningRefineJobs,
|
|
55403
55599
|
inlineMeshCache: this.inlineMeshCache,
|
|
55404
55600
|
meshGitProbeCache: this.meshGitProbeCache
|