@adhdev/daemon-core 0.9.82-rc.381 → 0.9.82-rc.383
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/router.d.ts +11 -1
- package/dist/index.js +234 -117
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +234 -117
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-event-forwarding.d.ts +1 -0
- package/dist/providers/cli-provider-instance.d.ts +18 -0
- package/package.json +2 -2
- package/src/commands/high-family/mesh-status.ts +36 -0
- package/src/commands/router.ts +50 -17
- package/src/mesh/mesh-event-forwarding.ts +46 -1
- package/src/mesh/mesh-reconcile-loop.ts +74 -30
- package/src/providers/cli-provider-instance.ts +27 -0
package/dist/index.mjs
CHANGED
|
@@ -378,10 +378,10 @@ function readInjected(value) {
|
|
|
378
378
|
}
|
|
379
379
|
function getDaemonBuildInfo() {
|
|
380
380
|
if (cached) return cached;
|
|
381
|
-
const commit = readInjected(true ? "
|
|
382
|
-
const commitShort = readInjected(true ? "
|
|
383
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
384
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
381
|
+
const commit = readInjected(true ? "6cca365bcea9757dd350c6bac460ca5a169a9280" : void 0) ?? "unknown";
|
|
382
|
+
const commitShort = readInjected(true ? "6cca365b" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
383
|
+
const version = readInjected(true ? "0.9.82-rc.383" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
384
|
+
const builtAt = readInjected(true ? "2026-06-25T15:14:41.579Z" : void 0);
|
|
385
385
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
386
386
|
return cached;
|
|
387
387
|
}
|
|
@@ -8574,6 +8574,109 @@ var init_mesh_active_work = __esm({
|
|
|
8574
8574
|
}
|
|
8575
8575
|
});
|
|
8576
8576
|
|
|
8577
|
+
// src/mesh/mesh-scheduling-runtime.ts
|
|
8578
|
+
var mesh_scheduling_runtime_exports = {};
|
|
8579
|
+
__export(mesh_scheduling_runtime_exports, {
|
|
8580
|
+
buildMeshSchedulingRuntime: () => buildMeshSchedulingRuntime
|
|
8581
|
+
});
|
|
8582
|
+
function isReadonly(task) {
|
|
8583
|
+
return task.taskMode === "live_debug_readonly";
|
|
8584
|
+
}
|
|
8585
|
+
function isAssigned(task) {
|
|
8586
|
+
return task.status === "assigned";
|
|
8587
|
+
}
|
|
8588
|
+
function buildMeshSchedulingRuntime(mesh, queue) {
|
|
8589
|
+
const strategy = normalizeMeshSchedulingStrategy(mesh?.policy?.schedulingStrategy);
|
|
8590
|
+
const maxParallelTasks = resolveMaxParallelTasks(mesh?.policy?.maxParallelTasks);
|
|
8591
|
+
const maxReadonlyParallelTasks = Math.max(2, maxParallelTasks * 2);
|
|
8592
|
+
const assignedTasks = (Array.isArray(queue) ? queue : []).filter(isAssigned);
|
|
8593
|
+
const activeWriteAssigned = assignedTasks.filter((t) => !isReadonly(t)).length;
|
|
8594
|
+
const activeReadonlyAssigned = assignedTasks.filter(isReadonly).length;
|
|
8595
|
+
const globalWriteCapReached = activeWriteAssigned >= maxParallelTasks;
|
|
8596
|
+
const globalReadonlyCapReached = activeReadonlyAssigned >= maxReadonlyParallelTasks;
|
|
8597
|
+
const writeAssignedByNode = /* @__PURE__ */ new Map();
|
|
8598
|
+
const assignedByNode = /* @__PURE__ */ new Map();
|
|
8599
|
+
const providerCountByNode = /* @__PURE__ */ new Map();
|
|
8600
|
+
for (const task of assignedTasks) {
|
|
8601
|
+
const nodeId = typeof task.assignedNodeId === "string" ? task.assignedNodeId.trim() : "";
|
|
8602
|
+
if (!nodeId) continue;
|
|
8603
|
+
assignedByNode.set(nodeId, (assignedByNode.get(nodeId) ?? 0) + 1);
|
|
8604
|
+
if (!isReadonly(task)) {
|
|
8605
|
+
writeAssignedByNode.set(nodeId, (writeAssignedByNode.get(nodeId) ?? 0) + 1);
|
|
8606
|
+
}
|
|
8607
|
+
const provider = typeof task.assignedProviderType === "string" ? task.assignedProviderType : "";
|
|
8608
|
+
if (provider) {
|
|
8609
|
+
let byProvider = providerCountByNode.get(nodeId);
|
|
8610
|
+
if (!byProvider) {
|
|
8611
|
+
byProvider = /* @__PURE__ */ new Map();
|
|
8612
|
+
providerCountByNode.set(nodeId, byProvider);
|
|
8613
|
+
}
|
|
8614
|
+
byProvider.set(provider, (byProvider.get(provider) ?? 0) + 1);
|
|
8615
|
+
}
|
|
8616
|
+
}
|
|
8617
|
+
const nodes = [];
|
|
8618
|
+
for (const rawNode of Array.isArray(mesh?.nodes) ? mesh.nodes : []) {
|
|
8619
|
+
const nodeId = normalizeMeshNodeId(rawNode);
|
|
8620
|
+
if (!nodeId) continue;
|
|
8621
|
+
const policy = rawNode?.policy || void 0;
|
|
8622
|
+
const load4 = assignedByNode.get(nodeId) ?? 0;
|
|
8623
|
+
const schedulingPriority = resolveNodeSchedulingPriority(policy);
|
|
8624
|
+
const capReasons = [];
|
|
8625
|
+
if (globalWriteCapReached) capReasons.push("global_max_parallel_tasks_reached");
|
|
8626
|
+
if ((writeAssignedByNode.get(nodeId) ?? 0) > 0) capReasons.push("node_has_active_assignment");
|
|
8627
|
+
let providerRoles;
|
|
8628
|
+
const declaredRoles = Array.isArray(policy?.providerRoles) ? policy.providerRoles : [];
|
|
8629
|
+
if (declaredRoles.length) {
|
|
8630
|
+
const byProvider = providerCountByNode.get(nodeId);
|
|
8631
|
+
providerRoles = [];
|
|
8632
|
+
for (const role of declaredRoles) {
|
|
8633
|
+
if (!role || typeof role !== "object") continue;
|
|
8634
|
+
const providerType = typeof role.providerType === "string" ? role.providerType.trim() : "";
|
|
8635
|
+
if (!providerType) continue;
|
|
8636
|
+
const maxParallel = resolveProviderMaxParallel(policy, providerType);
|
|
8637
|
+
const activeAssigned = byProvider?.get(providerType) ?? 0;
|
|
8638
|
+
const capReached = maxParallel !== void 0 && activeAssigned >= maxParallel;
|
|
8639
|
+
providerRoles.push({
|
|
8640
|
+
providerType,
|
|
8641
|
+
...maxParallel !== void 0 ? { maxParallel } : {},
|
|
8642
|
+
activeAssigned,
|
|
8643
|
+
capReached
|
|
8644
|
+
});
|
|
8645
|
+
if (capReached) capReasons.push(`max_provider_parallel_reached:${providerType}`);
|
|
8646
|
+
}
|
|
8647
|
+
if (!providerRoles.length) providerRoles = void 0;
|
|
8648
|
+
}
|
|
8649
|
+
const maxConcurrentSessions = Number(policy?.maxConcurrentSessions);
|
|
8650
|
+
const hasSessionCap = Number.isFinite(maxConcurrentSessions) && maxConcurrentSessions >= 0;
|
|
8651
|
+
nodes.push({
|
|
8652
|
+
nodeId,
|
|
8653
|
+
load: load4,
|
|
8654
|
+
schedulingPriority,
|
|
8655
|
+
...hasSessionCap ? { maxConcurrentSessions: Math.floor(maxConcurrentSessions) } : {},
|
|
8656
|
+
...providerRoles ? { providerRoles } : {},
|
|
8657
|
+
capReached: capReasons.length > 0,
|
|
8658
|
+
capReasons
|
|
8659
|
+
});
|
|
8660
|
+
}
|
|
8661
|
+
return {
|
|
8662
|
+
strategy,
|
|
8663
|
+
maxParallelTasks,
|
|
8664
|
+
maxReadonlyParallelTasks,
|
|
8665
|
+
activeWriteAssigned,
|
|
8666
|
+
activeReadonlyAssigned,
|
|
8667
|
+
globalWriteCapReached,
|
|
8668
|
+
globalReadonlyCapReached,
|
|
8669
|
+
nodes
|
|
8670
|
+
};
|
|
8671
|
+
}
|
|
8672
|
+
var init_mesh_scheduling_runtime = __esm({
|
|
8673
|
+
"src/mesh/mesh-scheduling-runtime.ts"() {
|
|
8674
|
+
"use strict";
|
|
8675
|
+
init_repo_mesh_types();
|
|
8676
|
+
init_dist();
|
|
8677
|
+
}
|
|
8678
|
+
});
|
|
8679
|
+
|
|
8577
8680
|
// src/mesh/mesh-events-utils.ts
|
|
8578
8681
|
function readNonEmptyString2(value) {
|
|
8579
8682
|
return typeof value === "string" && value.trim() ? value.trim() : "";
|
|
@@ -13805,6 +13908,20 @@ function recoverMeshIdByNodeId(nodeId) {
|
|
|
13805
13908
|
}
|
|
13806
13909
|
return "";
|
|
13807
13910
|
}
|
|
13911
|
+
function recoverMeshIdByCoordinatorAndNode(coordinatorDaemonId, nodeId) {
|
|
13912
|
+
if (!coordinatorDaemonId) return "";
|
|
13913
|
+
const hosted = listMeshes().filter((mesh) => {
|
|
13914
|
+
const host = resolveMeshHostStatus(mesh);
|
|
13915
|
+
return host.role === "host" && (!host.hostDaemonId || daemonIdsEquivalent(host.hostDaemonId, coordinatorDaemonId));
|
|
13916
|
+
});
|
|
13917
|
+
if (hosted.length === 0) return "";
|
|
13918
|
+
if (nodeId) {
|
|
13919
|
+
const byNode = hosted.find((mesh) => Array.isArray(mesh.nodes) && mesh.nodes.some((n) => meshNodeIdMatches(n, nodeId)));
|
|
13920
|
+
if (byNode) return readNonEmptyString2(byNode.id);
|
|
13921
|
+
return "";
|
|
13922
|
+
}
|
|
13923
|
+
return hosted.length === 1 ? readNonEmptyString2(hosted[0].id) : "";
|
|
13924
|
+
}
|
|
13808
13925
|
function resolveForwardEventMeshId(components, payload) {
|
|
13809
13926
|
const direct = readNonEmptyString2(payload.meshId);
|
|
13810
13927
|
if (direct) return direct;
|
|
@@ -14551,7 +14668,10 @@ function handleMeshForwardEvent(components, payload) {
|
|
|
14551
14668
|
}
|
|
14552
14669
|
const nodeId = readNonEmptyString2(payload.nodeId);
|
|
14553
14670
|
const workspace = readNonEmptyString2(payload.workspace);
|
|
14554
|
-
const meshId = readNonEmptyString2(payload.meshId) || (workspace ? readNonEmptyString2(getCachedMeshByWorkspace(workspace)?.id) : "") || recoverMeshIdByNodeId(nodeId)
|
|
14671
|
+
const meshId = readNonEmptyString2(payload.meshId) || (workspace ? readNonEmptyString2(getCachedMeshByWorkspace(workspace)?.id) : "") || recoverMeshIdByNodeId(nodeId) || recoverMeshIdByCoordinatorAndNode(
|
|
14672
|
+
readNonEmptyString2(payload.meshCoordinatorDaemonId) || readNonEmptyString2(payload.coordinatorDaemonId),
|
|
14673
|
+
nodeId
|
|
14674
|
+
);
|
|
14555
14675
|
if (!meshId) {
|
|
14556
14676
|
traceMeshEventDrop("meshId_required", {
|
|
14557
14677
|
taskId: payload.taskId,
|
|
@@ -14606,7 +14726,12 @@ function forwardUnresolvedDelegateEvent(components, routing, event) {
|
|
|
14606
14726
|
...event,
|
|
14607
14727
|
event: eventName,
|
|
14608
14728
|
nodeId: readNonEmptyString2(routing.nodeId) || readNonEmptyString2(event.meshNodeId) || void 0,
|
|
14609
|
-
workspace: readNonEmptyString2(routing.workspace) || readNonEmptyString2(event.workspace) || void 0
|
|
14729
|
+
workspace: readNonEmptyString2(routing.workspace) || readNonEmptyString2(event.workspace) || void 0,
|
|
14730
|
+
// Fix B: carry the resolved coordinator anchor so the coordinator's receive-side
|
|
14731
|
+
// recovery (recoverMeshIdByCoordinatorAndNode) can match this forward to one of the
|
|
14732
|
+
// meshes it hosts when workspace + nodeId both miss. routing.coordinatorDaemonId is
|
|
14733
|
+
// the same anchor this forward is addressed to (coordinatorDaemonId below).
|
|
14734
|
+
meshCoordinatorDaemonId: coordinatorDaemonId
|
|
14610
14735
|
};
|
|
14611
14736
|
const resolvedMeshId = resolveForwardEventMeshId(components, payload);
|
|
14612
14737
|
if (resolvedMeshId) payload.meshId = resolvedMeshId;
|
|
@@ -14735,6 +14860,7 @@ var init_mesh_event_forwarding = __esm({
|
|
|
14735
14860
|
init_mesh_runtime_store();
|
|
14736
14861
|
init_mesh_events_pending();
|
|
14737
14862
|
init_mesh_routing();
|
|
14863
|
+
init_mesh_host_ownership();
|
|
14738
14864
|
init_mesh_unresolved_forward_outbox();
|
|
14739
14865
|
init_mesh_event_trace();
|
|
14740
14866
|
init_snapshot();
|
|
@@ -15026,8 +15152,7 @@ async function runMeshReconcileTick(components) {
|
|
|
15026
15152
|
const idleCoordinators = meshCoordinators.filter((c) => c.idle);
|
|
15027
15153
|
const generatingCoordinators = meshCoordinators.filter((c) => !c.idle && !c.modalParked);
|
|
15028
15154
|
const modalParkedCoordinators = meshCoordinators.filter((c) => !c.idle && c.modalParked);
|
|
15029
|
-
const targetCoordinators = idleCoordinators
|
|
15030
|
-
const forceOnly = idleCoordinators.length === 0;
|
|
15155
|
+
const targetCoordinators = idleCoordinators;
|
|
15031
15156
|
if (targetCoordinators.length === 0) {
|
|
15032
15157
|
if (modalParkedCoordinators.length > 0) {
|
|
15033
15158
|
const liveSessionIds = new Set(
|
|
@@ -15094,6 +15219,23 @@ async function runMeshReconcileTick(components) {
|
|
|
15094
15219
|
modalParkedCoordinators.length
|
|
15095
15220
|
);
|
|
15096
15221
|
}
|
|
15222
|
+
} else if (generatingCoordinators.length > 0) {
|
|
15223
|
+
let hasPending = true;
|
|
15224
|
+
if (store) {
|
|
15225
|
+
try {
|
|
15226
|
+
hasPending = store.pendingEventCount(meshId) > 0;
|
|
15227
|
+
} catch {
|
|
15228
|
+
}
|
|
15229
|
+
}
|
|
15230
|
+
if (hasPending) {
|
|
15231
|
+
LOG.info("MeshReconcile", `Reconcile skip \u2192 generating: holding pending event(s) for mesh ${meshId} (${generatingCoordinators.length} coordinator(s) busy; events left queued for the next idle tick)`);
|
|
15232
|
+
recordHeldTerminalEventsToLedger(
|
|
15233
|
+
meshId,
|
|
15234
|
+
drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId ? [localDaemonId] : [],
|
|
15235
|
+
"generating_no_idle_coordinator",
|
|
15236
|
+
generatingCoordinators.length
|
|
15237
|
+
);
|
|
15238
|
+
}
|
|
15097
15239
|
}
|
|
15098
15240
|
continue;
|
|
15099
15241
|
}
|
|
@@ -15107,16 +15249,14 @@ async function runMeshReconcileTick(components) {
|
|
|
15107
15249
|
try {
|
|
15108
15250
|
pendingEvents = drainPendingMeshCoordinatorEvents(
|
|
15109
15251
|
meshId,
|
|
15110
|
-
drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId
|
|
15111
|
-
forceOnly ? { onlyEvents: MESH_FORCE_INJECT_EVENTS } : void 0
|
|
15252
|
+
drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId
|
|
15112
15253
|
);
|
|
15113
15254
|
} catch (e) {
|
|
15114
15255
|
LOG.warn("MeshReconcile", `Drain failed for mesh ${meshId}: ${e?.message || e}`);
|
|
15115
15256
|
continue;
|
|
15116
15257
|
}
|
|
15117
15258
|
if (pendingEvents.length === 0) continue;
|
|
15118
|
-
|
|
15119
|
-
LOG.info("MeshReconcile", `Reconcile ${mode}: ${pendingEvents.length} pending event(s) \u2192 ${targetCoordinators.length} coordinator(s) for mesh ${meshId}`);
|
|
15259
|
+
LOG.info("MeshReconcile", `Reconcile inject \u2192 idle: ${pendingEvents.length} pending event(s) \u2192 ${targetCoordinators.length} coordinator(s) for mesh ${meshId}`);
|
|
15120
15260
|
for (const pending of pendingEvents) {
|
|
15121
15261
|
const wantSession = readNonEmptyString2(pending.targetCoordinatorSessionId);
|
|
15122
15262
|
if (wantSession) {
|
|
@@ -22974,102 +23114,7 @@ function buildMeshLedgerReconciliationEvidence(meshId, replicas) {
|
|
|
22974
23114
|
init_mesh_work_queue();
|
|
22975
23115
|
init_mesh_active_work();
|
|
22976
23116
|
init_mesh_refine_status();
|
|
22977
|
-
|
|
22978
|
-
// src/mesh/mesh-scheduling-runtime.ts
|
|
22979
|
-
init_repo_mesh_types();
|
|
22980
|
-
init_dist();
|
|
22981
|
-
function isReadonly(task) {
|
|
22982
|
-
return task.taskMode === "live_debug_readonly";
|
|
22983
|
-
}
|
|
22984
|
-
function isAssigned(task) {
|
|
22985
|
-
return task.status === "assigned";
|
|
22986
|
-
}
|
|
22987
|
-
function buildMeshSchedulingRuntime(mesh, queue) {
|
|
22988
|
-
const strategy = normalizeMeshSchedulingStrategy(mesh?.policy?.schedulingStrategy);
|
|
22989
|
-
const maxParallelTasks = resolveMaxParallelTasks(mesh?.policy?.maxParallelTasks);
|
|
22990
|
-
const maxReadonlyParallelTasks = Math.max(2, maxParallelTasks * 2);
|
|
22991
|
-
const assignedTasks = (Array.isArray(queue) ? queue : []).filter(isAssigned);
|
|
22992
|
-
const activeWriteAssigned = assignedTasks.filter((t) => !isReadonly(t)).length;
|
|
22993
|
-
const activeReadonlyAssigned = assignedTasks.filter(isReadonly).length;
|
|
22994
|
-
const globalWriteCapReached = activeWriteAssigned >= maxParallelTasks;
|
|
22995
|
-
const globalReadonlyCapReached = activeReadonlyAssigned >= maxReadonlyParallelTasks;
|
|
22996
|
-
const writeAssignedByNode = /* @__PURE__ */ new Map();
|
|
22997
|
-
const assignedByNode = /* @__PURE__ */ new Map();
|
|
22998
|
-
const providerCountByNode = /* @__PURE__ */ new Map();
|
|
22999
|
-
for (const task of assignedTasks) {
|
|
23000
|
-
const nodeId = typeof task.assignedNodeId === "string" ? task.assignedNodeId.trim() : "";
|
|
23001
|
-
if (!nodeId) continue;
|
|
23002
|
-
assignedByNode.set(nodeId, (assignedByNode.get(nodeId) ?? 0) + 1);
|
|
23003
|
-
if (!isReadonly(task)) {
|
|
23004
|
-
writeAssignedByNode.set(nodeId, (writeAssignedByNode.get(nodeId) ?? 0) + 1);
|
|
23005
|
-
}
|
|
23006
|
-
const provider = typeof task.assignedProviderType === "string" ? task.assignedProviderType : "";
|
|
23007
|
-
if (provider) {
|
|
23008
|
-
let byProvider = providerCountByNode.get(nodeId);
|
|
23009
|
-
if (!byProvider) {
|
|
23010
|
-
byProvider = /* @__PURE__ */ new Map();
|
|
23011
|
-
providerCountByNode.set(nodeId, byProvider);
|
|
23012
|
-
}
|
|
23013
|
-
byProvider.set(provider, (byProvider.get(provider) ?? 0) + 1);
|
|
23014
|
-
}
|
|
23015
|
-
}
|
|
23016
|
-
const nodes = [];
|
|
23017
|
-
for (const rawNode of Array.isArray(mesh?.nodes) ? mesh.nodes : []) {
|
|
23018
|
-
const nodeId = normalizeMeshNodeId(rawNode);
|
|
23019
|
-
if (!nodeId) continue;
|
|
23020
|
-
const policy = rawNode?.policy || void 0;
|
|
23021
|
-
const load4 = assignedByNode.get(nodeId) ?? 0;
|
|
23022
|
-
const schedulingPriority = resolveNodeSchedulingPriority(policy);
|
|
23023
|
-
const capReasons = [];
|
|
23024
|
-
if (globalWriteCapReached) capReasons.push("global_max_parallel_tasks_reached");
|
|
23025
|
-
if ((writeAssignedByNode.get(nodeId) ?? 0) > 0) capReasons.push("node_has_active_assignment");
|
|
23026
|
-
let providerRoles;
|
|
23027
|
-
const declaredRoles = Array.isArray(policy?.providerRoles) ? policy.providerRoles : [];
|
|
23028
|
-
if (declaredRoles.length) {
|
|
23029
|
-
const byProvider = providerCountByNode.get(nodeId);
|
|
23030
|
-
providerRoles = [];
|
|
23031
|
-
for (const role of declaredRoles) {
|
|
23032
|
-
if (!role || typeof role !== "object") continue;
|
|
23033
|
-
const providerType = typeof role.providerType === "string" ? role.providerType.trim() : "";
|
|
23034
|
-
if (!providerType) continue;
|
|
23035
|
-
const maxParallel = resolveProviderMaxParallel(policy, providerType);
|
|
23036
|
-
const activeAssigned = byProvider?.get(providerType) ?? 0;
|
|
23037
|
-
const capReached = maxParallel !== void 0 && activeAssigned >= maxParallel;
|
|
23038
|
-
providerRoles.push({
|
|
23039
|
-
providerType,
|
|
23040
|
-
...maxParallel !== void 0 ? { maxParallel } : {},
|
|
23041
|
-
activeAssigned,
|
|
23042
|
-
capReached
|
|
23043
|
-
});
|
|
23044
|
-
if (capReached) capReasons.push(`max_provider_parallel_reached:${providerType}`);
|
|
23045
|
-
}
|
|
23046
|
-
if (!providerRoles.length) providerRoles = void 0;
|
|
23047
|
-
}
|
|
23048
|
-
const maxConcurrentSessions = Number(policy?.maxConcurrentSessions);
|
|
23049
|
-
const hasSessionCap = Number.isFinite(maxConcurrentSessions) && maxConcurrentSessions >= 0;
|
|
23050
|
-
nodes.push({
|
|
23051
|
-
nodeId,
|
|
23052
|
-
load: load4,
|
|
23053
|
-
schedulingPriority,
|
|
23054
|
-
...hasSessionCap ? { maxConcurrentSessions: Math.floor(maxConcurrentSessions) } : {},
|
|
23055
|
-
...providerRoles ? { providerRoles } : {},
|
|
23056
|
-
capReached: capReasons.length > 0,
|
|
23057
|
-
capReasons
|
|
23058
|
-
});
|
|
23059
|
-
}
|
|
23060
|
-
return {
|
|
23061
|
-
strategy,
|
|
23062
|
-
maxParallelTasks,
|
|
23063
|
-
maxReadonlyParallelTasks,
|
|
23064
|
-
activeWriteAssigned,
|
|
23065
|
-
activeReadonlyAssigned,
|
|
23066
|
-
globalWriteCapReached,
|
|
23067
|
-
globalReadonlyCapReached,
|
|
23068
|
-
nodes
|
|
23069
|
-
};
|
|
23070
|
-
}
|
|
23071
|
-
|
|
23072
|
-
// src/index.ts
|
|
23117
|
+
init_mesh_scheduling_runtime();
|
|
23073
23118
|
init_mesh_host_ownership();
|
|
23074
23119
|
init_mesh_events();
|
|
23075
23120
|
init_mesh_events_utils();
|
|
@@ -38852,9 +38897,35 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
38852
38897
|
* terminal state. Leaving meshNodeFor pinned would route this session's
|
|
38853
38898
|
* subsequent unrelated turns (e.g. ad-hoc dashboard chats) to the
|
|
38854
38899
|
* coordinator as if they were task completions.
|
|
38900
|
+
*
|
|
38901
|
+
* MESHID-DROP-ON-DETACH (Fix C): a coordinator-LAUNCHED worker session
|
|
38902
|
+
* (launchedByCoordinator) holds its mesh membership (meshNodeFor / meshNodeId /
|
|
38903
|
+
* meshCoordinatorDaemonId) at the SESSION level — set once at launch
|
|
38904
|
+
* (mesh_launch_session / queue auto-launch), independent of any single task.
|
|
38905
|
+
* The original detach wiped meshNodeFor + meshNodeId together with the
|
|
38906
|
+
* task-level meshActiveTaskId, so the FIRST task completion stripped the
|
|
38907
|
+
* membership and EVERY subsequent completion forwarded with meshId absent —
|
|
38908
|
+
* resolveWorkerDelegateRouting fell to mesh_unresolved and the coordinator
|
|
38909
|
+
* rejected the forward "meshId required". For a launched member we therefore
|
|
38910
|
+
* clear ONLY the task-level marker (meshActiveTaskId) and preserve the
|
|
38911
|
+
* session-level membership so its next task's completion still resolves.
|
|
38912
|
+
* A task-less ad-hoc turn on a preserved-membership session is NOT misrouted:
|
|
38913
|
+
* its completion carries no taskId and the session holds no active assignment,
|
|
38914
|
+
* so the forwarder's WARMUPGAP guard skips the dispatch-row flip (it only
|
|
38915
|
+
* injects a benign task-less notification). A NON-launched session (a plain CLI
|
|
38916
|
+
* session adopted by mesh_send_task --direct, launchedByCoordinator falsy)
|
|
38917
|
+
* keeps the original full clear so an ad-hoc session is never left pinned.
|
|
38855
38918
|
*/
|
|
38856
38919
|
detachMeshAssignment() {
|
|
38857
38920
|
if (!this.settings.meshNodeFor && !this.settings.meshActiveTaskId && !this.settings.meshNodeId) return;
|
|
38921
|
+
if (this.settings.launchedByCoordinator === true) {
|
|
38922
|
+
if (!this.settings.meshActiveTaskId) return;
|
|
38923
|
+
const { meshActiveTaskId: meshActiveTaskId2, ...rest2 } = this.settings;
|
|
38924
|
+
void meshActiveTaskId2;
|
|
38925
|
+
this.settings = rest2;
|
|
38926
|
+
this.adapter.updateRuntimeSettings?.(this.settings);
|
|
38927
|
+
return;
|
|
38928
|
+
}
|
|
38858
38929
|
const { meshNodeFor, meshNodeId, meshActiveTaskId, ...rest } = this.settings;
|
|
38859
38930
|
void meshNodeFor;
|
|
38860
38931
|
void meshActiveTaskId;
|
|
@@ -48728,6 +48799,9 @@ var meshStatusHandlers = {
|
|
|
48728
48799
|
const { getMeshQueueStats: getMeshQueueStats2, getQueue: getQueue2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
48729
48800
|
const queue = getQueue2(meshId);
|
|
48730
48801
|
const queueSummary = getMeshQueueStats2(meshId);
|
|
48802
|
+
const { buildMeshSchedulingRuntime: buildMeshSchedulingRuntime2 } = await Promise.resolve().then(() => (init_mesh_scheduling_runtime(), mesh_scheduling_runtime_exports));
|
|
48803
|
+
const schedulingRuntime = buildMeshSchedulingRuntime2(mesh, queue);
|
|
48804
|
+
const schedulingByNode = new Map(schedulingRuntime.nodes.map((n) => [n.nodeId, n]));
|
|
48731
48805
|
const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
48732
48806
|
const ledgerEntries = readLedgerEntries2(meshId, { tail: 20 });
|
|
48733
48807
|
const asyncRefineLedgerEntries = readLedgerEntries2(meshId, { tail: 100 });
|
|
@@ -48842,6 +48916,11 @@ var meshStatusHandlers = {
|
|
|
48842
48916
|
activeSessionDetails: [],
|
|
48843
48917
|
launchReady: false
|
|
48844
48918
|
};
|
|
48919
|
+
const nodeScheduling = schedulingByNode.get(nodeId);
|
|
48920
|
+
if (nodeScheduling) {
|
|
48921
|
+
const { nodeId: _omitNodeId, ...nodeSchedulingRest } = nodeScheduling;
|
|
48922
|
+
status.scheduling = nodeSchedulingRest;
|
|
48923
|
+
}
|
|
48845
48924
|
if (isSelfNode) {
|
|
48846
48925
|
status.connection = {
|
|
48847
48926
|
perspective: "selected_coordinator",
|
|
@@ -49042,6 +49121,19 @@ var meshStatusHandlers = {
|
|
|
49042
49121
|
branchConvergenceSummary: summarizeInlineMeshBranchConvergence(nodeStatuses),
|
|
49043
49122
|
...previewFreshness ? { previewFreshness, deployFreshness: previewFreshness } : {},
|
|
49044
49123
|
nodes: nodeStatuses,
|
|
49124
|
+
// Mesh-level scheduling rollup (strategy + global cap consumption). Mirrors
|
|
49125
|
+
// the MCP `mesh_status` tool's `scheduling` block field-for-field so both
|
|
49126
|
+
// surfaces read the same runtime; per-node detail lives on each
|
|
49127
|
+
// nodes[].scheduling above.
|
|
49128
|
+
scheduling: {
|
|
49129
|
+
strategy: schedulingRuntime.strategy,
|
|
49130
|
+
maxParallelTasks: schedulingRuntime.maxParallelTasks,
|
|
49131
|
+
maxReadonlyParallelTasks: schedulingRuntime.maxReadonlyParallelTasks,
|
|
49132
|
+
activeWriteAssigned: schedulingRuntime.activeWriteAssigned,
|
|
49133
|
+
activeReadonlyAssigned: schedulingRuntime.activeReadonlyAssigned,
|
|
49134
|
+
globalWriteCapReached: schedulingRuntime.globalWriteCapReached,
|
|
49135
|
+
globalReadonlyCapReached: schedulingRuntime.globalReadonlyCapReached
|
|
49136
|
+
},
|
|
49045
49137
|
queue: { tasks: queue, summary: queueSummary },
|
|
49046
49138
|
ledger: { entries: ledgerEntries, summary: ledgerSummary },
|
|
49047
49139
|
...missions.length > 0 ? { missions } : {},
|
|
@@ -51986,17 +52078,40 @@ var DaemonCommandRouter = class {
|
|
|
51986
52078
|
* the wider plural-shape scan so a controlbar/modal command targeting a non-primary remote
|
|
51987
52079
|
* session still resolves its owner — the singular readCachedInlineMeshActiveSessions semantics
|
|
51988
52080
|
* other consumers depend on stay untouched.
|
|
52081
|
+
*
|
|
52082
|
+
* CANCEL-STOP-RELAY: the session-id cache scan above only matches when the coordinator's
|
|
52083
|
+
* cached status snapshot already lists the worker's session id in a recognized active-sessions
|
|
52084
|
+
* shape. A worktree-clone worker session whose id form/timing differs from the cached snapshot
|
|
52085
|
+
* (or is simply not yet reflected) misses the scan, so a stop that carries the authoritative
|
|
52086
|
+
* owning nodeId (mesh_queue_cancel knows assignedNodeId) used to silently fail to forward.
|
|
52087
|
+
* `ownerNodeIdHint` adds a deterministic fallback: when the session-id scan misses, resolve the
|
|
52088
|
+
* owner daemonId by matching the node by id (meshNodeIdMatches — same form-tolerant compare the
|
|
52089
|
+
* rest of the router uses, no new raw compare). The same self-loopback guard applies to both
|
|
52090
|
+
* paths, so a coordinator-hosted node is still never force-forwarded to a remote form of itself.
|
|
51989
52091
|
*/
|
|
51990
|
-
resolveRemoteMeshSessionOwnerDaemonId(sessionId) {
|
|
52092
|
+
resolveRemoteMeshSessionOwnerDaemonId(sessionId, ownerNodeIdHint) {
|
|
51991
52093
|
const trimmed = typeof sessionId === "string" ? sessionId.trim() : "";
|
|
51992
|
-
|
|
52094
|
+
const nodeHint = typeof ownerNodeIdHint === "string" ? ownerNodeIdHint.trim() : "";
|
|
52095
|
+
if (!trimmed && !nodeHint) return void 0;
|
|
51993
52096
|
const selfDaemonId = this.deps.statusInstanceId;
|
|
51994
|
-
|
|
51995
|
-
|
|
51996
|
-
const
|
|
51997
|
-
|
|
51998
|
-
|
|
51999
|
-
|
|
52097
|
+
const candidates = this.collectMeshSessionOwnerCandidateNodes();
|
|
52098
|
+
if (trimmed) {
|
|
52099
|
+
for (const node of candidates) {
|
|
52100
|
+
if (!collectMeshNodeHostedSessionIds(node).has(trimmed)) continue;
|
|
52101
|
+
const nodeDaemonId = readMeshNodeDaemonId(readObjectRecord(node));
|
|
52102
|
+
if (!nodeDaemonId) continue;
|
|
52103
|
+
if (selfDaemonId && daemonIdsEquivalent(nodeDaemonId, selfDaemonId)) return void 0;
|
|
52104
|
+
return nodeDaemonId;
|
|
52105
|
+
}
|
|
52106
|
+
}
|
|
52107
|
+
if (nodeHint) {
|
|
52108
|
+
for (const node of candidates) {
|
|
52109
|
+
if (!meshNodeIdMatches(node, nodeHint)) continue;
|
|
52110
|
+
const nodeDaemonId = readMeshNodeDaemonId(readObjectRecord(node));
|
|
52111
|
+
if (!nodeDaemonId) continue;
|
|
52112
|
+
if (selfDaemonId && daemonIdsEquivalent(nodeDaemonId, selfDaemonId)) return void 0;
|
|
52113
|
+
return nodeDaemonId;
|
|
52114
|
+
}
|
|
52000
52115
|
}
|
|
52001
52116
|
return void 0;
|
|
52002
52117
|
}
|
|
@@ -54130,7 +54245,9 @@ ${hintLines.join("\n")}` : "",
|
|
|
54130
54245
|
const localInstance = this.deps.instanceManager?.getInstance(targetSessionId);
|
|
54131
54246
|
const localRegistry = this.deps.sessionRegistry?.get?.(targetSessionId);
|
|
54132
54247
|
if (!localInstance && !localRegistry) {
|
|
54133
|
-
const
|
|
54248
|
+
const meshContext = readObjectRecord(args?.meshContext);
|
|
54249
|
+
const ownerNodeIdHint = readStringValue(meshContext.nodeId);
|
|
54250
|
+
const ownerDaemonId = this.resolveRemoteMeshSessionOwnerDaemonId(targetSessionId, ownerNodeIdHint);
|
|
54134
54251
|
if (ownerDaemonId) {
|
|
54135
54252
|
LOG.info("Mesh", `[Mesh] Forwarding session-scoped '${cmd}' for remote worker session ${targetSessionId.split("_")[0]} \u2192 daemon ${ownerDaemonId.slice(0, 12)}`);
|
|
54136
54253
|
const forwarded = await this.deps.dispatchMeshCommand(ownerDaemonId, cmd, {
|