@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.mjs
CHANGED
|
@@ -311,10 +311,10 @@ function readInjected(value) {
|
|
|
311
311
|
}
|
|
312
312
|
function getDaemonBuildInfo() {
|
|
313
313
|
if (cached) return cached;
|
|
314
|
-
const commit = readInjected(true ? "
|
|
315
|
-
const commitShort = readInjected(true ? "
|
|
316
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
317
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
314
|
+
const commit = readInjected(true ? "4464cd9f1effac841aa1fbef3b1691d2f06d64e4" : void 0) ?? "unknown";
|
|
315
|
+
const commitShort = readInjected(true ? "4464cd9f" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
316
|
+
const version = readInjected(true ? "0.9.82-rc.369" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
317
|
+
const builtAt = readInjected(true ? "2026-06-24T08:22:14.501Z" : void 0);
|
|
318
318
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
319
319
|
return cached;
|
|
320
320
|
}
|
|
@@ -10377,6 +10377,90 @@ var init_mesh_event_trace = __esm({
|
|
|
10377
10377
|
}
|
|
10378
10378
|
});
|
|
10379
10379
|
|
|
10380
|
+
// src/mesh/mesh-warmup-deadline.ts
|
|
10381
|
+
function awaitWithWarmupDeadline(work, opts) {
|
|
10382
|
+
const pollMs = Math.max(1, Math.min(opts.pollIntervalMs ?? 200, opts.connectTimeoutMs));
|
|
10383
|
+
return new Promise((resolve24, reject) => {
|
|
10384
|
+
let done = false;
|
|
10385
|
+
let poll;
|
|
10386
|
+
let responseTimer;
|
|
10387
|
+
const startedAt = Date.now();
|
|
10388
|
+
const cleanup = () => {
|
|
10389
|
+
if (poll) {
|
|
10390
|
+
clearInterval(poll);
|
|
10391
|
+
poll = void 0;
|
|
10392
|
+
}
|
|
10393
|
+
if (responseTimer) {
|
|
10394
|
+
clearTimeout(responseTimer);
|
|
10395
|
+
responseTimer = void 0;
|
|
10396
|
+
}
|
|
10397
|
+
};
|
|
10398
|
+
const settle = (fn) => {
|
|
10399
|
+
if (done) return;
|
|
10400
|
+
done = true;
|
|
10401
|
+
cleanup();
|
|
10402
|
+
fn();
|
|
10403
|
+
};
|
|
10404
|
+
const armResponse = () => {
|
|
10405
|
+
if (responseTimer || done) return;
|
|
10406
|
+
responseTimer = setTimeout(
|
|
10407
|
+
() => settle(() => reject(new Error("timeout"))),
|
|
10408
|
+
opts.responseTimeoutMs
|
|
10409
|
+
);
|
|
10410
|
+
if (typeof responseTimer.unref === "function") responseTimer.unref();
|
|
10411
|
+
};
|
|
10412
|
+
const onPoll = () => {
|
|
10413
|
+
if (done) return;
|
|
10414
|
+
if (opts.isConnected()) {
|
|
10415
|
+
if (poll) {
|
|
10416
|
+
clearInterval(poll);
|
|
10417
|
+
poll = void 0;
|
|
10418
|
+
}
|
|
10419
|
+
armResponse();
|
|
10420
|
+
return;
|
|
10421
|
+
}
|
|
10422
|
+
if (Date.now() - startedAt >= opts.connectTimeoutMs) {
|
|
10423
|
+
settle(() => reject(new Error("timeout")));
|
|
10424
|
+
}
|
|
10425
|
+
};
|
|
10426
|
+
if (opts.isConnected()) {
|
|
10427
|
+
armResponse();
|
|
10428
|
+
} else {
|
|
10429
|
+
poll = setInterval(onPoll, pollMs);
|
|
10430
|
+
if (typeof poll.unref === "function") poll.unref();
|
|
10431
|
+
}
|
|
10432
|
+
work.then(
|
|
10433
|
+
(val) => settle(() => resolve24(val)),
|
|
10434
|
+
(err) => settle(() => reject(err))
|
|
10435
|
+
);
|
|
10436
|
+
});
|
|
10437
|
+
}
|
|
10438
|
+
function readWarmupConnectionState(connection) {
|
|
10439
|
+
const state = connection?.state;
|
|
10440
|
+
return typeof state === "string" && state.length > 0 ? state : void 0;
|
|
10441
|
+
}
|
|
10442
|
+
function resolveWarmupDeadlineOpts(opts) {
|
|
10443
|
+
const { getConnection, daemonId, connectTimeoutMs, responseTimeoutMs } = opts;
|
|
10444
|
+
if (getConnection) {
|
|
10445
|
+
return {
|
|
10446
|
+
isConnected: () => readWarmupConnectionState(getConnection(daemonId)) === "connected",
|
|
10447
|
+
connectTimeoutMs,
|
|
10448
|
+
responseTimeoutMs
|
|
10449
|
+
};
|
|
10450
|
+
}
|
|
10451
|
+
opts.onMissingGetter?.(daemonId);
|
|
10452
|
+
return {
|
|
10453
|
+
isConnected: () => false,
|
|
10454
|
+
connectTimeoutMs: connectTimeoutMs + responseTimeoutMs,
|
|
10455
|
+
responseTimeoutMs
|
|
10456
|
+
};
|
|
10457
|
+
}
|
|
10458
|
+
var init_mesh_warmup_deadline = __esm({
|
|
10459
|
+
"src/mesh/mesh-warmup-deadline.ts"() {
|
|
10460
|
+
"use strict";
|
|
10461
|
+
}
|
|
10462
|
+
});
|
|
10463
|
+
|
|
10380
10464
|
// src/config/state-store.ts
|
|
10381
10465
|
import { existsSync as existsSync16, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "fs";
|
|
10382
10466
|
import { join as join18 } from "path";
|
|
@@ -12813,7 +12897,12 @@ function resolveActiveDirectDispatchTaskId(meshId, sessionId) {
|
|
|
12813
12897
|
return void 0;
|
|
12814
12898
|
}
|
|
12815
12899
|
}
|
|
12816
|
-
function
|
|
12900
|
+
function warnDispatchWarmupGetterMissingOnce(daemonId) {
|
|
12901
|
+
if (dispatchWarmupGetterMissingWarned.has(daemonId)) return;
|
|
12902
|
+
dispatchWarmupGetterMissingWarned.add(daemonId);
|
|
12903
|
+
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.`);
|
|
12904
|
+
}
|
|
12905
|
+
function deliverTaskToSession(dispatchThunk, ctx, warmup) {
|
|
12817
12906
|
const delivery = createSessionDelivery({
|
|
12818
12907
|
meshId: ctx.meshId,
|
|
12819
12908
|
nodeId: ctx.nodeId,
|
|
@@ -12833,16 +12922,27 @@ function deliverTaskToSession(dispatchThunk, ctx) {
|
|
|
12833
12922
|
dispatchPromise = Promise.reject(e);
|
|
12834
12923
|
}
|
|
12835
12924
|
let timer;
|
|
12836
|
-
|
|
12837
|
-
|
|
12838
|
-
|
|
12839
|
-
|
|
12840
|
-
|
|
12841
|
-
|
|
12842
|
-
|
|
12843
|
-
|
|
12844
|
-
})
|
|
12845
|
-
|
|
12925
|
+
let guarded;
|
|
12926
|
+
if (warmup) {
|
|
12927
|
+
guarded = awaitWithWarmupDeadline(dispatchPromise, resolveWarmupDeadlineOpts({
|
|
12928
|
+
getConnection: warmup.getConnection,
|
|
12929
|
+
daemonId: warmup.daemonId,
|
|
12930
|
+
connectTimeoutMs: DISPATCH_CONNECT_TIMEOUT_MS,
|
|
12931
|
+
responseTimeoutMs: DISPATCH_CONFIRM_TIMEOUT_MS,
|
|
12932
|
+
onMissingGetter: warnDispatchWarmupGetterMissingOnce
|
|
12933
|
+
}));
|
|
12934
|
+
} else {
|
|
12935
|
+
guarded = Promise.race([
|
|
12936
|
+
dispatchPromise,
|
|
12937
|
+
new Promise((_, reject) => {
|
|
12938
|
+
timer = setTimeout(
|
|
12939
|
+
() => reject(new Error(`dispatch_confirm_timeout after ${DISPATCH_CONFIRM_TIMEOUT_MS}ms`)),
|
|
12940
|
+
DISPATCH_CONFIRM_TIMEOUT_MS
|
|
12941
|
+
);
|
|
12942
|
+
if (typeof timer?.unref === "function") timer.unref();
|
|
12943
|
+
})
|
|
12944
|
+
]);
|
|
12945
|
+
}
|
|
12846
12946
|
guarded.then(() => {
|
|
12847
12947
|
if (timer) clearTimeout(timer);
|
|
12848
12948
|
updateSessionDeliveryStatus(delivery.id, "delivered");
|
|
@@ -12866,13 +12966,25 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
|
|
|
12866
12966
|
const mesh = getMeshWithCache(components, meshId);
|
|
12867
12967
|
const node = mesh?.nodes.find((n) => readMeshNodeId(n) === nodeId);
|
|
12868
12968
|
const localClaimAdapter = components.cliManager?.adapters?.get(sessionId);
|
|
12869
|
-
|
|
12870
|
-
|
|
12871
|
-
|
|
12872
|
-
|
|
12873
|
-
|
|
12969
|
+
let claimInstanceWorkspace = "";
|
|
12970
|
+
let claimStampedNodeId = "";
|
|
12971
|
+
try {
|
|
12972
|
+
const claimState = components.instanceManager?.getInstance?.(sessionId)?.getState?.();
|
|
12973
|
+
claimInstanceWorkspace = readNonEmptyString2(claimState?.workspace);
|
|
12974
|
+
const claimSettings = claimState?.settings || {};
|
|
12975
|
+
claimStampedNodeId = readNonEmptyString2(claimSettings.meshNodeId);
|
|
12976
|
+
} catch {
|
|
12977
|
+
}
|
|
12978
|
+
const nodeWorkspaceRaw = readNonEmptyString2(node?.workspace);
|
|
12979
|
+
const sessionWorkspaceRaw = readNonEmptyString2(localClaimAdapter?.workingDir) || claimInstanceWorkspace;
|
|
12980
|
+
if (claimStampedNodeId && nodeId) {
|
|
12981
|
+
if (!meshNodeIdMatches({ id: claimStampedNodeId }, nodeId)) {
|
|
12982
|
+
LOG.info("MeshQueue", `WTDISPATCH: refusing claim for node ${nodeId} (${sessionId}) \u2014 session is bound to node "${claimStampedNodeId}" (cross-node claim blocked)`);
|
|
12874
12983
|
return false;
|
|
12875
12984
|
}
|
|
12985
|
+
} else if (sessionWorkspaceRaw && nodeWorkspaceRaw && !meshWorkspacesEquivalent(sessionWorkspaceRaw, nodeWorkspaceRaw)) {
|
|
12986
|
+
LOG.info("MeshQueue", `WTCLAIM: refusing claim for node ${nodeId} (${sessionId}) \u2014 session workspace "${normalizeMeshWorkspaceForCompare(sessionWorkspaceRaw)}" \u2260 node workspace "${normalizeMeshWorkspaceForCompare(nodeWorkspaceRaw)}" (cross-workspace dispatch blocked)`);
|
|
12987
|
+
return false;
|
|
12876
12988
|
}
|
|
12877
12989
|
const capabilityTags = buildMeshNodeCapabilityTags(node, providerType);
|
|
12878
12990
|
const providerMaxParallel = resolveProviderMaxParallel(node?.policy, providerType);
|
|
@@ -12914,7 +13026,11 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
|
|
|
12914
13026
|
transport: "remote",
|
|
12915
13027
|
...sourceCoordinatorSessionId ? { sourceCoordinatorSessionId } : {},
|
|
12916
13028
|
...localDaemonIdForDispatch ? { sourceCoordinatorDaemonId: localDaemonIdForDispatch } : {}
|
|
12917
|
-
}
|
|
13029
|
+
},
|
|
13030
|
+
// Warmup-aware deadline: this dispatch can be the FIRST command to a
|
|
13031
|
+
// peer whose mesh DataChannel is still opening — charge the cold-open
|
|
13032
|
+
// handshake to the connect budget, not the response budget.
|
|
13033
|
+
{ daemonId: remoteDaemonId, getConnection: components.getMeshPeerConnectionStatus }
|
|
12918
13034
|
);
|
|
12919
13035
|
return true;
|
|
12920
13036
|
}
|
|
@@ -14150,6 +14266,25 @@ function handleMeshForwardEvent(components, payload) {
|
|
|
14150
14266
|
metadataEvent: buildRelayMetadataEvent(payload)
|
|
14151
14267
|
});
|
|
14152
14268
|
}
|
|
14269
|
+
function enqueueCoordinatorForwardPush(coordinatorDaemonId, run) {
|
|
14270
|
+
let lane = coordinatorForwardLanes.get(coordinatorDaemonId);
|
|
14271
|
+
if (!lane) {
|
|
14272
|
+
lane = { tail: Promise.resolve(), depth: 0 };
|
|
14273
|
+
coordinatorForwardLanes.set(coordinatorDaemonId, lane);
|
|
14274
|
+
}
|
|
14275
|
+
const wasIdle = lane.depth === 0;
|
|
14276
|
+
lane.depth += 1;
|
|
14277
|
+
const dec = () => {
|
|
14278
|
+
lane.depth -= 1;
|
|
14279
|
+
};
|
|
14280
|
+
if (wasIdle) {
|
|
14281
|
+
lane.tail = Promise.resolve(run()).catch(() => {
|
|
14282
|
+
}).then(dec, dec);
|
|
14283
|
+
} else {
|
|
14284
|
+
lane.tail = lane.tail.then(() => run()).catch(() => {
|
|
14285
|
+
}).then(dec, dec);
|
|
14286
|
+
}
|
|
14287
|
+
}
|
|
14153
14288
|
function forwardUnresolvedDelegateEvent(components, routing, event) {
|
|
14154
14289
|
const coordinatorDaemonId = readNonEmptyString2(routing.coordinatorDaemonId);
|
|
14155
14290
|
if (!coordinatorDaemonId) return false;
|
|
@@ -14181,7 +14316,8 @@ function forwardUnresolvedDelegateEvent(components, routing, event) {
|
|
|
14181
14316
|
};
|
|
14182
14317
|
traceMeshEventStage("outbox_enqueue", fwdTraceCtx, `coordinatorDaemon=${coordinatorDaemonId} meshId=absent`);
|
|
14183
14318
|
traceMeshEventStage("forward_send", fwdTraceCtx, "immediate push");
|
|
14184
|
-
|
|
14319
|
+
const dispatchMeshCommand = components.dispatchMeshCommand;
|
|
14320
|
+
enqueueCoordinatorForwardPush(coordinatorDaemonId, () => Promise.resolve(dispatchMeshCommand(coordinatorDaemonId, "mesh_forward_event", payload)).then((result) => {
|
|
14185
14321
|
if (result && result.success === false) {
|
|
14186
14322
|
LOG.warn("MeshEvents", `Immediate forward of ${eventName} to coordinator ${coordinatorDaemonId} rejected (${readNonEmptyString2(result.error) || "no reason"}) \u2014 left queued for retry`);
|
|
14187
14323
|
traceMeshEventDrop("immediate_forward_rejected", fwdTraceCtx, readNonEmptyString2(result.error) || "no reason");
|
|
@@ -14190,7 +14326,7 @@ function forwardUnresolvedDelegateEvent(components, routing, event) {
|
|
|
14190
14326
|
if (persisted) ackUnresolvedDelegateForwardByFingerprint(coordinatorDaemonId, eventName, payload);
|
|
14191
14327
|
}).catch((e) => {
|
|
14192
14328
|
LOG.warn("MeshEvents", `Immediate forward of ${eventName} to coordinator ${coordinatorDaemonId} failed: ${e?.message || e} \u2014 left queued for retry`);
|
|
14193
|
-
});
|
|
14329
|
+
}));
|
|
14194
14330
|
LOG.info("MeshEvents", `Durably forwarded ${eventName} for unresolved-mesh worker at ${routing.workspace || "(no workspace)"} to coordinator daemon ${coordinatorDaemonId}`);
|
|
14195
14331
|
return true;
|
|
14196
14332
|
}
|
|
@@ -14273,7 +14409,7 @@ function setupMeshEventForwarding(components) {
|
|
|
14273
14409
|
});
|
|
14274
14410
|
});
|
|
14275
14411
|
}
|
|
14276
|
-
var 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;
|
|
14412
|
+
var 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;
|
|
14277
14413
|
var init_mesh_events_coordinator = __esm({
|
|
14278
14414
|
"src/mesh/mesh-events-coordinator.ts"() {
|
|
14279
14415
|
"use strict";
|
|
@@ -14290,6 +14426,7 @@ var init_mesh_events_coordinator = __esm({
|
|
|
14290
14426
|
init_mesh_routing();
|
|
14291
14427
|
init_mesh_unresolved_forward_outbox();
|
|
14292
14428
|
init_mesh_event_trace();
|
|
14429
|
+
init_mesh_warmup_deadline();
|
|
14293
14430
|
init_snapshot();
|
|
14294
14431
|
init_repo_mesh_types();
|
|
14295
14432
|
init_dist();
|
|
@@ -14303,6 +14440,8 @@ var init_mesh_events_coordinator = __esm({
|
|
|
14303
14440
|
INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS = 30 * 60 * 1e3;
|
|
14304
14441
|
RECENT_COMPLETION_FINGERPRINT_TTL_MS = 10 * 60 * 1e3;
|
|
14305
14442
|
DISPATCH_CONFIRM_TIMEOUT_MS = 12e4;
|
|
14443
|
+
DISPATCH_CONNECT_TIMEOUT_MS = 45e3;
|
|
14444
|
+
dispatchWarmupGetterMissingWarned = /* @__PURE__ */ new Set();
|
|
14306
14445
|
autoLaunchInProgress = /* @__PURE__ */ new Set();
|
|
14307
14446
|
autoLaunchCooldownUntil = /* @__PURE__ */ new Map();
|
|
14308
14447
|
AUTO_LAUNCH_COOLDOWN_MS = 5e3;
|
|
@@ -14337,6 +14476,7 @@ var init_mesh_events_coordinator = __esm({
|
|
|
14337
14476
|
"worktree_bootstrap_complete",
|
|
14338
14477
|
"worktree_bootstrap_failed"
|
|
14339
14478
|
]);
|
|
14479
|
+
coordinatorForwardLanes = /* @__PURE__ */ new Map();
|
|
14340
14480
|
}
|
|
14341
14481
|
});
|
|
14342
14482
|
|
|
@@ -41173,6 +41313,18 @@ var DaemonCliManager = class {
|
|
|
41173
41313
|
throw new Error(`Failed to start ${provider.displayName || provider.name || cliType}: ${spawnErr?.message}`);
|
|
41174
41314
|
}
|
|
41175
41315
|
this.adapters.set(key, cliInstance.getAdapter());
|
|
41316
|
+
const launchMeshNodeId = typeof settings?.meshNodeId === "string" ? settings.meshNodeId.trim() : "";
|
|
41317
|
+
const launchMeshNodeFor = typeof settings?.meshNodeFor === "string" ? settings.meshNodeFor.trim() : "";
|
|
41318
|
+
if (launchMeshNodeId || launchMeshNodeFor) {
|
|
41319
|
+
try {
|
|
41320
|
+
cliInstance.getAdapter().updateRuntimeMeta?.({
|
|
41321
|
+
...launchMeshNodeId ? { meshNodeId: launchMeshNodeId } : {},
|
|
41322
|
+
...launchMeshNodeFor ? { meshNodeFor: launchMeshNodeFor } : {},
|
|
41323
|
+
...settings?.launchedByCoordinator === true ? { launchedByCoordinator: true } : {}
|
|
41324
|
+
});
|
|
41325
|
+
} catch {
|
|
41326
|
+
}
|
|
41327
|
+
}
|
|
41176
41328
|
this.startCliExitMonitor(key, cliType);
|
|
41177
41329
|
}
|
|
41178
41330
|
// ─── Session start/management ──────────────────────────────
|
|
@@ -41440,6 +41592,14 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
41440
41592
|
let restored = 0;
|
|
41441
41593
|
const restoredBindings = /* @__PURE__ */ new Set();
|
|
41442
41594
|
const managerTag = this.deps.hostedRuntimeManagerTag;
|
|
41595
|
+
const restoredRuntimeIds = /* @__PURE__ */ new Set();
|
|
41596
|
+
const workspaceTypeCounts = /* @__PURE__ */ new Map();
|
|
41597
|
+
for (const r of sessions) {
|
|
41598
|
+
if (!r?.runtimeId || !r?.cliType || !r?.workspace) continue;
|
|
41599
|
+
restoredRuntimeIds.add(r.runtimeId);
|
|
41600
|
+
const key = `${r.workspace}::${r.cliType}`;
|
|
41601
|
+
workspaceTypeCounts.set(key, (workspaceTypeCounts.get(key) || 0) + 1);
|
|
41602
|
+
}
|
|
41443
41603
|
for (const record of sessions) {
|
|
41444
41604
|
if (!record?.runtimeId || !record?.cliType || !record?.workspace) continue;
|
|
41445
41605
|
if (!shouldRestoreHostedRuntime(record, managerTag)) {
|
|
@@ -41477,11 +41637,21 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
41477
41637
|
if (!coordinatorEntry?.meshId && record.workspace) {
|
|
41478
41638
|
const workspaceCoordinators = listCoordinatorsForWorkspace(record.workspace).filter((e) => e.meshId && (!e.cliType || e.cliType === record.cliType));
|
|
41479
41639
|
if (workspaceCoordinators.length === 1) {
|
|
41480
|
-
|
|
41481
|
-
|
|
41482
|
-
|
|
41483
|
-
|
|
41484
|
-
|
|
41640
|
+
const candidate = workspaceCoordinators[0];
|
|
41641
|
+
const coordinatorPresentById = !!candidate.sessionId && restoredRuntimeIds.has(candidate.sessionId);
|
|
41642
|
+
const siblingCount = workspaceTypeCounts.get(`${record.workspace}::${record.cliType}`) || 1;
|
|
41643
|
+
if (!coordinatorPresentById && siblingCount === 1) {
|
|
41644
|
+
coordinatorEntry = candidate;
|
|
41645
|
+
LOG.info(
|
|
41646
|
+
"CLI",
|
|
41647
|
+
`\u21BB Rebound coordinator mark by workspace for ${record.runtimeKey || record.runtimeId} (mesh ${candidate.meshId} @ ${record.workspace}); registry key did not match runtimeId`
|
|
41648
|
+
);
|
|
41649
|
+
} else {
|
|
41650
|
+
LOG.info(
|
|
41651
|
+
"CLI",
|
|
41652
|
+
`\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)`}`
|
|
41653
|
+
);
|
|
41654
|
+
}
|
|
41485
41655
|
}
|
|
41486
41656
|
}
|
|
41487
41657
|
if (coordinatorEntry?.meshId) {
|
|
@@ -47963,6 +48133,7 @@ var meshStatusHandlers = {
|
|
|
47963
48133
|
const remoteGit = await meshGitProbeCache.probe(daemonId, workspace, runNodeProbe);
|
|
47964
48134
|
if (remoteGit) {
|
|
47965
48135
|
status.git = remoteGit;
|
|
48136
|
+
status[MESH_NODE_LIVE_TRUTH_MARKER] = true;
|
|
47966
48137
|
status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
|
|
47967
48138
|
const connection = readObjectRecord(status.connection);
|
|
47968
48139
|
const connectionState = readStringValue(connection.state);
|
|
@@ -47988,13 +48159,13 @@ var meshStatusHandlers = {
|
|
|
47988
48159
|
pendingPeerGitProbe ? { skipGit: true, skipError: true, skipHealth: true } : void 0
|
|
47989
48160
|
)) {
|
|
47990
48161
|
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
47991
|
-
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
48162
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
|
|
47992
48163
|
nodeStatuses.push(status);
|
|
47993
48164
|
continue;
|
|
47994
48165
|
}
|
|
47995
48166
|
if (meshRecord?.source === "inline_cache" && !isSelfNode) {
|
|
47996
48167
|
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
47997
|
-
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
48168
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
|
|
47998
48169
|
nodeStatuses.push(status);
|
|
47999
48170
|
continue;
|
|
48000
48171
|
}
|
|
@@ -48003,6 +48174,7 @@ var meshStatusHandlers = {
|
|
|
48003
48174
|
try {
|
|
48004
48175
|
const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
48005
48176
|
status.git = gitStatus;
|
|
48177
|
+
status[MESH_NODE_LIVE_TRUTH_MARKER] = true;
|
|
48006
48178
|
const reporter = recordInlineMeshDirectGitTruth(node, gitStatus, "selected_coordinator_local_git");
|
|
48007
48179
|
persistNodeReporterPlatform(meshRecord.source, mesh, nodeId, reporter);
|
|
48008
48180
|
if (gitStatus.isGitRepo) {
|
|
@@ -48021,7 +48193,7 @@ var meshStatusHandlers = {
|
|
|
48021
48193
|
applyCachedInlineMeshNodeStatus(status, node);
|
|
48022
48194
|
}
|
|
48023
48195
|
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
48024
|
-
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
48196
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
|
|
48025
48197
|
nodeStatuses.push(status);
|
|
48026
48198
|
}
|
|
48027
48199
|
const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : ctx.deps.statusInstanceId || void 0;
|
|
@@ -48435,6 +48607,7 @@ function orderMeshRefineBatchNodes(changeAreas) {
|
|
|
48435
48607
|
|
|
48436
48608
|
// src/commands/router.ts
|
|
48437
48609
|
init_mesh_work_queue();
|
|
48610
|
+
init_mesh_warmup_deadline();
|
|
48438
48611
|
init_repo_mesh_types();
|
|
48439
48612
|
import { homedir as homedir26 } from "os";
|
|
48440
48613
|
import { basename as pathBasename, join as pathJoin2, resolve as pathResolve2 } from "path";
|
|
@@ -49176,14 +49349,92 @@ function synthesizeMeshNodeFreshnessFromConnection(status) {
|
|
|
49176
49349
|
status.updatedAt = gitCheckedAt ?? connectionFreshAt;
|
|
49177
49350
|
}
|
|
49178
49351
|
}
|
|
49352
|
+
var MESH_NODE_LIVE_TRUTH_MARKER = "__liveTruthProbed";
|
|
49353
|
+
var MESH_FRESHNESS_FRESH_MS = 3e4;
|
|
49354
|
+
var MESH_FRESHNESS_RECENT_MS = 3e5;
|
|
49355
|
+
function classifyMeshNodeStaleness(dataSource, ageMs) {
|
|
49356
|
+
if (dataSource === "self" || dataSource === "live") return "fresh";
|
|
49357
|
+
if (ageMs === null) return "unknown";
|
|
49358
|
+
if (ageMs < MESH_FRESHNESS_FRESH_MS) return "fresh";
|
|
49359
|
+
if (ageMs < MESH_FRESHNESS_RECENT_MS) return "recent";
|
|
49360
|
+
return "stale";
|
|
49361
|
+
}
|
|
49362
|
+
function buildMeshNodeDataFreshness(args) {
|
|
49363
|
+
const { status, node, isSelfNode, daemonId, liveTruthProbed, directTruthUnavailable } = args;
|
|
49364
|
+
const now = args.now ?? Date.now;
|
|
49365
|
+
const connection = readObjectRecord(status.connection);
|
|
49366
|
+
const connectionState = readStringValue(connection.state);
|
|
49367
|
+
const git = readObjectRecord(status.git);
|
|
49368
|
+
const hasGit = readBooleanValue(git.isGitRepo) === true || !!readStringValue(git.branch, git.headCommit, git.head, git.upstream);
|
|
49369
|
+
const connectionFreshAt = toIsoTimestamp(connection.lastCommandAt ?? connection.lastConnectedAt ?? connection.lastStateChangeAt);
|
|
49370
|
+
const liveGitCheckedAt = liveTruthProbed ? toIsoTimestamp(git.lastCheckedAt) : null;
|
|
49371
|
+
const heldGit = readObjectRecord(node?.lastGit ?? node?.last_git);
|
|
49372
|
+
const heldCheckedAt = toIsoTimestamp(heldGit.checkedAt ?? heldGit.checked_at);
|
|
49373
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
49374
|
+
const cachedGitCheckedAt = toIsoTimestamp(readObjectRecord(cachedStatus.git).lastCheckedAt);
|
|
49375
|
+
const lastProbeAt = liveGitCheckedAt ?? heldCheckedAt ?? cachedGitCheckedAt ?? toIsoTimestamp(git.lastCheckedAt) ?? connectionFreshAt ?? toIsoTimestamp(status.updatedAt) ?? toIsoTimestamp(status.lastSeenAt);
|
|
49376
|
+
const connectionReachable = connectionState === "connected" ? true : !connectionState || connectionState === "unknown" || connectionState === "connecting" ? connectionState === "connecting" ? true : null : false;
|
|
49377
|
+
let dataSource;
|
|
49378
|
+
let reachable;
|
|
49379
|
+
if (isSelfNode) {
|
|
49380
|
+
dataSource = "self";
|
|
49381
|
+
reachable = true;
|
|
49382
|
+
} else if (liveTruthProbed) {
|
|
49383
|
+
dataSource = "live";
|
|
49384
|
+
reachable = true;
|
|
49385
|
+
} else if (readBooleanValue(status.gitProbePending) === true) {
|
|
49386
|
+
dataSource = "pending";
|
|
49387
|
+
reachable = connectionReachable;
|
|
49388
|
+
} else if (directTruthUnavailable) {
|
|
49389
|
+
dataSource = "unreachable";
|
|
49390
|
+
reachable = false;
|
|
49391
|
+
} else if (hasGit) {
|
|
49392
|
+
dataSource = "cached";
|
|
49393
|
+
reachable = connectionReachable;
|
|
49394
|
+
} else if (!daemonId) {
|
|
49395
|
+
dataSource = "unconfigured";
|
|
49396
|
+
reachable = null;
|
|
49397
|
+
} else if (connectionState === "connected") {
|
|
49398
|
+
dataSource = "empty";
|
|
49399
|
+
reachable = true;
|
|
49400
|
+
} else {
|
|
49401
|
+
dataSource = "unreachable";
|
|
49402
|
+
reachable = false;
|
|
49403
|
+
}
|
|
49404
|
+
const probeOk = dataSource === "live" || dataSource === "self";
|
|
49405
|
+
let ageMs = null;
|
|
49406
|
+
if (lastProbeAt) {
|
|
49407
|
+
const parsed = Date.parse(lastProbeAt);
|
|
49408
|
+
if (Number.isFinite(parsed)) ageMs = Math.max(0, now() - parsed);
|
|
49409
|
+
}
|
|
49410
|
+
const staleness = classifyMeshNodeStaleness(dataSource, ageMs);
|
|
49411
|
+
return {
|
|
49412
|
+
dataSource,
|
|
49413
|
+
probeOk,
|
|
49414
|
+
reachable,
|
|
49415
|
+
lastProbeAt: lastProbeAt ?? null,
|
|
49416
|
+
ageMs,
|
|
49417
|
+
staleness
|
|
49418
|
+
};
|
|
49419
|
+
}
|
|
49179
49420
|
function finalizeMeshNodeStatus(args) {
|
|
49180
|
-
const { status, node, daemonId, isSelfNode } = args;
|
|
49421
|
+
const { status, node, daemonId, isSelfNode, directTruthUnavailable } = args;
|
|
49181
49422
|
if (!readStringValue(status.machineStatus)) {
|
|
49182
49423
|
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
49183
49424
|
const machineStatus = readStringValue(cachedStatus.machineStatus, cachedStatus.machine_status, node?.machineStatus);
|
|
49184
49425
|
if (machineStatus) status.machineStatus = machineStatus;
|
|
49185
49426
|
}
|
|
49186
49427
|
synthesizeMeshNodeFreshnessFromConnection(status);
|
|
49428
|
+
const liveTruthProbed = readBooleanValue(status[MESH_NODE_LIVE_TRUTH_MARKER]) === true;
|
|
49429
|
+
delete status[MESH_NODE_LIVE_TRUTH_MARKER];
|
|
49430
|
+
status.dataFreshness = buildMeshNodeDataFreshness({
|
|
49431
|
+
status,
|
|
49432
|
+
node,
|
|
49433
|
+
isSelfNode,
|
|
49434
|
+
daemonId,
|
|
49435
|
+
liveTruthProbed,
|
|
49436
|
+
directTruthUnavailable
|
|
49437
|
+
});
|
|
49187
49438
|
const bootstrap = readObjectRecord(node?.worktreeBootstrap);
|
|
49188
49439
|
if (node?.isLocalWorktree && readStringValue(bootstrap.status)) {
|
|
49189
49440
|
status.worktreeBootstrap = bootstrap;
|
|
@@ -49251,73 +49502,16 @@ var MeshGitProbeCache = class {
|
|
|
49251
49502
|
}
|
|
49252
49503
|
}
|
|
49253
49504
|
};
|
|
49254
|
-
function awaitWithWarmupDeadline(work, opts) {
|
|
49255
|
-
const pollMs = Math.max(1, Math.min(opts.pollIntervalMs ?? 200, opts.connectTimeoutMs));
|
|
49256
|
-
return new Promise((resolve24, reject) => {
|
|
49257
|
-
let done = false;
|
|
49258
|
-
let poll;
|
|
49259
|
-
let responseTimer;
|
|
49260
|
-
const startedAt = Date.now();
|
|
49261
|
-
const cleanup = () => {
|
|
49262
|
-
if (poll) {
|
|
49263
|
-
clearInterval(poll);
|
|
49264
|
-
poll = void 0;
|
|
49265
|
-
}
|
|
49266
|
-
if (responseTimer) {
|
|
49267
|
-
clearTimeout(responseTimer);
|
|
49268
|
-
responseTimer = void 0;
|
|
49269
|
-
}
|
|
49270
|
-
};
|
|
49271
|
-
const settle = (fn) => {
|
|
49272
|
-
if (done) return;
|
|
49273
|
-
done = true;
|
|
49274
|
-
cleanup();
|
|
49275
|
-
fn();
|
|
49276
|
-
};
|
|
49277
|
-
const armResponse = () => {
|
|
49278
|
-
if (responseTimer || done) return;
|
|
49279
|
-
responseTimer = setTimeout(
|
|
49280
|
-
() => settle(() => reject(new Error("timeout"))),
|
|
49281
|
-
opts.responseTimeoutMs
|
|
49282
|
-
);
|
|
49283
|
-
if (typeof responseTimer.unref === "function") responseTimer.unref();
|
|
49284
|
-
};
|
|
49285
|
-
const onPoll = () => {
|
|
49286
|
-
if (done) return;
|
|
49287
|
-
if (opts.isConnected()) {
|
|
49288
|
-
if (poll) {
|
|
49289
|
-
clearInterval(poll);
|
|
49290
|
-
poll = void 0;
|
|
49291
|
-
}
|
|
49292
|
-
armResponse();
|
|
49293
|
-
return;
|
|
49294
|
-
}
|
|
49295
|
-
if (Date.now() - startedAt >= opts.connectTimeoutMs) {
|
|
49296
|
-
settle(() => reject(new Error("timeout")));
|
|
49297
|
-
}
|
|
49298
|
-
};
|
|
49299
|
-
if (opts.isConnected()) {
|
|
49300
|
-
armResponse();
|
|
49301
|
-
} else {
|
|
49302
|
-
poll = setInterval(onPoll, pollMs);
|
|
49303
|
-
if (typeof poll.unref === "function") poll.unref();
|
|
49304
|
-
}
|
|
49305
|
-
work.then(
|
|
49306
|
-
(val) => settle(() => resolve24(val)),
|
|
49307
|
-
(err) => settle(() => reject(err))
|
|
49308
|
-
);
|
|
49309
|
-
});
|
|
49310
|
-
}
|
|
49311
49505
|
async function probeRemoteMeshGitStatus(args) {
|
|
49312
49506
|
if (!args.dispatchMeshCommand) return null;
|
|
49313
49507
|
const dispatch = args.dispatchMeshCommand(args.daemonId, "git_status", { workspace: args.workspace, refreshUpstream: true });
|
|
49314
|
-
const
|
|
49315
|
-
|
|
49316
|
-
|
|
49317
|
-
isConnected,
|
|
49508
|
+
const remoteResult = await awaitWithWarmupDeadline(dispatch, resolveWarmupDeadlineOpts({
|
|
49509
|
+
getConnection: args.getConnection,
|
|
49510
|
+
daemonId: args.daemonId,
|
|
49318
49511
|
connectTimeoutMs: args.connectTimeoutMs,
|
|
49319
|
-
responseTimeoutMs: args.responseTimeoutMs
|
|
49320
|
-
|
|
49512
|
+
responseTimeoutMs: args.responseTimeoutMs,
|
|
49513
|
+
onMissingGetter: warnMeshWarmupGetterMissingOnce
|
|
49514
|
+
}));
|
|
49321
49515
|
const remoteGit = remoteResult?.status ?? remoteResult?.git ?? remoteResult;
|
|
49322
49516
|
if (!remoteGit || typeof remoteGit !== "object" || typeof remoteGit.isGitRepo !== "boolean") return null;
|
|
49323
49517
|
const reporterPlatform = readStringValue(remoteResult?.reporterPlatform);
|
|
@@ -49331,6 +49525,12 @@ var MESH_DIRECT_PROBE_MAX_RETRIES = 2;
|
|
|
49331
49525
|
function readMeshConnectionState(connection) {
|
|
49332
49526
|
return readStringValue(connection?.state);
|
|
49333
49527
|
}
|
|
49528
|
+
var meshWarmupGetterMissingWarned = /* @__PURE__ */ new Set();
|
|
49529
|
+
function warnMeshWarmupGetterMissingOnce(daemonId) {
|
|
49530
|
+
if (meshWarmupGetterMissingWarned.has(daemonId)) return;
|
|
49531
|
+
meshWarmupGetterMissingWarned.add(daemonId);
|
|
49532
|
+
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.`);
|
|
49533
|
+
}
|
|
49334
49534
|
function isMeshConnectionDefinitivelyDown(connection) {
|
|
49335
49535
|
if (!connection) return true;
|
|
49336
49536
|
const state = readMeshConnectionState(connection);
|
|
@@ -61414,6 +61614,7 @@ async function initDaemonComponents(config) {
|
|
|
61414
61614
|
detectedIdes: detectedIdesRef,
|
|
61415
61615
|
refreshProviderAvailability,
|
|
61416
61616
|
dispatchMeshCommand: config.dispatchMeshCommand,
|
|
61617
|
+
getMeshPeerConnectionStatus: config.getMeshPeerConnectionStatus,
|
|
61417
61618
|
onMeshCoordinatorEventForwarded: config.onMeshCoordinatorEventForwarded,
|
|
61418
61619
|
statusInstanceId: config.statusInstanceId
|
|
61419
61620
|
};
|