@adhdev/daemon-standalone 1.0.28 → 1.0.29-rc.10
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/index.js +847 -137
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/public/assets/{index-Dm68eVOH.js → index-CKyjF8wa.js} +51 -51
- package/public/assets/{index-Jy4W-yh-.css → index-DaANjDZS.css} +1 -1
- package/public/assets/{terminal-BZj_X5zy.js → terminal-DiXj2eIR.js} +1 -1
- package/public/assets/{vendor-cL4V2vaO.js → vendor-DyCWA2YZ.js} +57 -49
- package/public/index.html +3 -3
- package/vendor/mcp-server/index.js +56 -18
- package/vendor/mcp-server/index.js.map +1 -1
- package/vendor/session-host-daemon/index.js +0 -0
- package/vendor/session-host-daemon/index.mjs +0 -0
package/dist/index.js
CHANGED
|
@@ -33311,10 +33311,10 @@ var require_dist3 = __commonJS({
|
|
|
33311
33311
|
}
|
|
33312
33312
|
function getDaemonBuildInfo() {
|
|
33313
33313
|
if (cached2) return cached2;
|
|
33314
|
-
const commit = readInjected(true ? "
|
|
33315
|
-
const commitShort = readInjected(true ? "
|
|
33316
|
-
const version2 = readInjected(true ? "1.0.
|
|
33317
|
-
const builtAt = readInjected(true ? "2026-
|
|
33314
|
+
const commit = readInjected(true ? "8f47a188527a03de6f207dbc0c6d844f72dcfcc5" : void 0) ?? "unknown";
|
|
33315
|
+
const commitShort = readInjected(true ? "8f47a188" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
33316
|
+
const version2 = readInjected(true ? "1.0.29-rc.10" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
33317
|
+
const builtAt = readInjected(true ? "2026-08-02T07:59:04.126Z" : void 0);
|
|
33318
33318
|
cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
|
|
33319
33319
|
return cached2;
|
|
33320
33320
|
}
|
|
@@ -36155,20 +36155,40 @@ ${error48.message || ""}`;
|
|
|
36155
36155
|
let hostDaemonId = readString3(raw?.hostDaemonId);
|
|
36156
36156
|
let hostNodeId = readString3(raw?.hostNodeId);
|
|
36157
36157
|
const hostAddress = readString3(raw?.hostAddress);
|
|
36158
|
+
let hostSynthesized = false;
|
|
36159
|
+
const nodes = Array.isArray(meshRecord?.nodes) ? meshRecord.nodes : [];
|
|
36160
|
+
const nodeDaemonIdOf = (node) => {
|
|
36161
|
+
const record2 = readObject(node);
|
|
36162
|
+
return readString3(record2?.daemonId) ?? readString3(record2?.daemon_id);
|
|
36163
|
+
};
|
|
36164
|
+
if (role === "host" && !hostDaemonId) {
|
|
36165
|
+
const declaredHostNode = nodes.find((n) => normalizeMeshDaemonRole(readObject(n)?.role) === "host");
|
|
36166
|
+
if (declaredHostNode) {
|
|
36167
|
+
const declaredDaemonId = nodeDaemonIdOf(declaredHostNode);
|
|
36168
|
+
if (declaredDaemonId) {
|
|
36169
|
+
hostDaemonId = declaredDaemonId;
|
|
36170
|
+
if (!hostNodeId) hostNodeId = readString3(readObject(declaredHostNode)?.id);
|
|
36171
|
+
}
|
|
36172
|
+
}
|
|
36173
|
+
}
|
|
36158
36174
|
const localDaemonId = readString3(opts?.localDaemonId);
|
|
36159
|
-
|
|
36175
|
+
const hasForeignDaemonNode = localDaemonId ? nodes.some((n) => {
|
|
36176
|
+
const nodeDaemonId = nodeDaemonIdOf(n);
|
|
36177
|
+
return nodeDaemonId ? !daemonIdsEquivalent(nodeDaemonId, localDaemonId) : false;
|
|
36178
|
+
}) : false;
|
|
36179
|
+
if (role === "host" && !hostDaemonId && !hostNodeId && localDaemonId && !hasForeignDaemonNode) {
|
|
36160
36180
|
hostDaemonId = localDaemonId;
|
|
36161
|
-
|
|
36162
|
-
|
|
36163
|
-
|
|
36164
|
-
|
|
36165
|
-
|
|
36166
|
-
|
|
36167
|
-
|
|
36168
|
-
}
|
|
36181
|
+
hostSynthesized = true;
|
|
36182
|
+
const selfNode = nodes.find((n) => {
|
|
36183
|
+
const nodeDaemonId = nodeDaemonIdOf(n);
|
|
36184
|
+
return nodeDaemonId ? daemonIdsEquivalent(nodeDaemonId, localDaemonId) : false;
|
|
36185
|
+
});
|
|
36186
|
+
const selfNodeId = readString3(readObject(selfNode)?.id);
|
|
36187
|
+
if (selfNodeId) hostNodeId = selfNodeId;
|
|
36169
36188
|
}
|
|
36170
36189
|
if (hostDaemonId) normalized.hostDaemonId = hostDaemonId;
|
|
36171
36190
|
if (hostNodeId) normalized.hostNodeId = hostNodeId;
|
|
36191
|
+
if (hostSynthesized) normalized.hostSynthesized = true;
|
|
36172
36192
|
if (hostAddress) normalized.hostAddress = hostAddress;
|
|
36173
36193
|
if (pairing) {
|
|
36174
36194
|
const status = pairing.status === "pairing" || pairing.status === "paired" || pairing.status === "rejected" || pairing.status === "revoked" ? pairing.status : "not_configured";
|
|
@@ -36235,8 +36255,10 @@ ${error48.message || ""}`;
|
|
|
36235
36255
|
normalizeRepoIdentity: () => normalizeRepoIdentity,
|
|
36236
36256
|
removeMagiKindPanel: () => removeMagiKindPanel,
|
|
36237
36257
|
removeNode: () => removeNode,
|
|
36258
|
+
resolveScopedMeshId: () => resolveScopedMeshId,
|
|
36238
36259
|
setDifficultyBrains: () => setDifficultyBrains,
|
|
36239
36260
|
setMagiKindPanel: () => setMagiKindPanel,
|
|
36261
|
+
setMeshHostPin: () => setMeshHostPin,
|
|
36240
36262
|
tokenIdForManualPairing: () => tokenIdForManualPairing,
|
|
36241
36263
|
updateMesh: () => updateMesh,
|
|
36242
36264
|
updateNode: () => updateNode
|
|
@@ -36265,15 +36287,41 @@ ${error48.message || ""}`;
|
|
|
36265
36287
|
}
|
|
36266
36288
|
function migrateLoadedMeshConfig(config2) {
|
|
36267
36289
|
let changed = false;
|
|
36290
|
+
if (foldLegacyTopLevelMeshSetting(config2, "magiKindPanels", "mesh_magi_kind_panel_set({ meshId, task_kind, slots })")) changed = true;
|
|
36291
|
+
if (foldLegacyTopLevelMeshSetting(config2, "difficultyBrains", "difficulty_brains_set({ meshId, difficultyBrains })")) changed = true;
|
|
36268
36292
|
for (const mesh of config2.meshes) {
|
|
36269
36293
|
if (!mesh || !Array.isArray(mesh.nodes)) continue;
|
|
36294
|
+
const brains = normalizeDifficultyBrainMap(mesh.difficultyBrains);
|
|
36295
|
+
const ownerBrains = Object.keys(brains).length > 0 ? brains : { ...DEFAULT_DIFFICULTY_BRAINS };
|
|
36270
36296
|
for (const node of mesh.nodes) {
|
|
36271
|
-
if (migrateProviderRolesToSlots(node?.policy)) changed = true;
|
|
36297
|
+
if (migrateProviderRolesToSlots(node?.policy, ownerBrains)) changed = true;
|
|
36272
36298
|
}
|
|
36273
36299
|
}
|
|
36274
36300
|
return changed;
|
|
36275
36301
|
}
|
|
36276
|
-
function
|
|
36302
|
+
function foldLegacyTopLevelMeshSetting(config2, key2, rebindHint) {
|
|
36303
|
+
const root = config2;
|
|
36304
|
+
const legacy = root[key2];
|
|
36305
|
+
if (!legacy || typeof legacy !== "object" || Array.isArray(legacy)) {
|
|
36306
|
+
if (key2 in root) {
|
|
36307
|
+
delete root[key2];
|
|
36308
|
+
return true;
|
|
36309
|
+
}
|
|
36310
|
+
return false;
|
|
36311
|
+
}
|
|
36312
|
+
delete root[key2];
|
|
36313
|
+
const entryKeys = Object.keys(legacy);
|
|
36314
|
+
if (config2.meshes.length === 1 && entryKeys.length > 0) {
|
|
36315
|
+
const mesh = config2.meshes[0];
|
|
36316
|
+
mesh[key2] = { ...legacy, ...mesh[key2] ?? {} };
|
|
36317
|
+
} else if (entryKeys.length > 0) {
|
|
36318
|
+
console.warn(
|
|
36319
|
+
`[mesh-config] Dropped legacy top-level ${key2} (keys: ${entryKeys.join(", ")}) \u2014 ${config2.meshes.length} meshes are configured, so the owning mesh cannot be determined. Re-apply it per mesh with ${rebindHint}.`
|
|
36320
|
+
);
|
|
36321
|
+
}
|
|
36322
|
+
return true;
|
|
36323
|
+
}
|
|
36324
|
+
function migrateProviderRolesToSlots(policy, ownerDifficultyBrains) {
|
|
36277
36325
|
if (!policy || typeof policy !== "object" || Array.isArray(policy)) return false;
|
|
36278
36326
|
const p = policy;
|
|
36279
36327
|
const rawRoles = p.providerRoles;
|
|
@@ -36296,12 +36344,7 @@ ${error48.message || ""}`;
|
|
|
36296
36344
|
}
|
|
36297
36345
|
p.slots = explicitSlots;
|
|
36298
36346
|
} else if (roleCap.size) {
|
|
36299
|
-
|
|
36300
|
-
try {
|
|
36301
|
-
difficultyBrains = getDifficultyBrains();
|
|
36302
|
-
} catch {
|
|
36303
|
-
difficultyBrains = void 0;
|
|
36304
|
-
}
|
|
36347
|
+
const difficultyBrains = ownerDifficultyBrains;
|
|
36305
36348
|
const priority = Array.isArray(p.providerPriority) ? p.providerPriority.map((t) => typeof t === "string" ? t.trim() : "").filter(Boolean) : [];
|
|
36306
36349
|
const derived = deriveSlotsFromLegacy({ providerPriority: priority, difficultyBrains });
|
|
36307
36350
|
const slots = derived.length ? derived : [...roleCap.values()].map((r) => ({ provider: r.provider }));
|
|
@@ -36382,7 +36425,11 @@ ${error48.message || ""}`;
|
|
|
36382
36425
|
defaultBranch: opts.defaultBranch,
|
|
36383
36426
|
policy: mergeMeshPolicy(void 0, opts.policy),
|
|
36384
36427
|
coordinator: opts.coordinator || {},
|
|
36385
|
-
meshHost: opts.meshHost ||
|
|
36428
|
+
meshHost: opts.meshHost || (() => {
|
|
36429
|
+
const base = createDefaultMeshHostMetadata();
|
|
36430
|
+
const creatingDaemonId = typeof opts.hostDaemonId === "string" ? opts.hostDaemonId.trim() : "";
|
|
36431
|
+
return creatingDaemonId ? { ...base, hostDaemonId: creatingDaemonId } : base;
|
|
36432
|
+
})(),
|
|
36386
36433
|
nodes: [],
|
|
36387
36434
|
createdAt: now,
|
|
36388
36435
|
updatedAt: now
|
|
@@ -36568,6 +36615,86 @@ ${error48.message || ""}`;
|
|
|
36568
36615
|
saveMeshConfig(config2);
|
|
36569
36616
|
return { accepted: true, mesh, meshHost: mesh.meshHost, node, tokenId: validation.tokenId };
|
|
36570
36617
|
}
|
|
36618
|
+
function setMeshHostPin(meshId, opts) {
|
|
36619
|
+
const config2 = loadMeshConfig();
|
|
36620
|
+
const mesh = config2.meshes.find((m) => m.id === meshId);
|
|
36621
|
+
if (!mesh) return void 0;
|
|
36622
|
+
const hostDaemonId = typeof opts.hostDaemonId === "string" ? opts.hostDaemonId.trim() : "";
|
|
36623
|
+
const hostNodeId = typeof opts.hostNodeId === "string" ? opts.hostNodeId.trim() : "";
|
|
36624
|
+
const previous = mesh.meshHost || createDefaultMeshHostMetadata();
|
|
36625
|
+
if (!hostDaemonId && !hostNodeId) {
|
|
36626
|
+
return {
|
|
36627
|
+
mesh,
|
|
36628
|
+
meshHost: previous,
|
|
36629
|
+
applied: false,
|
|
36630
|
+
reason: "invalid_host_daemon_id",
|
|
36631
|
+
...previous.hostDaemonId ? { hostDaemonId: previous.hostDaemonId } : {},
|
|
36632
|
+
...previous.hostNodeId ? { hostNodeId: previous.hostNodeId } : {}
|
|
36633
|
+
};
|
|
36634
|
+
}
|
|
36635
|
+
if (previous.role === "member") {
|
|
36636
|
+
return {
|
|
36637
|
+
mesh,
|
|
36638
|
+
meshHost: previous,
|
|
36639
|
+
applied: false,
|
|
36640
|
+
reason: "not_host_role",
|
|
36641
|
+
...previous.hostDaemonId ? { hostDaemonId: previous.hostDaemonId } : {},
|
|
36642
|
+
...previous.hostNodeId ? { hostNodeId: previous.hostNodeId } : {}
|
|
36643
|
+
};
|
|
36644
|
+
}
|
|
36645
|
+
const existingDaemonId = typeof previous.hostDaemonId === "string" ? previous.hostDaemonId.trim() : "";
|
|
36646
|
+
if (existingDaemonId && !opts.force) {
|
|
36647
|
+
const sameHost = hostDaemonId ? daemonIdsEquivalent(existingDaemonId, hostDaemonId) : true;
|
|
36648
|
+
if (!sameHost) {
|
|
36649
|
+
return {
|
|
36650
|
+
mesh,
|
|
36651
|
+
meshHost: previous,
|
|
36652
|
+
applied: false,
|
|
36653
|
+
reason: "host_already_pinned",
|
|
36654
|
+
hostDaemonId: existingDaemonId,
|
|
36655
|
+
...previous.hostNodeId ? { hostNodeId: previous.hostNodeId } : {}
|
|
36656
|
+
};
|
|
36657
|
+
}
|
|
36658
|
+
const existingNodeId = typeof previous.hostNodeId === "string" ? previous.hostNodeId.trim() : "";
|
|
36659
|
+
if (!hostNodeId || hostNodeId === existingNodeId) {
|
|
36660
|
+
return {
|
|
36661
|
+
mesh,
|
|
36662
|
+
meshHost: previous,
|
|
36663
|
+
applied: false,
|
|
36664
|
+
reason: "already_pinned_same",
|
|
36665
|
+
hostDaemonId: existingDaemonId,
|
|
36666
|
+
...existingNodeId ? { hostNodeId: existingNodeId } : {}
|
|
36667
|
+
};
|
|
36668
|
+
}
|
|
36669
|
+
}
|
|
36670
|
+
const now = opts.now || (/* @__PURE__ */ new Date()).toISOString();
|
|
36671
|
+
const effectiveDaemonId = hostDaemonId || existingDaemonId;
|
|
36672
|
+
mesh.meshHost = {
|
|
36673
|
+
...previous,
|
|
36674
|
+
role: "host",
|
|
36675
|
+
...effectiveDaemonId ? { hostDaemonId: effectiveDaemonId } : {},
|
|
36676
|
+
...hostNodeId ? { hostNodeId } : previous.hostNodeId ? { hostNodeId: previous.hostNodeId } : {},
|
|
36677
|
+
...opts.hostAddress?.trim() ? { hostAddress: opts.hostAddress.trim() } : {}
|
|
36678
|
+
};
|
|
36679
|
+
const hostNode = hostNodeId ? mesh.nodes.find((n) => n.id === hostNodeId) : effectiveDaemonId ? mesh.nodes.find((n) => n.daemonId && daemonIdsEquivalent(n.daemonId, effectiveDaemonId)) : void 0;
|
|
36680
|
+
if (hostNode) {
|
|
36681
|
+
for (const node of mesh.nodes) {
|
|
36682
|
+
if (node.role === "host" && node !== hostNode) node.role = void 0;
|
|
36683
|
+
}
|
|
36684
|
+
hostNode.role = "host";
|
|
36685
|
+
if (!mesh.meshHost.hostNodeId) mesh.meshHost.hostNodeId = hostNode.id;
|
|
36686
|
+
}
|
|
36687
|
+
mesh.updatedAt = now;
|
|
36688
|
+
saveMeshConfig(config2);
|
|
36689
|
+
return {
|
|
36690
|
+
mesh,
|
|
36691
|
+
meshHost: mesh.meshHost,
|
|
36692
|
+
applied: true,
|
|
36693
|
+
reason: "pinned",
|
|
36694
|
+
...mesh.meshHost.hostDaemonId ? { hostDaemonId: mesh.meshHost.hostDaemonId } : {},
|
|
36695
|
+
...mesh.meshHost.hostNodeId ? { hostNodeId: mesh.meshHost.hostNodeId } : {}
|
|
36696
|
+
};
|
|
36697
|
+
}
|
|
36571
36698
|
function markMeshHostPairingJoined(meshId, opts) {
|
|
36572
36699
|
const config2 = loadMeshConfig();
|
|
36573
36700
|
const mesh = config2.meshes.find((m) => m.id === meshId);
|
|
@@ -36628,6 +36755,12 @@ ${error48.message || ""}`;
|
|
|
36628
36755
|
worktreeBootstrap: opts.worktreeBootstrap,
|
|
36629
36756
|
role: opts.role
|
|
36630
36757
|
};
|
|
36758
|
+
const pinnedHostDaemonId = typeof mesh.meshHost?.hostDaemonId === "string" ? mesh.meshHost.hostDaemonId.trim() : "";
|
|
36759
|
+
const anchorMissing = !(typeof mesh.meshHost?.hostNodeId === "string" && mesh.meshHost.hostNodeId.trim());
|
|
36760
|
+
if (!node.role && anchorMissing && pinnedHostDaemonId && mesh.meshHost?.role !== "member" && node.daemonId && daemonIdsEquivalent(node.daemonId, pinnedHostDaemonId) && !mesh.nodes.some((n) => n.role === "host")) {
|
|
36761
|
+
node.role = "host";
|
|
36762
|
+
mesh.meshHost = { ...mesh.meshHost || createDefaultMeshHostMetadata(), hostNodeId: node.id };
|
|
36763
|
+
}
|
|
36631
36764
|
mesh.nodes.push(node);
|
|
36632
36765
|
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
36633
36766
|
saveMeshConfig(config2);
|
|
@@ -36640,6 +36773,7 @@ ${error48.message || ""}`;
|
|
|
36640
36773
|
const idx = mesh.nodes.findIndex((n) => n.id === nodeId);
|
|
36641
36774
|
if (idx === -1) return false;
|
|
36642
36775
|
mesh.nodes.splice(idx, 1);
|
|
36776
|
+
pruneMagiKindPanelsForRemovedNode(mesh, nodeId);
|
|
36643
36777
|
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
36644
36778
|
saveMeshConfig(config2);
|
|
36645
36779
|
return true;
|
|
@@ -36696,7 +36830,8 @@ ${error48.message || ""}`;
|
|
|
36696
36830
|
}
|
|
36697
36831
|
return s2;
|
|
36698
36832
|
}
|
|
36699
|
-
function normalizeMagiSlots(slots) {
|
|
36833
|
+
function normalizeMagiSlots(slots, knownNodeIds) {
|
|
36834
|
+
const allowed = knownNodeIds ? new Set(knownNodeIds) : void 0;
|
|
36700
36835
|
if (!Array.isArray(slots) || slots.length === 0) {
|
|
36701
36836
|
throw new Error("invalid_magi_kind_panel: slots must be a non-empty array");
|
|
36702
36837
|
}
|
|
@@ -36713,6 +36848,11 @@ ${error48.message || ""}`;
|
|
|
36713
36848
|
throw new Error(`invalid_magi_kind_panel: slot[${idx}].provider is required`);
|
|
36714
36849
|
}
|
|
36715
36850
|
const nodeId = typeof s2.nodeId === "string" && s2.nodeId.trim() ? s2.nodeId.trim() : void 0;
|
|
36851
|
+
if (nodeId && allowed && !allowed.has(nodeId)) {
|
|
36852
|
+
throw new Error(
|
|
36853
|
+
`invalid_magi_kind_panel: slot[${idx}].nodeId '${nodeId}' is not a node of this mesh (known: ${[...allowed].join(", ") || "(none)"}). Pin a node from this mesh, or omit nodeId to let the fan-out pick any node offering the provider.`
|
|
36854
|
+
);
|
|
36855
|
+
}
|
|
36716
36856
|
const model = typeof s2.model === "string" && s2.model.trim() ? s2.model.trim() : void 0;
|
|
36717
36857
|
const capabilityTags = normalizeCapabilityTags(s2.capabilityTags);
|
|
36718
36858
|
const n = normalizeReplicaCount(s2.n);
|
|
@@ -36725,32 +36865,51 @@ ${error48.message || ""}`;
|
|
|
36725
36865
|
};
|
|
36726
36866
|
});
|
|
36727
36867
|
}
|
|
36728
|
-
function
|
|
36729
|
-
|
|
36868
|
+
function resolveScopedMeshId(config2) {
|
|
36869
|
+
const meshes = (config2 ?? loadMeshConfig({ persistMigrations: false })).meshes;
|
|
36870
|
+
return meshes.length === 1 ? meshes[0].id : void 0;
|
|
36871
|
+
}
|
|
36872
|
+
function resolveScopedMesh(config2, meshId) {
|
|
36873
|
+
const id = meshId?.trim() || resolveScopedMeshId(config2);
|
|
36874
|
+
if (!id) return void 0;
|
|
36875
|
+
return config2.meshes.find((m) => m.id === id);
|
|
36730
36876
|
}
|
|
36731
|
-
function
|
|
36732
|
-
|
|
36877
|
+
function listMagiKindPanels(meshId) {
|
|
36878
|
+
const config2 = loadMeshConfig();
|
|
36879
|
+
return resolveScopedMesh(config2, meshId)?.magiKindPanels ?? {};
|
|
36880
|
+
}
|
|
36881
|
+
function listMagiKindPanelsReadOnly(meshId) {
|
|
36882
|
+
const config2 = loadMeshConfig({ persistMigrations: false });
|
|
36883
|
+
return resolveScopedMesh(config2, meshId)?.magiKindPanels ?? {};
|
|
36733
36884
|
}
|
|
36734
|
-
function getMagiKindPanel(kind) {
|
|
36885
|
+
function getMagiKindPanel(kind, meshId) {
|
|
36735
36886
|
let key2;
|
|
36736
36887
|
try {
|
|
36737
36888
|
key2 = normalizeMagiTaskKindKey(kind);
|
|
36738
36889
|
} catch {
|
|
36739
36890
|
return void 0;
|
|
36740
36891
|
}
|
|
36741
|
-
|
|
36892
|
+
const config2 = loadMeshConfig();
|
|
36893
|
+
return resolveScopedMesh(config2, meshId)?.magiKindPanels?.[key2];
|
|
36742
36894
|
}
|
|
36743
|
-
function setMagiKindPanel(kind, slots) {
|
|
36895
|
+
function setMagiKindPanel(kind, slots, meshId) {
|
|
36744
36896
|
const key2 = normalizeMagiTaskKindKey(kind);
|
|
36745
|
-
const normalized = normalizeMagiSlots(slots);
|
|
36746
36897
|
const stored = loadMeshConfig();
|
|
36747
|
-
const
|
|
36898
|
+
const mesh = resolveScopedMesh(stored, meshId);
|
|
36899
|
+
if (!mesh) {
|
|
36900
|
+
throw new Error(
|
|
36901
|
+
meshId?.trim() ? `invalid_magi_kind_panel: mesh '${meshId.trim()}' not found` : `magi_kind_panel_mesh_ambiguous: this machine hosts ${stored.meshes.length} meshes, so a MAGI kind-panel write must name its mesh explicitly (meshId). Panels are per mesh.`
|
|
36902
|
+
);
|
|
36903
|
+
}
|
|
36904
|
+
const normalized = normalizeMagiSlots(slots, mesh.nodes.map((n) => n.id));
|
|
36905
|
+
const map3 = mesh.magiKindPanels ?? {};
|
|
36748
36906
|
map3[key2] = normalized;
|
|
36749
|
-
|
|
36907
|
+
mesh.magiKindPanels = map3;
|
|
36908
|
+
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
36750
36909
|
saveMeshConfig(stored);
|
|
36751
36910
|
return normalized;
|
|
36752
36911
|
}
|
|
36753
|
-
function removeMagiKindPanel(kind) {
|
|
36912
|
+
function removeMagiKindPanel(kind, meshId) {
|
|
36754
36913
|
let key2;
|
|
36755
36914
|
try {
|
|
36756
36915
|
key2 = normalizeMagiTaskKindKey(kind);
|
|
@@ -36758,21 +36917,47 @@ ${error48.message || ""}`;
|
|
|
36758
36917
|
return false;
|
|
36759
36918
|
}
|
|
36760
36919
|
const stored = loadMeshConfig();
|
|
36761
|
-
|
|
36762
|
-
|
|
36920
|
+
const mesh = resolveScopedMesh(stored, meshId);
|
|
36921
|
+
if (!mesh?.magiKindPanels?.[key2]) return false;
|
|
36922
|
+
delete mesh.magiKindPanels[key2];
|
|
36923
|
+
if (Object.keys(mesh.magiKindPanels).length === 0) delete mesh.magiKindPanels;
|
|
36924
|
+
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
36763
36925
|
saveMeshConfig(stored);
|
|
36764
36926
|
return true;
|
|
36765
36927
|
}
|
|
36766
|
-
function
|
|
36767
|
-
const
|
|
36928
|
+
function pruneMagiKindPanelsForRemovedNode(mesh, nodeId) {
|
|
36929
|
+
const panels = mesh.magiKindPanels;
|
|
36930
|
+
if (!panels) return false;
|
|
36931
|
+
let changed = false;
|
|
36932
|
+
for (const [kind, slots] of Object.entries(panels)) {
|
|
36933
|
+
if (!Array.isArray(slots)) continue;
|
|
36934
|
+
const kept = slots.filter((slot) => slot.nodeId !== nodeId);
|
|
36935
|
+
if (kept.length === slots.length) continue;
|
|
36936
|
+
changed = true;
|
|
36937
|
+
if (kept.length === 0) delete panels[kind];
|
|
36938
|
+
else panels[kind] = kept;
|
|
36939
|
+
}
|
|
36940
|
+
if (changed && Object.keys(panels).length === 0) delete mesh.magiKindPanels;
|
|
36941
|
+
return changed;
|
|
36942
|
+
}
|
|
36943
|
+
function getDifficultyBrains(meshId) {
|
|
36944
|
+
const config2 = loadMeshConfig();
|
|
36945
|
+
const stored = resolveScopedMesh(config2, meshId)?.difficultyBrains;
|
|
36768
36946
|
const normalized = normalizeDifficultyBrainMap(stored);
|
|
36769
36947
|
return Object.keys(normalized).length > 0 ? normalized : { ...DEFAULT_DIFFICULTY_BRAINS };
|
|
36770
36948
|
}
|
|
36771
|
-
function setDifficultyBrains(map3) {
|
|
36949
|
+
function setDifficultyBrains(map3, meshId) {
|
|
36772
36950
|
const normalized = normalizeDifficultyBrainMap(map3);
|
|
36773
36951
|
const stored = loadMeshConfig();
|
|
36774
|
-
|
|
36775
|
-
|
|
36952
|
+
const mesh = resolveScopedMesh(stored, meshId);
|
|
36953
|
+
if (!mesh) {
|
|
36954
|
+
throw new Error(
|
|
36955
|
+
meshId?.trim() ? `invalid_difficulty_brains: mesh '${meshId.trim()}' not found` : `difficulty_brains_mesh_ambiguous: this machine hosts ${stored.meshes.length} meshes, so a difficulty-brain write must name its mesh explicitly (meshId). Presets are per mesh \u2014 they decide which model a task runs on, so writing to the wrong mesh changes what it costs.`
|
|
36956
|
+
);
|
|
36957
|
+
}
|
|
36958
|
+
if (Object.keys(normalized).length > 0) mesh.difficultyBrains = normalized;
|
|
36959
|
+
else delete mesh.difficultyBrains;
|
|
36960
|
+
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
36776
36961
|
saveMeshConfig(stored);
|
|
36777
36962
|
return normalized;
|
|
36778
36963
|
}
|
|
@@ -36808,12 +36993,12 @@ ${error48.message || ""}`;
|
|
|
36808
36993
|
return true;
|
|
36809
36994
|
});
|
|
36810
36995
|
}
|
|
36811
|
-
function resolveNodeCapabilitySlots(node) {
|
|
36996
|
+
function resolveNodeCapabilitySlots(node, meshId) {
|
|
36812
36997
|
const explicit = normalizeNodeCapabilitySlots(node?.policy?.slots);
|
|
36813
36998
|
if (explicit.length) return explicit;
|
|
36814
36999
|
let difficultyBrains;
|
|
36815
37000
|
try {
|
|
36816
|
-
difficultyBrains = getDifficultyBrains();
|
|
37001
|
+
difficultyBrains = getDifficultyBrains(meshId);
|
|
36817
37002
|
} catch {
|
|
36818
37003
|
difficultyBrains = void 0;
|
|
36819
37004
|
}
|
|
@@ -39298,9 +39483,20 @@ Next step: ${nextStep}`;
|
|
|
39298
39483
|
}
|
|
39299
39484
|
continue;
|
|
39300
39485
|
}
|
|
39486
|
+
if (validated.intendedFor && !validated.intendedFor.sessionId && daemonIdsEquivalent(validated.intendedFor.daemonId, drainer.daemonId)) {
|
|
39487
|
+
const liveSessions = ctx.countLiveCoordinatorSessions?.(validated.intendedFor.daemonId) ?? 0;
|
|
39488
|
+
if (liveSessions > 1) {
|
|
39489
|
+
warnV2Once(
|
|
39490
|
+
`${event.meshId}::${eventId}::ambiguous-unicast`,
|
|
39491
|
+
`v2 unicast ${event.event} on mesh ${event.meshId} carries NO coordinator session but ${liveSessions} coordinator sessions are live on ${validated.intendedFor.daemonId} \u2014 delivery is first-come-first-served and may reach the wrong coordinator. Delivered to ${coordinatorIdentityKey(drainer)}. The EMITTING path must stamp targetCoordinatorSessionId.`
|
|
39492
|
+
);
|
|
39493
|
+
bump("v2AmbiguousUnicastDelivered");
|
|
39494
|
+
}
|
|
39495
|
+
}
|
|
39301
39496
|
if (validated.intendedFor && identityDeliversTo(validated.intendedFor, drainer)) {
|
|
39302
39497
|
ctx.batchSeen.add(eventId);
|
|
39303
39498
|
bump("v2Delivered");
|
|
39499
|
+
LOG2.debug("MeshEventsV2", `unicast ${event.event} (mesh ${event.meshId}, eventId ${eventId}) delivered to ${coordinatorIdentityKey(drainer)}; intendedFor=${coordinatorIdentityKey(validated.intendedFor)}`);
|
|
39304
39500
|
kept.push(event);
|
|
39305
39501
|
continue;
|
|
39306
39502
|
}
|
|
@@ -39315,6 +39511,7 @@ Next step: ${nextStep}`;
|
|
|
39315
39511
|
kept.push(event);
|
|
39316
39512
|
continue;
|
|
39317
39513
|
}
|
|
39514
|
+
LOG2.debug("MeshEventsV2", `unicast ${event.event} (mesh ${event.meshId}, eventId ${eventId}) NOT delivered to ${coordinatorIdentityKey(drainer)}; intendedFor=${validated.intendedFor ? coordinatorIdentityKey(validated.intendedFor) : "none"} \u2014 left for its own drainer`);
|
|
39318
39515
|
bump("v2RoutedAway");
|
|
39319
39516
|
}
|
|
39320
39517
|
return kept;
|
|
@@ -39767,7 +39964,12 @@ Next step: ${nextStep}`;
|
|
|
39767
39964
|
try {
|
|
39768
39965
|
const store = MeshRuntimeStore.getInstance();
|
|
39769
39966
|
if (store.pendingEventCount(meshId) > 0) {
|
|
39770
|
-
|
|
39967
|
+
const drainedBy = drainer ? JSON.stringify(drainer) : null;
|
|
39968
|
+
for (const row of store.drainPendingEvents(
|
|
39969
|
+
meshId,
|
|
39970
|
+
daemonIds.length > 0 ? daemonIds : void 0,
|
|
39971
|
+
{ ...onlyEvents ? { onlyEvents } : {}, drainedBy }
|
|
39972
|
+
)) {
|
|
39771
39973
|
const event = row.payload;
|
|
39772
39974
|
if (event) pushUnique(event);
|
|
39773
39975
|
}
|
|
@@ -39806,7 +40008,8 @@ Next step: ${nextStep}`;
|
|
|
39806
40008
|
const routed = routeV2EventsForDrainer(merged, drainer, {
|
|
39807
40009
|
alreadyDrained: (eventId) => priorDrainedEventIds.has(eventId),
|
|
39808
40010
|
batchSeen: /* @__PURE__ */ new Set(),
|
|
39809
|
-
countMetrics: true
|
|
40011
|
+
countMetrics: true,
|
|
40012
|
+
...opts?.countLiveCoordinatorSessions ? { countLiveCoordinatorSessions: opts.countLiveCoordinatorSessions } : {}
|
|
39810
40013
|
});
|
|
39811
40014
|
return reconcilePendingMeshCoordinatorEvents(meshId, routed);
|
|
39812
40015
|
}
|
|
@@ -40026,6 +40229,11 @@ Next step: ${nextStep}`;
|
|
|
40026
40229
|
/** unicast events re-attributed to the drainer via daemon-core match (a
|
|
40027
40230
|
* coordinatorRunId change orphaned them). */
|
|
40028
40231
|
v2ReattributedToDrainer: 0,
|
|
40232
|
+
/** REFINE-EVENT-SESSION-SCOPED-UNICAST: unicast events delivered while addressed only
|
|
40233
|
+
* at DAEMON granularity (no sessionId in intendedFor) even though >1 coordinator
|
|
40234
|
+
* session was live on that daemon — i.e. delivered by race, not by address. Non-zero
|
|
40235
|
+
* here names an emit path that still fails to stamp targetCoordinatorSessionId. */
|
|
40236
|
+
v2AmbiguousUnicastDelivered: 0,
|
|
40029
40237
|
/** v1 (unversioned) events passed through as broadcast (rollout baseline). */
|
|
40030
40238
|
v1BroadcastAccepted: 0,
|
|
40031
40239
|
/** T6 enforce: v2 events that FAILED validation and were QUARANTINED (held back
|
|
@@ -40828,7 +41036,7 @@ Next step: ${nextStep}`;
|
|
|
40828
41036
|
const taskDifficulty = isMeshTaskDifficulty(opts?.difficulty) ? opts.difficulty : void 0;
|
|
40829
41037
|
if (isMeshTaskDifficulty(opts?.difficulty)) {
|
|
40830
41038
|
try {
|
|
40831
|
-
const preset = getDifficultyBrains()[opts.difficulty];
|
|
41039
|
+
const preset = getDifficultyBrains(meshId)[opts.difficulty];
|
|
40832
41040
|
if (preset) {
|
|
40833
41041
|
if (!effectiveModel && preset.model) effectiveModel = preset.model;
|
|
40834
41042
|
if (!effectiveThinkingLevel && preset.thinkingLevel) effectiveThinkingLevel = preset.thinkingLevel;
|
|
@@ -41784,7 +41992,15 @@ Next step: ${nextStep}`;
|
|
|
41784
41992
|
event_id TEXT,
|
|
41785
41993
|
scope TEXT,
|
|
41786
41994
|
dispatched_by TEXT,
|
|
41787
|
-
intended_for TEXT
|
|
41995
|
+
intended_for TEXT,
|
|
41996
|
+
-- REFINE-EVENT-SESSION-SCOPED-UNICAST: WHO consumed this row. The ledger
|
|
41997
|
+
-- previously recorded only THAT an event was drained, never by which
|
|
41998
|
+
-- coordinator identity \u2014 so a mis-delivered unicast (a sibling session
|
|
41999
|
+
-- consuming another coordinator's event) left no evidence and had to be
|
|
42000
|
+
-- inferred. Written at drain time as the JSON-serialized drainer
|
|
42001
|
+
-- CoordinatorIdentity. NULL on rows drained before this column existed
|
|
42002
|
+
-- and on any drain whose caller passed no identity (daemon-level drain).
|
|
42003
|
+
drained_by TEXT
|
|
41788
42004
|
);
|
|
41789
42005
|
|
|
41790
42006
|
CREATE INDEX IF NOT EXISTS idx_mesh_pending_events_mesh_drained
|
|
@@ -42030,7 +42246,7 @@ Next step: ${nextStep}`;
|
|
|
42030
42246
|
this.db.exec(`ALTER TABLE mesh_missions ADD COLUMN close_candidate_emitted_at TEXT`);
|
|
42031
42247
|
}
|
|
42032
42248
|
const pendingCols = this.tableColumns("mesh_pending_events");
|
|
42033
|
-
for (const col of ["protocol_version", "event_id", "scope", "dispatched_by", "intended_for"]) {
|
|
42249
|
+
for (const col of ["protocol_version", "event_id", "scope", "dispatched_by", "intended_for", "drained_by"]) {
|
|
42034
42250
|
if (!pendingCols.has(col)) {
|
|
42035
42251
|
this.db.exec(`ALTER TABLE mesh_pending_events ADD COLUMN ${col} TEXT`);
|
|
42036
42252
|
}
|
|
@@ -43299,8 +43515,8 @@ Next step: ${nextStep}`;
|
|
|
43299
43515
|
const ids = rows.map((r) => r.id);
|
|
43300
43516
|
const now = Date.now();
|
|
43301
43517
|
this.db.prepare(
|
|
43302
|
-
`UPDATE mesh_pending_events SET drained = 1, drained_at = ? WHERE id IN (${ids.map(() => "?").join(",")})`
|
|
43303
|
-
).run(now, ...ids);
|
|
43518
|
+
`UPDATE mesh_pending_events SET drained = 1, drained_at = ?, drained_by = ? WHERE id IN (${ids.map(() => "?").join(",")})`
|
|
43519
|
+
).run(now, opts?.drainedBy ?? null, ...ids);
|
|
43304
43520
|
return rows.map((r) => ({
|
|
43305
43521
|
id: r.id,
|
|
43306
43522
|
event: r.event,
|
|
@@ -43334,6 +43550,30 @@ Next step: ${nextStep}`;
|
|
|
43334
43550
|
})()
|
|
43335
43551
|
}));
|
|
43336
43552
|
}
|
|
43553
|
+
/**
|
|
43554
|
+
* REFINE-EVENT-SESSION-SCOPED-UNICAST — drain attribution audit. Returns the most
|
|
43555
|
+
* recent pending-event rows for a mesh with WHO drained each one, so a suspected
|
|
43556
|
+
* mis-delivery ("my refine result went to another coordinator session") is answered
|
|
43557
|
+
* from the ledger instead of inferred from timing. `drainedBy` is the serialized
|
|
43558
|
+
* drainer CoordinatorIdentity, or null when the row is still queued, was drained
|
|
43559
|
+
* before this column existed, or was drained by a caller that passed no identity.
|
|
43560
|
+
*/
|
|
43561
|
+
recentDrainedPendingEvents(meshId, limit = 100) {
|
|
43562
|
+
const rows = this.db.prepare(
|
|
43563
|
+
`SELECT id, event, scope, intended_for, drained_by, drained, queued_at, drained_at
|
|
43564
|
+
FROM mesh_pending_events WHERE mesh_id = ? ORDER BY queued_at DESC LIMIT ?`
|
|
43565
|
+
).all(meshId, Math.max(1, limit));
|
|
43566
|
+
return rows.map((r) => ({
|
|
43567
|
+
id: r.id,
|
|
43568
|
+
event: r.event,
|
|
43569
|
+
scope: r.scope ?? null,
|
|
43570
|
+
intendedFor: r.intended_for ?? null,
|
|
43571
|
+
drainedBy: r.drained_by ?? null,
|
|
43572
|
+
drained: r.drained === 1,
|
|
43573
|
+
queuedAt: r.queued_at,
|
|
43574
|
+
drainedAt: r.drained_at ?? null
|
|
43575
|
+
}));
|
|
43576
|
+
}
|
|
43337
43577
|
hasPendingEventFingerprint(meshId, fingerprint) {
|
|
43338
43578
|
const row = this.db.prepare(
|
|
43339
43579
|
"SELECT 1 FROM mesh_pending_events WHERE mesh_id = ? AND fingerprint = ? AND drained = 0 LIMIT 1"
|
|
@@ -43508,7 +43748,7 @@ Next step: ${nextStep}`;
|
|
|
43508
43748
|
requeueDrainedPendingEventByFingerprint(meshId, fingerprint) {
|
|
43509
43749
|
if (!fingerprint) return false;
|
|
43510
43750
|
const changes = this.db.prepare(
|
|
43511
|
-
`UPDATE mesh_pending_events SET drained = 0, drained_at = NULL
|
|
43751
|
+
`UPDATE mesh_pending_events SET drained = 0, drained_at = NULL, drained_by = NULL
|
|
43512
43752
|
WHERE mesh_id = ? AND fingerprint = ? AND drained = 1`
|
|
43513
43753
|
).run(meshId, fingerprint).changes;
|
|
43514
43754
|
if (changes > 0) this.maybeCheckpointWal();
|
|
@@ -54047,6 +54287,77 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
54047
54287
|
]);
|
|
54048
54288
|
}
|
|
54049
54289
|
});
|
|
54290
|
+
function normalizeLiteral(model) {
|
|
54291
|
+
return model.toLowerCase().replace(/[_/\\().,]+/g, " ").replace(/-+/g, " ").replace(/\s+/g, " ").trim();
|
|
54292
|
+
}
|
|
54293
|
+
function canonicalizeModelName(model) {
|
|
54294
|
+
if (typeof model !== "string") return void 0;
|
|
54295
|
+
const literal2 = normalizeLiteral(model);
|
|
54296
|
+
if (!literal2) return void 0;
|
|
54297
|
+
const tokens = literal2.split(" ").filter((t) => t && !MODIFIER_WORDS.has(t));
|
|
54298
|
+
const family = CLAUDE_FAMILIES.find((f) => tokens.includes(f));
|
|
54299
|
+
let version2;
|
|
54300
|
+
if (family) {
|
|
54301
|
+
const after = tokens.slice(tokens.indexOf(family) + 1).filter((t) => /^\d+$/.test(t));
|
|
54302
|
+
if (after.length) version2 = after.join(".");
|
|
54303
|
+
else {
|
|
54304
|
+
const dotted = tokens.find((t) => /^\d+(\.\d+)+$/.test(t));
|
|
54305
|
+
if (dotted) version2 = dotted;
|
|
54306
|
+
}
|
|
54307
|
+
}
|
|
54308
|
+
return { family, version: version2, literal: literal2 };
|
|
54309
|
+
}
|
|
54310
|
+
function modelNamesEquivalent(a, b) {
|
|
54311
|
+
const ca = canonicalizeModelName(a);
|
|
54312
|
+
const cb = canonicalizeModelName(b);
|
|
54313
|
+
if (!ca || !cb) return false;
|
|
54314
|
+
if (ca.family && cb.family) {
|
|
54315
|
+
if (ca.family !== cb.family) return false;
|
|
54316
|
+
if (ca.version && cb.version) return ca.version === cb.version;
|
|
54317
|
+
return true;
|
|
54318
|
+
}
|
|
54319
|
+
if (ca.family || cb.family) return false;
|
|
54320
|
+
return ca.literal === cb.literal;
|
|
54321
|
+
}
|
|
54322
|
+
function isModelAllowedBySlot(model, slot) {
|
|
54323
|
+
if (!slot) return true;
|
|
54324
|
+
const declared = typeof slot.model === "string" ? slot.model.trim() : "";
|
|
54325
|
+
const requested = typeof model === "string" ? model.trim() : "";
|
|
54326
|
+
if (!declared) return !requested;
|
|
54327
|
+
if (!requested) return true;
|
|
54328
|
+
return modelNamesEquivalent(requested, declared);
|
|
54329
|
+
}
|
|
54330
|
+
function decideSlotForModel(input) {
|
|
54331
|
+
const { requestedModel, slots } = input;
|
|
54332
|
+
const declaring = slots.filter((s2) => isModelAllowedBySlot(requestedModel, s2.slot));
|
|
54333
|
+
if (!declaring.length) {
|
|
54334
|
+
const declaredModels = slots.map((s2) => typeof s2.slot.model === "string" && s2.slot.model.trim() ? s2.slot.model.trim() : "(provider default)").filter((v, i, a) => a.indexOf(v) === i);
|
|
54335
|
+
return { outcome: "notify", reason: SLOT_MODEL_ABSENT_SKIP_REASON, declaredModels };
|
|
54336
|
+
}
|
|
54337
|
+
const free = declaring.find((s2) => s2.available);
|
|
54338
|
+
if (free) {
|
|
54339
|
+
const declared = typeof free.slot.model === "string" && free.slot.model.trim() ? free.slot.model.trim() : void 0;
|
|
54340
|
+
return { outcome: "run", slot: free.slot, model: declared };
|
|
54341
|
+
}
|
|
54342
|
+
return {
|
|
54343
|
+
outcome: "wait",
|
|
54344
|
+
reason: SLOT_MODEL_BUSY_SKIP_REASON,
|
|
54345
|
+
busySlots: declaring.map((s2) => s2.slot)
|
|
54346
|
+
};
|
|
54347
|
+
}
|
|
54348
|
+
var CLAUDE_FAMILIES;
|
|
54349
|
+
var MODIFIER_WORDS;
|
|
54350
|
+
var SLOT_MODEL_BUSY_SKIP_REASON;
|
|
54351
|
+
var SLOT_MODEL_ABSENT_SKIP_REASON;
|
|
54352
|
+
var init_slot_model_enforcement = __esm2({
|
|
54353
|
+
"src/mesh/slot-model-enforcement.ts"() {
|
|
54354
|
+
"use strict";
|
|
54355
|
+
CLAUDE_FAMILIES = ["opus", "sonnet", "haiku"];
|
|
54356
|
+
MODIFIER_WORDS = /* @__PURE__ */ new Set(["thinking", "latest", "preview", "claude", "anthropic"]);
|
|
54357
|
+
SLOT_MODEL_BUSY_SKIP_REASON = "slot_for_model_busy";
|
|
54358
|
+
SLOT_MODEL_ABSENT_SKIP_REASON = "no_slot_declares_requested_model";
|
|
54359
|
+
}
|
|
54360
|
+
});
|
|
54050
54361
|
function encodeDuplicateMeshDispatchCode(holderSessionId) {
|
|
54051
54362
|
const holder = typeof holderSessionId === "string" ? holderSessionId.trim() : "";
|
|
54052
54363
|
return holder ? `${DUPLICATE_MESH_DISPATCH_CODE}:${holder}` : DUPLICATE_MESH_DISPATCH_CODE;
|
|
@@ -54111,11 +54422,34 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
54111
54422
|
if (!workspace) return null;
|
|
54112
54423
|
try {
|
|
54113
54424
|
const result = loadRepoMeshJsonConfig(workspace);
|
|
54114
|
-
|
|
54425
|
+
if (result.sourceType !== "repo_file" || !result.config) return null;
|
|
54426
|
+
if (!isConfigPathInsideWorkspace(result.path, workspace)) return null;
|
|
54427
|
+
return result.config;
|
|
54115
54428
|
} catch {
|
|
54116
54429
|
return null;
|
|
54117
54430
|
}
|
|
54118
54431
|
}
|
|
54432
|
+
function isConfigPathInsideWorkspace(configPath, workspace) {
|
|
54433
|
+
if (typeof configPath !== "string" || !configPath) return false;
|
|
54434
|
+
const toPosix = (value) => value.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
54435
|
+
const ws = toPosix(workspace);
|
|
54436
|
+
const target = toPosix(configPath);
|
|
54437
|
+
return !!ws && (target === ws || target.startsWith(`${ws}/`));
|
|
54438
|
+
}
|
|
54439
|
+
function warnUnreadableRepoConfigForNode(node, providerType) {
|
|
54440
|
+
const workspace = typeof node?.workspace === "string" && node.workspace.trim() ? node.workspace.trim() : "";
|
|
54441
|
+
if (!workspace) return;
|
|
54442
|
+
const nodeId = readNonEmptyString(node?.id) || readNonEmptyString(node?.nodeId) || "unknown-node";
|
|
54443
|
+
LOG2.warn(
|
|
54444
|
+
"MeshQueue",
|
|
54445
|
+
`repo mesh.json unreadable from this daemon for node=${nodeId} workspace=${workspace} provider=${providerType || "unknown"} \u2014 delegated auto-approve MODE falls back to the provider default here; the worker daemon re-resolves it from its own checkout at launch`
|
|
54446
|
+
);
|
|
54447
|
+
}
|
|
54448
|
+
function delegatedWorkerAutoApproveSettingsForNode(mesh, node, provider, providerType) {
|
|
54449
|
+
const repoConfig = loadRepoConfigForNode(node);
|
|
54450
|
+
if (!repoConfig) warnUnreadableRepoConfigForNode(node, providerType);
|
|
54451
|
+
return delegatedWorkerAutoApproveSettings(mesh?.policy, node?.policy, provider, repoConfig, providerType);
|
|
54452
|
+
}
|
|
54119
54453
|
function getMeshWithCache(components, meshId) {
|
|
54120
54454
|
const localMesh = getMesh(meshId);
|
|
54121
54455
|
const cachedMesh = components.router?.getCachedInlineMesh(meshId);
|
|
@@ -54395,7 +54729,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
54395
54729
|
return false;
|
|
54396
54730
|
}
|
|
54397
54731
|
const capabilityTags = buildMeshNodeCapabilityTags(node, providerType);
|
|
54398
|
-
const providerMaxParallel = resolveProviderMaxParallel(resolveNodeCapabilitySlots(node), providerType);
|
|
54732
|
+
const providerMaxParallel = resolveProviderMaxParallel(resolveNodeCapabilitySlots(node, meshId), providerType);
|
|
54399
54733
|
const nodeIsWorktree = node?.isLocalWorktree === true;
|
|
54400
54734
|
const assignedTranscriptProfile = resolveClaimingSessionTranscriptProfile(components, sessionId);
|
|
54401
54735
|
const task = claimNextTask(meshId, nodeId, sessionId, capabilityTags, {
|
|
@@ -54532,11 +54866,10 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
54532
54866
|
meshNodeFor: meshId,
|
|
54533
54867
|
meshNodeId: nodeId,
|
|
54534
54868
|
launchedByCoordinator: true,
|
|
54535
|
-
...
|
|
54536
|
-
mesh
|
|
54537
|
-
node
|
|
54869
|
+
...delegatedWorkerAutoApproveSettingsForNode(
|
|
54870
|
+
mesh,
|
|
54871
|
+
node,
|
|
54538
54872
|
components.providerLoader?.getMeta(providerType),
|
|
54539
|
-
loadRepoConfigForNode(node),
|
|
54540
54873
|
providerType
|
|
54541
54874
|
),
|
|
54542
54875
|
...localDaemonId ? { meshCoordinatorDaemonId: localDaemonId } : {},
|
|
@@ -54696,6 +55029,10 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
54696
55029
|
summary: "the node's workspace is dirty, so auto-launch is blocked to avoid clobbering uncommitted changes",
|
|
54697
55030
|
nextAction: "Clean or commit the node's working tree (or fast-forward it); the task will then auto-assign."
|
|
54698
55031
|
};
|
|
55032
|
+
if (reason === SLOT_MODEL_ABSENT_SKIP_REASON) return {
|
|
55033
|
+
summary: "no capability slot on the node declares the model this task resolved to (its difficulty\u2192brain preset picked a model the node was never configured to run)",
|
|
55034
|
+
nextAction: "Re-enqueue with a difficulty/model the node's slots declare, target a node that declares this model, or add a slot for it. The task is NOT run on a substitute model \u2014 an undeclared model is never launched."
|
|
55035
|
+
};
|
|
54699
55036
|
return {
|
|
54700
55037
|
summary: `it cannot be dispatched (${reason})`,
|
|
54701
55038
|
nextAction: "Inspect the node/mesh state with mesh_status and resolve the blocker, or re-enqueue the task."
|
|
@@ -54887,8 +55224,8 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
54887
55224
|
}
|
|
54888
55225
|
return score;
|
|
54889
55226
|
}
|
|
54890
|
-
function bestSlotForTask(node, task) {
|
|
54891
|
-
const slots = resolveNodeCapabilitySlots(node);
|
|
55227
|
+
function bestSlotForTask(node, task, meshId) {
|
|
55228
|
+
const slots = resolveNodeCapabilitySlots(node, meshId);
|
|
54892
55229
|
if (!slots.length) return null;
|
|
54893
55230
|
let best = null;
|
|
54894
55231
|
for (const slot of slots) {
|
|
@@ -54897,8 +55234,8 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
54897
55234
|
}
|
|
54898
55235
|
return best;
|
|
54899
55236
|
}
|
|
54900
|
-
function nodeFitnessForTask(node, task) {
|
|
54901
|
-
return bestSlotForTask(node, task)?.score ?? 0;
|
|
55237
|
+
function nodeFitnessForTask(node, task, meshId) {
|
|
55238
|
+
return bestSlotForTask(node, task, meshId)?.score ?? 0;
|
|
54902
55239
|
}
|
|
54903
55240
|
function orderEligibleNodes(meshId, strategy, nodes, opts) {
|
|
54904
55241
|
if (strategy === "first_eligible" || nodes.length <= 1) {
|
|
@@ -54907,7 +55244,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
54907
55244
|
if (strategy === "fitness" && opts?.task) {
|
|
54908
55245
|
const task = opts.task;
|
|
54909
55246
|
return [...nodes].sort((a, b) => {
|
|
54910
|
-
const fitDelta = nodeFitnessForTask(b.node, task) - nodeFitnessForTask(a.node, task);
|
|
55247
|
+
const fitDelta = nodeFitnessForTask(b.node, task, meshId) - nodeFitnessForTask(a.node, task, meshId);
|
|
54911
55248
|
if (fitDelta !== 0) return fitDelta;
|
|
54912
55249
|
const prioDelta = resolveNodeSchedulingPriority(b.node?.policy) - resolveNodeSchedulingPriority(a.node?.policy);
|
|
54913
55250
|
if (prioDelta !== 0) return prioDelta;
|
|
@@ -54936,6 +55273,13 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
54936
55273
|
function activeProviderAssignedCount(meshId, nodeId, providerType) {
|
|
54937
55274
|
return getQueue(meshId, { status: ["assigned"] }).filter((task) => daemonIdsEquivalent(task.assignedNodeId, nodeId) && task.assignedProviderType === providerType).length;
|
|
54938
55275
|
}
|
|
55276
|
+
function slotHasCapacity(meshId, nodeId, node, slot) {
|
|
55277
|
+
const providerType = typeof slot.provider === "string" ? slot.provider.trim() : "";
|
|
55278
|
+
if (!providerType) return false;
|
|
55279
|
+
const cap = resolveProviderMaxParallel(resolveNodeCapabilitySlots(node, meshId), providerType);
|
|
55280
|
+
if (cap === void 0) return true;
|
|
55281
|
+
return activeProviderAssignedCount(meshId, nodeId, providerType) < cap;
|
|
55282
|
+
}
|
|
54939
55283
|
function sessionHasActiveAssignment(meshId, sessionId) {
|
|
54940
55284
|
if (getQueue(meshId, { status: ["assigned"] }).some((task) => sessionIdsEquivalent(task.assignedSessionId, sessionId))) {
|
|
54941
55285
|
return true;
|
|
@@ -55073,10 +55417,10 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
55073
55417
|
retractActionableSkipIfPreviouslyNotified(meshId, taskId);
|
|
55074
55418
|
}
|
|
55075
55419
|
}
|
|
55076
|
-
async function resolveUsableProvider(components, nodeId, node, requiredTags, task) {
|
|
55420
|
+
async function resolveUsableProvider(components, nodeId, node, meshId, requiredTags, task) {
|
|
55077
55421
|
const providerLoader = components.providerLoader;
|
|
55078
55422
|
if (!providerLoader) return { reason: "provider_loader_unavailable" };
|
|
55079
|
-
const slots = resolveNodeCapabilitySlots(node);
|
|
55423
|
+
const slots = resolveNodeCapabilitySlots(node, meshId);
|
|
55080
55424
|
if (!slots.length) return { reason: "missing_provider_priority" };
|
|
55081
55425
|
const orderedSlots = task ? [...slots].sort((a, b) => scoreSlotForTask(b, task) - scoreSlotForTask(a, task)) : slots;
|
|
55082
55426
|
const failed = [];
|
|
@@ -55110,7 +55454,12 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
55110
55454
|
return {
|
|
55111
55455
|
providerType: normalizedType,
|
|
55112
55456
|
...slot.model ? { model: slot.model } : {},
|
|
55113
|
-
...slot.thinkingLevel ? { thinkingLevel: slot.thinkingLevel } : {}
|
|
55457
|
+
...slot.thinkingLevel ? { thinkingLevel: slot.thinkingLevel } : {},
|
|
55458
|
+
// The slot that won selection. Returned so the caller can enforce
|
|
55459
|
+
// "the launch model must be one this slot declares" — a preset
|
|
55460
|
+
// model must not widen what the operator configured. See
|
|
55461
|
+
// slot-model-enforcement.ts.
|
|
55462
|
+
slot
|
|
55114
55463
|
};
|
|
55115
55464
|
}
|
|
55116
55465
|
failed.push(`${requestedType}: not detected`);
|
|
@@ -55247,7 +55596,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
55247
55596
|
if (task.targetNodeId && !meshNodeIdMatches(node, task.targetNodeId)) return false;
|
|
55248
55597
|
if (task.taskMode === "convergence" && node?.isLocalWorktree === true) return false;
|
|
55249
55598
|
if (task.requiredTags?.length) {
|
|
55250
|
-
const slotProviders = resolveNodeCapabilitySlots(node).map((s2) => s2.provider).filter(Boolean);
|
|
55599
|
+
const slotProviders = resolveNodeCapabilitySlots(node, meshId).map((s2) => s2.provider).filter(Boolean);
|
|
55251
55600
|
const priorities = slotProviders.length ? slotProviders : normalizeProviderPriority2(node?.policy);
|
|
55252
55601
|
const providerCandidates = priorities.length ? priorities : [void 0];
|
|
55253
55602
|
return providerCandidates.some(
|
|
@@ -55336,18 +55685,36 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
55336
55685
|
}
|
|
55337
55686
|
autoLaunchInProgress.add(launchKey);
|
|
55338
55687
|
try {
|
|
55339
|
-
const resolved = await resolveUsableProvider(components, nodeId, node, task.requiredTags, { difficulty: task.difficulty, requiredTags: task.requiredTags });
|
|
55688
|
+
const resolved = await resolveUsableProvider(components, nodeId, node, meshId, task.requiredTags, { difficulty: task.difficulty, requiredTags: task.requiredTags });
|
|
55340
55689
|
if (!resolved.providerType) {
|
|
55341
55690
|
markSkip(nodeId, resolved.reason || "provider_unusable");
|
|
55342
55691
|
continue;
|
|
55343
55692
|
}
|
|
55344
|
-
const
|
|
55693
|
+
const requestedModel = typeof task.model === "string" && task.model.trim() ? task.model.trim() : resolved.model;
|
|
55345
55694
|
const effectiveThinkingLevel = typeof task.thinkingLevel === "string" && task.thinkingLevel.trim() ? task.thinkingLevel.trim() : resolved.thinkingLevel;
|
|
55695
|
+
const slotDecision = decideSlotForModel({
|
|
55696
|
+
requestedModel,
|
|
55697
|
+
slots: resolveNodeCapabilitySlots(node, meshId).map((slot) => ({
|
|
55698
|
+
slot,
|
|
55699
|
+
available: slotHasCapacity(meshId, nodeId, node, slot)
|
|
55700
|
+
}))
|
|
55701
|
+
});
|
|
55702
|
+
if (slotDecision.outcome === "wait") {
|
|
55703
|
+
LOG2.info("MeshQueue", `SLOT MODEL GUARD: model '${requestedModel}' is declared on node ${nodeId} but every matching slot is at its maxParallel cap (task ${task.id}); leaving the task queued until a slot goes idle`);
|
|
55704
|
+
markSkip(nodeId, slotDecision.reason, { providerType: resolved.providerType });
|
|
55705
|
+
continue;
|
|
55706
|
+
}
|
|
55707
|
+
if (slotDecision.outcome === "notify") {
|
|
55708
|
+
LOG2.warn("MeshQueue", `SLOT MODEL GUARD: no slot on node ${nodeId} declares model '${requestedModel}' (declared: ${slotDecision.declaredModels.join(", ") || "none"}) for task ${task.id}; not launching \u2014 surfacing to the coordinator to re-drive`);
|
|
55709
|
+
markSkip(nodeId, slotDecision.reason, { providerType: resolved.providerType });
|
|
55710
|
+
continue;
|
|
55711
|
+
}
|
|
55712
|
+
const rawEffectiveModel = slotDecision.model;
|
|
55346
55713
|
const effectiveModel = isModelCompatibleWithProvider(rawEffectiveModel, resolved.providerType) ? rawEffectiveModel : void 0;
|
|
55347
55714
|
if (rawEffectiveModel && effectiveModel === void 0) {
|
|
55348
55715
|
LOG2.info("MeshQueue", `CODEX-400 GUARD: dropped incompatible launch model '${rawEffectiveModel}' for non-Anthropic provider '${resolved.providerType}' on node ${nodeId} (task ${task.id}); provider will use its own default model`);
|
|
55349
55716
|
}
|
|
55350
|
-
const providerCap = resolveProviderMaxParallel(resolveNodeCapabilitySlots(node), resolved.providerType);
|
|
55717
|
+
const providerCap = resolveProviderMaxParallel(resolveNodeCapabilitySlots(node, meshId), resolved.providerType);
|
|
55351
55718
|
if (providerCap !== void 0 && activeProviderAssignedCount(meshId, nodeId, resolved.providerType) >= providerCap) {
|
|
55352
55719
|
markSkip(nodeId, "max_provider_parallel_reached", { providerType: resolved.providerType });
|
|
55353
55720
|
continue;
|
|
@@ -55361,11 +55728,10 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
55361
55728
|
// Coordinator-dispatched worker: auto-approve unless mesh/node policy
|
|
55362
55729
|
// opts out (default true). Lands in settingsOverride and beats the
|
|
55363
55730
|
// global per-provider-type boolean/mode through explicit opposite-key clearing.
|
|
55364
|
-
...
|
|
55365
|
-
mesh
|
|
55366
|
-
node
|
|
55731
|
+
...delegatedWorkerAutoApproveSettingsForNode(
|
|
55732
|
+
mesh,
|
|
55733
|
+
node,
|
|
55367
55734
|
components.providerLoader?.getMeta(resolved.providerType),
|
|
55368
|
-
loadRepoConfigForNode(node),
|
|
55369
55735
|
resolved.providerType
|
|
55370
55736
|
),
|
|
55371
55737
|
launchedByCoordinator: true,
|
|
@@ -55441,7 +55807,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
55441
55807
|
const requiredTags = Array.isArray(task.requiredTags) ? task.requiredTags.filter((t) => !!t) : [];
|
|
55442
55808
|
const routingDecision = {
|
|
55443
55809
|
source: "autoLaunch",
|
|
55444
|
-
fitnessScore: nodeFitnessForTask(node, { difficulty: task.difficulty, requiredTags: task.requiredTags }),
|
|
55810
|
+
fitnessScore: nodeFitnessForTask(node, { difficulty: task.difficulty, requiredTags: task.requiredTags }, meshId),
|
|
55445
55811
|
...skippedCandidates.length ? { skippedCandidates } : {},
|
|
55446
55812
|
requiredTagsResult: {
|
|
55447
55813
|
required: requiredTags,
|
|
@@ -55885,6 +56251,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
55885
56251
|
init_mesh_clone_grace();
|
|
55886
56252
|
init_mesh_task_inflight();
|
|
55887
56253
|
init_model_provider_compat();
|
|
56254
|
+
init_slot_model_enforcement();
|
|
55888
56255
|
init_mesh_turn_ledger();
|
|
55889
56256
|
init_mesh_duplicate_dispatch();
|
|
55890
56257
|
IDLE_AUTO_FAST_FORWARD_THROTTLE_MS = 30 * 60 * 1e3;
|
|
@@ -55917,7 +56284,13 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
55917
56284
|
"provider_loader_unavailable",
|
|
55918
56285
|
"provider_priority_unusable",
|
|
55919
56286
|
"provider_unusable",
|
|
55920
|
-
"dirty_workspace"
|
|
56287
|
+
"dirty_workspace",
|
|
56288
|
+
// SLOT MODEL GUARD (absent): no slot on the node declares the task's model.
|
|
56289
|
+
// Permanent — no amount of waiting produces a slot, so the coordinator must
|
|
56290
|
+
// re-drive (adjust difficulty, target another node, ask the owner). Its
|
|
56291
|
+
// busy counterpart SLOT_MODEL_BUSY_SKIP_REASON is deliberately NOT listed:
|
|
56292
|
+
// that one clears on its own when the slot goes idle.
|
|
56293
|
+
SLOT_MODEL_ABSENT_SKIP_REASON
|
|
55921
56294
|
];
|
|
55922
56295
|
TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON = "target_node_bootstrap_pending";
|
|
55923
56296
|
lastActionableSkipNotified = /* @__PURE__ */ new Map();
|
|
@@ -61308,7 +61681,15 @@ ${cleanBody}`;
|
|
|
61308
61681
|
try {
|
|
61309
61682
|
pendingEvents = drainPendingMeshCoordinatorEvents(
|
|
61310
61683
|
meshId,
|
|
61311
|
-
drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId
|
|
61684
|
+
drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId,
|
|
61685
|
+
{
|
|
61686
|
+
// AMBIGUOUS-UNICAST guard (REFINE-EVENT-SESSION-SCOPED-UNICAST): observability
|
|
61687
|
+
// only — it warns when a session-less unicast event is delivered while several
|
|
61688
|
+
// coordinator sessions are live and racing for it. Never changes delivery, so
|
|
61689
|
+
// an event can't be stranded by it. targetCoordinators is this daemon's live
|
|
61690
|
+
// coordinator set for the mesh, which is exactly the racing population.
|
|
61691
|
+
countLiveCoordinatorSessions: () => new Set(targetCoordinators.map((c) => c.sessionId).filter(Boolean)).size
|
|
61692
|
+
}
|
|
61312
61693
|
);
|
|
61313
61694
|
} catch (e) {
|
|
61314
61695
|
LOG2.warn("MeshReconcile", `Drain failed for mesh ${meshId}: ${e?.message || e}`);
|
|
@@ -71152,6 +71533,7 @@ ${lastSnapshot}`;
|
|
|
71152
71533
|
buildChatMessageSignature: () => buildChatMessageSignature,
|
|
71153
71534
|
buildChatTailDeliverySignature: () => buildChatTailDeliverySignature,
|
|
71154
71535
|
buildClaudeInteractiveToolResult: () => buildClaudeInteractiveToolResult,
|
|
71536
|
+
buildCloudStatusReportPayload: () => buildCloudStatusReportPayload,
|
|
71155
71537
|
buildCompactStaleDirectWorkSummary: () => buildCompactStaleDirectWorkSummary,
|
|
71156
71538
|
buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt,
|
|
71157
71539
|
buildIdleReminderMessage: () => buildIdleReminderMessage,
|
|
@@ -71451,6 +71833,7 @@ ${lastSnapshot}`;
|
|
|
71451
71833
|
resolveNotBefore: () => resolveNotBefore,
|
|
71452
71834
|
resolveProviderChannel: () => resolveProviderChannel,
|
|
71453
71835
|
resolveProviderMaxParallel: () => resolveProviderMaxParallel,
|
|
71836
|
+
resolveScopedMeshId: () => resolveScopedMeshId,
|
|
71454
71837
|
resolveSessionHostAppName: () => resolveSessionHostAppName,
|
|
71455
71838
|
resolveSessionHostAppNameResolution: () => resolveSessionHostAppNameResolution2,
|
|
71456
71839
|
resolveSessionTurnPresentation: () => resolveSessionTurnPresentation,
|
|
@@ -73026,7 +73409,7 @@ ${lastSnapshot}`;
|
|
|
73026
73409
|
const bootstrapLoaded = loadMeshWorktreeBootstrapConfig(mesh, workspace);
|
|
73027
73410
|
let magiKindPanels = {};
|
|
73028
73411
|
try {
|
|
73029
|
-
magiKindPanels = listMagiKindPanelsReadOnly();
|
|
73412
|
+
magiKindPanels = listMagiKindPanelsReadOnly(typeof mesh?.id === "string" ? mesh.id : void 0);
|
|
73030
73413
|
} catch {
|
|
73031
73414
|
magiKindPanels = {};
|
|
73032
73415
|
}
|
|
@@ -85484,6 +85867,84 @@ ${body}
|
|
|
85484
85867
|
init_hash();
|
|
85485
85868
|
init_coordinator_registry();
|
|
85486
85869
|
init_mesh_duplicate_dispatch();
|
|
85870
|
+
init_mesh_json_config();
|
|
85871
|
+
init_logger();
|
|
85872
|
+
init_repo_mesh_types();
|
|
85873
|
+
function resolveDelegatedWorkerAutoApproveModeForLaunch(input) {
|
|
85874
|
+
const settings = input.settings;
|
|
85875
|
+
const envelopeMode = typeof settings?.autoApproveMode === "string" && settings.autoApproveMode.trim() ? settings.autoApproveMode.trim() : void 0;
|
|
85876
|
+
if (settings?.launchedByCoordinator !== true) {
|
|
85877
|
+
return { autoApproveMode: envelopeMode, changed: false, source: "not_delegated" };
|
|
85878
|
+
}
|
|
85879
|
+
if (settings.autoApprove === false) {
|
|
85880
|
+
return { autoApproveMode: void 0, changed: false, source: "enable_gate_off" };
|
|
85881
|
+
}
|
|
85882
|
+
const providerType = typeof input.providerType === "string" ? input.providerType.trim() : "";
|
|
85883
|
+
if (!providerType || !input.provider?.autoApproveModes) {
|
|
85884
|
+
return { autoApproveMode: envelopeMode, changed: false, source: "no_provider_modes" };
|
|
85885
|
+
}
|
|
85886
|
+
const workspace = typeof input.workspace === "string" ? input.workspace.trim() : "";
|
|
85887
|
+
if (!workspace) {
|
|
85888
|
+
return { autoApproveMode: envelopeMode, changed: false, source: "no_repo_config" };
|
|
85889
|
+
}
|
|
85890
|
+
let repoConfig = null;
|
|
85891
|
+
try {
|
|
85892
|
+
const result = loadRepoMeshJsonConfig(workspace);
|
|
85893
|
+
const fromThisWorkspace = result.sourceType === "repo_file" && typeof result.path === "string" && isPathInsideWorkspace(result.path, workspace);
|
|
85894
|
+
repoConfig = fromThisWorkspace && result.config ? result.config : null;
|
|
85895
|
+
} catch {
|
|
85896
|
+
repoConfig = null;
|
|
85897
|
+
}
|
|
85898
|
+
const requestedMode = repoConfig?.providerDefaults?.autoApproveModes?.[providerType];
|
|
85899
|
+
const requestedModeId = typeof requestedMode === "string" && requestedMode.trim() ? requestedMode.trim() : "";
|
|
85900
|
+
if (!requestedModeId) {
|
|
85901
|
+
return { autoApproveMode: envelopeMode, changed: false, source: "no_repo_config" };
|
|
85902
|
+
}
|
|
85903
|
+
const dangerousAllowed = settings.delegatedWorkerDangerousModeAllow === true;
|
|
85904
|
+
const resolved = resolveDelegatedWorkerAutoApprove(
|
|
85905
|
+
{ delegatedWorkerAutoApprove: true, delegatedWorkerDangerousModeAllow: dangerousAllowed },
|
|
85906
|
+
void 0,
|
|
85907
|
+
input.provider,
|
|
85908
|
+
repoConfig,
|
|
85909
|
+
providerType
|
|
85910
|
+
);
|
|
85911
|
+
if (typeof resolved !== "string") {
|
|
85912
|
+
return { autoApproveMode: envelopeMode, changed: false, source: "no_repo_config" };
|
|
85913
|
+
}
|
|
85914
|
+
return {
|
|
85915
|
+
autoApproveMode: resolved,
|
|
85916
|
+
changed: resolved !== envelopeMode,
|
|
85917
|
+
source: "worker_repo_file"
|
|
85918
|
+
};
|
|
85919
|
+
}
|
|
85920
|
+
function isPathInsideWorkspace(configPath, workspace) {
|
|
85921
|
+
const normalize4 = (value) => value.replace(/[\\/]+$/, "");
|
|
85922
|
+
const ws = normalize4(workspace);
|
|
85923
|
+
if (!ws) return false;
|
|
85924
|
+
const separatorAgnostic = (value) => value.replace(/\\/g, "/");
|
|
85925
|
+
const normalizedPath = separatorAgnostic(configPath);
|
|
85926
|
+
const normalizedWs = separatorAgnostic(ws);
|
|
85927
|
+
return normalizedPath === normalizedWs || normalizedPath.startsWith(`${normalizedWs}/`);
|
|
85928
|
+
}
|
|
85929
|
+
function logDelegatedWorkerModeDelivery(resolution, context) {
|
|
85930
|
+
if (resolution.source !== "worker_repo_file" && resolution.source !== "no_repo_config") return;
|
|
85931
|
+
const node = context.meshNodeId || "unknown-node";
|
|
85932
|
+
const workspace = context.workspace || "unknown-workspace";
|
|
85933
|
+
const provider = context.providerType || "unknown-provider";
|
|
85934
|
+
if (resolution.source === "worker_repo_file" && resolution.changed) {
|
|
85935
|
+
LOG2.info(
|
|
85936
|
+
"MeshWorker",
|
|
85937
|
+
`auto-approve mode re-resolved from worker repo config: node=${node} workspace=${workspace} provider=${provider} coordinatorMode=${context.envelopeMode ?? "(none)"} workerMode=${resolution.autoApproveMode}`
|
|
85938
|
+
);
|
|
85939
|
+
return;
|
|
85940
|
+
}
|
|
85941
|
+
if (resolution.source === "no_repo_config" && context.envelopeMode) {
|
|
85942
|
+
LOG2.warn(
|
|
85943
|
+
"MeshWorker",
|
|
85944
|
+
`auto-approve mode NOT confirmed by worker repo config (keeping coordinator value): node=${node} workspace=${workspace} provider=${provider} mode=${context.envelopeMode} \u2014 no readable .adhdev/mesh.json in this workspace`
|
|
85945
|
+
);
|
|
85946
|
+
}
|
|
85947
|
+
}
|
|
85487
85948
|
init_summary_metadata();
|
|
85488
85949
|
var os19 = __toESM2(require("os"));
|
|
85489
85950
|
var crypto5 = __toESM2(require("crypto"));
|
|
@@ -87981,6 +88442,48 @@ ${body}
|
|
|
87981
88442
|
}
|
|
87982
88443
|
return screenText;
|
|
87983
88444
|
}
|
|
88445
|
+
/**
|
|
88446
|
+
* Is `reread` a re-render of the SAME picker page as `landed`?
|
|
88447
|
+
*
|
|
88448
|
+
* Guards the return-pass screenText swap in captureClaudeTuiPrompt, which
|
|
88449
|
+
* replaces a page's entire raw screen and therefore must never be handed a
|
|
88450
|
+
* frame belonging to a different question.
|
|
88451
|
+
*
|
|
88452
|
+
* WHAT WE COMPARE — the question line, via the same parser the capture
|
|
88453
|
+
* itself uses (readFocusedClaudeTuiQuestion). Rationale:
|
|
88454
|
+
* - The question text is the one field that is per-page, always rendered
|
|
88455
|
+
* (it is the parse anchor — a page without it yields no question at all),
|
|
88456
|
+
* and stable across the redraw we are waiting on. The redraw races the
|
|
88457
|
+
* option-row GLYPH COLUMN, not the question line.
|
|
88458
|
+
* - The header is NOT usable on its own: on the headered variant every page
|
|
88459
|
+
* renders the identical nav line, and `page.header` is assigned by index
|
|
88460
|
+
* from that shared line rather than read from the page body — so it is
|
|
88461
|
+
* equal across pages by construction and would accept any frame.
|
|
88462
|
+
* - The option-label set is rejected as the primary key: it is drawn in the
|
|
88463
|
+
* very region that is mid-redraw, and rows can be clipped or scrolled out
|
|
88464
|
+
* of the captured frame (the same truncation that forced the headerless
|
|
88465
|
+
* parser to stop requiring the freeform escape hatch). Comparing it would
|
|
88466
|
+
* reject legitimate repairs — exactly the frames this pass exists to fix.
|
|
88467
|
+
*
|
|
88468
|
+
* STRICTNESS — deliberately asymmetric, because the two error directions are
|
|
88469
|
+
* not equally costly. Wrongly ALLOWING a swap corrupts a question into a
|
|
88470
|
+
* duplicate of another (the reported user-visible defect). Wrongly BLOCKING
|
|
88471
|
+
* one merely leaves the forward-pass capture in place — at worst a
|
|
88472
|
+
* multi-select page stays flagged single-select, which the live status-tick
|
|
88473
|
+
* upgrade (maybeUpgradeClaudeTuiMultiSelect) then repairs anyway. So this
|
|
88474
|
+
* blocks only on POSITIVE EVIDENCE of a different page: if either side fails
|
|
88475
|
+
* to parse we return true and defer to the pre-existing glyph gate, keeping
|
|
88476
|
+
* behaviour identical to before for every frame whose identity we cannot
|
|
88477
|
+
* read. Comparison is whitespace-normalised so a reflow or trailing-pad
|
|
88478
|
+
* difference does not read as a different question.
|
|
88479
|
+
*/
|
|
88480
|
+
claudeTuiPagesLookLikeSameQuestion(landed, reread) {
|
|
88481
|
+
const landedQuestion = readFocusedClaudeTuiQuestion(landed.screenText);
|
|
88482
|
+
const rereadQuestion = readFocusedClaudeTuiQuestion(reread);
|
|
88483
|
+
if (!landedQuestion || !rereadQuestion) return true;
|
|
88484
|
+
const normalize4 = (text) => text.replace(/\s+/g, " ").trim();
|
|
88485
|
+
return normalize4(landedQuestion.question) === normalize4(rereadQuestion.question);
|
|
88486
|
+
}
|
|
87984
88487
|
async captureClaudeTuiPrompt(firstScreen, headers) {
|
|
87985
88488
|
const pages = [{ screenText: firstScreen, header: headers[0] }];
|
|
87986
88489
|
for (let index = 1; index < headers.length; index += 1) {
|
|
@@ -87993,7 +88496,7 @@ ${body}
|
|
|
87993
88496
|
await new Promise((resolve29) => setTimeout(resolve29, _SpecCliAdapter.CLAUDE_TUI_PAGE_POLL_INTERVAL_MS));
|
|
87994
88497
|
const reread = await this.snapshotSettledClaudeTuiPage();
|
|
87995
88498
|
const landed = pages[index - 1];
|
|
87996
|
-
if (landed && !detectClaudeTuiMultiSelect(landed.screenText) && detectClaudeTuiMultiSelect(reread)) {
|
|
88499
|
+
if (landed && !detectClaudeTuiMultiSelect(landed.screenText) && detectClaudeTuiMultiSelect(reread) && this.claudeTuiPagesLookLikeSameQuestion(landed, reread)) {
|
|
87997
88500
|
landed.screenText = reread;
|
|
87998
88501
|
}
|
|
87999
88502
|
}
|
|
@@ -94794,7 +95297,29 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
94794
95297
|
if (!cliType) throw new Error("cliType required");
|
|
94795
95298
|
const providerType = this.providerLoader.resolveAlias(cliType);
|
|
94796
95299
|
const provLookup = this.providerLoader.getMeta(providerType);
|
|
94797
|
-
|
|
95300
|
+
let settingsOverride = args?.settings && typeof args.settings === "object" ? args.settings : void 0;
|
|
95301
|
+
if (settingsOverride?.launchedByCoordinator === true) {
|
|
95302
|
+
const envelopeMode = typeof settingsOverride.autoApproveMode === "string" ? settingsOverride.autoApproveMode : void 0;
|
|
95303
|
+
const modeResolution = resolveDelegatedWorkerAutoApproveModeForLaunch({
|
|
95304
|
+
workspace: dir,
|
|
95305
|
+
providerType,
|
|
95306
|
+
provider: provLookup,
|
|
95307
|
+
settings: settingsOverride
|
|
95308
|
+
});
|
|
95309
|
+
logDelegatedWorkerModeDelivery(modeResolution, {
|
|
95310
|
+
workspace: dir,
|
|
95311
|
+
providerType,
|
|
95312
|
+
meshNodeId: typeof settingsOverride.meshNodeId === "string" ? settingsOverride.meshNodeId : void 0,
|
|
95313
|
+
envelopeMode
|
|
95314
|
+
});
|
|
95315
|
+
if (modeResolution.changed && modeResolution.autoApproveMode) {
|
|
95316
|
+
settingsOverride = {
|
|
95317
|
+
...settingsOverride,
|
|
95318
|
+
autoApproveMode: modeResolution.autoApproveMode,
|
|
95319
|
+
autoApprove: void 0
|
|
95320
|
+
};
|
|
95321
|
+
}
|
|
95322
|
+
}
|
|
94798
95323
|
const delegatedLaunch = settingsOverride?.launchedByCoordinator === true ? buildCoordinatorDelegatedCliLaunchOptions({
|
|
94799
95324
|
cliType,
|
|
94800
95325
|
workspace: dir,
|
|
@@ -100893,7 +101418,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
100893
101418
|
}
|
|
100894
101419
|
return { success: true, mesh: meshRecord.mesh, sourceOfTruth };
|
|
100895
101420
|
},
|
|
100896
|
-
create_mesh: async (
|
|
101421
|
+
create_mesh: async (ctx, args) => {
|
|
100897
101422
|
const name = typeof args?.name === "string" ? args.name.trim() : "";
|
|
100898
101423
|
const repoIdentity = typeof args?.repoIdentity === "string" ? args.repoIdentity.trim() : "";
|
|
100899
101424
|
const repoRemoteUrl = typeof args?.repoRemoteUrl === "string" ? args.repoRemoteUrl.trim() : void 0;
|
|
@@ -100902,12 +101427,71 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
100902
101427
|
try {
|
|
100903
101428
|
const { createMesh: createMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
100904
101429
|
const meshHost = args?.meshHost && typeof args.meshHost === "object" && !Array.isArray(args.meshHost) ? args.meshHost : void 0;
|
|
100905
|
-
const
|
|
101430
|
+
const requestedHostDaemonId = typeof args?.hostDaemonId === "string" && args.hostDaemonId.trim() ? args.hostDaemonId.trim() : ctx.deps.statusInstanceId || "";
|
|
101431
|
+
const mesh = createMesh2({
|
|
101432
|
+
name,
|
|
101433
|
+
repoIdentity,
|
|
101434
|
+
repoRemoteUrl,
|
|
101435
|
+
defaultBranch,
|
|
101436
|
+
policy: args?.policy,
|
|
101437
|
+
meshHost,
|
|
101438
|
+
...requestedHostDaemonId ? { hostDaemonId: requestedHostDaemonId } : {}
|
|
101439
|
+
});
|
|
100906
101440
|
return { success: true, mesh };
|
|
100907
101441
|
} catch (e) {
|
|
100908
101442
|
return { success: false, error: e.message };
|
|
100909
101443
|
}
|
|
100910
101444
|
},
|
|
101445
|
+
// HOST-PIN-WRITER — establish this mesh's host daemon as a DELIBERATE operator act.
|
|
101446
|
+
//
|
|
101447
|
+
// The dashboard's first-setup flow lets the operator pick which connected daemon
|
|
101448
|
+
// becomes the host; this is the command that actually persists that choice. It is a
|
|
101449
|
+
// separate surface from coordinator launch on purpose: the pin is effectively
|
|
101450
|
+
// permanent ("Fixed when the mesh is created — it cannot be reassigned here"), so it
|
|
101451
|
+
// must not be an incidental side effect of a button whose stated job is launching a
|
|
101452
|
+
// session. A mis-click must not permanently re-home a mesh.
|
|
101453
|
+
//
|
|
101454
|
+
// Reassignment to a DIFFERENT daemon is refused unless the caller passes
|
|
101455
|
+
// force:true — the mutator returns code 'host_already_pinned' and changes nothing.
|
|
101456
|
+
// Re-pinning the same daemon is a no-op, so retries/races are safe.
|
|
101457
|
+
set_mesh_host: async (ctx, args) => {
|
|
101458
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
101459
|
+
const hostDaemonId = typeof args?.hostDaemonId === "string" ? args.hostDaemonId.trim() : "";
|
|
101460
|
+
const hostNodeId = typeof args?.hostNodeId === "string" ? args.hostNodeId.trim() : "";
|
|
101461
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
101462
|
+
if (!hostDaemonId && !hostNodeId) return { success: false, error: "hostDaemonId or hostNodeId required" };
|
|
101463
|
+
try {
|
|
101464
|
+
const { setMeshHostPin: setMeshHostPin2, getMesh: getMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
101465
|
+
const result = setMeshHostPin2(meshId, {
|
|
101466
|
+
...hostDaemonId ? { hostDaemonId } : {},
|
|
101467
|
+
...hostNodeId ? { hostNodeId } : {},
|
|
101468
|
+
force: args?.force === true
|
|
101469
|
+
});
|
|
101470
|
+
if (!result) return { success: false, error: "Mesh not found" };
|
|
101471
|
+
if (!result.applied && result.reason !== "already_pinned_same") {
|
|
101472
|
+
return {
|
|
101473
|
+
success: false,
|
|
101474
|
+
code: result.reason,
|
|
101475
|
+
error: result.reason === "host_already_pinned" ? `Mesh host is already pinned to ${result.hostDaemonId}. Pass force:true to reassign it.` : result.reason === "not_host_role" ? "This daemon joined the mesh as a member; its host lives on the daemon it paired with." : "hostDaemonId or hostNodeId required",
|
|
101476
|
+
meshId,
|
|
101477
|
+
meshHost: resolveMeshHostStatus(result.mesh)
|
|
101478
|
+
};
|
|
101479
|
+
}
|
|
101480
|
+
const fresh = getMesh2(meshId) || result.mesh;
|
|
101481
|
+
if (ctx.getCachedInlineMesh(meshId)) ctx.inlineMeshCache.set(meshId, fresh);
|
|
101482
|
+
ctx.invalidateAggregateMeshStatus(meshId);
|
|
101483
|
+
return {
|
|
101484
|
+
success: true,
|
|
101485
|
+
code: result.reason,
|
|
101486
|
+
meshId,
|
|
101487
|
+
applied: result.applied,
|
|
101488
|
+
meshHost: resolveMeshHostStatus(fresh),
|
|
101489
|
+
mesh: fresh
|
|
101490
|
+
};
|
|
101491
|
+
} catch (e) {
|
|
101492
|
+
return { success: false, error: e.message };
|
|
101493
|
+
}
|
|
101494
|
+
},
|
|
100911
101495
|
update_mesh: async (ctx, args) => {
|
|
100912
101496
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
100913
101497
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
@@ -101184,19 +101768,37 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
101184
101768
|
}
|
|
101185
101769
|
},
|
|
101186
101770
|
// ─── MAGI kind → panel bindings (MAGI-KIND-PANEL, machine-local config) ───
|
|
101187
|
-
// Per-task_kind slot lists in ~/.adhdev/meshes.json
|
|
101188
|
-
// MAGI panel-resolution surface (the former
|
|
101189
|
-
// removed).
|
|
101771
|
+
// Per-task_kind slot lists stored PER MESH in ~/.adhdev/meshes.json
|
|
101772
|
+
// (`meshes[].magiKindPanels`) — the SOLE MAGI panel-resolution surface (the former
|
|
101773
|
+
// named-panel magi_panel_* handlers were removed). `meshId` is optional on all three
|
|
101774
|
+
// so existing callers keep working: it resolves to the sole mesh on a single-mesh
|
|
101775
|
+
// machine, and is REQUIRED (loud error, never a silent pick) when several meshes
|
|
101776
|
+
// exist. Owner-only gating: intentionally NOT listed in
|
|
101190
101777
|
// canPeerUsePrivilegedShareCommand (daemon-cloud data-channel-router), so a peer
|
|
101191
101778
|
// holding ANY share permission hits its `default → false` branch — identical
|
|
101192
101779
|
// owner-only gating to create_mesh / update_mesh / list_meshes. A trusted peer (no
|
|
101193
101780
|
// permission = the owner) passes the top `!permission → true` guard. set/remove are
|
|
101194
101781
|
// WRITE commands; list is read-only. normalizeMagiSlots (inside setMagiKindPanel)
|
|
101195
|
-
// surfaces invalid_magi_kind_panel: … messages verbatim for the editor
|
|
101196
|
-
|
|
101782
|
+
// surfaces invalid_magi_kind_panel: … messages verbatim for the editor, including
|
|
101783
|
+
// a nodeId that is not a member of the target mesh.
|
|
101784
|
+
magi_kind_panel_list: async (_ctx, args) => {
|
|
101785
|
+
const requestedMeshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
101197
101786
|
try {
|
|
101198
|
-
const { listMagiKindPanels: listMagiKindPanels2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
101199
|
-
|
|
101787
|
+
const { listMagiKindPanels: listMagiKindPanels2, resolveScopedMeshId: resolveScopedMeshId2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
101788
|
+
const meshId = requestedMeshId || resolveScopedMeshId2();
|
|
101789
|
+
return {
|
|
101790
|
+
success: true,
|
|
101791
|
+
kindPanels: listMagiKindPanels2(requestedMeshId || void 0),
|
|
101792
|
+
scope: {
|
|
101793
|
+
kind: "mesh",
|
|
101794
|
+
storage: "machine_local",
|
|
101795
|
+
meshId: meshId ?? null,
|
|
101796
|
+
resolvedFrom: requestedMeshId ? "explicit" : meshId ? "sole_mesh" : "ambiguous",
|
|
101797
|
+
...requestedMeshId || meshId ? {} : {
|
|
101798
|
+
note: "Several meshes are configured and no meshId was given, so no panels could be read. Pass meshId."
|
|
101799
|
+
}
|
|
101800
|
+
}
|
|
101801
|
+
};
|
|
101200
101802
|
} catch (e) {
|
|
101201
101803
|
return { success: false, error: e.message };
|
|
101202
101804
|
}
|
|
@@ -101204,10 +101806,12 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
101204
101806
|
magi_kind_panel_set: async (_ctx, args) => {
|
|
101205
101807
|
const kind = typeof args?.kind === "string" ? args.kind.trim() : "";
|
|
101206
101808
|
if (!kind) return { success: false, error: "invalid_magi_kind_panel: task_kind is required" };
|
|
101809
|
+
const requestedMeshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
101207
101810
|
try {
|
|
101208
|
-
const { setMagiKindPanel: setMagiKindPanel2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
101209
|
-
const slots = setMagiKindPanel2(kind, args?.slots);
|
|
101210
|
-
|
|
101811
|
+
const { setMagiKindPanel: setMagiKindPanel2, resolveScopedMeshId: resolveScopedMeshId2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
101812
|
+
const slots = setMagiKindPanel2(kind, args?.slots, requestedMeshId || void 0);
|
|
101813
|
+
const meshId = requestedMeshId || resolveScopedMeshId2();
|
|
101814
|
+
return { success: true, kind, slots, meshId: meshId ?? null };
|
|
101211
101815
|
} catch (e) {
|
|
101212
101816
|
return { success: false, error: e.message };
|
|
101213
101817
|
}
|
|
@@ -101215,30 +101819,52 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
101215
101819
|
magi_kind_panel_remove: async (_ctx, args) => {
|
|
101216
101820
|
const kind = typeof args?.kind === "string" ? args.kind.trim() : "";
|
|
101217
101821
|
if (!kind) return { success: false, error: "invalid_magi_kind_panel: task_kind is required" };
|
|
101822
|
+
const requestedMeshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
101218
101823
|
try {
|
|
101219
|
-
const { removeMagiKindPanel: removeMagiKindPanel2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
101220
|
-
const removed = removeMagiKindPanel2(kind);
|
|
101221
|
-
|
|
101824
|
+
const { removeMagiKindPanel: removeMagiKindPanel2, resolveScopedMeshId: resolveScopedMeshId2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
101825
|
+
const removed = removeMagiKindPanel2(kind, requestedMeshId || void 0);
|
|
101826
|
+
const meshId = requestedMeshId || resolveScopedMeshId2();
|
|
101827
|
+
return { success: true, removed, meshId: meshId ?? null };
|
|
101222
101828
|
} catch (e) {
|
|
101223
101829
|
return { success: false, error: e.message };
|
|
101224
101830
|
}
|
|
101225
101831
|
},
|
|
101226
|
-
// ─── Brain routing: per-difficulty brain presets (machine-local) ───
|
|
101227
|
-
// getDifficultyBrains returns the seeded defaults when
|
|
101228
|
-
// so the editor always shows a usable mapping. set replaces the whole
|
|
101229
|
-
|
|
101832
|
+
// ─── Brain routing: per-difficulty brain presets (PER MESH, machine-local) ───
|
|
101833
|
+
// getDifficultyBrains returns the seeded defaults when the mesh has nothing
|
|
101834
|
+
// configured, so the editor always shows a usable mapping. set replaces the whole
|
|
101835
|
+
// map for ONE mesh. `meshId` is optional and resolves to the sole mesh, so
|
|
101836
|
+
// existing callers keep working; with several meshes a write must name its mesh
|
|
101837
|
+
// (these presets choose the model a task runs on — writing to the wrong mesh
|
|
101838
|
+
// changes what that mesh costs).
|
|
101839
|
+
difficulty_brains_get: async (_ctx, args) => {
|
|
101840
|
+
const requestedMeshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
101230
101841
|
try {
|
|
101231
|
-
const { getDifficultyBrains: getDifficultyBrains2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
101232
|
-
|
|
101842
|
+
const { getDifficultyBrains: getDifficultyBrains2, resolveScopedMeshId: resolveScopedMeshId2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
101843
|
+
const meshId = requestedMeshId || resolveScopedMeshId2();
|
|
101844
|
+
return {
|
|
101845
|
+
success: true,
|
|
101846
|
+
difficultyBrains: getDifficultyBrains2(requestedMeshId || void 0),
|
|
101847
|
+
scope: {
|
|
101848
|
+
kind: "mesh",
|
|
101849
|
+
storage: "machine_local",
|
|
101850
|
+
meshId: meshId ?? null,
|
|
101851
|
+
resolvedFrom: requestedMeshId ? "explicit" : meshId ? "sole_mesh" : "ambiguous",
|
|
101852
|
+
...requestedMeshId || meshId ? {} : {
|
|
101853
|
+
note: "Several meshes are configured and no meshId was given, so these are the shipped defaults, not any mesh's saved presets. Pass meshId."
|
|
101854
|
+
}
|
|
101855
|
+
}
|
|
101856
|
+
};
|
|
101233
101857
|
} catch (e) {
|
|
101234
101858
|
return { success: false, error: e.message };
|
|
101235
101859
|
}
|
|
101236
101860
|
},
|
|
101237
101861
|
difficulty_brains_set: async (_ctx, args) => {
|
|
101862
|
+
const requestedMeshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
101238
101863
|
try {
|
|
101239
|
-
const { setDifficultyBrains: setDifficultyBrains2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
101240
|
-
const difficultyBrains = setDifficultyBrains2(args?.difficultyBrains);
|
|
101241
|
-
|
|
101864
|
+
const { setDifficultyBrains: setDifficultyBrains2, resolveScopedMeshId: resolveScopedMeshId2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
101865
|
+
const difficultyBrains = setDifficultyBrains2(args?.difficultyBrains, requestedMeshId || void 0);
|
|
101866
|
+
const meshId = requestedMeshId || resolveScopedMeshId2();
|
|
101867
|
+
return { success: true, difficultyBrains, meshId: meshId ?? null };
|
|
101242
101868
|
} catch (e) {
|
|
101243
101869
|
return { success: false, error: e.message };
|
|
101244
101870
|
}
|
|
@@ -102810,6 +103436,26 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
102810
103436
|
init_mesh_coordinator();
|
|
102811
103437
|
init_dist();
|
|
102812
103438
|
init_repo_mesh_types();
|
|
103439
|
+
async function backfillMeshHostPinAfterLaunch(opts) {
|
|
103440
|
+
try {
|
|
103441
|
+
const existingPin = typeof opts.mesh?.meshHost?.hostDaemonId === "string" ? opts.mesh.meshHost.hostDaemonId.trim() : "";
|
|
103442
|
+
if (existingPin) return;
|
|
103443
|
+
const { getMesh: getMesh2, setMeshHostPin: setMeshHostPin2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
103444
|
+
if (!getMesh2(opts.meshId)) return;
|
|
103445
|
+
const nodeDaemonId = typeof opts.coordinatorNode?.daemonId === "string" && opts.coordinatorNode.daemonId.trim() ? opts.coordinatorNode.daemonId.trim() : typeof opts.coordinatorNode?.daemon_id === "string" && opts.coordinatorNode.daemon_id.trim() ? opts.coordinatorNode.daemon_id.trim() : opts.localDaemonId || "";
|
|
103446
|
+
const nodeId = String(normalizeMeshNodeId(opts.coordinatorNode) || "");
|
|
103447
|
+
if (!nodeDaemonId && !nodeId) return;
|
|
103448
|
+
const result = setMeshHostPin2(opts.meshId, {
|
|
103449
|
+
...nodeDaemonId ? { hostDaemonId: nodeDaemonId } : {},
|
|
103450
|
+
...nodeId ? { hostNodeId: nodeId } : {}
|
|
103451
|
+
});
|
|
103452
|
+
if (result?.applied) {
|
|
103453
|
+
LOG2.info("MeshCoordinator", `Pinned mesh ${opts.meshId} host to ${result.hostDaemonId || nodeDaemonId} (node ${result.hostNodeId || nodeId}) after coordinator launch`);
|
|
103454
|
+
}
|
|
103455
|
+
} catch (error48) {
|
|
103456
|
+
LOG2.warn("MeshCoordinator", `Host pin backfill skipped for mesh ${opts.meshId}: ${error48?.message || String(error48)}`);
|
|
103457
|
+
}
|
|
103458
|
+
}
|
|
102813
103459
|
var meshCoordinatorLaunchHandlers = {
|
|
102814
103460
|
launch_mesh_coordinator: async (ctx, args) => {
|
|
102815
103461
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
@@ -102889,10 +103535,10 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
102889
103535
|
return void 0;
|
|
102890
103536
|
}
|
|
102891
103537
|
};
|
|
102892
|
-
const loadMagiKindPanelsBestEffort = async () => {
|
|
103538
|
+
const loadMagiKindPanelsBestEffort = async (forMeshId) => {
|
|
102893
103539
|
try {
|
|
102894
103540
|
const { listMagiKindPanels: listMagiKindPanels2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
102895
|
-
return listMagiKindPanels2();
|
|
103541
|
+
return listMagiKindPanels2(forMeshId);
|
|
102896
103542
|
} catch {
|
|
102897
103543
|
return void 0;
|
|
102898
103544
|
}
|
|
@@ -102994,7 +103640,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
102994
103640
|
if (coordinatorSetup.kind === "cli_command") {
|
|
102995
103641
|
let cliCmdSystemPrompt = "";
|
|
102996
103642
|
try {
|
|
102997
|
-
cliCmdSystemPrompt = buildCoordinatorSystemPrompt2({ mesh: effectiveMesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id), recentActivity: await buildRecentActivityBestEffort(mesh.id), operatingNotes: await buildEffectiveOperatingNotes(mesh.id), magiKindPanels: await loadMagiKindPanelsBestEffort() });
|
|
103643
|
+
cliCmdSystemPrompt = buildCoordinatorSystemPrompt2({ mesh: effectiveMesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id), recentActivity: await buildRecentActivityBestEffort(mesh.id), operatingNotes: await buildEffectiveOperatingNotes(mesh.id), magiKindPanels: await loadMagiKindPanelsBestEffort(meshId) });
|
|
102998
103644
|
} catch (error48) {
|
|
102999
103645
|
const message = error48?.message || String(error48);
|
|
103000
103646
|
LOG2.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
|
|
@@ -103169,6 +103815,12 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
103169
103815
|
});
|
|
103170
103816
|
} catch {
|
|
103171
103817
|
}
|
|
103818
|
+
await backfillMeshHostPinAfterLaunch({
|
|
103819
|
+
meshId,
|
|
103820
|
+
mesh,
|
|
103821
|
+
coordinatorNode,
|
|
103822
|
+
localDaemonId: ctx.deps.statusInstanceId
|
|
103823
|
+
});
|
|
103172
103824
|
return {
|
|
103173
103825
|
success: true,
|
|
103174
103826
|
meshId,
|
|
@@ -103191,7 +103843,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
103191
103843
|
}
|
|
103192
103844
|
let systemPrompt = "";
|
|
103193
103845
|
try {
|
|
103194
|
-
systemPrompt = buildCoordinatorSystemPrompt2({ mesh: effectiveMesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id), recentActivity: await buildRecentActivityBestEffort(mesh.id), operatingNotes: await buildEffectiveOperatingNotes(mesh.id), magiKindPanels: await loadMagiKindPanelsBestEffort() });
|
|
103846
|
+
systemPrompt = buildCoordinatorSystemPrompt2({ mesh: effectiveMesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id), recentActivity: await buildRecentActivityBestEffort(mesh.id), operatingNotes: await buildEffectiveOperatingNotes(mesh.id), magiKindPanels: await loadMagiKindPanelsBestEffort(meshId) });
|
|
103195
103847
|
} catch (error48) {
|
|
103196
103848
|
const message = error48?.message || String(error48);
|
|
103197
103849
|
LOG2.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
|
|
@@ -103367,6 +104019,12 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
103367
104019
|
});
|
|
103368
104020
|
} catch {
|
|
103369
104021
|
}
|
|
104022
|
+
await backfillMeshHostPinAfterLaunch({
|
|
104023
|
+
meshId,
|
|
104024
|
+
mesh,
|
|
104025
|
+
coordinatorNode,
|
|
104026
|
+
localDaemonId: ctx.deps.statusInstanceId
|
|
104027
|
+
});
|
|
103370
104028
|
return {
|
|
103371
104029
|
success: true,
|
|
103372
104030
|
meshId,
|
|
@@ -105769,6 +106427,7 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
105769
106427
|
...args.completedAt ? { completedAt: args.completedAt } : {},
|
|
105770
106428
|
...args.retryOfJobId ? { retryOfJobId: args.retryOfJobId } : {},
|
|
105771
106429
|
...args.coordinatorDaemonId ? { targetCoordinatorDaemonId: args.coordinatorDaemonId } : {},
|
|
106430
|
+
...args.coordinatorSessionId ? { targetCoordinatorSessionId: args.coordinatorSessionId } : {},
|
|
105772
106431
|
eventDelivery: { pendingEvents: true, ledger: true },
|
|
105773
106432
|
evidence: {
|
|
105774
106433
|
pendingEventsCommand: "get_pending_mesh_events",
|
|
@@ -105867,9 +106526,23 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
105867
106526
|
nodeLabel: handle.targetNodeId,
|
|
105868
106527
|
nodeId: handle.targetNodeId,
|
|
105869
106528
|
workspace: handle.workspace,
|
|
105870
|
-
metadataEvent
|
|
106529
|
+
metadataEvent: {
|
|
106530
|
+
...metadataEvent,
|
|
106531
|
+
// REFINE-EVENT-SESSION-SCOPED-UNICAST: mirror the session INSIDE
|
|
106532
|
+
// metadataEvent too. handleMeshForwardEvent reads the coordinator session
|
|
106533
|
+
// anchor from `metadataEvent.meshCoordinatorSessionId` (a top-level field
|
|
106534
|
+
// alone is dropped when the event crosses a machine boundary), so this is
|
|
106535
|
+
// what survives the P2P relay for a remote-executing refine.
|
|
106536
|
+
...handle.targetCoordinatorSessionId ? { meshCoordinatorSessionId: handle.targetCoordinatorSessionId } : {}
|
|
106537
|
+
},
|
|
105871
106538
|
queuedAt: Date.now(),
|
|
105872
|
-
...handle.targetCoordinatorDaemonId ? { targetCoordinatorDaemonId: handle.targetCoordinatorDaemonId } : {}
|
|
106539
|
+
...handle.targetCoordinatorDaemonId ? { targetCoordinatorDaemonId: handle.targetCoordinatorDaemonId } : {},
|
|
106540
|
+
// THE FIX: address the terminal event to the requesting coordinator SESSION,
|
|
106541
|
+
// not just its daemon. stampPendingEventV2 folds this into the v2 unicast
|
|
106542
|
+
// `intendedFor`, so identityDeliversTo's both-sides-session branch excludes a
|
|
106543
|
+
// sibling coordinator session on the same daemon. Absent (legacy requester) →
|
|
106544
|
+
// session-less intendedFor → daemon-level delivery exactly as before.
|
|
106545
|
+
...handle.targetCoordinatorSessionId ? { targetCoordinatorSessionId: handle.targetCoordinatorSessionId } : {}
|
|
105873
106546
|
};
|
|
105874
106547
|
if (typeof self.deps.instanceManager?.getByCategory === "function") {
|
|
105875
106548
|
const forwarded = handleMeshForwardEvent(
|
|
@@ -105893,6 +106566,14 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
105893
106566
|
// re-queued event self-fallbacks to THIS (the executing/worker)
|
|
105894
106567
|
// daemon and the real coordinator's drain excludes it.
|
|
105895
106568
|
...handle.targetCoordinatorDaemonId ? { targetCoordinatorDaemonId: handle.targetCoordinatorDaemonId } : {},
|
|
106569
|
+
// REFINE-EVENT-SESSION-SCOPED-UNICAST: carry the SESSION half of the
|
|
106570
|
+
// return address across the relay as well. buildRelayMetadataEvent
|
|
106571
|
+
// reads meshCoordinatorSessionId (falling back to
|
|
106572
|
+
// targetCoordinatorSessionId), so both spellings are supplied.
|
|
106573
|
+
...handle.targetCoordinatorSessionId ? {
|
|
106574
|
+
targetCoordinatorSessionId: handle.targetCoordinatorSessionId,
|
|
106575
|
+
meshCoordinatorSessionId: handle.targetCoordinatorSessionId
|
|
106576
|
+
} : {},
|
|
105896
106577
|
...slimResult ? { result: slimResult } : {}
|
|
105897
106578
|
}
|
|
105898
106579
|
);
|
|
@@ -107317,6 +107998,7 @@ ${e?.stderr || ""}`;
|
|
|
107317
107998
|
startedAt: args.startedAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
107318
107999
|
...args.completedAt ? { completedAt: args.completedAt } : {},
|
|
107319
108000
|
...args.coordinatorDaemonId ? { targetCoordinatorDaemonId: args.coordinatorDaemonId } : {},
|
|
108001
|
+
...args.coordinatorSessionId ? { targetCoordinatorSessionId: args.coordinatorSessionId } : {},
|
|
107320
108002
|
eventDelivery: { pendingEvents: true, ledger: true },
|
|
107321
108003
|
evidence: {
|
|
107322
108004
|
pendingEventsCommand: "get_pending_mesh_events",
|
|
@@ -107346,9 +108028,16 @@ ${e?.stderr || ""}`;
|
|
|
107346
108028
|
meshId: handle.meshId,
|
|
107347
108029
|
nodeLabel: handle.batchLabel,
|
|
107348
108030
|
nodeId: handle.batchLabel,
|
|
107349
|
-
metadataEvent
|
|
108031
|
+
metadataEvent: {
|
|
108032
|
+
...metadataEvent,
|
|
108033
|
+
// REFINE-EVENT-SESSION-SCOPED-UNICAST — see queueRefineJobEvent.
|
|
108034
|
+
...handle.targetCoordinatorSessionId ? { meshCoordinatorSessionId: handle.targetCoordinatorSessionId } : {}
|
|
108035
|
+
},
|
|
107350
108036
|
queuedAt: Date.now(),
|
|
107351
|
-
...handle.targetCoordinatorDaemonId ? { targetCoordinatorDaemonId: handle.targetCoordinatorDaemonId } : {}
|
|
108037
|
+
...handle.targetCoordinatorDaemonId ? { targetCoordinatorDaemonId: handle.targetCoordinatorDaemonId } : {},
|
|
108038
|
+
// THE FIX (batch half) — address the batch terminal event to the requesting
|
|
108039
|
+
// coordinator SESSION so a sibling session cannot consume it.
|
|
108040
|
+
...handle.targetCoordinatorSessionId ? { targetCoordinatorSessionId: handle.targetCoordinatorSessionId } : {}
|
|
107352
108041
|
};
|
|
107353
108042
|
if (typeof self.deps.instanceManager?.getByCategory === "function") {
|
|
107354
108043
|
const forwarded = handleMeshForwardEvent(
|
|
@@ -107366,6 +108055,12 @@ ${e?.stderr || ""}`;
|
|
|
107366
108055
|
// the sessionless batch job's terminal event must stay targeted
|
|
107367
108056
|
// at the originating coordinator, not self-fallback to this daemon.
|
|
107368
108057
|
...handle.targetCoordinatorDaemonId ? { targetCoordinatorDaemonId: handle.targetCoordinatorDaemonId } : {},
|
|
108058
|
+
// REFINE-EVENT-SESSION-SCOPED-UNICAST — session half of the return
|
|
108059
|
+
// address, both spellings (see queueRefineJobEvent).
|
|
108060
|
+
...handle.targetCoordinatorSessionId ? {
|
|
108061
|
+
targetCoordinatorSessionId: handle.targetCoordinatorSessionId,
|
|
108062
|
+
meshCoordinatorSessionId: handle.targetCoordinatorSessionId
|
|
108063
|
+
} : {},
|
|
107369
108064
|
...result ? { result } : {}
|
|
107370
108065
|
}
|
|
107371
108066
|
);
|
|
@@ -107438,7 +108133,10 @@ ${e?.stderr || ""}`;
|
|
|
107438
108133
|
completedAt,
|
|
107439
108134
|
jobId: handle.jobId,
|
|
107440
108135
|
interactionId: handle.interactionId,
|
|
107441
|
-
coordinatorDaemonId: handle.targetCoordinatorDaemonId
|
|
108136
|
+
coordinatorDaemonId: handle.targetCoordinatorDaemonId,
|
|
108137
|
+
// REFINE-EVENT-SESSION-SCOPED-UNICAST — carry the requester's session onto the
|
|
108138
|
+
// terminal batch handle (see the single-node path).
|
|
108139
|
+
coordinatorSessionId: handle.targetCoordinatorSessionId
|
|
107442
108140
|
});
|
|
107443
108141
|
const terminal = { ...terminalHandle, result: normalizedResult };
|
|
107444
108142
|
self.terminalRefineBatchJobs.set(key2, terminal);
|
|
@@ -107472,7 +108170,8 @@ ${e?.stderr || ""}`;
|
|
|
107472
108170
|
rationale: planRecord.orderingRationale
|
|
107473
108171
|
};
|
|
107474
108172
|
const coordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : self.deps.statusInstanceId || void 0;
|
|
107475
|
-
const
|
|
108173
|
+
const coordinatorSessionId = typeof args?.coordinatorSessionId === "string" && args.coordinatorSessionId.trim() ? args.coordinatorSessionId.trim() : void 0;
|
|
108174
|
+
const handle = buildRefineBatchJobHandle(self, { meshId, nodeIds, order, coordinatorDaemonId, coordinatorSessionId });
|
|
107476
108175
|
self.runningRefineBatchJobs.set(key2, handle);
|
|
107477
108176
|
await appendRefineBatchJobLedger(self, "task_dispatched", handle);
|
|
107478
108177
|
queueRefineBatchJobEvent(self, "refine:accepted", handle);
|
|
@@ -107563,7 +108262,12 @@ ${e?.stderr || ""}`;
|
|
|
107563
108262
|
interactionId: handle.interactionId,
|
|
107564
108263
|
retryOfJobId: handle.retryOfJobId,
|
|
107565
108264
|
node: { daemonId: handle.targetDaemonId, workspace: handle.workspace },
|
|
107566
|
-
coordinatorDaemonId: handle.targetCoordinatorDaemonId
|
|
108265
|
+
coordinatorDaemonId: handle.targetCoordinatorDaemonId,
|
|
108266
|
+
// REFINE-EVENT-SESSION-SCOPED-UNICAST: carry the requester's session from the
|
|
108267
|
+
// accepted handle onto the TERMINAL handle. Dropping it here would leave the
|
|
108268
|
+
// completed/failed event — the one the coordinator actually waits on — back at
|
|
108269
|
+
// daemon-level addressing, i.e. the original defect.
|
|
108270
|
+
coordinatorSessionId: handle.targetCoordinatorSessionId
|
|
107567
108271
|
});
|
|
107568
108272
|
const terminal = { ...terminalHandle, result: normalizedResult };
|
|
107569
108273
|
self.terminalRefineJobs.set(key2, terminal);
|
|
@@ -107583,7 +108287,8 @@ ${e?.stderr || ""}`;
|
|
|
107583
108287
|
if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
|
|
107584
108288
|
if (!node.isLocalWorktree || !node.workspace) return { success: false, error: `Refinery requires a local worktree node` };
|
|
107585
108289
|
const coordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : self.deps.statusInstanceId || void 0;
|
|
107586
|
-
const
|
|
108290
|
+
const coordinatorSessionId = typeof args?.coordinatorSessionId === "string" && args.coordinatorSessionId.trim() ? args.coordinatorSessionId.trim() : void 0;
|
|
108291
|
+
const handle = buildRefineJobHandle(self, { meshId, nodeId, node, retryOfJobId: terminal?.jobId, coordinatorDaemonId, coordinatorSessionId });
|
|
107587
108292
|
self.runningRefineJobs.set(key2, handle);
|
|
107588
108293
|
await appendRefineJobLedger(self, "task_dispatched", handle);
|
|
107589
108294
|
queueRefineJobEvent(self, "refine:accepted", handle);
|
|
@@ -109175,6 +109880,32 @@ ${e?.stderr || ""}`;
|
|
|
109175
109880
|
init_logger();
|
|
109176
109881
|
init_runtime_defaults();
|
|
109177
109882
|
init_snapshot();
|
|
109883
|
+
function buildCloudStatusReportPayload(sessions, p2p, timestamp2) {
|
|
109884
|
+
const list = Array.isArray(sessions) ? sessions : [];
|
|
109885
|
+
return {
|
|
109886
|
+
sessions: list.map((raw) => {
|
|
109887
|
+
const session = raw || {};
|
|
109888
|
+
return {
|
|
109889
|
+
id: session.id,
|
|
109890
|
+
parentId: session.parentId ?? null,
|
|
109891
|
+
providerType: session.providerType,
|
|
109892
|
+
providerName: session.providerName || session.providerType,
|
|
109893
|
+
kind: session.kind,
|
|
109894
|
+
transport: session.transport,
|
|
109895
|
+
status: session.status,
|
|
109896
|
+
workspace: session.workspace ?? null,
|
|
109897
|
+
cdpConnected: session.cdpConnected,
|
|
109898
|
+
// Forward surfaceHidden/muted so the server can gate push notifications
|
|
109899
|
+
// for coordinator-hidden and user-muted sessions (the WS path is the
|
|
109900
|
+
// only one the server sees). Both are plain booleans, not content.
|
|
109901
|
+
surfaceHidden: session.surfaceHidden,
|
|
109902
|
+
muted: session.muted
|
|
109903
|
+
};
|
|
109904
|
+
}),
|
|
109905
|
+
p2p,
|
|
109906
|
+
timestamp: timestamp2
|
|
109907
|
+
};
|
|
109908
|
+
}
|
|
109178
109909
|
var DaemonStatusReporter = class {
|
|
109179
109910
|
deps;
|
|
109180
109911
|
log;
|
|
@@ -109388,28 +110119,7 @@ ${e?.stderr || ""}`;
|
|
|
109388
110119
|
}
|
|
109389
110120
|
if (opts?.p2pOnly) return;
|
|
109390
110121
|
if (!serverConnected || !serverConn) return;
|
|
109391
|
-
const
|
|
109392
|
-
const wsPayload = {
|
|
109393
|
-
sessions: payloadSessions.map((session) => ({
|
|
109394
|
-
id: session.id,
|
|
109395
|
-
parentId: session.parentId,
|
|
109396
|
-
providerType: session.providerType,
|
|
109397
|
-
providerName: session.providerName || session.providerType,
|
|
109398
|
-
kind: session.kind,
|
|
109399
|
-
transport: session.transport,
|
|
109400
|
-
status: session.status,
|
|
109401
|
-
workspace: session.workspace ?? null,
|
|
109402
|
-
title: session.title,
|
|
109403
|
-
cdpConnected: session.cdpConnected,
|
|
109404
|
-
summaryMetadata: session.summaryMetadata,
|
|
109405
|
-
settings: session.settings,
|
|
109406
|
-
// Forward surfaceHidden so the server can gate push notifications for
|
|
109407
|
-
// coordinator-hidden sessions (the WS path is the only one the server sees).
|
|
109408
|
-
surfaceHidden: session.surfaceHidden
|
|
109409
|
-
})),
|
|
109410
|
-
p2p: payload.p2p,
|
|
109411
|
-
timestamp: now
|
|
109412
|
-
};
|
|
110122
|
+
const wsPayload = buildCloudStatusReportPayload(payload.sessions, payload.p2p, now);
|
|
109413
110123
|
const wsHash = this.simpleHash(JSON.stringify({
|
|
109414
110124
|
...wsPayload,
|
|
109415
110125
|
timestamp: void 0
|