@adhdev/daemon-core 0.9.82-rc.367 → 0.9.82-rc.369
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/boot/daemon-lifecycle.d.ts +1 -0
- package/dist/commands/router.d.ts +37 -32
- package/dist/index.js +297 -96
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +297 -96
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-warmup-deadline.d.ts +68 -0
- package/package.json +2 -2
- package/src/boot/daemon-lifecycle.ts +8 -0
- package/src/commands/cli-manager.ts +79 -10
- package/src/commands/high-family/mesh-status.ts +6 -3
- package/src/commands/router.ts +188 -94
- package/src/mesh/mesh-events-coordinator.ts +172 -33
- package/src/mesh/mesh-warmup-deadline.ts +152 -0
package/dist/index.js
CHANGED
|
@@ -316,10 +316,10 @@ function readInjected(value) {
|
|
|
316
316
|
}
|
|
317
317
|
function getDaemonBuildInfo() {
|
|
318
318
|
if (cached) return cached;
|
|
319
|
-
const commit = readInjected(true ? "
|
|
320
|
-
const commitShort = readInjected(true ? "
|
|
321
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
322
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
319
|
+
const commit = readInjected(true ? "4464cd9f1effac841aa1fbef3b1691d2f06d64e4" : void 0) ?? "unknown";
|
|
320
|
+
const commitShort = readInjected(true ? "4464cd9f" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
321
|
+
const version = readInjected(true ? "0.9.82-rc.369" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
322
|
+
const builtAt = readInjected(true ? "2026-06-24T08:22:14.501Z" : void 0);
|
|
323
323
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
324
324
|
return cached;
|
|
325
325
|
}
|
|
@@ -10382,6 +10382,90 @@ var init_mesh_event_trace = __esm({
|
|
|
10382
10382
|
}
|
|
10383
10383
|
});
|
|
10384
10384
|
|
|
10385
|
+
// src/mesh/mesh-warmup-deadline.ts
|
|
10386
|
+
function awaitWithWarmupDeadline(work, opts) {
|
|
10387
|
+
const pollMs = Math.max(1, Math.min(opts.pollIntervalMs ?? 200, opts.connectTimeoutMs));
|
|
10388
|
+
return new Promise((resolve24, reject) => {
|
|
10389
|
+
let done = false;
|
|
10390
|
+
let poll;
|
|
10391
|
+
let responseTimer;
|
|
10392
|
+
const startedAt = Date.now();
|
|
10393
|
+
const cleanup = () => {
|
|
10394
|
+
if (poll) {
|
|
10395
|
+
clearInterval(poll);
|
|
10396
|
+
poll = void 0;
|
|
10397
|
+
}
|
|
10398
|
+
if (responseTimer) {
|
|
10399
|
+
clearTimeout(responseTimer);
|
|
10400
|
+
responseTimer = void 0;
|
|
10401
|
+
}
|
|
10402
|
+
};
|
|
10403
|
+
const settle = (fn) => {
|
|
10404
|
+
if (done) return;
|
|
10405
|
+
done = true;
|
|
10406
|
+
cleanup();
|
|
10407
|
+
fn();
|
|
10408
|
+
};
|
|
10409
|
+
const armResponse = () => {
|
|
10410
|
+
if (responseTimer || done) return;
|
|
10411
|
+
responseTimer = setTimeout(
|
|
10412
|
+
() => settle(() => reject(new Error("timeout"))),
|
|
10413
|
+
opts.responseTimeoutMs
|
|
10414
|
+
);
|
|
10415
|
+
if (typeof responseTimer.unref === "function") responseTimer.unref();
|
|
10416
|
+
};
|
|
10417
|
+
const onPoll = () => {
|
|
10418
|
+
if (done) return;
|
|
10419
|
+
if (opts.isConnected()) {
|
|
10420
|
+
if (poll) {
|
|
10421
|
+
clearInterval(poll);
|
|
10422
|
+
poll = void 0;
|
|
10423
|
+
}
|
|
10424
|
+
armResponse();
|
|
10425
|
+
return;
|
|
10426
|
+
}
|
|
10427
|
+
if (Date.now() - startedAt >= opts.connectTimeoutMs) {
|
|
10428
|
+
settle(() => reject(new Error("timeout")));
|
|
10429
|
+
}
|
|
10430
|
+
};
|
|
10431
|
+
if (opts.isConnected()) {
|
|
10432
|
+
armResponse();
|
|
10433
|
+
} else {
|
|
10434
|
+
poll = setInterval(onPoll, pollMs);
|
|
10435
|
+
if (typeof poll.unref === "function") poll.unref();
|
|
10436
|
+
}
|
|
10437
|
+
work.then(
|
|
10438
|
+
(val) => settle(() => resolve24(val)),
|
|
10439
|
+
(err) => settle(() => reject(err))
|
|
10440
|
+
);
|
|
10441
|
+
});
|
|
10442
|
+
}
|
|
10443
|
+
function readWarmupConnectionState(connection) {
|
|
10444
|
+
const state = connection?.state;
|
|
10445
|
+
return typeof state === "string" && state.length > 0 ? state : void 0;
|
|
10446
|
+
}
|
|
10447
|
+
function resolveWarmupDeadlineOpts(opts) {
|
|
10448
|
+
const { getConnection, daemonId, connectTimeoutMs, responseTimeoutMs } = opts;
|
|
10449
|
+
if (getConnection) {
|
|
10450
|
+
return {
|
|
10451
|
+
isConnected: () => readWarmupConnectionState(getConnection(daemonId)) === "connected",
|
|
10452
|
+
connectTimeoutMs,
|
|
10453
|
+
responseTimeoutMs
|
|
10454
|
+
};
|
|
10455
|
+
}
|
|
10456
|
+
opts.onMissingGetter?.(daemonId);
|
|
10457
|
+
return {
|
|
10458
|
+
isConnected: () => false,
|
|
10459
|
+
connectTimeoutMs: connectTimeoutMs + responseTimeoutMs,
|
|
10460
|
+
responseTimeoutMs
|
|
10461
|
+
};
|
|
10462
|
+
}
|
|
10463
|
+
var init_mesh_warmup_deadline = __esm({
|
|
10464
|
+
"src/mesh/mesh-warmup-deadline.ts"() {
|
|
10465
|
+
"use strict";
|
|
10466
|
+
}
|
|
10467
|
+
});
|
|
10468
|
+
|
|
10385
10469
|
// src/config/state-store.ts
|
|
10386
10470
|
function isPlainObject2(value) {
|
|
10387
10471
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
@@ -12817,7 +12901,12 @@ function resolveActiveDirectDispatchTaskId(meshId, sessionId) {
|
|
|
12817
12901
|
return void 0;
|
|
12818
12902
|
}
|
|
12819
12903
|
}
|
|
12820
|
-
function
|
|
12904
|
+
function warnDispatchWarmupGetterMissingOnce(daemonId) {
|
|
12905
|
+
if (dispatchWarmupGetterMissingWarned.has(daemonId)) return;
|
|
12906
|
+
dispatchWarmupGetterMissingWarned.add(daemonId);
|
|
12907
|
+
LOG.warn("MeshQueue", `Mesh peer connection getter unavailable for ${String(daemonId).slice(0, 12)}; remote task-dispatch warmup deadline degraded to the combined connect+response window. Avoids a cold-open false-timeout but loses warm/cold precision \u2014 wire getMeshPeerConnectionStatus on this daemon.`);
|
|
12908
|
+
}
|
|
12909
|
+
function deliverTaskToSession(dispatchThunk, ctx, warmup) {
|
|
12821
12910
|
const delivery = createSessionDelivery({
|
|
12822
12911
|
meshId: ctx.meshId,
|
|
12823
12912
|
nodeId: ctx.nodeId,
|
|
@@ -12837,16 +12926,27 @@ function deliverTaskToSession(dispatchThunk, ctx) {
|
|
|
12837
12926
|
dispatchPromise = Promise.reject(e);
|
|
12838
12927
|
}
|
|
12839
12928
|
let timer;
|
|
12840
|
-
|
|
12841
|
-
|
|
12842
|
-
|
|
12843
|
-
|
|
12844
|
-
|
|
12845
|
-
|
|
12846
|
-
|
|
12847
|
-
|
|
12848
|
-
})
|
|
12849
|
-
|
|
12929
|
+
let guarded;
|
|
12930
|
+
if (warmup) {
|
|
12931
|
+
guarded = awaitWithWarmupDeadline(dispatchPromise, resolveWarmupDeadlineOpts({
|
|
12932
|
+
getConnection: warmup.getConnection,
|
|
12933
|
+
daemonId: warmup.daemonId,
|
|
12934
|
+
connectTimeoutMs: DISPATCH_CONNECT_TIMEOUT_MS,
|
|
12935
|
+
responseTimeoutMs: DISPATCH_CONFIRM_TIMEOUT_MS,
|
|
12936
|
+
onMissingGetter: warnDispatchWarmupGetterMissingOnce
|
|
12937
|
+
}));
|
|
12938
|
+
} else {
|
|
12939
|
+
guarded = Promise.race([
|
|
12940
|
+
dispatchPromise,
|
|
12941
|
+
new Promise((_, reject) => {
|
|
12942
|
+
timer = setTimeout(
|
|
12943
|
+
() => reject(new Error(`dispatch_confirm_timeout after ${DISPATCH_CONFIRM_TIMEOUT_MS}ms`)),
|
|
12944
|
+
DISPATCH_CONFIRM_TIMEOUT_MS
|
|
12945
|
+
);
|
|
12946
|
+
if (typeof timer?.unref === "function") timer.unref();
|
|
12947
|
+
})
|
|
12948
|
+
]);
|
|
12949
|
+
}
|
|
12850
12950
|
guarded.then(() => {
|
|
12851
12951
|
if (timer) clearTimeout(timer);
|
|
12852
12952
|
updateSessionDeliveryStatus(delivery.id, "delivered");
|
|
@@ -12870,13 +12970,25 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
|
|
|
12870
12970
|
const mesh = getMeshWithCache(components, meshId);
|
|
12871
12971
|
const node = mesh?.nodes.find((n) => readMeshNodeId(n) === nodeId);
|
|
12872
12972
|
const localClaimAdapter = components.cliManager?.adapters?.get(sessionId);
|
|
12873
|
-
|
|
12874
|
-
|
|
12875
|
-
|
|
12876
|
-
|
|
12877
|
-
|
|
12973
|
+
let claimInstanceWorkspace = "";
|
|
12974
|
+
let claimStampedNodeId = "";
|
|
12975
|
+
try {
|
|
12976
|
+
const claimState = components.instanceManager?.getInstance?.(sessionId)?.getState?.();
|
|
12977
|
+
claimInstanceWorkspace = readNonEmptyString2(claimState?.workspace);
|
|
12978
|
+
const claimSettings = claimState?.settings || {};
|
|
12979
|
+
claimStampedNodeId = readNonEmptyString2(claimSettings.meshNodeId);
|
|
12980
|
+
} catch {
|
|
12981
|
+
}
|
|
12982
|
+
const nodeWorkspaceRaw = readNonEmptyString2(node?.workspace);
|
|
12983
|
+
const sessionWorkspaceRaw = readNonEmptyString2(localClaimAdapter?.workingDir) || claimInstanceWorkspace;
|
|
12984
|
+
if (claimStampedNodeId && nodeId) {
|
|
12985
|
+
if (!meshNodeIdMatches({ id: claimStampedNodeId }, nodeId)) {
|
|
12986
|
+
LOG.info("MeshQueue", `WTDISPATCH: refusing claim for node ${nodeId} (${sessionId}) \u2014 session is bound to node "${claimStampedNodeId}" (cross-node claim blocked)`);
|
|
12878
12987
|
return false;
|
|
12879
12988
|
}
|
|
12989
|
+
} else if (sessionWorkspaceRaw && nodeWorkspaceRaw && !meshWorkspacesEquivalent(sessionWorkspaceRaw, nodeWorkspaceRaw)) {
|
|
12990
|
+
LOG.info("MeshQueue", `WTCLAIM: refusing claim for node ${nodeId} (${sessionId}) \u2014 session workspace "${normalizeMeshWorkspaceForCompare(sessionWorkspaceRaw)}" \u2260 node workspace "${normalizeMeshWorkspaceForCompare(nodeWorkspaceRaw)}" (cross-workspace dispatch blocked)`);
|
|
12991
|
+
return false;
|
|
12880
12992
|
}
|
|
12881
12993
|
const capabilityTags = buildMeshNodeCapabilityTags(node, providerType);
|
|
12882
12994
|
const providerMaxParallel = resolveProviderMaxParallel(node?.policy, providerType);
|
|
@@ -12918,7 +13030,11 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
|
|
|
12918
13030
|
transport: "remote",
|
|
12919
13031
|
...sourceCoordinatorSessionId ? { sourceCoordinatorSessionId } : {},
|
|
12920
13032
|
...localDaemonIdForDispatch ? { sourceCoordinatorDaemonId: localDaemonIdForDispatch } : {}
|
|
12921
|
-
}
|
|
13033
|
+
},
|
|
13034
|
+
// Warmup-aware deadline: this dispatch can be the FIRST command to a
|
|
13035
|
+
// peer whose mesh DataChannel is still opening — charge the cold-open
|
|
13036
|
+
// handshake to the connect budget, not the response budget.
|
|
13037
|
+
{ daemonId: remoteDaemonId, getConnection: components.getMeshPeerConnectionStatus }
|
|
12922
13038
|
);
|
|
12923
13039
|
return true;
|
|
12924
13040
|
}
|
|
@@ -14154,6 +14270,25 @@ function handleMeshForwardEvent(components, payload) {
|
|
|
14154
14270
|
metadataEvent: buildRelayMetadataEvent(payload)
|
|
14155
14271
|
});
|
|
14156
14272
|
}
|
|
14273
|
+
function enqueueCoordinatorForwardPush(coordinatorDaemonId, run) {
|
|
14274
|
+
let lane = coordinatorForwardLanes.get(coordinatorDaemonId);
|
|
14275
|
+
if (!lane) {
|
|
14276
|
+
lane = { tail: Promise.resolve(), depth: 0 };
|
|
14277
|
+
coordinatorForwardLanes.set(coordinatorDaemonId, lane);
|
|
14278
|
+
}
|
|
14279
|
+
const wasIdle = lane.depth === 0;
|
|
14280
|
+
lane.depth += 1;
|
|
14281
|
+
const dec = () => {
|
|
14282
|
+
lane.depth -= 1;
|
|
14283
|
+
};
|
|
14284
|
+
if (wasIdle) {
|
|
14285
|
+
lane.tail = Promise.resolve(run()).catch(() => {
|
|
14286
|
+
}).then(dec, dec);
|
|
14287
|
+
} else {
|
|
14288
|
+
lane.tail = lane.tail.then(() => run()).catch(() => {
|
|
14289
|
+
}).then(dec, dec);
|
|
14290
|
+
}
|
|
14291
|
+
}
|
|
14157
14292
|
function forwardUnresolvedDelegateEvent(components, routing, event) {
|
|
14158
14293
|
const coordinatorDaemonId = readNonEmptyString2(routing.coordinatorDaemonId);
|
|
14159
14294
|
if (!coordinatorDaemonId) return false;
|
|
@@ -14185,7 +14320,8 @@ function forwardUnresolvedDelegateEvent(components, routing, event) {
|
|
|
14185
14320
|
};
|
|
14186
14321
|
traceMeshEventStage("outbox_enqueue", fwdTraceCtx, `coordinatorDaemon=${coordinatorDaemonId} meshId=absent`);
|
|
14187
14322
|
traceMeshEventStage("forward_send", fwdTraceCtx, "immediate push");
|
|
14188
|
-
|
|
14323
|
+
const dispatchMeshCommand = components.dispatchMeshCommand;
|
|
14324
|
+
enqueueCoordinatorForwardPush(coordinatorDaemonId, () => Promise.resolve(dispatchMeshCommand(coordinatorDaemonId, "mesh_forward_event", payload)).then((result) => {
|
|
14189
14325
|
if (result && result.success === false) {
|
|
14190
14326
|
LOG.warn("MeshEvents", `Immediate forward of ${eventName} to coordinator ${coordinatorDaemonId} rejected (${readNonEmptyString2(result.error) || "no reason"}) \u2014 left queued for retry`);
|
|
14191
14327
|
traceMeshEventDrop("immediate_forward_rejected", fwdTraceCtx, readNonEmptyString2(result.error) || "no reason");
|
|
@@ -14194,7 +14330,7 @@ function forwardUnresolvedDelegateEvent(components, routing, event) {
|
|
|
14194
14330
|
if (persisted) ackUnresolvedDelegateForwardByFingerprint(coordinatorDaemonId, eventName, payload);
|
|
14195
14331
|
}).catch((e) => {
|
|
14196
14332
|
LOG.warn("MeshEvents", `Immediate forward of ${eventName} to coordinator ${coordinatorDaemonId} failed: ${e?.message || e} \u2014 left queued for retry`);
|
|
14197
|
-
});
|
|
14333
|
+
}));
|
|
14198
14334
|
LOG.info("MeshEvents", `Durably forwarded ${eventName} for unresolved-mesh worker at ${routing.workspace || "(no workspace)"} to coordinator daemon ${coordinatorDaemonId}`);
|
|
14199
14335
|
return true;
|
|
14200
14336
|
}
|
|
@@ -14277,7 +14413,7 @@ function setupMeshEventForwarding(components) {
|
|
|
14277
14413
|
});
|
|
14278
14414
|
});
|
|
14279
14415
|
}
|
|
14280
|
-
var import_fs13, REMOTE_IDLE_SESSION_TTL_MS, meshByWorkspaceCache, MESH_WORKSPACE_CACHE_TTL_MS, IDLE_AUTO_FAST_FORWARD_THROTTLE_MS, idleAutoFastForwardLastAttempt, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, RECENT_COMPLETION_FINGERPRINT_TTL_MS, DISPATCH_CONFIRM_TIMEOUT_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, AUTO_LAUNCH_AWAIT_CLAIM_MS, lastAutoLaunchLedgerKey, AUTO_LAUNCH_LEDGER_DEDUP_MAX, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, MESH_FORCE_INJECT_EVENTS;
|
|
14416
|
+
var import_fs13, REMOTE_IDLE_SESSION_TTL_MS, meshByWorkspaceCache, MESH_WORKSPACE_CACHE_TTL_MS, IDLE_AUTO_FAST_FORWARD_THROTTLE_MS, idleAutoFastForwardLastAttempt, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, RECENT_COMPLETION_FINGERPRINT_TTL_MS, DISPATCH_CONFIRM_TIMEOUT_MS, DISPATCH_CONNECT_TIMEOUT_MS, dispatchWarmupGetterMissingWarned, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, AUTO_LAUNCH_AWAIT_CLAIM_MS, lastAutoLaunchLedgerKey, AUTO_LAUNCH_LEDGER_DEDUP_MAX, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, MESH_FORCE_INJECT_EVENTS, coordinatorForwardLanes;
|
|
14281
14417
|
var init_mesh_events_coordinator = __esm({
|
|
14282
14418
|
"src/mesh/mesh-events-coordinator.ts"() {
|
|
14283
14419
|
"use strict";
|
|
@@ -14295,6 +14431,7 @@ var init_mesh_events_coordinator = __esm({
|
|
|
14295
14431
|
init_mesh_routing();
|
|
14296
14432
|
init_mesh_unresolved_forward_outbox();
|
|
14297
14433
|
init_mesh_event_trace();
|
|
14434
|
+
init_mesh_warmup_deadline();
|
|
14298
14435
|
init_snapshot();
|
|
14299
14436
|
init_repo_mesh_types();
|
|
14300
14437
|
init_dist();
|
|
@@ -14308,6 +14445,8 @@ var init_mesh_events_coordinator = __esm({
|
|
|
14308
14445
|
INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS = 30 * 60 * 1e3;
|
|
14309
14446
|
RECENT_COMPLETION_FINGERPRINT_TTL_MS = 10 * 60 * 1e3;
|
|
14310
14447
|
DISPATCH_CONFIRM_TIMEOUT_MS = 12e4;
|
|
14448
|
+
DISPATCH_CONNECT_TIMEOUT_MS = 45e3;
|
|
14449
|
+
dispatchWarmupGetterMissingWarned = /* @__PURE__ */ new Set();
|
|
14311
14450
|
autoLaunchInProgress = /* @__PURE__ */ new Set();
|
|
14312
14451
|
autoLaunchCooldownUntil = /* @__PURE__ */ new Map();
|
|
14313
14452
|
AUTO_LAUNCH_COOLDOWN_MS = 5e3;
|
|
@@ -14342,6 +14481,7 @@ var init_mesh_events_coordinator = __esm({
|
|
|
14342
14481
|
"worktree_bootstrap_complete",
|
|
14343
14482
|
"worktree_bootstrap_failed"
|
|
14344
14483
|
]);
|
|
14484
|
+
coordinatorForwardLanes = /* @__PURE__ */ new Map();
|
|
14345
14485
|
}
|
|
14346
14486
|
});
|
|
14347
14487
|
|
|
@@ -41537,6 +41677,18 @@ var DaemonCliManager = class {
|
|
|
41537
41677
|
throw new Error(`Failed to start ${provider.displayName || provider.name || cliType}: ${spawnErr?.message}`);
|
|
41538
41678
|
}
|
|
41539
41679
|
this.adapters.set(key, cliInstance.getAdapter());
|
|
41680
|
+
const launchMeshNodeId = typeof settings?.meshNodeId === "string" ? settings.meshNodeId.trim() : "";
|
|
41681
|
+
const launchMeshNodeFor = typeof settings?.meshNodeFor === "string" ? settings.meshNodeFor.trim() : "";
|
|
41682
|
+
if (launchMeshNodeId || launchMeshNodeFor) {
|
|
41683
|
+
try {
|
|
41684
|
+
cliInstance.getAdapter().updateRuntimeMeta?.({
|
|
41685
|
+
...launchMeshNodeId ? { meshNodeId: launchMeshNodeId } : {},
|
|
41686
|
+
...launchMeshNodeFor ? { meshNodeFor: launchMeshNodeFor } : {},
|
|
41687
|
+
...settings?.launchedByCoordinator === true ? { launchedByCoordinator: true } : {}
|
|
41688
|
+
});
|
|
41689
|
+
} catch {
|
|
41690
|
+
}
|
|
41691
|
+
}
|
|
41540
41692
|
this.startCliExitMonitor(key, cliType);
|
|
41541
41693
|
}
|
|
41542
41694
|
// ─── Session start/management ──────────────────────────────
|
|
@@ -41804,6 +41956,14 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
41804
41956
|
let restored = 0;
|
|
41805
41957
|
const restoredBindings = /* @__PURE__ */ new Set();
|
|
41806
41958
|
const managerTag = this.deps.hostedRuntimeManagerTag;
|
|
41959
|
+
const restoredRuntimeIds = /* @__PURE__ */ new Set();
|
|
41960
|
+
const workspaceTypeCounts = /* @__PURE__ */ new Map();
|
|
41961
|
+
for (const r of sessions) {
|
|
41962
|
+
if (!r?.runtimeId || !r?.cliType || !r?.workspace) continue;
|
|
41963
|
+
restoredRuntimeIds.add(r.runtimeId);
|
|
41964
|
+
const key = `${r.workspace}::${r.cliType}`;
|
|
41965
|
+
workspaceTypeCounts.set(key, (workspaceTypeCounts.get(key) || 0) + 1);
|
|
41966
|
+
}
|
|
41807
41967
|
for (const record of sessions) {
|
|
41808
41968
|
if (!record?.runtimeId || !record?.cliType || !record?.workspace) continue;
|
|
41809
41969
|
if (!shouldRestoreHostedRuntime(record, managerTag)) {
|
|
@@ -41841,11 +42001,21 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
41841
42001
|
if (!coordinatorEntry?.meshId && record.workspace) {
|
|
41842
42002
|
const workspaceCoordinators = listCoordinatorsForWorkspace(record.workspace).filter((e) => e.meshId && (!e.cliType || e.cliType === record.cliType));
|
|
41843
42003
|
if (workspaceCoordinators.length === 1) {
|
|
41844
|
-
|
|
41845
|
-
|
|
41846
|
-
|
|
41847
|
-
|
|
41848
|
-
|
|
42004
|
+
const candidate = workspaceCoordinators[0];
|
|
42005
|
+
const coordinatorPresentById = !!candidate.sessionId && restoredRuntimeIds.has(candidate.sessionId);
|
|
42006
|
+
const siblingCount = workspaceTypeCounts.get(`${record.workspace}::${record.cliType}`) || 1;
|
|
42007
|
+
if (!coordinatorPresentById && siblingCount === 1) {
|
|
42008
|
+
coordinatorEntry = candidate;
|
|
42009
|
+
LOG.info(
|
|
42010
|
+
"CLI",
|
|
42011
|
+
`\u21BB Rebound coordinator mark by workspace for ${record.runtimeKey || record.runtimeId} (mesh ${candidate.meshId} @ ${record.workspace}); registry key did not match runtimeId`
|
|
42012
|
+
);
|
|
42013
|
+
} else {
|
|
42014
|
+
LOG.info(
|
|
42015
|
+
"CLI",
|
|
42016
|
+
`\u21B7 Skipping workspace coordinator rebind for ${record.runtimeKey || record.runtimeId} (${record.cliType} @ ${record.workspace}): ${coordinatorPresentById ? "registered coordinator is restoring under its own id \u2014 this is a delegated worker" : `ambiguous (${siblingCount} sessions share this workspace+cliType)`}`
|
|
42017
|
+
);
|
|
42018
|
+
}
|
|
41849
42019
|
}
|
|
41850
42020
|
}
|
|
41851
42021
|
if (coordinatorEntry?.meshId) {
|
|
@@ -48327,6 +48497,7 @@ var meshStatusHandlers = {
|
|
|
48327
48497
|
const remoteGit = await meshGitProbeCache.probe(daemonId, workspace, runNodeProbe);
|
|
48328
48498
|
if (remoteGit) {
|
|
48329
48499
|
status.git = remoteGit;
|
|
48500
|
+
status[MESH_NODE_LIVE_TRUTH_MARKER] = true;
|
|
48330
48501
|
status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
|
|
48331
48502
|
const connection = readObjectRecord(status.connection);
|
|
48332
48503
|
const connectionState = readStringValue(connection.state);
|
|
@@ -48352,13 +48523,13 @@ var meshStatusHandlers = {
|
|
|
48352
48523
|
pendingPeerGitProbe ? { skipGit: true, skipError: true, skipHealth: true } : void 0
|
|
48353
48524
|
)) {
|
|
48354
48525
|
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
48355
|
-
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
48526
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
|
|
48356
48527
|
nodeStatuses.push(status);
|
|
48357
48528
|
continue;
|
|
48358
48529
|
}
|
|
48359
48530
|
if (meshRecord?.source === "inline_cache" && !isSelfNode) {
|
|
48360
48531
|
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
48361
|
-
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
48532
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
|
|
48362
48533
|
nodeStatuses.push(status);
|
|
48363
48534
|
continue;
|
|
48364
48535
|
}
|
|
@@ -48367,6 +48538,7 @@ var meshStatusHandlers = {
|
|
|
48367
48538
|
try {
|
|
48368
48539
|
const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
48369
48540
|
status.git = gitStatus;
|
|
48541
|
+
status[MESH_NODE_LIVE_TRUTH_MARKER] = true;
|
|
48370
48542
|
const reporter = recordInlineMeshDirectGitTruth(node, gitStatus, "selected_coordinator_local_git");
|
|
48371
48543
|
persistNodeReporterPlatform(meshRecord.source, mesh, nodeId, reporter);
|
|
48372
48544
|
if (gitStatus.isGitRepo) {
|
|
@@ -48385,7 +48557,7 @@ var meshStatusHandlers = {
|
|
|
48385
48557
|
applyCachedInlineMeshNodeStatus(status, node);
|
|
48386
48558
|
}
|
|
48387
48559
|
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
48388
|
-
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
48560
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
|
|
48389
48561
|
nodeStatuses.push(status);
|
|
48390
48562
|
}
|
|
48391
48563
|
const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : ctx.deps.statusInstanceId || void 0;
|
|
@@ -48799,6 +48971,7 @@ function orderMeshRefineBatchNodes(changeAreas) {
|
|
|
48799
48971
|
|
|
48800
48972
|
// src/commands/router.ts
|
|
48801
48973
|
init_mesh_work_queue();
|
|
48974
|
+
init_mesh_warmup_deadline();
|
|
48802
48975
|
init_repo_mesh_types();
|
|
48803
48976
|
var import_os4 = require("os");
|
|
48804
48977
|
var import_path13 = require("path");
|
|
@@ -49540,14 +49713,92 @@ function synthesizeMeshNodeFreshnessFromConnection(status) {
|
|
|
49540
49713
|
status.updatedAt = gitCheckedAt ?? connectionFreshAt;
|
|
49541
49714
|
}
|
|
49542
49715
|
}
|
|
49716
|
+
var MESH_NODE_LIVE_TRUTH_MARKER = "__liveTruthProbed";
|
|
49717
|
+
var MESH_FRESHNESS_FRESH_MS = 3e4;
|
|
49718
|
+
var MESH_FRESHNESS_RECENT_MS = 3e5;
|
|
49719
|
+
function classifyMeshNodeStaleness(dataSource, ageMs) {
|
|
49720
|
+
if (dataSource === "self" || dataSource === "live") return "fresh";
|
|
49721
|
+
if (ageMs === null) return "unknown";
|
|
49722
|
+
if (ageMs < MESH_FRESHNESS_FRESH_MS) return "fresh";
|
|
49723
|
+
if (ageMs < MESH_FRESHNESS_RECENT_MS) return "recent";
|
|
49724
|
+
return "stale";
|
|
49725
|
+
}
|
|
49726
|
+
function buildMeshNodeDataFreshness(args) {
|
|
49727
|
+
const { status, node, isSelfNode, daemonId, liveTruthProbed, directTruthUnavailable } = args;
|
|
49728
|
+
const now = args.now ?? Date.now;
|
|
49729
|
+
const connection = readObjectRecord(status.connection);
|
|
49730
|
+
const connectionState = readStringValue(connection.state);
|
|
49731
|
+
const git = readObjectRecord(status.git);
|
|
49732
|
+
const hasGit = readBooleanValue(git.isGitRepo) === true || !!readStringValue(git.branch, git.headCommit, git.head, git.upstream);
|
|
49733
|
+
const connectionFreshAt = toIsoTimestamp(connection.lastCommandAt ?? connection.lastConnectedAt ?? connection.lastStateChangeAt);
|
|
49734
|
+
const liveGitCheckedAt = liveTruthProbed ? toIsoTimestamp(git.lastCheckedAt) : null;
|
|
49735
|
+
const heldGit = readObjectRecord(node?.lastGit ?? node?.last_git);
|
|
49736
|
+
const heldCheckedAt = toIsoTimestamp(heldGit.checkedAt ?? heldGit.checked_at);
|
|
49737
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
49738
|
+
const cachedGitCheckedAt = toIsoTimestamp(readObjectRecord(cachedStatus.git).lastCheckedAt);
|
|
49739
|
+
const lastProbeAt = liveGitCheckedAt ?? heldCheckedAt ?? cachedGitCheckedAt ?? toIsoTimestamp(git.lastCheckedAt) ?? connectionFreshAt ?? toIsoTimestamp(status.updatedAt) ?? toIsoTimestamp(status.lastSeenAt);
|
|
49740
|
+
const connectionReachable = connectionState === "connected" ? true : !connectionState || connectionState === "unknown" || connectionState === "connecting" ? connectionState === "connecting" ? true : null : false;
|
|
49741
|
+
let dataSource;
|
|
49742
|
+
let reachable;
|
|
49743
|
+
if (isSelfNode) {
|
|
49744
|
+
dataSource = "self";
|
|
49745
|
+
reachable = true;
|
|
49746
|
+
} else if (liveTruthProbed) {
|
|
49747
|
+
dataSource = "live";
|
|
49748
|
+
reachable = true;
|
|
49749
|
+
} else if (readBooleanValue(status.gitProbePending) === true) {
|
|
49750
|
+
dataSource = "pending";
|
|
49751
|
+
reachable = connectionReachable;
|
|
49752
|
+
} else if (directTruthUnavailable) {
|
|
49753
|
+
dataSource = "unreachable";
|
|
49754
|
+
reachable = false;
|
|
49755
|
+
} else if (hasGit) {
|
|
49756
|
+
dataSource = "cached";
|
|
49757
|
+
reachable = connectionReachable;
|
|
49758
|
+
} else if (!daemonId) {
|
|
49759
|
+
dataSource = "unconfigured";
|
|
49760
|
+
reachable = null;
|
|
49761
|
+
} else if (connectionState === "connected") {
|
|
49762
|
+
dataSource = "empty";
|
|
49763
|
+
reachable = true;
|
|
49764
|
+
} else {
|
|
49765
|
+
dataSource = "unreachable";
|
|
49766
|
+
reachable = false;
|
|
49767
|
+
}
|
|
49768
|
+
const probeOk = dataSource === "live" || dataSource === "self";
|
|
49769
|
+
let ageMs = null;
|
|
49770
|
+
if (lastProbeAt) {
|
|
49771
|
+
const parsed = Date.parse(lastProbeAt);
|
|
49772
|
+
if (Number.isFinite(parsed)) ageMs = Math.max(0, now() - parsed);
|
|
49773
|
+
}
|
|
49774
|
+
const staleness = classifyMeshNodeStaleness(dataSource, ageMs);
|
|
49775
|
+
return {
|
|
49776
|
+
dataSource,
|
|
49777
|
+
probeOk,
|
|
49778
|
+
reachable,
|
|
49779
|
+
lastProbeAt: lastProbeAt ?? null,
|
|
49780
|
+
ageMs,
|
|
49781
|
+
staleness
|
|
49782
|
+
};
|
|
49783
|
+
}
|
|
49543
49784
|
function finalizeMeshNodeStatus(args) {
|
|
49544
|
-
const { status, node, daemonId, isSelfNode } = args;
|
|
49785
|
+
const { status, node, daemonId, isSelfNode, directTruthUnavailable } = args;
|
|
49545
49786
|
if (!readStringValue(status.machineStatus)) {
|
|
49546
49787
|
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
49547
49788
|
const machineStatus = readStringValue(cachedStatus.machineStatus, cachedStatus.machine_status, node?.machineStatus);
|
|
49548
49789
|
if (machineStatus) status.machineStatus = machineStatus;
|
|
49549
49790
|
}
|
|
49550
49791
|
synthesizeMeshNodeFreshnessFromConnection(status);
|
|
49792
|
+
const liveTruthProbed = readBooleanValue(status[MESH_NODE_LIVE_TRUTH_MARKER]) === true;
|
|
49793
|
+
delete status[MESH_NODE_LIVE_TRUTH_MARKER];
|
|
49794
|
+
status.dataFreshness = buildMeshNodeDataFreshness({
|
|
49795
|
+
status,
|
|
49796
|
+
node,
|
|
49797
|
+
isSelfNode,
|
|
49798
|
+
daemonId,
|
|
49799
|
+
liveTruthProbed,
|
|
49800
|
+
directTruthUnavailable
|
|
49801
|
+
});
|
|
49551
49802
|
const bootstrap = readObjectRecord(node?.worktreeBootstrap);
|
|
49552
49803
|
if (node?.isLocalWorktree && readStringValue(bootstrap.status)) {
|
|
49553
49804
|
status.worktreeBootstrap = bootstrap;
|
|
@@ -49615,73 +49866,16 @@ var MeshGitProbeCache = class {
|
|
|
49615
49866
|
}
|
|
49616
49867
|
}
|
|
49617
49868
|
};
|
|
49618
|
-
function awaitWithWarmupDeadline(work, opts) {
|
|
49619
|
-
const pollMs = Math.max(1, Math.min(opts.pollIntervalMs ?? 200, opts.connectTimeoutMs));
|
|
49620
|
-
return new Promise((resolve24, reject) => {
|
|
49621
|
-
let done = false;
|
|
49622
|
-
let poll;
|
|
49623
|
-
let responseTimer;
|
|
49624
|
-
const startedAt = Date.now();
|
|
49625
|
-
const cleanup = () => {
|
|
49626
|
-
if (poll) {
|
|
49627
|
-
clearInterval(poll);
|
|
49628
|
-
poll = void 0;
|
|
49629
|
-
}
|
|
49630
|
-
if (responseTimer) {
|
|
49631
|
-
clearTimeout(responseTimer);
|
|
49632
|
-
responseTimer = void 0;
|
|
49633
|
-
}
|
|
49634
|
-
};
|
|
49635
|
-
const settle = (fn) => {
|
|
49636
|
-
if (done) return;
|
|
49637
|
-
done = true;
|
|
49638
|
-
cleanup();
|
|
49639
|
-
fn();
|
|
49640
|
-
};
|
|
49641
|
-
const armResponse = () => {
|
|
49642
|
-
if (responseTimer || done) return;
|
|
49643
|
-
responseTimer = setTimeout(
|
|
49644
|
-
() => settle(() => reject(new Error("timeout"))),
|
|
49645
|
-
opts.responseTimeoutMs
|
|
49646
|
-
);
|
|
49647
|
-
if (typeof responseTimer.unref === "function") responseTimer.unref();
|
|
49648
|
-
};
|
|
49649
|
-
const onPoll = () => {
|
|
49650
|
-
if (done) return;
|
|
49651
|
-
if (opts.isConnected()) {
|
|
49652
|
-
if (poll) {
|
|
49653
|
-
clearInterval(poll);
|
|
49654
|
-
poll = void 0;
|
|
49655
|
-
}
|
|
49656
|
-
armResponse();
|
|
49657
|
-
return;
|
|
49658
|
-
}
|
|
49659
|
-
if (Date.now() - startedAt >= opts.connectTimeoutMs) {
|
|
49660
|
-
settle(() => reject(new Error("timeout")));
|
|
49661
|
-
}
|
|
49662
|
-
};
|
|
49663
|
-
if (opts.isConnected()) {
|
|
49664
|
-
armResponse();
|
|
49665
|
-
} else {
|
|
49666
|
-
poll = setInterval(onPoll, pollMs);
|
|
49667
|
-
if (typeof poll.unref === "function") poll.unref();
|
|
49668
|
-
}
|
|
49669
|
-
work.then(
|
|
49670
|
-
(val) => settle(() => resolve24(val)),
|
|
49671
|
-
(err) => settle(() => reject(err))
|
|
49672
|
-
);
|
|
49673
|
-
});
|
|
49674
|
-
}
|
|
49675
49869
|
async function probeRemoteMeshGitStatus(args) {
|
|
49676
49870
|
if (!args.dispatchMeshCommand) return null;
|
|
49677
49871
|
const dispatch = args.dispatchMeshCommand(args.daemonId, "git_status", { workspace: args.workspace, refreshUpstream: true });
|
|
49678
|
-
const
|
|
49679
|
-
|
|
49680
|
-
|
|
49681
|
-
isConnected,
|
|
49872
|
+
const remoteResult = await awaitWithWarmupDeadline(dispatch, resolveWarmupDeadlineOpts({
|
|
49873
|
+
getConnection: args.getConnection,
|
|
49874
|
+
daemonId: args.daemonId,
|
|
49682
49875
|
connectTimeoutMs: args.connectTimeoutMs,
|
|
49683
|
-
responseTimeoutMs: args.responseTimeoutMs
|
|
49684
|
-
|
|
49876
|
+
responseTimeoutMs: args.responseTimeoutMs,
|
|
49877
|
+
onMissingGetter: warnMeshWarmupGetterMissingOnce
|
|
49878
|
+
}));
|
|
49685
49879
|
const remoteGit = remoteResult?.status ?? remoteResult?.git ?? remoteResult;
|
|
49686
49880
|
if (!remoteGit || typeof remoteGit !== "object" || typeof remoteGit.isGitRepo !== "boolean") return null;
|
|
49687
49881
|
const reporterPlatform = readStringValue(remoteResult?.reporterPlatform);
|
|
@@ -49695,6 +49889,12 @@ var MESH_DIRECT_PROBE_MAX_RETRIES = 2;
|
|
|
49695
49889
|
function readMeshConnectionState(connection) {
|
|
49696
49890
|
return readStringValue(connection?.state);
|
|
49697
49891
|
}
|
|
49892
|
+
var meshWarmupGetterMissingWarned = /* @__PURE__ */ new Set();
|
|
49893
|
+
function warnMeshWarmupGetterMissingOnce(daemonId) {
|
|
49894
|
+
if (meshWarmupGetterMissingWarned.has(daemonId)) return;
|
|
49895
|
+
meshWarmupGetterMissingWarned.add(daemonId);
|
|
49896
|
+
LOG.warn("Mesh", `Mesh peer connection getter unavailable for ${String(daemonId).slice(0, 12)}; warmup deadline degraded to the combined connect+response window (cannot observe DataChannel open). This avoids a cold-open false-timeout but loses warm/cold precision \u2014 wire getMeshPeerConnectionStatus on this daemon.`);
|
|
49897
|
+
}
|
|
49698
49898
|
function isMeshConnectionDefinitivelyDown(connection) {
|
|
49699
49899
|
if (!connection) return true;
|
|
49700
49900
|
const state = readMeshConnectionState(connection);
|
|
@@ -61771,6 +61971,7 @@ async function initDaemonComponents(config) {
|
|
|
61771
61971
|
detectedIdes: detectedIdesRef,
|
|
61772
61972
|
refreshProviderAvailability,
|
|
61773
61973
|
dispatchMeshCommand: config.dispatchMeshCommand,
|
|
61974
|
+
getMeshPeerConnectionStatus: config.getMeshPeerConnectionStatus,
|
|
61774
61975
|
onMeshCoordinatorEventForwarded: config.onMeshCoordinatorEventForwarded,
|
|
61775
61976
|
statusInstanceId: config.statusInstanceId
|
|
61776
61977
|
};
|