@adhdev/daemon-core 0.9.82-rc.47 → 0.9.82-rc.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/router.d.ts +1 -0
- package/dist/config/mesh-config.d.ts +66 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.js +954 -212
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +928 -198
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-host-ownership.d.ts +9 -0
- package/dist/mesh/mesh-ledger.d.ts +1 -1
- package/dist/mesh/mesh-work-queue.d.ts +8 -4
- package/dist/mesh/refine-config.d.ts +119 -0
- package/dist/repo-mesh-types.d.ts +32 -0
- package/package.json +1 -1
- package/src/commands/router.ts +412 -178
- package/src/config/mesh-config.ts +244 -1
- package/src/index.ts +23 -1
- package/src/mesh/mesh-host-ownership.ts +73 -0
- package/src/mesh/mesh-ledger.ts +1 -0
- package/src/mesh/mesh-work-queue.ts +14 -3
- package/src/mesh/refine-config.ts +306 -0
- package/src/repo-mesh-types.ts +36 -0
package/dist/index.js
CHANGED
|
@@ -662,17 +662,91 @@ var init_config = __esm({
|
|
|
662
662
|
}
|
|
663
663
|
});
|
|
664
664
|
|
|
665
|
+
// src/mesh/mesh-host-ownership.ts
|
|
666
|
+
function readObject(value) {
|
|
667
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
668
|
+
}
|
|
669
|
+
function readString(value) {
|
|
670
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
671
|
+
}
|
|
672
|
+
function normalizeMeshDaemonRole(value) {
|
|
673
|
+
return value === "host" || value === "member" ? value : void 0;
|
|
674
|
+
}
|
|
675
|
+
function resolveMeshHostStatus(mesh) {
|
|
676
|
+
const meshRecord = readObject(mesh);
|
|
677
|
+
const raw = readObject(meshRecord?.meshHost);
|
|
678
|
+
const role = normalizeMeshDaemonRole(raw?.role) ?? "host";
|
|
679
|
+
const pairing = readObject(raw?.pairing);
|
|
680
|
+
const normalized = {
|
|
681
|
+
role,
|
|
682
|
+
canOwnCoordinator: role === "host",
|
|
683
|
+
canOwnQueue: role === "host",
|
|
684
|
+
defaulted: !raw
|
|
685
|
+
};
|
|
686
|
+
const hostDaemonId = readString(raw?.hostDaemonId);
|
|
687
|
+
const hostNodeId = readString(raw?.hostNodeId);
|
|
688
|
+
const hostAddress = readString(raw?.hostAddress);
|
|
689
|
+
if (hostDaemonId) normalized.hostDaemonId = hostDaemonId;
|
|
690
|
+
if (hostNodeId) normalized.hostNodeId = hostNodeId;
|
|
691
|
+
if (hostAddress) normalized.hostAddress = hostAddress;
|
|
692
|
+
if (pairing) {
|
|
693
|
+
const status = pairing.status === "pairing" || pairing.status === "paired" || pairing.status === "rejected" || pairing.status === "revoked" ? pairing.status : "not_configured";
|
|
694
|
+
normalized.pairing = {
|
|
695
|
+
status,
|
|
696
|
+
...readString(pairing.tokenId) ? { tokenId: readString(pairing.tokenId) } : {},
|
|
697
|
+
...readString(pairing.joinedAt) ? { joinedAt: readString(pairing.joinedAt) } : {},
|
|
698
|
+
...readString(pairing.lastPairedAt) ? { lastPairedAt: readString(pairing.lastPairedAt) } : {},
|
|
699
|
+
...readString(pairing.lastRejectedAt) ? { lastRejectedAt: readString(pairing.lastRejectedAt) } : {},
|
|
700
|
+
...readString(pairing.expiresAt) ? { expiresAt: readString(pairing.expiresAt) } : {}
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
return normalized;
|
|
704
|
+
}
|
|
705
|
+
function isMeshHostOwner(mesh) {
|
|
706
|
+
return resolveMeshHostStatus(mesh).role === "host";
|
|
707
|
+
}
|
|
708
|
+
function buildMeshHostRequiredFailure(mesh, operation) {
|
|
709
|
+
const meshHost = resolveMeshHostStatus(mesh);
|
|
710
|
+
return {
|
|
711
|
+
success: false,
|
|
712
|
+
code: "mesh_host_required",
|
|
713
|
+
error: `Mesh Host daemon required for ${operation}; member daemons must pair with the host and cannot own coordinator/queue mutations.`,
|
|
714
|
+
meshHost
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
function requireMeshHostQueueOwner(opts) {
|
|
718
|
+
if (opts?.ownerRole === "member") {
|
|
719
|
+
throw new Error("Mesh Host daemon required to mutate mesh queue; member daemons must use the host-owned queue.");
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
function createDefaultMeshHostMetadata() {
|
|
723
|
+
return {
|
|
724
|
+
role: "host",
|
|
725
|
+
pairing: { status: "not_configured" }
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
var init_mesh_host_ownership = __esm({
|
|
729
|
+
"src/mesh/mesh-host-ownership.ts"() {
|
|
730
|
+
"use strict";
|
|
731
|
+
}
|
|
732
|
+
});
|
|
733
|
+
|
|
665
734
|
// src/config/mesh-config.ts
|
|
666
735
|
var mesh_config_exports = {};
|
|
667
736
|
__export(mesh_config_exports, {
|
|
668
737
|
addNode: () => addNode,
|
|
738
|
+
applyMeshHostJoinRequest: () => applyMeshHostJoinRequest,
|
|
739
|
+
configureMeshHostPairing: () => configureMeshHostPairing,
|
|
669
740
|
createMesh: () => createMesh,
|
|
741
|
+
createMeshHostPairingToken: () => createMeshHostPairingToken,
|
|
670
742
|
deleteMesh: () => deleteMesh,
|
|
671
743
|
getMesh: () => getMesh,
|
|
672
744
|
getMeshByRepo: () => getMeshByRepo,
|
|
673
745
|
listMeshes: () => listMeshes,
|
|
746
|
+
markMeshHostPairingJoined: () => markMeshHostPairingJoined,
|
|
674
747
|
normalizeRepoIdentity: () => normalizeRepoIdentity,
|
|
675
748
|
removeNode: () => removeNode,
|
|
749
|
+
tokenIdForManualPairing: () => tokenIdForManualPairing,
|
|
676
750
|
updateMesh: () => updateMesh,
|
|
677
751
|
updateNode: () => updateNode
|
|
678
752
|
});
|
|
@@ -748,6 +822,7 @@ function createMesh(opts) {
|
|
|
748
822
|
defaultBranch: opts.defaultBranch,
|
|
749
823
|
policy: mergeMeshPolicy(void 0, opts.policy),
|
|
750
824
|
coordinator: opts.coordinator || {},
|
|
825
|
+
meshHost: opts.meshHost || createDefaultMeshHostMetadata(),
|
|
751
826
|
nodes: [],
|
|
752
827
|
createdAt: now,
|
|
753
828
|
updatedAt: now
|
|
@@ -764,6 +839,7 @@ function updateMesh(meshId, opts) {
|
|
|
764
839
|
if (opts.defaultBranch !== void 0) mesh.defaultBranch = opts.defaultBranch;
|
|
765
840
|
if (opts.policy) mesh.policy = mergeMeshPolicy(mesh.policy, opts.policy);
|
|
766
841
|
if (opts.coordinator) mesh.coordinator = opts.coordinator;
|
|
842
|
+
if (opts.meshHost) mesh.meshHost = opts.meshHost;
|
|
767
843
|
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
768
844
|
saveMeshConfig(config);
|
|
769
845
|
return mesh;
|
|
@@ -776,6 +852,186 @@ function deleteMesh(meshId) {
|
|
|
776
852
|
saveMeshConfig(config);
|
|
777
853
|
return true;
|
|
778
854
|
}
|
|
855
|
+
function normalizeManualHostAddress(hostAddress) {
|
|
856
|
+
const normalized = hostAddress.trim().replace(/\/+$/, "");
|
|
857
|
+
if (!normalized) throw new Error("hostAddress required");
|
|
858
|
+
let parsed;
|
|
859
|
+
try {
|
|
860
|
+
parsed = new URL(normalized);
|
|
861
|
+
} catch {
|
|
862
|
+
throw new Error("hostAddress must be a valid http(s) or ws(s) URL");
|
|
863
|
+
}
|
|
864
|
+
if (!["http:", "https:", "ws:", "wss:"].includes(parsed.protocol)) {
|
|
865
|
+
throw new Error("hostAddress must use http, https, ws, or wss");
|
|
866
|
+
}
|
|
867
|
+
return normalized;
|
|
868
|
+
}
|
|
869
|
+
function tokenIdForManualPairing(token) {
|
|
870
|
+
return `tok_${(0, import_crypto3.createHash)("sha256").update(token).digest("hex").slice(0, 16)}`;
|
|
871
|
+
}
|
|
872
|
+
function normalizeTokenExpiry(value) {
|
|
873
|
+
if (typeof value !== "string" || !value.trim()) return void 0;
|
|
874
|
+
const date = new Date(value);
|
|
875
|
+
if (Number.isNaN(date.getTime())) throw new Error("expiresAt must be a valid ISO date");
|
|
876
|
+
return date.toISOString();
|
|
877
|
+
}
|
|
878
|
+
function assertPairingTokenValid(pairing, rawToken, nowIso) {
|
|
879
|
+
const token = rawToken.trim();
|
|
880
|
+
if (!token) return { ok: false, reason: "token required" };
|
|
881
|
+
const presentedTokenId = tokenIdForManualPairing(token);
|
|
882
|
+
const expectedTokenId = pairing?.tokenId;
|
|
883
|
+
if (!expectedTokenId || pairing?.status === "not_configured" || pairing?.status === "revoked") {
|
|
884
|
+
return { ok: false, reason: "host pairing token is not configured", presentedTokenId };
|
|
885
|
+
}
|
|
886
|
+
if (pairing.expiresAt && new Date(pairing.expiresAt).getTime() <= new Date(nowIso).getTime()) {
|
|
887
|
+
return { ok: false, reason: "host pairing token expired", expectedTokenId, presentedTokenId };
|
|
888
|
+
}
|
|
889
|
+
if (presentedTokenId !== expectedTokenId) {
|
|
890
|
+
return { ok: false, reason: "invalid pairing token", expectedTokenId, presentedTokenId };
|
|
891
|
+
}
|
|
892
|
+
return { ok: true, tokenId: presentedTokenId };
|
|
893
|
+
}
|
|
894
|
+
function configureMeshHostPairing(meshId, opts) {
|
|
895
|
+
const hostAddress = normalizeManualHostAddress(opts.hostAddress);
|
|
896
|
+
const token = opts.token.trim();
|
|
897
|
+
if (!token) throw new Error("token required");
|
|
898
|
+
const config = loadMeshConfig();
|
|
899
|
+
const mesh = config.meshes.find((m) => m.id === meshId);
|
|
900
|
+
if (!mesh) return void 0;
|
|
901
|
+
const now = opts.now || (/* @__PURE__ */ new Date()).toISOString();
|
|
902
|
+
const previous = mesh.meshHost || createDefaultMeshHostMetadata();
|
|
903
|
+
const meshHost = {
|
|
904
|
+
...previous,
|
|
905
|
+
role: "member",
|
|
906
|
+
hostAddress,
|
|
907
|
+
pairing: {
|
|
908
|
+
status: "pairing",
|
|
909
|
+
tokenId: tokenIdForManualPairing(token),
|
|
910
|
+
lastPairedAt: now
|
|
911
|
+
}
|
|
912
|
+
};
|
|
913
|
+
mesh.meshHost = meshHost;
|
|
914
|
+
mesh.updatedAt = now;
|
|
915
|
+
saveMeshConfig(config);
|
|
916
|
+
return { mesh, meshHost, hostAddress };
|
|
917
|
+
}
|
|
918
|
+
function createMeshHostPairingToken(meshId, opts = {}) {
|
|
919
|
+
const config = loadMeshConfig();
|
|
920
|
+
const mesh = config.meshes.find((m) => m.id === meshId);
|
|
921
|
+
if (!mesh) return void 0;
|
|
922
|
+
const now = opts.now || (/* @__PURE__ */ new Date()).toISOString();
|
|
923
|
+
const token = (opts.token || `mhj_${(0, import_crypto3.randomBytes)(24).toString("base64url")}`).trim();
|
|
924
|
+
if (!token) throw new Error("token required");
|
|
925
|
+
const tokenId = tokenIdForManualPairing(token);
|
|
926
|
+
const expiresAt = normalizeTokenExpiry(opts.expiresAt);
|
|
927
|
+
const previous = mesh.meshHost || createDefaultMeshHostMetadata();
|
|
928
|
+
if (previous.role === "member") {
|
|
929
|
+
throw new Error("Mesh Host daemon required to create host pairing tokens; member daemons cannot mint host join tokens.");
|
|
930
|
+
}
|
|
931
|
+
const meshHost = {
|
|
932
|
+
...previous,
|
|
933
|
+
role: "host",
|
|
934
|
+
pairing: {
|
|
935
|
+
status: "pairing",
|
|
936
|
+
tokenId,
|
|
937
|
+
lastPairedAt: now,
|
|
938
|
+
...expiresAt ? { expiresAt } : {}
|
|
939
|
+
}
|
|
940
|
+
};
|
|
941
|
+
mesh.meshHost = meshHost;
|
|
942
|
+
mesh.updatedAt = now;
|
|
943
|
+
saveMeshConfig(config);
|
|
944
|
+
return { mesh, meshHost, token, tokenId, ...expiresAt ? { expiresAt } : {} };
|
|
945
|
+
}
|
|
946
|
+
function applyMeshHostJoinRequest(meshId, opts) {
|
|
947
|
+
const config = loadMeshConfig();
|
|
948
|
+
const mesh = config.meshes.find((m) => m.id === meshId);
|
|
949
|
+
if (!mesh) return void 0;
|
|
950
|
+
const now = opts.now || (/* @__PURE__ */ new Date()).toISOString();
|
|
951
|
+
const previous = mesh.meshHost || createDefaultMeshHostMetadata();
|
|
952
|
+
if (previous.role === "member") {
|
|
953
|
+
return { accepted: false, mesh, meshHost: previous, reason: "Mesh Host daemon required to accept join requests" };
|
|
954
|
+
}
|
|
955
|
+
const meshHost = { ...previous, role: "host" };
|
|
956
|
+
const validation = assertPairingTokenValid(meshHost.pairing, opts.token, now);
|
|
957
|
+
if (!validation.ok) {
|
|
958
|
+
mesh.meshHost = {
|
|
959
|
+
...meshHost,
|
|
960
|
+
pairing: {
|
|
961
|
+
...meshHost.pairing || { status: "not_configured" },
|
|
962
|
+
status: "rejected",
|
|
963
|
+
lastRejectedAt: now
|
|
964
|
+
}
|
|
965
|
+
};
|
|
966
|
+
mesh.updatedAt = now;
|
|
967
|
+
saveMeshConfig(config);
|
|
968
|
+
return { accepted: false, mesh, meshHost: mesh.meshHost, tokenId: validation.presentedTokenId, reason: validation.reason };
|
|
969
|
+
}
|
|
970
|
+
const workspace = opts.memberNode.workspace.trim();
|
|
971
|
+
if (!workspace) throw new Error("memberNode.workspace required");
|
|
972
|
+
const memberId = opts.memberNode.id?.trim();
|
|
973
|
+
let node = mesh.nodes.find((n) => memberId && n.id === memberId || n.workspace === workspace);
|
|
974
|
+
if (node) {
|
|
975
|
+
node.workspace = workspace;
|
|
976
|
+
node.repoRoot = opts.memberNode.repoRoot;
|
|
977
|
+
node.daemonId = opts.memberNode.daemonId;
|
|
978
|
+
node.machineId = opts.memberNode.machineId;
|
|
979
|
+
node.userOverrides = opts.memberNode.userOverrides || node.userOverrides || {};
|
|
980
|
+
node.policy = { ...node.policy || {}, ...opts.memberNode.policy || {} };
|
|
981
|
+
node.role = "member";
|
|
982
|
+
} else {
|
|
983
|
+
if (mesh.nodes.length >= 10) throw new Error("Maximum 10 nodes per mesh");
|
|
984
|
+
node = {
|
|
985
|
+
id: memberId || `node_${(0, import_crypto3.randomUUID)().replace(/-/g, "")}`,
|
|
986
|
+
workspace,
|
|
987
|
+
repoRoot: opts.memberNode.repoRoot,
|
|
988
|
+
daemonId: opts.memberNode.daemonId,
|
|
989
|
+
machineId: opts.memberNode.machineId,
|
|
990
|
+
userOverrides: opts.memberNode.userOverrides || {},
|
|
991
|
+
policy: opts.memberNode.policy || {},
|
|
992
|
+
role: "member"
|
|
993
|
+
};
|
|
994
|
+
mesh.nodes.push(node);
|
|
995
|
+
}
|
|
996
|
+
mesh.meshHost = {
|
|
997
|
+
...meshHost,
|
|
998
|
+
pairing: {
|
|
999
|
+
...meshHost.pairing || {},
|
|
1000
|
+
status: "paired",
|
|
1001
|
+
tokenId: validation.tokenId,
|
|
1002
|
+
joinedAt: now,
|
|
1003
|
+
lastPairedAt: meshHost.pairing?.lastPairedAt || now,
|
|
1004
|
+
...meshHost.pairing?.expiresAt ? { expiresAt: meshHost.pairing.expiresAt } : {}
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
mesh.updatedAt = now;
|
|
1008
|
+
saveMeshConfig(config);
|
|
1009
|
+
return { accepted: true, mesh, meshHost: mesh.meshHost, node, tokenId: validation.tokenId };
|
|
1010
|
+
}
|
|
1011
|
+
function markMeshHostPairingJoined(meshId, opts) {
|
|
1012
|
+
const config = loadMeshConfig();
|
|
1013
|
+
const mesh = config.meshes.find((m) => m.id === meshId);
|
|
1014
|
+
if (!mesh) return void 0;
|
|
1015
|
+
const now = opts.joinedAt || (/* @__PURE__ */ new Date()).toISOString();
|
|
1016
|
+
const previous = mesh.meshHost || createDefaultMeshHostMetadata();
|
|
1017
|
+
const tokenId = opts.tokenId || (opts.token ? tokenIdForManualPairing(opts.token) : previous.pairing?.tokenId);
|
|
1018
|
+
mesh.meshHost = {
|
|
1019
|
+
...previous,
|
|
1020
|
+
role: "member",
|
|
1021
|
+
...opts.hostDaemonId ? { hostDaemonId: opts.hostDaemonId } : {},
|
|
1022
|
+
...opts.hostNodeId ? { hostNodeId: opts.hostNodeId } : {},
|
|
1023
|
+
pairing: {
|
|
1024
|
+
...previous.pairing || {},
|
|
1025
|
+
status: "paired",
|
|
1026
|
+
...tokenId ? { tokenId } : {},
|
|
1027
|
+
joinedAt: now,
|
|
1028
|
+
lastPairedAt: previous.pairing?.lastPairedAt || now
|
|
1029
|
+
}
|
|
1030
|
+
};
|
|
1031
|
+
mesh.updatedAt = now;
|
|
1032
|
+
saveMeshConfig(config);
|
|
1033
|
+
return { mesh, meshHost: mesh.meshHost };
|
|
1034
|
+
}
|
|
779
1035
|
function addNode(meshId, opts) {
|
|
780
1036
|
const config = loadMeshConfig();
|
|
781
1037
|
const mesh = config.meshes.find((m) => m.id === meshId);
|
|
@@ -796,7 +1052,8 @@ function addNode(meshId, opts) {
|
|
|
796
1052
|
policy: opts.policy || {},
|
|
797
1053
|
isLocalWorktree: opts.isLocalWorktree,
|
|
798
1054
|
worktreeBranch: opts.worktreeBranch,
|
|
799
|
-
clonedFromNodeId: opts.clonedFromNodeId
|
|
1055
|
+
clonedFromNodeId: opts.clonedFromNodeId,
|
|
1056
|
+
role: opts.role
|
|
800
1057
|
};
|
|
801
1058
|
mesh.nodes.push(node);
|
|
802
1059
|
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -835,6 +1092,7 @@ var init_mesh_config = __esm({
|
|
|
835
1092
|
import_crypto3 = require("crypto");
|
|
836
1093
|
init_config();
|
|
837
1094
|
init_repo_mesh_types();
|
|
1095
|
+
init_mesh_host_ownership();
|
|
838
1096
|
SESSION_CLEANUP_MODES = /* @__PURE__ */ new Set(["preserve", "stop", "delete_stopped", "stop_and_delete"]);
|
|
839
1097
|
SPAWNED_SESSION_VISIBILITY_MODES = /* @__PURE__ */ new Set(["visible", "hidden"]);
|
|
840
1098
|
}
|
|
@@ -1018,19 +1276,19 @@ function isIntentionalCleanupStopEntry(entry) {
|
|
|
1018
1276
|
return payload.intentional === true && (payload.reason === "operator_cleanup" || payload.intentionalStopReason === "operator_cleanup" || payload.source === "mesh_cleanup_sessions" || payload.source === "mesh_remove_node");
|
|
1019
1277
|
}
|
|
1020
1278
|
function getLedgerDir() {
|
|
1021
|
-
const dir = (0,
|
|
1022
|
-
if (!(0,
|
|
1023
|
-
(0,
|
|
1279
|
+
const dir = (0, import_path4.join)(getConfigDir(), LEDGER_DIR_NAME);
|
|
1280
|
+
if (!(0, import_fs4.existsSync)(dir)) {
|
|
1281
|
+
(0, import_fs4.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
1024
1282
|
}
|
|
1025
1283
|
return dir;
|
|
1026
1284
|
}
|
|
1027
1285
|
function getLedgerPath(meshId) {
|
|
1028
1286
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1029
|
-
return (0,
|
|
1287
|
+
return (0, import_path4.join)(getLedgerDir(), `${safe}.jsonl`);
|
|
1030
1288
|
}
|
|
1031
1289
|
function getRotatedPath(meshId, index) {
|
|
1032
1290
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1033
|
-
return (0,
|
|
1291
|
+
return (0, import_path4.join)(getLedgerDir(), `${safe}.${index}.jsonl`);
|
|
1034
1292
|
}
|
|
1035
1293
|
function buildTaskCompletionEvidence(opts) {
|
|
1036
1294
|
const providerSessionId = opts.providerSessionId?.trim() || void 0;
|
|
@@ -1071,9 +1329,9 @@ function appendLedgerEntry(meshId, partial) {
|
|
|
1071
1329
|
...partial
|
|
1072
1330
|
};
|
|
1073
1331
|
const filePath = getLedgerPath(meshId);
|
|
1074
|
-
if ((0,
|
|
1332
|
+
if ((0, import_fs4.existsSync)(filePath)) {
|
|
1075
1333
|
try {
|
|
1076
|
-
const stat2 = (0,
|
|
1334
|
+
const stat2 = (0, import_fs4.statSync)(filePath);
|
|
1077
1335
|
if (stat2.size >= MAX_FILE_SIZE_BYTES) {
|
|
1078
1336
|
rotateLedgerFile(meshId, filePath);
|
|
1079
1337
|
}
|
|
@@ -1082,7 +1340,7 @@ function appendLedgerEntry(meshId, partial) {
|
|
|
1082
1340
|
}
|
|
1083
1341
|
try {
|
|
1084
1342
|
const line = JSON.stringify(entry) + "\n";
|
|
1085
|
-
(0,
|
|
1343
|
+
(0, import_fs4.appendFileSync)(filePath, line, { encoding: "utf-8", mode: 384 });
|
|
1086
1344
|
meshLedgerEvents.emit("append", meshId, entry);
|
|
1087
1345
|
return entry;
|
|
1088
1346
|
} catch (e) {
|
|
@@ -1127,7 +1385,7 @@ function appendRemoteLedgerEntries(meshId, entries) {
|
|
|
1127
1385
|
}
|
|
1128
1386
|
try {
|
|
1129
1387
|
const lines = validEntries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
1130
|
-
(0,
|
|
1388
|
+
(0, import_fs4.appendFileSync)(ledgerPath, lines, { encoding: "utf-8", mode: 384 });
|
|
1131
1389
|
for (const entry of validEntries) {
|
|
1132
1390
|
meshLedgerEvents.emit("append", meshId, entry);
|
|
1133
1391
|
}
|
|
@@ -1138,10 +1396,10 @@ function appendRemoteLedgerEntries(meshId, entries) {
|
|
|
1138
1396
|
}
|
|
1139
1397
|
function readLedgerEntries(meshId, opts) {
|
|
1140
1398
|
const filePath = getLedgerPath(meshId);
|
|
1141
|
-
if (!(0,
|
|
1399
|
+
if (!(0, import_fs4.existsSync)(filePath)) return [];
|
|
1142
1400
|
let content;
|
|
1143
1401
|
try {
|
|
1144
|
-
content = (0,
|
|
1402
|
+
content = (0, import_fs4.readFileSync)(filePath, "utf-8");
|
|
1145
1403
|
} catch {
|
|
1146
1404
|
return [];
|
|
1147
1405
|
}
|
|
@@ -1313,22 +1571,22 @@ function getSessionRecoveryContext(meshId, opts) {
|
|
|
1313
1571
|
}
|
|
1314
1572
|
function rotateLedgerFile(meshId, currentPath) {
|
|
1315
1573
|
let index = 1;
|
|
1316
|
-
while ((0,
|
|
1574
|
+
while ((0, import_fs4.existsSync)(getRotatedPath(meshId, index))) {
|
|
1317
1575
|
index++;
|
|
1318
1576
|
if (index > 10) break;
|
|
1319
1577
|
}
|
|
1320
1578
|
if (index > 10) index = 10;
|
|
1321
1579
|
try {
|
|
1322
|
-
(0,
|
|
1580
|
+
(0, import_fs4.renameSync)(currentPath, getRotatedPath(meshId, index));
|
|
1323
1581
|
} catch {
|
|
1324
1582
|
}
|
|
1325
1583
|
}
|
|
1326
|
-
var
|
|
1584
|
+
var import_fs4, import_path4, import_crypto4, import_events, LEDGER_DIR_NAME, MAX_FILE_SIZE_BYTES, RECENT_FAILURE_WINDOW_MS, DEFAULT_LEDGER_SLICE_LIMIT, MAX_LEDGER_SLICE_LIMIT, meshLedgerEvents;
|
|
1327
1585
|
var init_mesh_ledger = __esm({
|
|
1328
1586
|
"src/mesh/mesh-ledger.ts"() {
|
|
1329
1587
|
"use strict";
|
|
1330
|
-
|
|
1331
|
-
|
|
1588
|
+
import_fs4 = require("fs");
|
|
1589
|
+
import_path4 = require("path");
|
|
1332
1590
|
import_crypto4 = require("crypto");
|
|
1333
1591
|
init_config();
|
|
1334
1592
|
import_events = require("events");
|
|
@@ -1358,18 +1616,18 @@ __export(mesh_work_queue_exports, {
|
|
|
1358
1616
|
});
|
|
1359
1617
|
function getQueuePath(meshId) {
|
|
1360
1618
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1361
|
-
return (0,
|
|
1619
|
+
return (0, import_path5.join)(getLedgerDir(), `${safe}.queue.json`);
|
|
1362
1620
|
}
|
|
1363
1621
|
function getLockPath(meshId) {
|
|
1364
1622
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1365
|
-
return (0,
|
|
1623
|
+
return (0, import_path5.join)(getLedgerDir(), `${safe}.queue.lock`);
|
|
1366
1624
|
}
|
|
1367
1625
|
function withQueueLock(meshId, fn) {
|
|
1368
1626
|
const lockPath = getLockPath(meshId);
|
|
1369
1627
|
let fd = -1;
|
|
1370
1628
|
for (let i = 0; i < 10; i++) {
|
|
1371
1629
|
try {
|
|
1372
|
-
fd = (0,
|
|
1630
|
+
fd = (0, import_fs5.openSync)(lockPath, "wx");
|
|
1373
1631
|
break;
|
|
1374
1632
|
} catch {
|
|
1375
1633
|
const deadline = Date.now() + 30;
|
|
@@ -1381,20 +1639,20 @@ function withQueueLock(meshId, fn) {
|
|
|
1381
1639
|
return fn();
|
|
1382
1640
|
} finally {
|
|
1383
1641
|
if (fd !== -1) try {
|
|
1384
|
-
(0,
|
|
1642
|
+
(0, import_fs5.closeSync)(fd);
|
|
1385
1643
|
} catch {
|
|
1386
1644
|
}
|
|
1387
1645
|
try {
|
|
1388
|
-
(0,
|
|
1646
|
+
(0, import_fs5.unlinkSync)(lockPath);
|
|
1389
1647
|
} catch {
|
|
1390
1648
|
}
|
|
1391
1649
|
}
|
|
1392
1650
|
}
|
|
1393
1651
|
function readQueue(meshId) {
|
|
1394
1652
|
const path28 = getQueuePath(meshId);
|
|
1395
|
-
if (!(0,
|
|
1653
|
+
if (!(0, import_fs5.existsSync)(path28)) return [];
|
|
1396
1654
|
try {
|
|
1397
|
-
const content = (0,
|
|
1655
|
+
const content = (0, import_fs5.readFileSync)(path28, "utf-8");
|
|
1398
1656
|
return JSON.parse(content);
|
|
1399
1657
|
} catch {
|
|
1400
1658
|
return [];
|
|
@@ -1402,9 +1660,10 @@ function readQueue(meshId) {
|
|
|
1402
1660
|
}
|
|
1403
1661
|
function writeQueue(meshId, queue) {
|
|
1404
1662
|
const path28 = getQueuePath(meshId);
|
|
1405
|
-
(0,
|
|
1663
|
+
(0, import_fs5.writeFileSync)(path28, JSON.stringify(queue, null, 2), "utf-8");
|
|
1406
1664
|
}
|
|
1407
1665
|
function enqueueTask(meshId, message, opts) {
|
|
1666
|
+
requireMeshHostQueueOwner(opts);
|
|
1408
1667
|
return withQueueLock(meshId, () => {
|
|
1409
1668
|
const queue = readQueue(meshId);
|
|
1410
1669
|
const entry = {
|
|
@@ -1453,7 +1712,8 @@ function claimNextTask(meshId, nodeId, sessionId) {
|
|
|
1453
1712
|
return entry;
|
|
1454
1713
|
});
|
|
1455
1714
|
}
|
|
1456
|
-
function updateTaskStatus(meshId, taskId, status) {
|
|
1715
|
+
function updateTaskStatus(meshId, taskId, status, opts) {
|
|
1716
|
+
requireMeshHostQueueOwner(opts);
|
|
1457
1717
|
return withQueueLock(meshId, () => {
|
|
1458
1718
|
const queue = readQueue(meshId);
|
|
1459
1719
|
const idx = queue.findIndex((q) => q.id === taskId);
|
|
@@ -1477,6 +1737,7 @@ function recordTaskAutoLaunch(meshId, taskId, autoLaunch) {
|
|
|
1477
1737
|
});
|
|
1478
1738
|
}
|
|
1479
1739
|
function cancelTask(meshId, taskId, opts) {
|
|
1740
|
+
requireMeshHostQueueOwner(opts);
|
|
1480
1741
|
return withQueueLock(meshId, () => {
|
|
1481
1742
|
const queue = readQueue(meshId);
|
|
1482
1743
|
const idx = queue.findIndex((q) => q.id === taskId);
|
|
@@ -1491,6 +1752,7 @@ function cancelTask(meshId, taskId, opts) {
|
|
|
1491
1752
|
});
|
|
1492
1753
|
}
|
|
1493
1754
|
function requeueTask(meshId, taskId, opts) {
|
|
1755
|
+
requireMeshHostQueueOwner(opts);
|
|
1494
1756
|
return withQueueLock(meshId, () => {
|
|
1495
1757
|
const queue = readQueue(meshId);
|
|
1496
1758
|
const idx = queue.findIndex((q) => q.id === taskId);
|
|
@@ -1570,14 +1832,15 @@ function getMeshQueueStats(meshId) {
|
|
|
1570
1832
|
}))
|
|
1571
1833
|
};
|
|
1572
1834
|
}
|
|
1573
|
-
var
|
|
1835
|
+
var import_fs5, import_path5, import_crypto5, ACTIVE_MESH_QUEUE_STATUSES, HISTORICAL_MESH_QUEUE_STATUSES;
|
|
1574
1836
|
var init_mesh_work_queue = __esm({
|
|
1575
1837
|
"src/mesh/mesh-work-queue.ts"() {
|
|
1576
1838
|
"use strict";
|
|
1577
|
-
|
|
1578
|
-
|
|
1839
|
+
import_fs5 = require("fs");
|
|
1840
|
+
import_path5 = require("path");
|
|
1579
1841
|
import_crypto5 = require("crypto");
|
|
1580
1842
|
init_mesh_ledger();
|
|
1843
|
+
init_mesh_host_ownership();
|
|
1581
1844
|
ACTIVE_MESH_QUEUE_STATUSES = ["pending", "assigned"];
|
|
1582
1845
|
HISTORICAL_MESH_QUEUE_STATUSES = ["completed", "failed", "cancelled"];
|
|
1583
1846
|
}
|
|
@@ -1607,7 +1870,7 @@ function resolveCommandPath(command) {
|
|
|
1607
1870
|
if (isExplicitCommandPath(trimmed)) {
|
|
1608
1871
|
const expanded = expandHome(trimmed);
|
|
1609
1872
|
const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
|
|
1610
|
-
return (0,
|
|
1873
|
+
return (0, import_fs6.existsSync)(candidate) ? candidate : null;
|
|
1611
1874
|
}
|
|
1612
1875
|
return null;
|
|
1613
1876
|
}
|
|
@@ -1707,14 +1970,14 @@ async function detectCLI(cliId, providerLoader, options) {
|
|
|
1707
1970
|
const all = await detectCLIs(providerLoader, options);
|
|
1708
1971
|
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
1709
1972
|
}
|
|
1710
|
-
var import_child_process, os2, path8,
|
|
1973
|
+
var import_child_process, os2, path8, import_fs6;
|
|
1711
1974
|
var init_cli_detector = __esm({
|
|
1712
1975
|
"src/detection/cli-detector.ts"() {
|
|
1713
1976
|
"use strict";
|
|
1714
1977
|
import_child_process = require("child_process");
|
|
1715
1978
|
os2 = __toESM(require("os"));
|
|
1716
1979
|
path8 = __toESM(require("path"));
|
|
1717
|
-
|
|
1980
|
+
import_fs6 = require("fs");
|
|
1718
1981
|
}
|
|
1719
1982
|
});
|
|
1720
1983
|
|
|
@@ -1952,11 +2215,11 @@ function sweepExpiredRemoteIdleSessions() {
|
|
|
1952
2215
|
}
|
|
1953
2216
|
function getPendingEventsPath(meshId) {
|
|
1954
2217
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1955
|
-
return (0,
|
|
2218
|
+
return (0, import_path6.join)(getLedgerDir(), `${safe}.pending-events.jsonl`);
|
|
1956
2219
|
}
|
|
1957
2220
|
function queuePendingMeshCoordinatorEvent(event) {
|
|
1958
2221
|
try {
|
|
1959
|
-
(0,
|
|
2222
|
+
(0, import_fs7.appendFileSync)(getPendingEventsPath(event.meshId), JSON.stringify(event) + "\n", "utf-8");
|
|
1960
2223
|
return true;
|
|
1961
2224
|
} catch (e) {
|
|
1962
2225
|
LOG.warn("MeshEvents", `Failed to persist pending coordinator event: ${e?.message || e}`);
|
|
@@ -1966,11 +2229,11 @@ function queuePendingMeshCoordinatorEvent(event) {
|
|
|
1966
2229
|
function drainPendingMeshCoordinatorEvents(meshId) {
|
|
1967
2230
|
if (!meshId) return [];
|
|
1968
2231
|
const path28 = getPendingEventsPath(meshId);
|
|
1969
|
-
if (!(0,
|
|
2232
|
+
if (!(0, import_fs7.existsSync)(path28)) return [];
|
|
1970
2233
|
try {
|
|
1971
|
-
const raw = (0,
|
|
2234
|
+
const raw = (0, import_fs7.readFileSync)(path28, "utf-8");
|
|
1972
2235
|
try {
|
|
1973
|
-
(0,
|
|
2236
|
+
(0, import_fs7.unlinkSync)(path28);
|
|
1974
2237
|
} catch {
|
|
1975
2238
|
}
|
|
1976
2239
|
return raw.split("\n").filter(Boolean).flatMap((line) => {
|
|
@@ -1987,9 +2250,9 @@ function drainPendingMeshCoordinatorEvents(meshId) {
|
|
|
1987
2250
|
function getPendingMeshCoordinatorEvents(meshId) {
|
|
1988
2251
|
if (!meshId) return [];
|
|
1989
2252
|
const path28 = getPendingEventsPath(meshId);
|
|
1990
|
-
if (!(0,
|
|
2253
|
+
if (!(0, import_fs7.existsSync)(path28)) return [];
|
|
1991
2254
|
try {
|
|
1992
|
-
const raw = (0,
|
|
2255
|
+
const raw = (0, import_fs7.readFileSync)(path28, "utf-8");
|
|
1993
2256
|
return raw.split("\n").filter(Boolean).flatMap((line) => {
|
|
1994
2257
|
try {
|
|
1995
2258
|
return [JSON.parse(line)];
|
|
@@ -2004,8 +2267,8 @@ function getPendingMeshCoordinatorEvents(meshId) {
|
|
|
2004
2267
|
function clearPendingMeshCoordinatorEvents(meshId) {
|
|
2005
2268
|
if (!meshId) return;
|
|
2006
2269
|
const path28 = getPendingEventsPath(meshId);
|
|
2007
|
-
if ((0,
|
|
2008
|
-
(0,
|
|
2270
|
+
if ((0, import_fs7.existsSync)(path28)) try {
|
|
2271
|
+
(0, import_fs7.unlinkSync)(path28);
|
|
2009
2272
|
} catch {
|
|
2010
2273
|
}
|
|
2011
2274
|
}
|
|
@@ -2727,12 +2990,12 @@ function setupMeshEventForwarding(components) {
|
|
|
2727
2990
|
});
|
|
2728
2991
|
});
|
|
2729
2992
|
}
|
|
2730
|
-
var
|
|
2993
|
+
var import_fs7, import_path6, REMOTE_IDLE_SESSION_TTL_MS, remoteIdleSessions, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, RECENT_COMPLETION_FINGERPRINT_TTL_MS, recentCompletionFingerprints, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS;
|
|
2731
2994
|
var init_mesh_events = __esm({
|
|
2732
2995
|
"src/mesh/mesh-events.ts"() {
|
|
2733
2996
|
"use strict";
|
|
2734
|
-
|
|
2735
|
-
|
|
2997
|
+
import_fs7 = require("fs");
|
|
2998
|
+
import_path6 = require("path");
|
|
2736
2999
|
init_config();
|
|
2737
3000
|
init_mesh_config();
|
|
2738
3001
|
init_cli_detector();
|
|
@@ -5881,6 +6144,8 @@ __export(index_exports, {
|
|
|
5881
6144
|
InMemoryGitSnapshotStore: () => InMemoryGitSnapshotStore,
|
|
5882
6145
|
LOG: () => LOG,
|
|
5883
6146
|
MAX_LEDGER_SLICE_LIMIT: () => MAX_LEDGER_SLICE_LIMIT,
|
|
6147
|
+
MESH_REFINE_CONFIG_LOCATIONS: () => MESH_REFINE_CONFIG_LOCATIONS,
|
|
6148
|
+
MESH_REFINE_CONFIG_SCHEMA: () => MESH_REFINE_CONFIG_SCHEMA,
|
|
5884
6149
|
MIN_GIT_WORKSPACE_POLL_INTERVAL_MS: () => MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
|
|
5885
6150
|
MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS: () => MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
|
|
5886
6151
|
MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS: () => MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
|
|
@@ -5903,6 +6168,7 @@ __export(index_exports, {
|
|
|
5903
6168
|
buildChatTailDeliverySignature: () => buildChatTailDeliverySignature,
|
|
5904
6169
|
buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt,
|
|
5905
6170
|
buildMachineInfo: () => buildMachineInfo,
|
|
6171
|
+
buildMeshHostRequiredFailure: () => buildMeshHostRequiredFailure,
|
|
5906
6172
|
buildMeshLedgerReconciliationEvidence: () => buildMeshLedgerReconciliationEvidence,
|
|
5907
6173
|
buildMeshLedgerReplicaEvidence: () => buildMeshLedgerReplicaEvidence,
|
|
5908
6174
|
buildP2pRelayFailurePayload: () => buildP2pRelayFailurePayload,
|
|
@@ -5928,6 +6194,7 @@ __export(index_exports, {
|
|
|
5928
6194
|
connectCdpManager: () => connectCdpManager,
|
|
5929
6195
|
createDebugTraceStore: () => createDebugTraceStore,
|
|
5930
6196
|
createDefaultGitCommandServices: () => createDefaultGitCommandServices,
|
|
6197
|
+
createDefaultMeshHostMetadata: () => createDefaultMeshHostMetadata,
|
|
5931
6198
|
createGitCompactSummary: () => createGitCompactSummary,
|
|
5932
6199
|
createGitSnapshotStore: () => createGitSnapshotStore,
|
|
5933
6200
|
createGitWorkspaceMonitor: () => createGitWorkspaceMonitor,
|
|
@@ -5991,6 +6258,7 @@ __export(index_exports, {
|
|
|
5991
6258
|
isInternalChatMessage: () => isInternalChatMessage,
|
|
5992
6259
|
isManagedStatusWaiting: () => isManagedStatusWaiting,
|
|
5993
6260
|
isManagedStatusWorking: () => isManagedStatusWorking,
|
|
6261
|
+
isMeshHostOwner: () => isMeshHostOwner,
|
|
5994
6262
|
isP2pRelayTransportFailure: () => isP2pRelayTransportFailure,
|
|
5995
6263
|
isPathInside: () => isPathInside,
|
|
5996
6264
|
isSessionHostLiveRuntime: () => isSessionHostLiveRuntime,
|
|
@@ -6004,6 +6272,7 @@ __export(index_exports, {
|
|
|
6004
6272
|
listMeshes: () => listMeshes,
|
|
6005
6273
|
listWorktrees: () => listWorktrees,
|
|
6006
6274
|
loadConfig: () => loadConfig,
|
|
6275
|
+
loadMeshRefineConfig: () => loadMeshRefineConfig,
|
|
6007
6276
|
loadState: () => loadState,
|
|
6008
6277
|
logCommand: () => logCommand,
|
|
6009
6278
|
markSetupComplete: () => markSetupComplete,
|
|
@@ -6017,6 +6286,7 @@ __export(index_exports, {
|
|
|
6017
6286
|
normalizeGitWorkspaceSubscriptionParams: () => normalizeGitWorkspaceSubscriptionParams,
|
|
6018
6287
|
normalizeInputEnvelope: () => normalizeInputEnvelope,
|
|
6019
6288
|
normalizeManagedStatus: () => normalizeManagedStatus,
|
|
6289
|
+
normalizeMeshDaemonRole: () => normalizeMeshDaemonRole,
|
|
6020
6290
|
normalizeMessageParts: () => normalizeMessageParts,
|
|
6021
6291
|
normalizeRepoIdentity: () => normalizeRepoIdentity,
|
|
6022
6292
|
normalizeSessionModalFields: () => normalizeSessionModalFields,
|
|
@@ -6037,6 +6307,7 @@ __export(index_exports, {
|
|
|
6037
6307
|
removeNode: () => removeNode,
|
|
6038
6308
|
removeWorktree: () => removeWorktree,
|
|
6039
6309
|
requeueTask: () => requeueTask,
|
|
6310
|
+
requireMeshHostQueueOwner: () => requireMeshHostQueueOwner,
|
|
6040
6311
|
resetConfig: () => resetConfig,
|
|
6041
6312
|
resetDebugRuntimeConfig: () => resetDebugRuntimeConfig,
|
|
6042
6313
|
resetState: () => resetState,
|
|
@@ -6044,6 +6315,8 @@ __export(index_exports, {
|
|
|
6044
6315
|
resolveCurrentGlobalInstallSurface: () => resolveCurrentGlobalInstallSurface,
|
|
6045
6316
|
resolveDebugRuntimeConfig: () => resolveDebugRuntimeConfig,
|
|
6046
6317
|
resolveGitRepository: () => resolveGitRepository,
|
|
6318
|
+
resolveMeshHostStatus: () => resolveMeshHostStatus,
|
|
6319
|
+
resolveMeshRefineValidationPlan: () => resolveMeshRefineValidationPlan,
|
|
6047
6320
|
resolveSessionHostAppName: () => resolveSessionHostAppName,
|
|
6048
6321
|
resolveSessionHostAppNameResolution: () => resolveSessionHostAppNameResolution,
|
|
6049
6322
|
resolveWorktreePath: () => resolveWorktreePath,
|
|
@@ -6059,6 +6332,7 @@ __export(index_exports, {
|
|
|
6059
6332
|
shutdownDaemonComponents: () => shutdownDaemonComponents,
|
|
6060
6333
|
spawnDetachedDaemonUpgradeHelper: () => spawnDetachedDaemonUpgradeHelper,
|
|
6061
6334
|
startDaemonDevSupport: () => startDaemonDevSupport,
|
|
6335
|
+
suggestMeshRefineConfig: () => suggestMeshRefineConfig,
|
|
6062
6336
|
summarizeGitStatus: () => summarizeGitStatus,
|
|
6063
6337
|
syncMeshes: () => syncMeshes,
|
|
6064
6338
|
triggerMeshQueue: () => triggerMeshQueue,
|
|
@@ -6067,7 +6341,8 @@ __export(index_exports, {
|
|
|
6067
6341
|
updateNode: () => updateNode,
|
|
6068
6342
|
updateSessionTaskStatus: () => updateSessionTaskStatus,
|
|
6069
6343
|
updateTaskStatus: () => updateTaskStatus,
|
|
6070
|
-
upsertSavedProviderSession: () => upsertSavedProviderSession
|
|
6344
|
+
upsertSavedProviderSession: () => upsertSavedProviderSession,
|
|
6345
|
+
validateMeshRefineConfig: () => validateMeshRefineConfig
|
|
6071
6346
|
});
|
|
6072
6347
|
module.exports = __toCommonJS(index_exports);
|
|
6073
6348
|
init_repo_mesh_types();
|
|
@@ -7799,6 +8074,238 @@ function getSavedProviderSessions(state, filters) {
|
|
|
7799
8074
|
init_mesh_config();
|
|
7800
8075
|
init_coordinator_prompt();
|
|
7801
8076
|
|
|
8077
|
+
// src/mesh/refine-config.ts
|
|
8078
|
+
var import_fs3 = require("fs");
|
|
8079
|
+
var import_path3 = require("path");
|
|
8080
|
+
var yaml = __toESM(require("js-yaml"));
|
|
8081
|
+
var MESH_REFINE_VALIDATION_CATEGORIES = ["typecheck", "test", "lint", "build"];
|
|
8082
|
+
var MESH_REFINE_CONFIG_LOCATIONS = [
|
|
8083
|
+
".adhdev/refine.json",
|
|
8084
|
+
".adhdev/refine.yaml",
|
|
8085
|
+
".adhdev/refine.yml",
|
|
8086
|
+
".adhdev/repo-mesh-refine.json",
|
|
8087
|
+
".adhdev/repo-mesh-refine.yaml",
|
|
8088
|
+
".adhdev/repo-mesh-refine.yml",
|
|
8089
|
+
"repo-mesh.refine.json",
|
|
8090
|
+
"repo-mesh.refine.yaml",
|
|
8091
|
+
"repo-mesh.refine.yml"
|
|
8092
|
+
];
|
|
8093
|
+
var MESH_REFINE_CONFIG_SCHEMA = {
|
|
8094
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
8095
|
+
title: "ADHDev Repo Mesh Refinery Config",
|
|
8096
|
+
type: "object",
|
|
8097
|
+
additionalProperties: false,
|
|
8098
|
+
required: ["version"],
|
|
8099
|
+
properties: {
|
|
8100
|
+
version: { const: 1 },
|
|
8101
|
+
validation: {
|
|
8102
|
+
type: "object",
|
|
8103
|
+
additionalProperties: false,
|
|
8104
|
+
properties: {
|
|
8105
|
+
required: { type: "boolean", default: true },
|
|
8106
|
+
commands: {
|
|
8107
|
+
type: "array",
|
|
8108
|
+
minItems: 1,
|
|
8109
|
+
maxItems: 8,
|
|
8110
|
+
items: {
|
|
8111
|
+
type: "object",
|
|
8112
|
+
additionalProperties: false,
|
|
8113
|
+
required: ["command"],
|
|
8114
|
+
properties: {
|
|
8115
|
+
command: { type: "string", minLength: 1 },
|
|
8116
|
+
args: { type: "array", items: { type: "string" } },
|
|
8117
|
+
category: { enum: [...MESH_REFINE_VALIDATION_CATEGORIES, "custom"] },
|
|
8118
|
+
cwd: { type: "string" },
|
|
8119
|
+
timeoutMs: { type: "number", minimum: 1e3, maximum: 6e5 },
|
|
8120
|
+
env: { type: "object", additionalProperties: { type: "string" } }
|
|
8121
|
+
}
|
|
8122
|
+
}
|
|
8123
|
+
}
|
|
8124
|
+
}
|
|
8125
|
+
}
|
|
8126
|
+
}
|
|
8127
|
+
};
|
|
8128
|
+
function isRecord(value) {
|
|
8129
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
8130
|
+
}
|
|
8131
|
+
function tokenizeCommandString(command) {
|
|
8132
|
+
const trimmed = command.trim();
|
|
8133
|
+
if (!trimmed) return null;
|
|
8134
|
+
if (/[;&|<>`$\\\n\r'\"]/.test(trimmed)) return null;
|
|
8135
|
+
const tokens = trimmed.split(/\s+/).filter(Boolean);
|
|
8136
|
+
if (!tokens.length) return null;
|
|
8137
|
+
if (tokens.some((token) => !/^[A-Za-z0-9_@./:=+-]+$/.test(token))) return null;
|
|
8138
|
+
return tokens;
|
|
8139
|
+
}
|
|
8140
|
+
function validateCategory(value) {
|
|
8141
|
+
return typeof value === "string" && [...MESH_REFINE_VALIDATION_CATEGORIES, "custom"].includes(value) ? value : "custom";
|
|
8142
|
+
}
|
|
8143
|
+
function normalizeCommandConfig(entry, source) {
|
|
8144
|
+
if (!isRecord(entry) || typeof entry.command !== "string") {
|
|
8145
|
+
return { rejected: { source, reason: "validation command must be an object with a command string" } };
|
|
8146
|
+
}
|
|
8147
|
+
const commandText = entry.command.trim();
|
|
8148
|
+
const explicitArgs = Array.isArray(entry.args) ? entry.args : void 0;
|
|
8149
|
+
if (explicitArgs && !explicitArgs.every((arg) => typeof arg === "string")) {
|
|
8150
|
+
return { rejected: { source, command: commandText, reason: "args must be an array of strings" } };
|
|
8151
|
+
}
|
|
8152
|
+
let command = commandText;
|
|
8153
|
+
let args = explicitArgs ? [...explicitArgs] : [];
|
|
8154
|
+
if (!explicitArgs) {
|
|
8155
|
+
const tokens = tokenizeCommandString(commandText);
|
|
8156
|
+
if (!tokens) return { rejected: { source, command: commandText, reason: "unsafe command string is not allowlisted" } };
|
|
8157
|
+
command = tokens[0];
|
|
8158
|
+
args = tokens.slice(1);
|
|
8159
|
+
} else if (!tokenizeCommandString(command)) {
|
|
8160
|
+
return { rejected: { source, command: commandText, reason: "unsafe executable name is not allowlisted" } };
|
|
8161
|
+
}
|
|
8162
|
+
if (args.some((arg) => /[\n\r\0]/.test(arg))) {
|
|
8163
|
+
return { rejected: { source, command: commandText, reason: "args cannot contain control characters" } };
|
|
8164
|
+
}
|
|
8165
|
+
if (entry.cwd !== void 0 && typeof entry.cwd !== "string") {
|
|
8166
|
+
return { rejected: { source, command: commandText, reason: "cwd must be a string when provided" } };
|
|
8167
|
+
}
|
|
8168
|
+
if (entry.timeoutMs !== void 0 && (typeof entry.timeoutMs !== "number" || !Number.isFinite(entry.timeoutMs) || entry.timeoutMs < 1e3 || entry.timeoutMs > 6e5)) {
|
|
8169
|
+
return { rejected: { source, command: commandText, reason: "timeoutMs must be between 1000 and 600000" } };
|
|
8170
|
+
}
|
|
8171
|
+
if (entry.env !== void 0 && (!isRecord(entry.env) || !Object.values(entry.env).every((value) => typeof value === "string"))) {
|
|
8172
|
+
return { rejected: { source, command: commandText, reason: "env must be an object of string values" } };
|
|
8173
|
+
}
|
|
8174
|
+
return {
|
|
8175
|
+
command: {
|
|
8176
|
+
command,
|
|
8177
|
+
args,
|
|
8178
|
+
displayCommand: [command, ...args].join(" "),
|
|
8179
|
+
category: validateCategory(entry.category),
|
|
8180
|
+
source,
|
|
8181
|
+
...typeof entry.cwd === "string" && entry.cwd.trim() ? { cwd: entry.cwd.trim() } : {},
|
|
8182
|
+
...typeof entry.timeoutMs === "number" ? { timeoutMs: entry.timeoutMs } : {},
|
|
8183
|
+
...isRecord(entry.env) ? { env: entry.env } : {}
|
|
8184
|
+
}
|
|
8185
|
+
};
|
|
8186
|
+
}
|
|
8187
|
+
function validateMeshRefineConfig(config, source = "inline") {
|
|
8188
|
+
const errors = [];
|
|
8189
|
+
const commands = [];
|
|
8190
|
+
const rejectedCommands = [];
|
|
8191
|
+
if (!isRecord(config)) return { valid: false, errors: ["config must be an object"], commands, rejectedCommands };
|
|
8192
|
+
if (config.version !== 1) errors.push("version must be 1");
|
|
8193
|
+
const validation = config.validation;
|
|
8194
|
+
if (validation !== void 0 && !isRecord(validation)) errors.push("validation must be an object");
|
|
8195
|
+
const rawCommands = isRecord(validation) ? validation.commands : void 0;
|
|
8196
|
+
if (rawCommands !== void 0 && !Array.isArray(rawCommands)) errors.push("validation.commands must be an array");
|
|
8197
|
+
if (Array.isArray(rawCommands)) {
|
|
8198
|
+
rawCommands.forEach((entry, index) => {
|
|
8199
|
+
const normalized = normalizeCommandConfig(entry, `${source}:validation.commands[${index}]`);
|
|
8200
|
+
if (normalized.command) commands.push(normalized.command);
|
|
8201
|
+
if (normalized.rejected) rejectedCommands.push(normalized.rejected);
|
|
8202
|
+
});
|
|
8203
|
+
}
|
|
8204
|
+
if (rejectedCommands.length) errors.push("one or more validation commands are invalid");
|
|
8205
|
+
return { valid: errors.length === 0, errors, commands, rejectedCommands };
|
|
8206
|
+
}
|
|
8207
|
+
function parseConfigText(path28, text) {
|
|
8208
|
+
if (/\.json$/i.test(path28)) return JSON.parse(text);
|
|
8209
|
+
return yaml.load(text);
|
|
8210
|
+
}
|
|
8211
|
+
function loadMeshRefineConfig(mesh, workspace) {
|
|
8212
|
+
const policy = mesh?.policy && typeof mesh.policy === "object" && !Array.isArray(mesh.policy) ? mesh.policy : {};
|
|
8213
|
+
const inline = mesh?.refineConfig || policy.refineConfig || policy.refine;
|
|
8214
|
+
if (inline !== void 0) {
|
|
8215
|
+
const validation = validateMeshRefineConfig(inline, "mesh.policy.refineConfig");
|
|
8216
|
+
if (!validation.valid) return { source: "mesh.policy.refineConfig", sourceType: "invalid", error: String(validation.rejectedCommands[0]?.reason || validation.errors.join("; ")) };
|
|
8217
|
+
return { config: inline, source: "mesh.policy.refineConfig", sourceType: "mesh_policy" };
|
|
8218
|
+
}
|
|
8219
|
+
for (const relative3 of MESH_REFINE_CONFIG_LOCATIONS) {
|
|
8220
|
+
const configPath = (0, import_path3.join)(workspace, relative3);
|
|
8221
|
+
if (!(0, import_fs3.existsSync)(configPath)) continue;
|
|
8222
|
+
try {
|
|
8223
|
+
const parsed = parseConfigText(configPath, (0, import_fs3.readFileSync)(configPath, "utf-8"));
|
|
8224
|
+
const validation = validateMeshRefineConfig(parsed, relative3);
|
|
8225
|
+
if (!validation.valid) return { source: relative3, sourceType: "invalid", path: configPath, error: String(validation.rejectedCommands[0]?.reason || validation.errors.join("; ")) };
|
|
8226
|
+
return { config: parsed, source: relative3, sourceType: "repo_file", path: configPath };
|
|
8227
|
+
} catch (error) {
|
|
8228
|
+
return { source: relative3, sourceType: "invalid", path: configPath, error: error?.message || String(error) };
|
|
8229
|
+
}
|
|
8230
|
+
}
|
|
8231
|
+
return {
|
|
8232
|
+
source: "unavailable",
|
|
8233
|
+
sourceType: "unavailable",
|
|
8234
|
+
error: `No repo mesh/refine config found. Checked: ${MESH_REFINE_CONFIG_LOCATIONS.join(", ")}`
|
|
8235
|
+
};
|
|
8236
|
+
}
|
|
8237
|
+
function readPackageScripts(workspace) {
|
|
8238
|
+
try {
|
|
8239
|
+
const parsed = JSON.parse((0, import_fs3.readFileSync)((0, import_path3.join)(workspace, "package.json"), "utf-8"));
|
|
8240
|
+
return isRecord(parsed?.scripts) ? parsed.scripts : {};
|
|
8241
|
+
} catch {
|
|
8242
|
+
return {};
|
|
8243
|
+
}
|
|
8244
|
+
}
|
|
8245
|
+
function collectProjectContextSuggestions(mesh) {
|
|
8246
|
+
const commands = mesh?.projectContext?.commands;
|
|
8247
|
+
if (!isRecord(commands)) return [];
|
|
8248
|
+
const suggestions = [];
|
|
8249
|
+
for (const category of MESH_REFINE_VALIDATION_CATEGORIES) {
|
|
8250
|
+
const entries = Array.isArray(commands[category]) ? commands[category] : [];
|
|
8251
|
+
for (const entry of entries) {
|
|
8252
|
+
if (isRecord(entry) && typeof entry.command === "string") suggestions.push({ command: entry.command, category });
|
|
8253
|
+
}
|
|
8254
|
+
}
|
|
8255
|
+
return suggestions;
|
|
8256
|
+
}
|
|
8257
|
+
function collectPackageScriptSuggestions(workspace) {
|
|
8258
|
+
const scripts = readPackageScripts(workspace);
|
|
8259
|
+
const suggestions = [];
|
|
8260
|
+
for (const category of MESH_REFINE_VALIDATION_CATEGORIES) {
|
|
8261
|
+
for (const scriptName of Object.keys(scripts)) {
|
|
8262
|
+
if (scriptName === category || scriptName.startsWith(`${category}:`)) {
|
|
8263
|
+
suggestions.push({ command: "npm", args: ["run", scriptName], category });
|
|
8264
|
+
}
|
|
8265
|
+
}
|
|
8266
|
+
}
|
|
8267
|
+
return suggestions;
|
|
8268
|
+
}
|
|
8269
|
+
function suggestMeshRefineConfig(mesh, workspace) {
|
|
8270
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8271
|
+
const suggestions = [];
|
|
8272
|
+
for (const entry of [...collectProjectContextSuggestions(mesh), ...collectPackageScriptSuggestions(workspace)]) {
|
|
8273
|
+
const key = `${entry.command} ${(entry.args || []).join(" ")}`.trim();
|
|
8274
|
+
if (seen.has(key)) continue;
|
|
8275
|
+
seen.add(key);
|
|
8276
|
+
suggestions.push(entry);
|
|
8277
|
+
}
|
|
8278
|
+
return {
|
|
8279
|
+
suggestions,
|
|
8280
|
+
suggestedConfig: suggestions.length ? { version: 1, validation: { required: true, commands: suggestions.slice(0, 4) } } : void 0
|
|
8281
|
+
};
|
|
8282
|
+
}
|
|
8283
|
+
function resolveMeshRefineValidationPlan(mesh, workspace) {
|
|
8284
|
+
const loaded = loadMeshRefineConfig(mesh, workspace);
|
|
8285
|
+
const suggestion = suggestMeshRefineConfig(mesh, workspace);
|
|
8286
|
+
if (!loaded.config) {
|
|
8287
|
+
return {
|
|
8288
|
+
source: loaded.source,
|
|
8289
|
+
sourceType: loaded.sourceType,
|
|
8290
|
+
commands: [],
|
|
8291
|
+
rejectedCommands: loaded.error ? [{ source: loaded.source, reason: loaded.error }] : [],
|
|
8292
|
+
suggestions: suggestion.suggestions,
|
|
8293
|
+
suggestedConfig: suggestion.suggestedConfig,
|
|
8294
|
+
unavailableReason: loaded.error || "validation_unavailable: repo mesh/refine config missing"
|
|
8295
|
+
};
|
|
8296
|
+
}
|
|
8297
|
+
const validation = validateMeshRefineConfig(loaded.config, loaded.source);
|
|
8298
|
+
return {
|
|
8299
|
+
source: loaded.path || loaded.source,
|
|
8300
|
+
sourceType: loaded.sourceType,
|
|
8301
|
+
commands: validation.commands,
|
|
8302
|
+
rejectedCommands: validation.rejectedCommands,
|
|
8303
|
+
suggestions: suggestion.suggestions,
|
|
8304
|
+
suggestedConfig: suggestion.suggestedConfig,
|
|
8305
|
+
unavailableReason: validation.commands.length ? void 0 : "validation_unavailable: repo mesh/refine config has no validation.commands"
|
|
8306
|
+
};
|
|
8307
|
+
}
|
|
8308
|
+
|
|
7802
8309
|
// src/mesh/mesh-sync.ts
|
|
7803
8310
|
init_mesh_config();
|
|
7804
8311
|
async function syncMeshes(transport) {
|
|
@@ -7918,6 +8425,7 @@ function buildMeshLedgerReconciliationEvidence(meshId, replicas) {
|
|
|
7918
8425
|
|
|
7919
8426
|
// src/index.ts
|
|
7920
8427
|
init_mesh_work_queue();
|
|
8428
|
+
init_mesh_host_ownership();
|
|
7921
8429
|
init_mesh_events();
|
|
7922
8430
|
|
|
7923
8431
|
// src/mesh/p2p-relay-failure.ts
|
|
@@ -8031,8 +8539,8 @@ var P2pRelayFailureError = class extends Error {
|
|
|
8031
8539
|
};
|
|
8032
8540
|
|
|
8033
8541
|
// src/config/state-store.ts
|
|
8034
|
-
var
|
|
8035
|
-
var
|
|
8542
|
+
var import_fs8 = require("fs");
|
|
8543
|
+
var import_path7 = require("path");
|
|
8036
8544
|
init_config();
|
|
8037
8545
|
var DEFAULT_STATE = {
|
|
8038
8546
|
recentActivity: [],
|
|
@@ -8046,7 +8554,7 @@ function isPlainObject2(value) {
|
|
|
8046
8554
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
8047
8555
|
}
|
|
8048
8556
|
function getStatePath() {
|
|
8049
|
-
return (0,
|
|
8557
|
+
return (0, import_path7.join)(getConfigDir(), "state.json");
|
|
8050
8558
|
}
|
|
8051
8559
|
function normalizeState(raw) {
|
|
8052
8560
|
const parsed = isPlainObject2(raw) ? raw : {};
|
|
@@ -8082,11 +8590,11 @@ function normalizeState(raw) {
|
|
|
8082
8590
|
}
|
|
8083
8591
|
function loadState() {
|
|
8084
8592
|
const statePath = getStatePath();
|
|
8085
|
-
if (!(0,
|
|
8593
|
+
if (!(0, import_fs8.existsSync)(statePath)) {
|
|
8086
8594
|
return { ...DEFAULT_STATE };
|
|
8087
8595
|
}
|
|
8088
8596
|
try {
|
|
8089
|
-
const raw = (0,
|
|
8597
|
+
const raw = (0, import_fs8.readFileSync)(statePath, "utf-8");
|
|
8090
8598
|
return normalizeState(JSON.parse(raw));
|
|
8091
8599
|
} catch {
|
|
8092
8600
|
return { ...DEFAULT_STATE };
|
|
@@ -8095,7 +8603,7 @@ function loadState() {
|
|
|
8095
8603
|
function saveState(state) {
|
|
8096
8604
|
const statePath = getStatePath();
|
|
8097
8605
|
const normalized = normalizeState(state);
|
|
8098
|
-
(0,
|
|
8606
|
+
(0, import_fs8.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
|
|
8099
8607
|
}
|
|
8100
8608
|
function resetState() {
|
|
8101
8609
|
saveState({ ...DEFAULT_STATE });
|
|
@@ -8103,7 +8611,7 @@ function resetState() {
|
|
|
8103
8611
|
|
|
8104
8612
|
// src/detection/ide-detector.ts
|
|
8105
8613
|
var import_child_process2 = require("child_process");
|
|
8106
|
-
var
|
|
8614
|
+
var import_fs9 = require("fs");
|
|
8107
8615
|
var import_os2 = require("os");
|
|
8108
8616
|
var path10 = __toESM(require("path"));
|
|
8109
8617
|
var BUILTIN_IDE_DEFINITIONS = [];
|
|
@@ -8127,7 +8635,7 @@ function findCliCommand(command) {
|
|
|
8127
8635
|
if (path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
8128
8636
|
const candidate = trimmed.startsWith("~") ? path10.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
|
|
8129
8637
|
const resolved = path10.isAbsolute(candidate) ? candidate : path10.resolve(candidate);
|
|
8130
|
-
return (0,
|
|
8638
|
+
return (0, import_fs9.existsSync)(resolved) ? resolved : null;
|
|
8131
8639
|
}
|
|
8132
8640
|
try {
|
|
8133
8641
|
const result = (0, import_child_process2.execSync)(
|
|
@@ -8158,9 +8666,9 @@ function checkPathExists(paths) {
|
|
|
8158
8666
|
if (normalized.includes("*")) {
|
|
8159
8667
|
const username = home.split(/[\\/]/).pop() || "";
|
|
8160
8668
|
const resolved = normalized.replace("*", username);
|
|
8161
|
-
if ((0,
|
|
8669
|
+
if ((0, import_fs9.existsSync)(resolved)) return resolved;
|
|
8162
8670
|
} else {
|
|
8163
|
-
if ((0,
|
|
8671
|
+
if ((0, import_fs9.existsSync)(normalized)) return normalized;
|
|
8164
8672
|
}
|
|
8165
8673
|
}
|
|
8166
8674
|
return null;
|
|
@@ -8174,7 +8682,7 @@ async function detectIDEs(providerLoader) {
|
|
|
8174
8682
|
let resolvedCli = cliPath;
|
|
8175
8683
|
if (!resolvedCli && appPath && os22 === "darwin") {
|
|
8176
8684
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
8177
|
-
if ((0,
|
|
8685
|
+
if ((0, import_fs9.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
8178
8686
|
}
|
|
8179
8687
|
if (!resolvedCli && appPath && os22 === "win32") {
|
|
8180
8688
|
const { dirname: dirname9 } = await import("path");
|
|
@@ -8187,7 +8695,7 @@ async function detectIDEs(providerLoader) {
|
|
|
8187
8695
|
`${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
|
|
8188
8696
|
];
|
|
8189
8697
|
for (const c of candidates) {
|
|
8190
|
-
if ((0,
|
|
8698
|
+
if ((0, import_fs9.existsSync)(c)) {
|
|
8191
8699
|
resolvedCli = c;
|
|
8192
8700
|
break;
|
|
8193
8701
|
}
|
|
@@ -17340,7 +17848,7 @@ var DaemonCommandHandler = class {
|
|
|
17340
17848
|
var os13 = __toESM(require("os"));
|
|
17341
17849
|
var path18 = __toESM(require("path"));
|
|
17342
17850
|
var crypto4 = __toESM(require("crypto"));
|
|
17343
|
-
var
|
|
17851
|
+
var import_fs10 = require("fs");
|
|
17344
17852
|
var import_child_process6 = require("child_process");
|
|
17345
17853
|
var import_chalk = __toESM(require("chalk"));
|
|
17346
17854
|
init_provider_cli_adapter();
|
|
@@ -19812,7 +20320,7 @@ function commandExists(command) {
|
|
|
19812
20320
|
const trimmed = command.trim();
|
|
19813
20321
|
if (!trimmed) return false;
|
|
19814
20322
|
if (isExplicitCommand(trimmed)) {
|
|
19815
|
-
return (0,
|
|
20323
|
+
return (0, import_fs10.existsSync)(expandExecutable(trimmed));
|
|
19816
20324
|
}
|
|
19817
20325
|
try {
|
|
19818
20326
|
(0, import_child_process6.execFileSync)(process.platform === "win32" ? "where" : "which", [trimmed], {
|
|
@@ -19841,10 +20349,10 @@ function hasCliArg(args, flag) {
|
|
|
19841
20349
|
}
|
|
19842
20350
|
function ensureEmptyDelegatedMcpConfig(workspace) {
|
|
19843
20351
|
const baseDir = path18.join(os13.tmpdir(), "adhdev-delegated-agent-empty-mcp");
|
|
19844
|
-
(0,
|
|
20352
|
+
(0, import_fs10.mkdirSync)(baseDir, { recursive: true });
|
|
19845
20353
|
const workspaceHash = crypto4.createHash("sha256").update(path18.resolve(workspace || os13.tmpdir())).digest("hex").slice(0, 16);
|
|
19846
20354
|
const filePath = path18.join(baseDir, `${workspaceHash}.json`);
|
|
19847
|
-
(0,
|
|
20355
|
+
(0, import_fs10.writeFileSync)(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
|
|
19848
20356
|
return filePath;
|
|
19849
20357
|
}
|
|
19850
20358
|
function buildCoordinatorDelegatedCliLaunchOptions(input) {
|
|
@@ -23075,7 +23583,7 @@ function getRecentCommands(count = 50) {
|
|
|
23075
23583
|
cleanOldFiles();
|
|
23076
23584
|
|
|
23077
23585
|
// src/commands/router.ts
|
|
23078
|
-
var
|
|
23586
|
+
var yaml2 = __toESM(require("js-yaml"));
|
|
23079
23587
|
init_logger();
|
|
23080
23588
|
|
|
23081
23589
|
// src/commands/mesh-coordinator.ts
|
|
@@ -23369,6 +23877,7 @@ function normalizeExistingPath(filePath) {
|
|
|
23369
23877
|
|
|
23370
23878
|
// src/commands/router.ts
|
|
23371
23879
|
init_mesh_events();
|
|
23880
|
+
init_mesh_host_ownership();
|
|
23372
23881
|
|
|
23373
23882
|
// src/status/snapshot.ts
|
|
23374
23883
|
var os18 = __toESM(require("os"));
|
|
@@ -24023,7 +24532,7 @@ async function maybeRunDaemonUpgradeHelperFromEnv() {
|
|
|
24023
24532
|
|
|
24024
24533
|
// src/commands/router.ts
|
|
24025
24534
|
var import_os3 = require("os");
|
|
24026
|
-
var
|
|
24535
|
+
var import_path8 = require("path");
|
|
24027
24536
|
var fs10 = __toESM(require("fs"));
|
|
24028
24537
|
var CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
|
|
24029
24538
|
var CHANNEL_SERVER_URL = {
|
|
@@ -24664,11 +25173,9 @@ async function resolveProviderTypeFromPriority(args) {
|
|
|
24664
25173
|
}
|
|
24665
25174
|
return { error: `No usable provider detected for node '${args.nodeId}' from providerPriority: ${failed.join("; ")}` };
|
|
24666
25175
|
}
|
|
24667
|
-
var REFINE_VALIDATION_CATEGORIES = ["typecheck", "test", "lint", "build"];
|
|
24668
25176
|
var REFINE_VALIDATION_TIMEOUT_MS = 12e4;
|
|
24669
25177
|
var REFINE_VALIDATION_OUTPUT_LIMIT_BYTES = 128 * 1024;
|
|
24670
25178
|
var REFINE_VALIDATION_SUMMARY_CHARS = 2e3;
|
|
24671
|
-
var REFINE_VALIDATION_MAX_COMMANDS = 4;
|
|
24672
25179
|
var REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES = 4 * 1024 * 1024;
|
|
24673
25180
|
function truncateValidationOutput(value) {
|
|
24674
25181
|
const text = typeof value === "string" ? value : value == null ? "" : String(value);
|
|
@@ -24752,141 +25259,30 @@ async function runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead)
|
|
|
24752
25259
|
};
|
|
24753
25260
|
}
|
|
24754
25261
|
}
|
|
24755
|
-
function
|
|
24756
|
-
|
|
24757
|
-
const packageJsonPath = (0, import_path7.join)(workspace, "package.json");
|
|
24758
|
-
const parsed = JSON.parse(fs10.readFileSync(packageJsonPath, "utf-8"));
|
|
24759
|
-
return parsed?.scripts && typeof parsed.scripts === "object" && !Array.isArray(parsed.scripts) ? parsed.scripts : {};
|
|
24760
|
-
} catch {
|
|
24761
|
-
return {};
|
|
24762
|
-
}
|
|
24763
|
-
}
|
|
24764
|
-
function tokenizeValidationCommand(command) {
|
|
24765
|
-
const trimmed = command.trim();
|
|
24766
|
-
if (!trimmed) return null;
|
|
24767
|
-
if (/[;&|<>`$\\\n\r'\"]/.test(trimmed)) return null;
|
|
24768
|
-
const tokens = trimmed.split(/\s+/).filter(Boolean);
|
|
24769
|
-
if (!tokens.length) return null;
|
|
24770
|
-
if (tokens.some((token) => !/^[A-Za-z0-9_@./:=+-]+$/.test(token))) return null;
|
|
24771
|
-
return tokens;
|
|
24772
|
-
}
|
|
24773
|
-
function scriptMatchesValidationCategory(scriptName, category) {
|
|
24774
|
-
return scriptName === category || scriptName.startsWith(`${category}:`);
|
|
24775
|
-
}
|
|
24776
|
-
function parsePackageManagerValidationCommand(rawCommand, category, scripts, source) {
|
|
24777
|
-
const tokens = tokenizeValidationCommand(rawCommand);
|
|
24778
|
-
if (!tokens) {
|
|
24779
|
-
return { rejected: { command: rawCommand, category, source, reason: "unsafe command string is not allowlisted" } };
|
|
24780
|
-
}
|
|
24781
|
-
const [binary, second, third, ...rest] = tokens;
|
|
24782
|
-
let scriptName = "";
|
|
24783
|
-
let command = binary;
|
|
24784
|
-
let args = [];
|
|
24785
|
-
if ((binary === "npm" || binary === "pnpm" || binary === "bun") && second === "run" && third) {
|
|
24786
|
-
scriptName = third;
|
|
24787
|
-
args = ["run", scriptName, ...rest];
|
|
24788
|
-
} else if (binary === "npm" && second === "test" && !third) {
|
|
24789
|
-
scriptName = "test";
|
|
24790
|
-
args = ["test"];
|
|
24791
|
-
} else if (binary === "yarn" && second === "run" && third) {
|
|
24792
|
-
scriptName = third;
|
|
24793
|
-
args = ["run", scriptName, ...rest];
|
|
24794
|
-
} else if (binary === "yarn" && second && !third) {
|
|
24795
|
-
scriptName = second;
|
|
24796
|
-
args = [scriptName];
|
|
24797
|
-
} else {
|
|
24798
|
-
return { rejected: { command: rawCommand, category, source, reason: "command is not a supported package-manager script invocation" } };
|
|
24799
|
-
}
|
|
24800
|
-
if (!scriptName || !Object.prototype.hasOwnProperty.call(scripts, scriptName)) {
|
|
24801
|
-
return { rejected: { command: rawCommand, category, source, script: scriptName, reason: "script is not declared in package.json" } };
|
|
24802
|
-
}
|
|
24803
|
-
if (!scriptMatchesValidationCategory(scriptName, category)) {
|
|
24804
|
-
return { rejected: { command: rawCommand, category, source, script: scriptName, reason: "script name is outside the validation category allowlist" } };
|
|
24805
|
-
}
|
|
24806
|
-
return {
|
|
24807
|
-
command: {
|
|
24808
|
-
command,
|
|
24809
|
-
args,
|
|
24810
|
-
displayCommand: [command, ...args].join(" "),
|
|
24811
|
-
category,
|
|
24812
|
-
source
|
|
24813
|
-
}
|
|
24814
|
-
};
|
|
24815
|
-
}
|
|
24816
|
-
function collectProjectContextValidationCandidates(mesh) {
|
|
24817
|
-
const commands = mesh?.projectContext?.commands;
|
|
24818
|
-
if (!commands || typeof commands !== "object" || Array.isArray(commands)) return [];
|
|
24819
|
-
const candidates = [];
|
|
24820
|
-
for (const category of REFINE_VALIDATION_CATEGORIES) {
|
|
24821
|
-
const entries = Array.isArray(commands[category]) ? commands[category] : [];
|
|
24822
|
-
for (const entry of entries) {
|
|
24823
|
-
if (typeof entry?.command !== "string") continue;
|
|
24824
|
-
candidates.push({
|
|
24825
|
-
command: entry.command,
|
|
24826
|
-
category,
|
|
24827
|
-
source: typeof entry.sourcePath === "string" ? entry.sourcePath : "projectContext.commands",
|
|
24828
|
-
confidence: typeof entry.confidence === "string" ? entry.confidence : void 0
|
|
24829
|
-
});
|
|
24830
|
-
}
|
|
24831
|
-
}
|
|
24832
|
-
return candidates.sort((a, b) => {
|
|
24833
|
-
const rank = (value) => value === "high" ? 0 : value === "medium" ? 1 : 2;
|
|
24834
|
-
return rank(a.confidence) - rank(b.confidence);
|
|
24835
|
-
});
|
|
24836
|
-
}
|
|
24837
|
-
function collectPolicyValidationCandidates(mesh) {
|
|
24838
|
-
const policy = mesh?.policy && typeof mesh.policy === "object" && !Array.isArray(mesh.policy) ? mesh.policy : {};
|
|
24839
|
-
const configured = Array.isArray(policy.validationCommands) ? policy.validationCommands : Array.isArray(policy.validationGate?.commands) ? policy.validationGate.commands : [];
|
|
24840
|
-
return configured.map((entry) => typeof entry === "string" ? { command: entry, category: "", source: "mesh.policy.validationCommands" } : entry).filter((entry) => entry && typeof entry.command === "string").map((entry) => {
|
|
24841
|
-
const commandText = entry.command.trim();
|
|
24842
|
-
const category = REFINE_VALIDATION_CATEGORIES.find((cat) => commandText.includes(` ${cat}`)) ?? "";
|
|
24843
|
-
return { command: commandText, category, source: "mesh.policy.validationCommands" };
|
|
24844
|
-
}).filter((entry) => !!entry.category);
|
|
24845
|
-
}
|
|
24846
|
-
function selectMeshRefineValidationCommands(mesh, workspace) {
|
|
24847
|
-
const scripts = readPackageScripts(workspace);
|
|
24848
|
-
const rejectedCommands = [];
|
|
24849
|
-
const selected = [];
|
|
24850
|
-
const seen = /* @__PURE__ */ new Set();
|
|
24851
|
-
const candidates = [
|
|
24852
|
-
...collectPolicyValidationCandidates(mesh),
|
|
24853
|
-
...collectProjectContextValidationCandidates(mesh)
|
|
24854
|
-
];
|
|
24855
|
-
for (const candidate of candidates) {
|
|
24856
|
-
const parsed = parsePackageManagerValidationCommand(candidate.command, candidate.category, scripts, candidate.source);
|
|
24857
|
-
if (parsed.rejected) {
|
|
24858
|
-
rejectedCommands.push(parsed.rejected);
|
|
24859
|
-
continue;
|
|
24860
|
-
}
|
|
24861
|
-
if (!parsed.command || seen.has(parsed.command.displayCommand)) continue;
|
|
24862
|
-
selected.push(parsed.command);
|
|
24863
|
-
seen.add(parsed.command.displayCommand);
|
|
24864
|
-
if (selected.length >= REFINE_VALIDATION_MAX_COMMANDS) break;
|
|
24865
|
-
}
|
|
24866
|
-
if (!selected.length && candidates.length === 0) {
|
|
24867
|
-
for (const category of REFINE_VALIDATION_CATEGORIES) {
|
|
24868
|
-
if (!Object.prototype.hasOwnProperty.call(scripts, category)) continue;
|
|
24869
|
-
const fallback = parsePackageManagerValidationCommand(`npm run ${category}`, category, scripts, "package.json:scripts");
|
|
24870
|
-
if (fallback.command && !seen.has(fallback.command.displayCommand)) {
|
|
24871
|
-
selected.push(fallback.command);
|
|
24872
|
-
seen.add(fallback.command.displayCommand);
|
|
24873
|
-
} else if (fallback.rejected) {
|
|
24874
|
-
rejectedCommands.push(fallback.rejected);
|
|
24875
|
-
}
|
|
24876
|
-
if (selected.length >= 2) break;
|
|
24877
|
-
}
|
|
24878
|
-
}
|
|
25262
|
+
function buildMeshRefineValidationPlan(mesh, workspace) {
|
|
25263
|
+
const plan = resolveMeshRefineValidationPlan(mesh, workspace);
|
|
24879
25264
|
return {
|
|
24880
|
-
|
|
24881
|
-
|
|
24882
|
-
|
|
25265
|
+
source: plan.source,
|
|
25266
|
+
sourceType: plan.sourceType,
|
|
25267
|
+
commands: plan.commands.map((command) => ({
|
|
25268
|
+
displayCommand: command.displayCommand,
|
|
25269
|
+
category: command.category,
|
|
25270
|
+
source: command.source,
|
|
25271
|
+
cwd: command.cwd,
|
|
25272
|
+
timeoutMs: command.timeoutMs
|
|
25273
|
+
})),
|
|
25274
|
+
unavailableReason: plan.unavailableReason,
|
|
25275
|
+
rejectedCommands: plan.rejectedCommands,
|
|
25276
|
+
suggestions: plan.suggestions,
|
|
25277
|
+
suggestedConfig: plan.suggestedConfig,
|
|
25278
|
+
note: plan.sourceType === "unavailable" ? "No validation command will be executed until a repo mesh/refine config is provided. Heuristics are suggestions only." : "Validation commands are resolved from repo mesh/refine config; heuristics are suggestions only."
|
|
24883
25279
|
};
|
|
24884
25280
|
}
|
|
24885
25281
|
async function runMeshRefineValidationGate(mesh, workspace) {
|
|
24886
25282
|
const { execFile: execFile3 } = await import("child_process");
|
|
24887
25283
|
const { promisify: promisify3 } = await import("util");
|
|
24888
25284
|
const execFileAsync3 = promisify3(execFile3);
|
|
24889
|
-
const selection =
|
|
25285
|
+
const selection = resolveMeshRefineValidationPlan(mesh, workspace);
|
|
24890
25286
|
const summary = {
|
|
24891
25287
|
status: "skipped",
|
|
24892
25288
|
required: true,
|
|
@@ -24894,21 +25290,27 @@ async function runMeshRefineValidationGate(mesh, workspace) {
|
|
|
24894
25290
|
rejectedCommands: selection.rejectedCommands,
|
|
24895
25291
|
skippedReason: void 0,
|
|
24896
25292
|
timeoutMs: REFINE_VALIDATION_TIMEOUT_MS,
|
|
24897
|
-
outputLimitBytes: REFINE_VALIDATION_OUTPUT_LIMIT_BYTES
|
|
25293
|
+
outputLimitBytes: REFINE_VALIDATION_OUTPUT_LIMIT_BYTES,
|
|
25294
|
+
configSource: selection.source,
|
|
25295
|
+
configSourceType: selection.sourceType,
|
|
25296
|
+
suggestions: selection.suggestions,
|
|
25297
|
+
suggestedConfig: selection.suggestedConfig
|
|
24898
25298
|
};
|
|
24899
25299
|
if (!selection.commands.length) {
|
|
24900
|
-
summary.skippedReason = "validation_unavailable:
|
|
25300
|
+
summary.skippedReason = selection.unavailableReason || "validation_unavailable: repo mesh/refine config did not provide executable validation.commands";
|
|
24901
25301
|
return summary;
|
|
24902
25302
|
}
|
|
24903
25303
|
for (const candidate of selection.commands) {
|
|
24904
25304
|
const startedAt = Date.now();
|
|
25305
|
+
const cwd = candidate.cwd ? (0, import_path8.resolve)(workspace, candidate.cwd) : workspace;
|
|
25306
|
+
const timeout = candidate.timeoutMs || REFINE_VALIDATION_TIMEOUT_MS;
|
|
24905
25307
|
try {
|
|
24906
25308
|
const result = await execFileAsync3(candidate.command, candidate.args, {
|
|
24907
|
-
cwd
|
|
25309
|
+
cwd,
|
|
24908
25310
|
encoding: "utf8",
|
|
24909
|
-
timeout
|
|
25311
|
+
timeout,
|
|
24910
25312
|
maxBuffer: REFINE_VALIDATION_OUTPUT_LIMIT_BYTES,
|
|
24911
|
-
env: { ...process.env, CI: process.env.CI || "1" }
|
|
25313
|
+
env: { ...process.env, CI: process.env.CI || "1", ...candidate.env || {} }
|
|
24912
25314
|
});
|
|
24913
25315
|
summary.commandsRun.push({
|
|
24914
25316
|
command: candidate.command,
|
|
@@ -24916,6 +25318,7 @@ async function runMeshRefineValidationGate(mesh, workspace) {
|
|
|
24916
25318
|
displayCommand: candidate.displayCommand,
|
|
24917
25319
|
category: candidate.category,
|
|
24918
25320
|
source: candidate.source,
|
|
25321
|
+
cwd,
|
|
24919
25322
|
passed: true,
|
|
24920
25323
|
exitCode: 0,
|
|
24921
25324
|
durationMs: Date.now() - startedAt,
|
|
@@ -24929,6 +25332,7 @@ async function runMeshRefineValidationGate(mesh, workspace) {
|
|
|
24929
25332
|
displayCommand: candidate.displayCommand,
|
|
24930
25333
|
category: candidate.category,
|
|
24931
25334
|
source: candidate.source,
|
|
25335
|
+
cwd,
|
|
24932
25336
|
passed: false,
|
|
24933
25337
|
exitCode: typeof error?.code === "number" ? error.code : null,
|
|
24934
25338
|
signal: typeof error?.signal === "string" ? error.signal : null,
|
|
@@ -24945,7 +25349,7 @@ async function runMeshRefineValidationGate(mesh, workspace) {
|
|
|
24945
25349
|
return summary;
|
|
24946
25350
|
}
|
|
24947
25351
|
function loadYamlModule() {
|
|
24948
|
-
return
|
|
25352
|
+
return yaml2;
|
|
24949
25353
|
}
|
|
24950
25354
|
function getMcpServersKey(format) {
|
|
24951
25355
|
return format === "hermes_config_yaml" ? "mcp_servers" : "mcpServers";
|
|
@@ -24962,13 +25366,13 @@ function serializeMeshCoordinatorMcpConfig(config, format) {
|
|
|
24962
25366
|
}
|
|
24963
25367
|
function resolveHermesUserHome() {
|
|
24964
25368
|
const explicitHome = process.env.HERMES_HOME?.trim();
|
|
24965
|
-
return explicitHome || (0,
|
|
25369
|
+
return explicitHome || (0, import_path8.join)((0, import_os3.homedir)(), ".hermes");
|
|
24966
25370
|
}
|
|
24967
25371
|
function loadHermesCoordinatorBaseConfig(targetConfigPath) {
|
|
24968
25372
|
const sourceHome = resolveHermesUserHome();
|
|
24969
|
-
const sourceConfigPath = (0,
|
|
25373
|
+
const sourceConfigPath = (0, import_path8.join)(sourceHome, "config.yaml");
|
|
24970
25374
|
if (!fs10.existsSync(sourceConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
24971
|
-
if ((0,
|
|
25375
|
+
if ((0, import_path8.resolve)(sourceConfigPath) === (0, import_path8.resolve)(targetConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
24972
25376
|
const parsed = parseMeshCoordinatorMcpConfig(fs10.readFileSync(sourceConfigPath, "utf-8"), "hermes_config_yaml");
|
|
24973
25377
|
const { mcp_servers: _mcpServers, ...baseConfig } = parsed;
|
|
24974
25378
|
return { config: baseConfig, sourceHome, sourceConfigPath };
|
|
@@ -25002,10 +25406,10 @@ function stripHermesCoordinatorTempModelProviderOverrides(config) {
|
|
|
25002
25406
|
return sanitized;
|
|
25003
25407
|
}
|
|
25004
25408
|
function copyHermesCoordinatorCredentialFiles(sourceHome, targetHome) {
|
|
25005
|
-
if ((0,
|
|
25409
|
+
if ((0, import_path8.resolve)(sourceHome) === (0, import_path8.resolve)(targetHome)) return;
|
|
25006
25410
|
for (const fileName of [".env", "auth.json"]) {
|
|
25007
|
-
const sourcePath = (0,
|
|
25008
|
-
const targetPath = (0,
|
|
25411
|
+
const sourcePath = (0, import_path8.join)(sourceHome, fileName);
|
|
25412
|
+
const targetPath = (0, import_path8.join)(targetHome, fileName);
|
|
25009
25413
|
if (!fs10.existsSync(sourcePath)) continue;
|
|
25010
25414
|
try {
|
|
25011
25415
|
fs10.copyFileSync(sourcePath, targetPath);
|
|
@@ -25103,6 +25507,34 @@ function summarizeSessionHostPruneResult(result) {
|
|
|
25103
25507
|
keptCount: Array.isArray(value.keptSessionIds) ? value.keptSessionIds.length : void 0
|
|
25104
25508
|
};
|
|
25105
25509
|
}
|
|
25510
|
+
function normalizeStandaloneHostCommandUrl(hostAddress) {
|
|
25511
|
+
const raw = hostAddress.trim();
|
|
25512
|
+
if (!raw) throw new Error("hostAddress required");
|
|
25513
|
+
const url = new URL(raw.replace(/^ws:/, "http:").replace(/^wss:/, "https:"));
|
|
25514
|
+
url.pathname = "/api/v1/command";
|
|
25515
|
+
url.search = "";
|
|
25516
|
+
url.hash = "";
|
|
25517
|
+
return url.toString();
|
|
25518
|
+
}
|
|
25519
|
+
function buildMemberJoinNode(mesh, args, fallbackDaemonId) {
|
|
25520
|
+
const requestedNodeId = typeof args?.memberNodeId === "string" ? args.memberNodeId.trim() : "";
|
|
25521
|
+
const explicit = args?.memberNode && typeof args.memberNode === "object" && !Array.isArray(args.memberNode) ? args.memberNode : null;
|
|
25522
|
+
const configured = Array.isArray(mesh?.nodes) ? requestedNodeId ? mesh.nodes.find((node) => node?.id === requestedNodeId || node?.nodeId === requestedNodeId) : mesh.nodes[0] : null;
|
|
25523
|
+
const source = explicit || configured;
|
|
25524
|
+
const workspace = typeof source?.workspace === "string" && source.workspace.trim() ? source.workspace.trim() : typeof args?.workspace === "string" && args.workspace.trim() ? args.workspace.trim() : process.cwd();
|
|
25525
|
+
if (!workspace) return null;
|
|
25526
|
+
const nodeId = typeof source?.id === "string" && source.id.trim() ? source.id.trim() : typeof source?.nodeId === "string" && source.nodeId.trim() ? source.nodeId.trim() : void 0;
|
|
25527
|
+
return {
|
|
25528
|
+
...nodeId ? { id: nodeId } : {},
|
|
25529
|
+
workspace,
|
|
25530
|
+
...typeof source?.repoRoot === "string" && source.repoRoot.trim() ? { repoRoot: source.repoRoot.trim() } : {},
|
|
25531
|
+
...typeof source?.daemonId === "string" && source.daemonId.trim() ? { daemonId: source.daemonId.trim() } : fallbackDaemonId ? { daemonId: fallbackDaemonId } : {},
|
|
25532
|
+
...typeof source?.machineId === "string" && source.machineId.trim() ? { machineId: source.machineId.trim() } : {},
|
|
25533
|
+
userOverrides: source?.userOverrides && typeof source.userOverrides === "object" && !Array.isArray(source.userOverrides) ? source.userOverrides : {},
|
|
25534
|
+
policy: source?.policy && typeof source.policy === "object" && !Array.isArray(source.policy) ? source.policy : {},
|
|
25535
|
+
role: "member"
|
|
25536
|
+
};
|
|
25537
|
+
}
|
|
25106
25538
|
var DaemonCommandRouter = class {
|
|
25107
25539
|
deps;
|
|
25108
25540
|
/** In-memory cache for cloud-originating meshes passed via inlineMesh.
|
|
@@ -25276,6 +25708,16 @@ var DaemonCommandRouter = class {
|
|
|
25276
25708
|
invalidateAggregateMeshStatus(meshId) {
|
|
25277
25709
|
this.aggregateMeshStatusCache.delete(meshId);
|
|
25278
25710
|
}
|
|
25711
|
+
async requireMeshHostMutationOwner(meshId, inlineMesh, operation) {
|
|
25712
|
+
const meshRecord = await this.getMeshForCommand(meshId, inlineMesh, { preferInline: true });
|
|
25713
|
+
const mesh = meshRecord?.mesh;
|
|
25714
|
+
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
25715
|
+
const meshHost = resolveMeshHostStatus(mesh);
|
|
25716
|
+
if (!meshHost.canOwnCoordinator || !meshHost.canOwnQueue) {
|
|
25717
|
+
return { ...buildMeshHostRequiredFailure(mesh, operation), success: false, meshId };
|
|
25718
|
+
}
|
|
25719
|
+
return null;
|
|
25720
|
+
}
|
|
25279
25721
|
updateInlineMeshNode(meshId, mesh, node) {
|
|
25280
25722
|
if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
|
|
25281
25723
|
const idx = mesh.nodes.findIndex((entry) => entry?.id === node.id || entry?.nodeId === node.id);
|
|
@@ -25341,7 +25783,7 @@ var DaemonCommandRouter = class {
|
|
|
25341
25783
|
}
|
|
25342
25784
|
const { resolveWorktreePath: resolveWorktreePath2, listWorktrees: listWorktrees2, removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
25343
25785
|
const normalizePath = (value) => {
|
|
25344
|
-
const resolved = (0,
|
|
25786
|
+
const resolved = (0, import_path8.resolve)(value);
|
|
25345
25787
|
try {
|
|
25346
25788
|
return fs10.realpathSync(resolved);
|
|
25347
25789
|
} catch {
|
|
@@ -26314,7 +26756,8 @@ var DaemonCommandRouter = class {
|
|
|
26314
26756
|
if (!name) return { success: false, error: "name required" };
|
|
26315
26757
|
try {
|
|
26316
26758
|
const { createMesh: createMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
26317
|
-
const
|
|
26759
|
+
const meshHost = args?.meshHost && typeof args.meshHost === "object" && !Array.isArray(args.meshHost) ? args.meshHost : void 0;
|
|
26760
|
+
const mesh = createMesh2({ name, repoIdentity, repoRemoteUrl, defaultBranch, policy: args?.policy, meshHost });
|
|
26318
26761
|
return { success: true, mesh };
|
|
26319
26762
|
} catch (e) {
|
|
26320
26763
|
return { success: false, error: e.message };
|
|
@@ -26330,6 +26773,7 @@ var DaemonCommandRouter = class {
|
|
|
26330
26773
|
if (typeof args?.defaultBranch === "string") patch.defaultBranch = args.defaultBranch;
|
|
26331
26774
|
if (args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy)) patch.policy = args.policy;
|
|
26332
26775
|
if (args?.coordinator && typeof args.coordinator === "object" && !Array.isArray(args.coordinator)) patch.coordinator = args.coordinator;
|
|
26776
|
+
if (args?.meshHost && typeof args.meshHost === "object" && !Array.isArray(args.meshHost)) patch.meshHost = args.meshHost;
|
|
26333
26777
|
if (!Object.keys(patch).length) return { success: false, error: "No updates provided" };
|
|
26334
26778
|
const mesh = updateMesh2(meshId, patch);
|
|
26335
26779
|
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
@@ -26340,6 +26784,215 @@ var DaemonCommandRouter = class {
|
|
|
26340
26784
|
return { success: false, error: e.message };
|
|
26341
26785
|
}
|
|
26342
26786
|
}
|
|
26787
|
+
case "get_mesh_host_pairing": {
|
|
26788
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
26789
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
26790
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
26791
|
+
const mesh = meshRecord?.mesh;
|
|
26792
|
+
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
26793
|
+
const meshHost = resolveMeshHostStatus(mesh);
|
|
26794
|
+
const pairingStatus = meshHost.pairing?.status || "not_configured";
|
|
26795
|
+
return {
|
|
26796
|
+
success: true,
|
|
26797
|
+
code: pairingStatus === "not_configured" ? "mesh_host_pairing_not_configured" : "mesh_host_pairing_pending",
|
|
26798
|
+
meshId,
|
|
26799
|
+
hostAddress: meshHost.hostAddress,
|
|
26800
|
+
meshHost,
|
|
26801
|
+
manualPairing: {
|
|
26802
|
+
status: pairingStatus,
|
|
26803
|
+
joinImplemented: true,
|
|
26804
|
+
protocol: "standalone_command_direct_v1",
|
|
26805
|
+
description: "Standalone manual pairing can save address/token metadata, apply a host join over direct standalone command HTTP or injected mesh command dispatch, and check persisted status. P2P signaling remains outside this slice."
|
|
26806
|
+
}
|
|
26807
|
+
};
|
|
26808
|
+
}
|
|
26809
|
+
case "configure_mesh_host_pairing": {
|
|
26810
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
26811
|
+
const hostAddress = typeof args?.hostAddress === "string" ? args.hostAddress.trim() : "";
|
|
26812
|
+
const token = typeof args?.token === "string" ? args.token.trim() : "";
|
|
26813
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
26814
|
+
if (!hostAddress || !token) return { success: false, error: "hostAddress and token required" };
|
|
26815
|
+
try {
|
|
26816
|
+
const { configureMeshHostPairing: configureMeshHostPairing2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
26817
|
+
const configured = configureMeshHostPairing2(meshId, { hostAddress, token });
|
|
26818
|
+
if (!configured) return { success: false, error: "Mesh not found" };
|
|
26819
|
+
this.inlineMeshCache.set(meshId, configured.mesh);
|
|
26820
|
+
const meshHost = resolveMeshHostStatus(configured.mesh);
|
|
26821
|
+
return {
|
|
26822
|
+
success: true,
|
|
26823
|
+
code: "mesh_host_pairing_pending",
|
|
26824
|
+
meshId,
|
|
26825
|
+
hostAddress: configured.hostAddress,
|
|
26826
|
+
meshHost,
|
|
26827
|
+
manualPairing: {
|
|
26828
|
+
status: meshHost.pairing?.status || "pairing",
|
|
26829
|
+
joinImplemented: true,
|
|
26830
|
+
protocol: "standalone_command_direct_v1",
|
|
26831
|
+
description: "Manual Mesh Host pairing config was saved locally. Use join_mesh_host_pairing to apply it to the host. Raw token was not persisted."
|
|
26832
|
+
}
|
|
26833
|
+
};
|
|
26834
|
+
} catch (e) {
|
|
26835
|
+
return { success: false, code: "mesh_host_pairing_invalid", meshId, hostAddress, error: e.message };
|
|
26836
|
+
}
|
|
26837
|
+
}
|
|
26838
|
+
case "create_mesh_host_pairing_token": {
|
|
26839
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
26840
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
26841
|
+
try {
|
|
26842
|
+
const { createMeshHostPairingToken: createMeshHostPairingToken2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
26843
|
+
const created = createMeshHostPairingToken2(meshId, {
|
|
26844
|
+
token: typeof args?.token === "string" ? args.token : void 0,
|
|
26845
|
+
expiresAt: typeof args?.expiresAt === "string" ? args.expiresAt : void 0
|
|
26846
|
+
});
|
|
26847
|
+
if (!created) return { success: false, error: "Mesh not found" };
|
|
26848
|
+
this.inlineMeshCache.set(meshId, created.mesh);
|
|
26849
|
+
this.invalidateAggregateMeshStatus(meshId);
|
|
26850
|
+
return {
|
|
26851
|
+
success: true,
|
|
26852
|
+
code: "mesh_host_pairing_token_created",
|
|
26853
|
+
meshId,
|
|
26854
|
+
token: created.token,
|
|
26855
|
+
tokenId: created.tokenId,
|
|
26856
|
+
expiresAt: created.expiresAt,
|
|
26857
|
+
meshHost: resolveMeshHostStatus(created.mesh),
|
|
26858
|
+
warning: "Raw token is returned once and is not persisted; share it with member daemons over a trusted channel."
|
|
26859
|
+
};
|
|
26860
|
+
} catch (e) {
|
|
26861
|
+
return { success: false, code: "mesh_host_pairing_token_invalid", meshId, error: e.message };
|
|
26862
|
+
}
|
|
26863
|
+
}
|
|
26864
|
+
case "apply_mesh_host_join": {
|
|
26865
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
26866
|
+
const token = typeof args?.token === "string" ? args.token.trim() : "";
|
|
26867
|
+
const memberNode = args?.memberNode && typeof args.memberNode === "object" && !Array.isArray(args.memberNode) ? args.memberNode : null;
|
|
26868
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
26869
|
+
if (!token || !memberNode) return { success: false, error: "token and memberNode required" };
|
|
26870
|
+
try {
|
|
26871
|
+
const { applyMeshHostJoinRequest: applyMeshHostJoinRequest2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
26872
|
+
const applied = applyMeshHostJoinRequest2(meshId, {
|
|
26873
|
+
token,
|
|
26874
|
+
memberNode,
|
|
26875
|
+
memberMeshId: typeof args?.memberMeshId === "string" ? args.memberMeshId : void 0
|
|
26876
|
+
});
|
|
26877
|
+
if (!applied) return { success: false, error: "Mesh not found" };
|
|
26878
|
+
if (!applied.accepted) {
|
|
26879
|
+
return {
|
|
26880
|
+
success: false,
|
|
26881
|
+
code: "mesh_host_join_rejected",
|
|
26882
|
+
meshId,
|
|
26883
|
+
tokenId: applied.tokenId,
|
|
26884
|
+
meshHost: applied.meshHost ? resolveMeshHostStatus({ meshHost: applied.meshHost }) : void 0,
|
|
26885
|
+
error: applied.reason
|
|
26886
|
+
};
|
|
26887
|
+
}
|
|
26888
|
+
this.inlineMeshCache.set(meshId, applied.mesh);
|
|
26889
|
+
this.invalidateAggregateMeshStatus(meshId);
|
|
26890
|
+
try {
|
|
26891
|
+
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
26892
|
+
appendLedgerEntry2(meshId, {
|
|
26893
|
+
kind: "node_joined",
|
|
26894
|
+
nodeId: applied.node.id,
|
|
26895
|
+
payload: { role: "member", tokenId: applied.tokenId, workspace: applied.node.workspace }
|
|
26896
|
+
});
|
|
26897
|
+
} catch {
|
|
26898
|
+
}
|
|
26899
|
+
return {
|
|
26900
|
+
success: true,
|
|
26901
|
+
code: "mesh_host_join_accepted",
|
|
26902
|
+
meshId,
|
|
26903
|
+
node: applied.node,
|
|
26904
|
+
tokenId: applied.tokenId,
|
|
26905
|
+
meshHost: resolveMeshHostStatus(applied.mesh)
|
|
26906
|
+
};
|
|
26907
|
+
} catch (e) {
|
|
26908
|
+
return { success: false, code: "mesh_host_join_failed", meshId, error: e.message };
|
|
26909
|
+
}
|
|
26910
|
+
}
|
|
26911
|
+
case "join_mesh_host_pairing": {
|
|
26912
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
26913
|
+
const token = typeof args?.token === "string" ? args.token.trim() : "";
|
|
26914
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
26915
|
+
if (!token) return { success: false, error: "token required because raw pairing tokens are not persisted" };
|
|
26916
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
26917
|
+
const mesh = meshRecord?.mesh;
|
|
26918
|
+
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
26919
|
+
const meshHost = resolveMeshHostStatus(mesh);
|
|
26920
|
+
if (meshHost.role !== "member") {
|
|
26921
|
+
return { success: false, code: "mesh_host_join_not_member", meshId, meshHost, error: "join_mesh_host_pairing must run from a member daemon configured with a Mesh Host address/token." };
|
|
26922
|
+
}
|
|
26923
|
+
try {
|
|
26924
|
+
const { tokenIdForManualPairing: tokenIdForManualPairing2, markMeshHostPairingJoined: markMeshHostPairingJoined2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
26925
|
+
const tokenId = tokenIdForManualPairing2(token);
|
|
26926
|
+
if (meshHost.pairing?.tokenId && meshHost.pairing.tokenId !== tokenId) {
|
|
26927
|
+
return { success: false, code: "mesh_host_join_rejected", meshId, tokenId, meshHost, error: "invalid pairing token" };
|
|
26928
|
+
}
|
|
26929
|
+
const memberNode = buildMemberJoinNode(mesh, args, this.deps.statusInstanceId);
|
|
26930
|
+
if (!memberNode) return { success: false, error: "member node metadata unavailable" };
|
|
26931
|
+
const hostMeshId = typeof args?.hostMeshId === "string" && args.hostMeshId.trim() ? args.hostMeshId.trim() : meshId;
|
|
26932
|
+
const hostDaemonId = typeof args?.hostDaemonId === "string" && args.hostDaemonId.trim() ? args.hostDaemonId.trim() : meshHost.hostDaemonId;
|
|
26933
|
+
let hostResult;
|
|
26934
|
+
let transport;
|
|
26935
|
+
if (hostDaemonId && this.deps.dispatchMeshCommand) {
|
|
26936
|
+
transport = "mesh_command_dispatch";
|
|
26937
|
+
hostResult = await this.deps.dispatchMeshCommand(hostDaemonId, "apply_mesh_host_join", {
|
|
26938
|
+
meshId: hostMeshId,
|
|
26939
|
+
token,
|
|
26940
|
+
memberMeshId: meshId,
|
|
26941
|
+
memberNode
|
|
26942
|
+
});
|
|
26943
|
+
} else if (meshHost.hostAddress) {
|
|
26944
|
+
transport = "standalone_http_command";
|
|
26945
|
+
const commandUrl = normalizeStandaloneHostCommandUrl(meshHost.hostAddress);
|
|
26946
|
+
const response = await fetch(commandUrl, {
|
|
26947
|
+
method: "POST",
|
|
26948
|
+
headers: { "Content-Type": "application/json" },
|
|
26949
|
+
body: JSON.stringify({ type: "apply_mesh_host_join", payload: { meshId: hostMeshId, token, memberMeshId: meshId, memberNode } })
|
|
26950
|
+
});
|
|
26951
|
+
hostResult = await response.json().catch(() => ({ success: false, error: `Host returned HTTP ${response.status}` }));
|
|
26952
|
+
if (!response.ok && hostResult?.success !== false) hostResult = { success: false, error: `Host returned HTTP ${response.status}` };
|
|
26953
|
+
} else {
|
|
26954
|
+
return {
|
|
26955
|
+
success: false,
|
|
26956
|
+
code: "mesh_host_join_transport_unavailable",
|
|
26957
|
+
meshId,
|
|
26958
|
+
meshHost,
|
|
26959
|
+
error: "No hostDaemonId dispatch path or hostAddress HTTP command path is available. P2P signaling join is not implemented in this slice."
|
|
26960
|
+
};
|
|
26961
|
+
}
|
|
26962
|
+
if (!hostResult?.success) {
|
|
26963
|
+
return { success: false, code: hostResult?.code || "mesh_host_join_rejected", meshId, meshHost, transport, error: hostResult?.error || "Mesh Host rejected join request", hostResult };
|
|
26964
|
+
}
|
|
26965
|
+
const joined = meshRecord.inline ? null : markMeshHostPairingJoined2(meshId, {
|
|
26966
|
+
tokenId: hostResult.tokenId || tokenId,
|
|
26967
|
+
hostDaemonId: hostResult.meshHost?.hostDaemonId || hostDaemonId,
|
|
26968
|
+
hostNodeId: hostResult.meshHost?.hostNodeId,
|
|
26969
|
+
joinedAt: hostResult.meshHost?.pairing?.joinedAt
|
|
26970
|
+
});
|
|
26971
|
+
if (joined) {
|
|
26972
|
+
this.inlineMeshCache.set(meshId, joined.mesh);
|
|
26973
|
+
this.invalidateAggregateMeshStatus(meshId);
|
|
26974
|
+
}
|
|
26975
|
+
return {
|
|
26976
|
+
success: true,
|
|
26977
|
+
code: "mesh_host_join_applied",
|
|
26978
|
+
meshId,
|
|
26979
|
+
hostMeshId,
|
|
26980
|
+
transport,
|
|
26981
|
+
node: hostResult.node,
|
|
26982
|
+
tokenId: hostResult.tokenId || tokenId,
|
|
26983
|
+
meshHost: joined ? resolveMeshHostStatus(joined.mesh) : { ...meshHost, pairing: { ...meshHost.pairing || {}, status: "paired", tokenId: hostResult.tokenId || tokenId } },
|
|
26984
|
+
hostResult,
|
|
26985
|
+
manualPairing: {
|
|
26986
|
+
status: "paired",
|
|
26987
|
+
joinImplemented: true,
|
|
26988
|
+
protocol: "standalone_command_direct_v1",
|
|
26989
|
+
description: "Mesh Host accepted the join and local member pairing status was marked paired. P2P runtime signaling remains outside this slice."
|
|
26990
|
+
}
|
|
26991
|
+
};
|
|
26992
|
+
} catch (e) {
|
|
26993
|
+
return { success: false, code: "mesh_host_join_failed", meshId, meshHost, error: e.message };
|
|
26994
|
+
}
|
|
26995
|
+
}
|
|
26343
26996
|
case "delete_mesh": {
|
|
26344
26997
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
26345
26998
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
@@ -26422,6 +27075,8 @@ var DaemonCommandRouter = class {
|
|
|
26422
27075
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
26423
27076
|
const taskId = typeof args?.taskId === "string" ? args.taskId.trim() : "";
|
|
26424
27077
|
if (!meshId || !taskId) return { success: false, error: "meshId and taskId required" };
|
|
27078
|
+
const ownerFailure = await this.requireMeshHostMutationOwner(meshId, args?.inlineMesh, "queue cancellation");
|
|
27079
|
+
if (ownerFailure) return ownerFailure;
|
|
26425
27080
|
try {
|
|
26426
27081
|
const { cancelTask: cancelTask2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
26427
27082
|
const reason = typeof args?.reason === "string" ? args.reason : void 0;
|
|
@@ -26436,6 +27091,8 @@ var DaemonCommandRouter = class {
|
|
|
26436
27091
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
26437
27092
|
const taskId = typeof args?.taskId === "string" ? args.taskId.trim() : "";
|
|
26438
27093
|
if (!meshId || !taskId) return { success: false, error: "meshId and taskId required" };
|
|
27094
|
+
const ownerFailure = await this.requireMeshHostMutationOwner(meshId, args?.inlineMesh, "queue requeue");
|
|
27095
|
+
if (ownerFailure) return ownerFailure;
|
|
26439
27096
|
try {
|
|
26440
27097
|
const { requeueTask: requeueTask2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
26441
27098
|
const task = requeueTask2(meshId, taskId, {
|
|
@@ -26456,6 +27113,8 @@ var DaemonCommandRouter = class {
|
|
|
26456
27113
|
const workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";
|
|
26457
27114
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
26458
27115
|
if (!workspace) return { success: false, error: "workspace required" };
|
|
27116
|
+
const ownerFailure = await this.requireMeshHostMutationOwner(meshId, args?.inlineMesh, "node addition");
|
|
27117
|
+
if (ownerFailure) return ownerFailure;
|
|
26459
27118
|
try {
|
|
26460
27119
|
const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
26461
27120
|
const providerPriority = Array.isArray(args?.providerPriority) ? args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean) : [];
|
|
@@ -26464,7 +27123,8 @@ var DaemonCommandRouter = class {
|
|
|
26464
27123
|
...readOnly ? { readOnly: true } : {},
|
|
26465
27124
|
...providerPriority.length ? { providerPriority } : {}
|
|
26466
27125
|
};
|
|
26467
|
-
const
|
|
27126
|
+
const role = normalizeMeshDaemonRole(args?.role);
|
|
27127
|
+
const node = addNode3(meshId, { workspace, ...policy ? { policy } : {}, ...role ? { role } : {} });
|
|
26468
27128
|
if (!node) return { success: false, error: "Mesh not found" };
|
|
26469
27129
|
return { success: true, node };
|
|
26470
27130
|
} catch (e) {
|
|
@@ -26475,6 +27135,8 @@ var DaemonCommandRouter = class {
|
|
|
26475
27135
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
26476
27136
|
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
26477
27137
|
if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
|
|
27138
|
+
const ownerFailure = await this.requireMeshHostMutationOwner(meshId, args?.inlineMesh, "node update");
|
|
27139
|
+
if (ownerFailure) return ownerFailure;
|
|
26478
27140
|
try {
|
|
26479
27141
|
const { updateNode: updateNode2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
26480
27142
|
const policy = args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy) ? { ...args.policy } : {};
|
|
@@ -26498,6 +27160,8 @@ var DaemonCommandRouter = class {
|
|
|
26498
27160
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
26499
27161
|
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
26500
27162
|
if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
|
|
27163
|
+
const ownerFailure = await this.requireMeshHostMutationOwner(meshId, args?.inlineMesh, "node removal");
|
|
27164
|
+
if (ownerFailure) return ownerFailure;
|
|
26501
27165
|
try {
|
|
26502
27166
|
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
26503
27167
|
const mesh = meshRecord?.mesh;
|
|
@@ -26520,6 +27184,49 @@ var DaemonCommandRouter = class {
|
|
|
26520
27184
|
return { success: false, error: e.message };
|
|
26521
27185
|
}
|
|
26522
27186
|
}
|
|
27187
|
+
case "get_mesh_refine_config_schema": {
|
|
27188
|
+
return {
|
|
27189
|
+
success: true,
|
|
27190
|
+
schema: MESH_REFINE_CONFIG_SCHEMA,
|
|
27191
|
+
locations: MESH_REFINE_CONFIG_LOCATIONS,
|
|
27192
|
+
sourceOfTruth: "repo mesh/refine config",
|
|
27193
|
+
heuristicRole: "suggestions_only_not_execution_path"
|
|
27194
|
+
};
|
|
27195
|
+
}
|
|
27196
|
+
case "validate_mesh_refine_config": {
|
|
27197
|
+
const workspace = typeof args?.workspace === "string" ? args.workspace : process.cwd();
|
|
27198
|
+
const mesh = args?.inlineMesh || {};
|
|
27199
|
+
const loaded = args?.config !== void 0 ? { config: args.config, source: "inline", sourceType: "mesh_policy" } : loadMeshRefineConfig(mesh, workspace);
|
|
27200
|
+
const validation = loaded.config ? validateMeshRefineConfig(loaded.config, loaded.source) : { valid: false, errors: [loaded.error || "repo mesh/refine config unavailable"], commands: [], rejectedCommands: [] };
|
|
27201
|
+
return { success: validation.valid, ...loaded, ...validation };
|
|
27202
|
+
}
|
|
27203
|
+
case "suggest_mesh_refine_config": {
|
|
27204
|
+
const workspace = typeof args?.workspace === "string" ? args.workspace : process.cwd();
|
|
27205
|
+
const mesh = args?.inlineMesh || {};
|
|
27206
|
+
return {
|
|
27207
|
+
success: true,
|
|
27208
|
+
...suggestMeshRefineConfig(mesh, workspace),
|
|
27209
|
+
note: "Suggestions are heuristic scaffold only; Refinery will not execute them until saved into repo mesh/refine config."
|
|
27210
|
+
};
|
|
27211
|
+
}
|
|
27212
|
+
case "plan_mesh_refine_node": {
|
|
27213
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
27214
|
+
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
27215
|
+
if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
|
|
27216
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
27217
|
+
const mesh = meshRecord?.mesh;
|
|
27218
|
+
const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
|
|
27219
|
+
if (!node?.workspace) return { success: false, error: `Node '${nodeId}' workspace not found` };
|
|
27220
|
+
return {
|
|
27221
|
+
success: true,
|
|
27222
|
+
dryRun: true,
|
|
27223
|
+
nodeId,
|
|
27224
|
+
workspace: node.workspace,
|
|
27225
|
+
validationPlan: buildMeshRefineValidationPlan(mesh, node.workspace),
|
|
27226
|
+
mergeWillRun: false,
|
|
27227
|
+
cleanupWillRun: false
|
|
27228
|
+
};
|
|
27229
|
+
}
|
|
26523
27230
|
case "refine_mesh_node": {
|
|
26524
27231
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
26525
27232
|
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
@@ -26805,6 +27512,8 @@ var DaemonCommandRouter = class {
|
|
|
26805
27512
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
26806
27513
|
if (!sourceNodeId) return { success: false, error: "sourceNodeId required" };
|
|
26807
27514
|
if (!branch) return { success: false, error: "branch required" };
|
|
27515
|
+
const ownerFailure = await this.requireMeshHostMutationOwner(meshId, args?.inlineMesh, "worktree clone");
|
|
27516
|
+
if (ownerFailure) return ownerFailure;
|
|
26808
27517
|
try {
|
|
26809
27518
|
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
26810
27519
|
const mesh = meshRecord?.mesh;
|
|
@@ -26886,6 +27595,8 @@ var DaemonCommandRouter = class {
|
|
|
26886
27595
|
case "trigger_mesh_queue": {
|
|
26887
27596
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
26888
27597
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
27598
|
+
const ownerFailure = await this.requireMeshHostMutationOwner(meshId, args?.inlineMesh, "queue trigger");
|
|
27599
|
+
if (ownerFailure) return ownerFailure;
|
|
26889
27600
|
try {
|
|
26890
27601
|
const { triggerMeshQueue: triggerMeshQueue2 } = await Promise.resolve().then(() => (init_mesh_events(), mesh_events_exports));
|
|
26891
27602
|
if (meshId) {
|
|
@@ -26912,6 +27623,15 @@ var DaemonCommandRouter = class {
|
|
|
26912
27623
|
mesh = getMesh3(meshId);
|
|
26913
27624
|
}
|
|
26914
27625
|
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
27626
|
+
const meshHost = resolveMeshHostStatus(mesh);
|
|
27627
|
+
if (!meshHost.canOwnCoordinator) {
|
|
27628
|
+
return {
|
|
27629
|
+
success: false,
|
|
27630
|
+
...buildMeshHostRequiredFailure(mesh, "coordinator launch"),
|
|
27631
|
+
meshId,
|
|
27632
|
+
cliType
|
|
27633
|
+
};
|
|
27634
|
+
}
|
|
26915
27635
|
if (!Array.isArray(mesh.nodes) || mesh.nodes.length === 0) return { success: false, error: "No nodes in mesh" };
|
|
26916
27636
|
const requestedCoordinatorNodeId = typeof args?.coordinatorNodeId === "string" ? args.coordinatorNodeId.trim() : "";
|
|
26917
27637
|
const preferredCoordinatorNodeId = requestedCoordinatorNodeId || (typeof mesh.coordinator?.preferredNodeId === "string" ? mesh.coordinator.preferredNodeId.trim() : "");
|
|
@@ -27094,7 +27814,7 @@ ${block}`);
|
|
|
27094
27814
|
workspace
|
|
27095
27815
|
};
|
|
27096
27816
|
}
|
|
27097
|
-
const { existsSync:
|
|
27817
|
+
const { existsSync: existsSync27, readFileSync: readFileSync19, writeFileSync: writeFileSync15, copyFileSync: copyFileSync4, mkdirSync: mkdirSync17 } = await import("fs");
|
|
27098
27818
|
const { dirname: dirname9 } = await import("path");
|
|
27099
27819
|
const mcpConfigPath = coordinatorSetup.configPath;
|
|
27100
27820
|
const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
|
|
@@ -27137,14 +27857,14 @@ ${block}`);
|
|
|
27137
27857
|
if (hermesManualFallback) return returnManualFallback(message);
|
|
27138
27858
|
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
27139
27859
|
}
|
|
27140
|
-
const hadExistingMcpConfig =
|
|
27860
|
+
const hadExistingMcpConfig = existsSync27(mcpConfigPath);
|
|
27141
27861
|
let existingMcpConfig = hermesBaseConfig?.config || {};
|
|
27142
27862
|
if (hermesBaseConfig) {
|
|
27143
27863
|
copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname9(mcpConfigPath));
|
|
27144
27864
|
}
|
|
27145
27865
|
if (hadExistingMcpConfig) {
|
|
27146
27866
|
try {
|
|
27147
|
-
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(
|
|
27867
|
+
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync19(mcpConfigPath, "utf-8"), configFormat);
|
|
27148
27868
|
const existingCoordinatorConfig = hermesManualFallback ? stripHermesCoordinatorTempModelProviderOverrides(parsedExistingMcpConfig) : parsedExistingMcpConfig;
|
|
27149
27869
|
existingMcpConfig = { ...existingMcpConfig, ...existingCoordinatorConfig };
|
|
27150
27870
|
copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
|
|
@@ -27234,6 +27954,7 @@ ${block}`);
|
|
|
27234
27954
|
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
27235
27955
|
const mesh = meshRecord?.mesh;
|
|
27236
27956
|
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
27957
|
+
const meshHost = resolveMeshHostStatus(mesh);
|
|
27237
27958
|
const refreshRequested = args?.refresh === true || args?.forceRefresh === true;
|
|
27238
27959
|
const hadAggregateCache = this.aggregateMeshStatusCache.has(meshId);
|
|
27239
27960
|
if (!refreshRequested) {
|
|
@@ -27329,6 +28050,7 @@ ${block}`);
|
|
|
27329
28050
|
repoRoot: node.repoRoot,
|
|
27330
28051
|
isLocalWorktree: node.isLocalWorktree,
|
|
27331
28052
|
worktreeBranch: node.worktreeBranch,
|
|
28053
|
+
role: normalizeMeshDaemonRole(node.role) || (meshHost.hostNodeId && nodeId === meshHost.hostNodeId ? "host" : void 0),
|
|
27332
28054
|
daemonId,
|
|
27333
28055
|
machineId: node.machineId,
|
|
27334
28056
|
machineStatus: node.machineStatus,
|
|
@@ -27507,9 +28229,17 @@ ${block}`);
|
|
|
27507
28229
|
repoIdentity: mesh.repoIdentity,
|
|
27508
28230
|
defaultBranch: mesh.defaultBranch,
|
|
27509
28231
|
refreshedAt,
|
|
28232
|
+
meshHost,
|
|
27510
28233
|
sourceOfTruth: {
|
|
27511
28234
|
membership: meshRecord?.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord?.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
|
|
27512
28235
|
coordinatorOwnsLiveTruth: directTruthSatisfied,
|
|
28236
|
+
meshHost: {
|
|
28237
|
+
owner: "mesh_host_daemon",
|
|
28238
|
+
localRole: meshHost.role,
|
|
28239
|
+
hostDaemonId: meshHost.hostDaemonId,
|
|
28240
|
+
hostNodeId: meshHost.hostNodeId,
|
|
28241
|
+
hostAddress: meshHost.hostAddress
|
|
28242
|
+
},
|
|
27513
28243
|
...requireDirectPeerTruth ? {
|
|
27514
28244
|
currentStatus: directTruthSatisfied ? "live_git_and_session_probes" : "direct_peer_truth_unavailable",
|
|
27515
28245
|
directPeerTruth: {
|
|
@@ -35593,6 +36323,8 @@ async function shutdownDaemonComponents(components) {
|
|
|
35593
36323
|
InMemoryGitSnapshotStore,
|
|
35594
36324
|
LOG,
|
|
35595
36325
|
MAX_LEDGER_SLICE_LIMIT,
|
|
36326
|
+
MESH_REFINE_CONFIG_LOCATIONS,
|
|
36327
|
+
MESH_REFINE_CONFIG_SCHEMA,
|
|
35596
36328
|
MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
|
|
35597
36329
|
MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
|
|
35598
36330
|
MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
|
|
@@ -35615,6 +36347,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
35615
36347
|
buildChatTailDeliverySignature,
|
|
35616
36348
|
buildCoordinatorSystemPrompt,
|
|
35617
36349
|
buildMachineInfo,
|
|
36350
|
+
buildMeshHostRequiredFailure,
|
|
35618
36351
|
buildMeshLedgerReconciliationEvidence,
|
|
35619
36352
|
buildMeshLedgerReplicaEvidence,
|
|
35620
36353
|
buildP2pRelayFailurePayload,
|
|
@@ -35640,6 +36373,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
35640
36373
|
connectCdpManager,
|
|
35641
36374
|
createDebugTraceStore,
|
|
35642
36375
|
createDefaultGitCommandServices,
|
|
36376
|
+
createDefaultMeshHostMetadata,
|
|
35643
36377
|
createGitCompactSummary,
|
|
35644
36378
|
createGitSnapshotStore,
|
|
35645
36379
|
createGitWorkspaceMonitor,
|
|
@@ -35703,6 +36437,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
35703
36437
|
isInternalChatMessage,
|
|
35704
36438
|
isManagedStatusWaiting,
|
|
35705
36439
|
isManagedStatusWorking,
|
|
36440
|
+
isMeshHostOwner,
|
|
35706
36441
|
isP2pRelayTransportFailure,
|
|
35707
36442
|
isPathInside,
|
|
35708
36443
|
isSessionHostLiveRuntime,
|
|
@@ -35716,6 +36451,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
35716
36451
|
listMeshes,
|
|
35717
36452
|
listWorktrees,
|
|
35718
36453
|
loadConfig,
|
|
36454
|
+
loadMeshRefineConfig,
|
|
35719
36455
|
loadState,
|
|
35720
36456
|
logCommand,
|
|
35721
36457
|
markSetupComplete,
|
|
@@ -35729,6 +36465,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
35729
36465
|
normalizeGitWorkspaceSubscriptionParams,
|
|
35730
36466
|
normalizeInputEnvelope,
|
|
35731
36467
|
normalizeManagedStatus,
|
|
36468
|
+
normalizeMeshDaemonRole,
|
|
35732
36469
|
normalizeMessageParts,
|
|
35733
36470
|
normalizeRepoIdentity,
|
|
35734
36471
|
normalizeSessionModalFields,
|
|
@@ -35749,6 +36486,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
35749
36486
|
removeNode,
|
|
35750
36487
|
removeWorktree,
|
|
35751
36488
|
requeueTask,
|
|
36489
|
+
requireMeshHostQueueOwner,
|
|
35752
36490
|
resetConfig,
|
|
35753
36491
|
resetDebugRuntimeConfig,
|
|
35754
36492
|
resetState,
|
|
@@ -35756,6 +36494,8 @@ async function shutdownDaemonComponents(components) {
|
|
|
35756
36494
|
resolveCurrentGlobalInstallSurface,
|
|
35757
36495
|
resolveDebugRuntimeConfig,
|
|
35758
36496
|
resolveGitRepository,
|
|
36497
|
+
resolveMeshHostStatus,
|
|
36498
|
+
resolveMeshRefineValidationPlan,
|
|
35759
36499
|
resolveSessionHostAppName,
|
|
35760
36500
|
resolveSessionHostAppNameResolution,
|
|
35761
36501
|
resolveWorktreePath,
|
|
@@ -35771,6 +36511,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
35771
36511
|
shutdownDaemonComponents,
|
|
35772
36512
|
spawnDetachedDaemonUpgradeHelper,
|
|
35773
36513
|
startDaemonDevSupport,
|
|
36514
|
+
suggestMeshRefineConfig,
|
|
35774
36515
|
summarizeGitStatus,
|
|
35775
36516
|
syncMeshes,
|
|
35776
36517
|
triggerMeshQueue,
|
|
@@ -35779,6 +36520,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
35779
36520
|
updateNode,
|
|
35780
36521
|
updateSessionTaskStatus,
|
|
35781
36522
|
updateTaskStatus,
|
|
35782
|
-
upsertSavedProviderSession
|
|
36523
|
+
upsertSavedProviderSession,
|
|
36524
|
+
validateMeshRefineConfig
|
|
35783
36525
|
});
|
|
35784
36526
|
//# sourceMappingURL=index.js.map
|