adhdev 0.9.82-rc.4 → 0.9.82-rc.41
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/cli/index.js +2095 -739
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +1614 -349
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/vendor/mcp-server/index.js +331 -32
- package/vendor/mcp-server/index.js.map +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -784,8 +784,14 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
784
784
|
const includeSubmodules = options.includeSubmodules !== false;
|
|
785
785
|
try {
|
|
786
786
|
const repo = await resolveGitRepository(workspace, options);
|
|
787
|
-
|
|
788
|
-
|
|
787
|
+
let parsed = await readPorcelainStatus(repo, options);
|
|
788
|
+
let upstreamProbe = getInitialUpstreamProbe(parsed);
|
|
789
|
+
if (options.refreshUpstream) {
|
|
790
|
+
upstreamProbe = await refreshTrackedUpstream(repo, parsed, options);
|
|
791
|
+
if (upstreamProbe.upstreamStatus === "fresh") {
|
|
792
|
+
parsed = await readPorcelainStatus(repo, options);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
789
795
|
const head = await readHead(repo, options);
|
|
790
796
|
const stashCount = await readStashCount(repo, options);
|
|
791
797
|
let submodules;
|
|
@@ -800,6 +806,9 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
800
806
|
headCommit: head.commit,
|
|
801
807
|
headMessage: head.message,
|
|
802
808
|
upstream: parsed.upstream,
|
|
809
|
+
upstreamStatus: parsed.upstream ? upstreamProbe.upstreamStatus : "no_upstream",
|
|
810
|
+
upstreamFetchedAt: upstreamProbe.upstreamFetchedAt,
|
|
811
|
+
upstreamFetchError: upstreamProbe.upstreamFetchError,
|
|
803
812
|
ahead: parsed.ahead,
|
|
804
813
|
behind: parsed.behind,
|
|
805
814
|
staged: parsed.staged,
|
|
@@ -824,6 +833,60 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
824
833
|
);
|
|
825
834
|
}
|
|
826
835
|
}
|
|
836
|
+
async function readPorcelainStatus(repo, options) {
|
|
837
|
+
const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
|
|
838
|
+
return parsePorcelainV2Status(statusOutput.stdout);
|
|
839
|
+
}
|
|
840
|
+
function getInitialUpstreamProbe(parsed) {
|
|
841
|
+
return {
|
|
842
|
+
upstreamStatus: parsed.upstream ? "unchecked" : "no_upstream"
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
async function refreshTrackedUpstream(repo, parsed, options) {
|
|
846
|
+
if (!parsed.upstream || !parsed.branch) {
|
|
847
|
+
return { upstreamStatus: "no_upstream" };
|
|
848
|
+
}
|
|
849
|
+
const remoteName = await readBranchRemote(repo, parsed.branch, options) ?? inferRemoteName(parsed.upstream);
|
|
850
|
+
if (!remoteName) {
|
|
851
|
+
return {
|
|
852
|
+
upstreamStatus: "stale",
|
|
853
|
+
upstreamFetchError: `Unable to resolve remote for upstream '${parsed.upstream}'`
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
try {
|
|
857
|
+
await runGit(repo, ["fetch", "--quiet", "--prune", "--no-tags", remoteName], options);
|
|
858
|
+
return {
|
|
859
|
+
upstreamStatus: "fresh",
|
|
860
|
+
upstreamFetchedAt: Date.now()
|
|
861
|
+
};
|
|
862
|
+
} catch (error48) {
|
|
863
|
+
return {
|
|
864
|
+
upstreamStatus: "stale",
|
|
865
|
+
upstreamFetchError: formatGitError(error48)
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
async function readBranchRemote(repo, branch, options) {
|
|
870
|
+
try {
|
|
871
|
+
const result = await runGit(repo, ["config", "--get", `branch.${branch}.remote`], options);
|
|
872
|
+
return result.stdout.trim() || null;
|
|
873
|
+
} catch {
|
|
874
|
+
return null;
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
function inferRemoteName(upstream) {
|
|
878
|
+
const [remoteName] = upstream.split("/");
|
|
879
|
+
return remoteName?.trim() || null;
|
|
880
|
+
}
|
|
881
|
+
function formatGitError(error48) {
|
|
882
|
+
if (error48 instanceof GitCommandError) {
|
|
883
|
+
return error48.stderr || error48.message;
|
|
884
|
+
}
|
|
885
|
+
if (error48 instanceof Error) {
|
|
886
|
+
return error48.message;
|
|
887
|
+
}
|
|
888
|
+
return String(error48);
|
|
889
|
+
}
|
|
827
890
|
function parsePorcelainV2Status(output) {
|
|
828
891
|
const parsed = {
|
|
829
892
|
branch: null,
|
|
@@ -918,6 +981,7 @@ function emptyStatus(workspace, lastCheckedAt, error48) {
|
|
|
918
981
|
headCommit: null,
|
|
919
982
|
headMessage: null,
|
|
920
983
|
upstream: null,
|
|
984
|
+
upstreamStatus: "unavailable",
|
|
921
985
|
ahead: 0,
|
|
922
986
|
behind: 0,
|
|
923
987
|
staged: 0,
|
|
@@ -1210,6 +1274,9 @@ function createGitCompactSummary(status, diffSummary) {
|
|
|
1210
1274
|
isGitRepo: status.isGitRepo,
|
|
1211
1275
|
repoRoot: status.repoRoot,
|
|
1212
1276
|
branch: status.branch,
|
|
1277
|
+
upstreamStatus: status.upstreamStatus,
|
|
1278
|
+
upstreamFetchedAt: status.upstreamFetchedAt,
|
|
1279
|
+
upstreamFetchError: status.upstreamFetchError,
|
|
1213
1280
|
dirty: status.staged > 0 || status.modified > 0 || status.untracked > 0 || status.deleted > 0 || status.renamed > 0 || conflictCount > 0 || changedFiles > 0,
|
|
1214
1281
|
changedFiles,
|
|
1215
1282
|
ahead: status.ahead,
|
|
@@ -1537,7 +1604,7 @@ function serviceNotImplemented(command) {
|
|
|
1537
1604
|
}
|
|
1538
1605
|
function createDefaultGitCommandServices() {
|
|
1539
1606
|
return {
|
|
1540
|
-
getStatus: ({ workspace }) => getGitRepoStatus(workspace),
|
|
1607
|
+
getStatus: ({ workspace, refreshUpstream }) => getGitRepoStatus(workspace, { refreshUpstream }),
|
|
1541
1608
|
getDiffSummary: ({ workspace }) => getGitDiffSummary(workspace),
|
|
1542
1609
|
getDiffFile: ({ workspace, path: filePath }) => getGitFileDiff(workspace, filePath),
|
|
1543
1610
|
createSnapshot: ({ workspace, reason, sessionId, turnId }) => defaultSnapshotStore.create({
|
|
@@ -1622,7 +1689,7 @@ async function handleGitCommand(command, args, services = defaultGitCommandServi
|
|
|
1622
1689
|
switch (command) {
|
|
1623
1690
|
case "git_status": {
|
|
1624
1691
|
if (!services.getStatus) return serviceNotImplemented(command);
|
|
1625
|
-
const status = await runService(() => services.getStatus({ workspace }));
|
|
1692
|
+
const status = await runService(() => services.getStatus({ workspace, refreshUpstream: optionalBoolean(args?.refreshUpstream) }));
|
|
1626
1693
|
return "success" in status ? status : { success: true, status };
|
|
1627
1694
|
}
|
|
1628
1695
|
case "git_diff_summary": {
|
|
@@ -3743,6 +3810,36 @@ function getQueuePath(meshId) {
|
|
|
3743
3810
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3744
3811
|
return (0, import_path4.join)(getLedgerDir(), `${safe}.queue.json`);
|
|
3745
3812
|
}
|
|
3813
|
+
function getLockPath(meshId) {
|
|
3814
|
+
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3815
|
+
return (0, import_path4.join)(getLedgerDir(), `${safe}.queue.lock`);
|
|
3816
|
+
}
|
|
3817
|
+
function withQueueLock(meshId, fn) {
|
|
3818
|
+
const lockPath = getLockPath(meshId);
|
|
3819
|
+
let fd = -1;
|
|
3820
|
+
for (let i = 0; i < 10; i++) {
|
|
3821
|
+
try {
|
|
3822
|
+
fd = (0, import_fs4.openSync)(lockPath, "wx");
|
|
3823
|
+
break;
|
|
3824
|
+
} catch {
|
|
3825
|
+
const deadline = Date.now() + 30;
|
|
3826
|
+
while (Date.now() < deadline) {
|
|
3827
|
+
}
|
|
3828
|
+
}
|
|
3829
|
+
}
|
|
3830
|
+
try {
|
|
3831
|
+
return fn();
|
|
3832
|
+
} finally {
|
|
3833
|
+
if (fd !== -1) try {
|
|
3834
|
+
(0, import_fs4.closeSync)(fd);
|
|
3835
|
+
} catch {
|
|
3836
|
+
}
|
|
3837
|
+
try {
|
|
3838
|
+
(0, import_fs4.unlinkSync)(lockPath);
|
|
3839
|
+
} catch {
|
|
3840
|
+
}
|
|
3841
|
+
}
|
|
3842
|
+
}
|
|
3746
3843
|
function readQueue(meshId) {
|
|
3747
3844
|
const path42 = getQueuePath(meshId);
|
|
3748
3845
|
if (!(0, import_fs4.existsSync)(path42)) return [];
|
|
@@ -3758,20 +3855,22 @@ function writeQueue(meshId, queue) {
|
|
|
3758
3855
|
(0, import_fs4.writeFileSync)(path42, JSON.stringify(queue, null, 2), "utf-8");
|
|
3759
3856
|
}
|
|
3760
3857
|
function enqueueTask(meshId, message, opts) {
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3858
|
+
return withQueueLock(meshId, () => {
|
|
3859
|
+
const queue = readQueue(meshId);
|
|
3860
|
+
const entry = {
|
|
3861
|
+
id: (0, import_crypto5.randomUUID)(),
|
|
3862
|
+
meshId,
|
|
3863
|
+
message,
|
|
3864
|
+
status: "pending",
|
|
3865
|
+
targetNodeId: opts?.targetNodeId,
|
|
3866
|
+
targetSessionId: opts?.targetSessionId,
|
|
3867
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3868
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3869
|
+
};
|
|
3870
|
+
queue.push(entry);
|
|
3871
|
+
writeQueue(meshId, queue);
|
|
3872
|
+
return entry;
|
|
3873
|
+
});
|
|
3775
3874
|
}
|
|
3776
3875
|
function getQueue(meshId, opts) {
|
|
3777
3876
|
let queue = readQueue(meshId);
|
|
@@ -3782,100 +3881,111 @@ function getQueue(meshId, opts) {
|
|
|
3782
3881
|
return queue;
|
|
3783
3882
|
}
|
|
3784
3883
|
function claimNextTask(meshId, nodeId, sessionId) {
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3884
|
+
return withQueueLock(meshId, () => {
|
|
3885
|
+
const queue = readQueue(meshId);
|
|
3886
|
+
const hasActiveAssignment = queue.some((q) => q.status === "assigned" && (q.assignedSessionId === sessionId || q.assignedNodeId === nodeId));
|
|
3887
|
+
if (hasActiveAssignment) return null;
|
|
3888
|
+
let targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetSessionId === sessionId);
|
|
3889
|
+
if (targetIdx === -1) {
|
|
3890
|
+
targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetNodeId === nodeId && !q.targetSessionId);
|
|
3891
|
+
}
|
|
3892
|
+
if (targetIdx === -1) {
|
|
3893
|
+
targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId && !q.targetSessionId);
|
|
3894
|
+
}
|
|
3895
|
+
if (targetIdx === -1) return null;
|
|
3896
|
+
const entry = queue[targetIdx];
|
|
3897
|
+
entry.status = "assigned";
|
|
3898
|
+
entry.assignedNodeId = nodeId;
|
|
3899
|
+
entry.assignedSessionId = sessionId;
|
|
3900
|
+
entry.dispatchTimestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3901
|
+
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3902
|
+
writeQueue(meshId, queue);
|
|
3903
|
+
return entry;
|
|
3904
|
+
});
|
|
3804
3905
|
}
|
|
3805
3906
|
function updateTaskStatus(meshId, taskId, status) {
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3907
|
+
return withQueueLock(meshId, () => {
|
|
3908
|
+
const queue = readQueue(meshId);
|
|
3909
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
3910
|
+
if (idx === -1) return null;
|
|
3911
|
+
queue[idx].status = status;
|
|
3912
|
+
queue[idx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3913
|
+
writeQueue(meshId, queue);
|
|
3914
|
+
return queue[idx];
|
|
3915
|
+
});
|
|
3813
3916
|
}
|
|
3814
3917
|
function recordTaskAutoLaunch(meshId, taskId, autoLaunch) {
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
...autoLaunch,
|
|
3821
|
-
updatedAt
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
return queue[idx];
|
|
3918
|
+
return withQueueLock(meshId, () => {
|
|
3919
|
+
const queue = readQueue(meshId);
|
|
3920
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
3921
|
+
if (idx === -1) return null;
|
|
3922
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3923
|
+
queue[idx].autoLaunch = { ...autoLaunch, updatedAt: now };
|
|
3924
|
+
queue[idx].updatedAt = now;
|
|
3925
|
+
writeQueue(meshId, queue);
|
|
3926
|
+
return queue[idx];
|
|
3927
|
+
});
|
|
3826
3928
|
}
|
|
3827
3929
|
function cancelTask(meshId, taskId, opts) {
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3930
|
+
return withQueueLock(meshId, () => {
|
|
3931
|
+
const queue = readQueue(meshId);
|
|
3932
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
3933
|
+
if (idx === -1) return null;
|
|
3934
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3935
|
+
queue[idx].status = "cancelled";
|
|
3936
|
+
queue[idx].updatedAt = now;
|
|
3937
|
+
queue[idx].cancelledAt = now;
|
|
3938
|
+
if (opts?.reason) queue[idx].cancelReason = opts.reason;
|
|
3939
|
+
writeQueue(meshId, queue);
|
|
3940
|
+
return queue[idx];
|
|
3941
|
+
});
|
|
3838
3942
|
}
|
|
3839
3943
|
function requeueTask(meshId, taskId, opts) {
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3944
|
+
return withQueueLock(meshId, () => {
|
|
3945
|
+
const queue = readQueue(meshId);
|
|
3946
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
3947
|
+
if (idx === -1) return null;
|
|
3948
|
+
const entry = queue[idx];
|
|
3949
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3950
|
+
entry.status = "pending";
|
|
3951
|
+
delete entry.assignedNodeId;
|
|
3952
|
+
delete entry.assignedSessionId;
|
|
3953
|
+
delete entry.cancelledAt;
|
|
3954
|
+
delete entry.cancelReason;
|
|
3955
|
+
if (opts?.clearTargetNode) delete entry.targetNodeId;
|
|
3956
|
+
if (typeof opts?.targetNodeId === "string") entry.targetNodeId = opts.targetNodeId;
|
|
3957
|
+
if (opts?.clearTargetSession !== false) delete entry.targetSessionId;
|
|
3958
|
+
if (typeof opts?.targetSessionId === "string") entry.targetSessionId = opts.targetSessionId;
|
|
3959
|
+
entry.updatedAt = now;
|
|
3960
|
+
entry.requeuedAt = now;
|
|
3961
|
+
entry.requeueCount = (entry.requeueCount || 0) + 1;
|
|
3962
|
+
if (opts?.reason) entry.requeueReason = opts.reason;
|
|
3963
|
+
writeQueue(meshId, queue);
|
|
3964
|
+
return entry;
|
|
3965
|
+
});
|
|
3966
|
+
}
|
|
3967
|
+
function updateSessionTaskStatus(meshId, sessionId, status, opts) {
|
|
3968
|
+
return withQueueLock(meshId, () => {
|
|
3969
|
+
const queue = readQueue(meshId);
|
|
3970
|
+
const occurredAtTime = opts?.occurredAt ? new Date(opts.occurredAt).getTime() : Number.NaN;
|
|
3971
|
+
const hasOccurredAt = Number.isFinite(occurredAtTime);
|
|
3972
|
+
let bestIdx = -1;
|
|
3973
|
+
let bestTime = 0;
|
|
3974
|
+
for (let i = queue.length - 1; i >= 0; i--) {
|
|
3975
|
+
if (queue[i].assignedSessionId !== sessionId || queue[i].status !== "assigned") continue;
|
|
3867
3976
|
const time3 = new Date(queue[i].dispatchTimestamp || queue[i].updatedAt).getTime();
|
|
3977
|
+
if (hasOccurredAt && Number.isFinite(time3) && time3 > occurredAtTime) continue;
|
|
3868
3978
|
if (time3 > bestTime) {
|
|
3869
3979
|
bestTime = time3;
|
|
3870
3980
|
bestIdx = i;
|
|
3871
3981
|
}
|
|
3872
3982
|
}
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3983
|
+
if (bestIdx === -1) return null;
|
|
3984
|
+
queue[bestIdx].status = status;
|
|
3985
|
+
queue[bestIdx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3986
|
+
writeQueue(meshId, queue);
|
|
3987
|
+
return queue[bestIdx];
|
|
3988
|
+
});
|
|
3879
3989
|
}
|
|
3880
3990
|
function getMeshQueueStats(meshId) {
|
|
3881
3991
|
const queue = readQueue(meshId);
|
|
@@ -4279,18 +4389,75 @@ __export(mesh_events_exports, {
|
|
|
4279
4389
|
drainPendingMeshCoordinatorEvents: () => drainPendingMeshCoordinatorEvents,
|
|
4280
4390
|
getPendingMeshCoordinatorEvents: () => getPendingMeshCoordinatorEvents,
|
|
4281
4391
|
handleMeshForwardEvent: () => handleMeshForwardEvent,
|
|
4392
|
+
queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
|
|
4282
4393
|
setupMeshEventForwarding: () => setupMeshEventForwarding,
|
|
4283
4394
|
triggerMeshQueue: () => triggerMeshQueue,
|
|
4284
4395
|
tryAssignQueueTask: () => tryAssignQueueTask
|
|
4285
4396
|
});
|
|
4286
|
-
function
|
|
4287
|
-
|
|
4397
|
+
function sweepExpiredRemoteIdleSessions() {
|
|
4398
|
+
const now = Date.now();
|
|
4399
|
+
for (const [key, session] of remoteIdleSessions) {
|
|
4400
|
+
if (session.expiresAt <= now) remoteIdleSessions.delete(key);
|
|
4401
|
+
}
|
|
4402
|
+
}
|
|
4403
|
+
function getPendingEventsPath(meshId) {
|
|
4404
|
+
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
4405
|
+
return (0, import_path5.join)(getLedgerDir(), `${safe}.pending-events.jsonl`);
|
|
4288
4406
|
}
|
|
4289
|
-
function
|
|
4290
|
-
|
|
4407
|
+
function queuePendingMeshCoordinatorEvent(event) {
|
|
4408
|
+
try {
|
|
4409
|
+
(0, import_fs6.appendFileSync)(getPendingEventsPath(event.meshId), JSON.stringify(event) + "\n", "utf-8");
|
|
4410
|
+
return true;
|
|
4411
|
+
} catch (e) {
|
|
4412
|
+
LOG.warn("MeshEvents", `Failed to persist pending coordinator event: ${e?.message || e}`);
|
|
4413
|
+
return false;
|
|
4414
|
+
}
|
|
4415
|
+
}
|
|
4416
|
+
function drainPendingMeshCoordinatorEvents(meshId) {
|
|
4417
|
+
if (!meshId) return [];
|
|
4418
|
+
const path42 = getPendingEventsPath(meshId);
|
|
4419
|
+
if (!(0, import_fs6.existsSync)(path42)) return [];
|
|
4420
|
+
try {
|
|
4421
|
+
const raw = (0, import_fs6.readFileSync)(path42, "utf-8");
|
|
4422
|
+
try {
|
|
4423
|
+
(0, import_fs6.unlinkSync)(path42);
|
|
4424
|
+
} catch {
|
|
4425
|
+
}
|
|
4426
|
+
return raw.split("\n").filter(Boolean).flatMap((line) => {
|
|
4427
|
+
try {
|
|
4428
|
+
return [JSON.parse(line)];
|
|
4429
|
+
} catch {
|
|
4430
|
+
return [];
|
|
4431
|
+
}
|
|
4432
|
+
});
|
|
4433
|
+
} catch {
|
|
4434
|
+
return [];
|
|
4435
|
+
}
|
|
4436
|
+
}
|
|
4437
|
+
function getPendingMeshCoordinatorEvents(meshId) {
|
|
4438
|
+
if (!meshId) return [];
|
|
4439
|
+
const path42 = getPendingEventsPath(meshId);
|
|
4440
|
+
if (!(0, import_fs6.existsSync)(path42)) return [];
|
|
4441
|
+
try {
|
|
4442
|
+
const raw = (0, import_fs6.readFileSync)(path42, "utf-8");
|
|
4443
|
+
return raw.split("\n").filter(Boolean).flatMap((line) => {
|
|
4444
|
+
try {
|
|
4445
|
+
return [JSON.parse(line)];
|
|
4446
|
+
} catch {
|
|
4447
|
+
return [];
|
|
4448
|
+
}
|
|
4449
|
+
});
|
|
4450
|
+
} catch {
|
|
4451
|
+
return [];
|
|
4452
|
+
}
|
|
4291
4453
|
}
|
|
4292
|
-
function clearPendingMeshCoordinatorEvents() {
|
|
4293
|
-
|
|
4454
|
+
function clearPendingMeshCoordinatorEvents(meshId) {
|
|
4455
|
+
if (!meshId) return;
|
|
4456
|
+
const path42 = getPendingEventsPath(meshId);
|
|
4457
|
+
if ((0, import_fs6.existsSync)(path42)) try {
|
|
4458
|
+
(0, import_fs6.unlinkSync)(path42);
|
|
4459
|
+
} catch {
|
|
4460
|
+
}
|
|
4294
4461
|
}
|
|
4295
4462
|
function readNonEmptyString(value) {
|
|
4296
4463
|
return typeof value === "string" && value.trim() ? value.trim() : "";
|
|
@@ -4336,6 +4503,38 @@ function shouldSuppressIntentionalCleanupStop(args) {
|
|
|
4336
4503
|
if (isIntentionalCleanupStopMetadata(args.metadataEvent)) return true;
|
|
4337
4504
|
return hasRecentIntentionalCleanupStop(args.meshId, args.sessionId, args.nodeId);
|
|
4338
4505
|
}
|
|
4506
|
+
function readEventTimestamp(value) {
|
|
4507
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
4508
|
+
if (typeof value === "string" && value.trim()) {
|
|
4509
|
+
const numeric = Number(value);
|
|
4510
|
+
if (Number.isFinite(numeric)) return numeric;
|
|
4511
|
+
const parsed = Date.parse(value);
|
|
4512
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
4513
|
+
}
|
|
4514
|
+
return null;
|
|
4515
|
+
}
|
|
4516
|
+
function buildMeshCompletionFingerprint(args) {
|
|
4517
|
+
const timestampPart = Number.isFinite(args.timestamp) ? String(args.timestamp) : readNonEmptyString(args.finalSummary).slice(0, 200);
|
|
4518
|
+
return [
|
|
4519
|
+
args.meshId,
|
|
4520
|
+
args.event,
|
|
4521
|
+
args.sessionId,
|
|
4522
|
+
args.providerType || "",
|
|
4523
|
+
args.providerSessionId || "",
|
|
4524
|
+
timestampPart
|
|
4525
|
+
].join("::");
|
|
4526
|
+
}
|
|
4527
|
+
function isDuplicateMeshCompletionEvent(args) {
|
|
4528
|
+
const fingerprint = buildMeshCompletionFingerprint(args);
|
|
4529
|
+
if (!fingerprint) return false;
|
|
4530
|
+
const now = Date.now();
|
|
4531
|
+
for (const [key, seenAt] of recentCompletionFingerprints.entries()) {
|
|
4532
|
+
if (now - seenAt > RECENT_COMPLETION_FINGERPRINT_TTL_MS) recentCompletionFingerprints.delete(key);
|
|
4533
|
+
}
|
|
4534
|
+
if (recentCompletionFingerprints.has(fingerprint)) return true;
|
|
4535
|
+
recentCompletionFingerprints.set(fingerprint, now);
|
|
4536
|
+
return false;
|
|
4537
|
+
}
|
|
4339
4538
|
function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
|
|
4340
4539
|
const task = claimNextTask(meshId, nodeId, sessionId);
|
|
4341
4540
|
if (!task) {
|
|
@@ -4354,7 +4553,16 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
|
|
|
4354
4553
|
message: task.message
|
|
4355
4554
|
}).catch((e) => {
|
|
4356
4555
|
LOG.error("MeshQueue", `Failed to dispatch task via P2P to remote node ${nodeId}: ${e?.message}`);
|
|
4357
|
-
updateTaskStatus(meshId, task.id, "
|
|
4556
|
+
updateTaskStatus(meshId, task.id, "pending");
|
|
4557
|
+
try {
|
|
4558
|
+
appendLedgerEntry(meshId, {
|
|
4559
|
+
kind: "dispatch_failed",
|
|
4560
|
+
nodeId,
|
|
4561
|
+
sessionId,
|
|
4562
|
+
payload: { taskId: task.id, error: e?.message, retryable: true }
|
|
4563
|
+
});
|
|
4564
|
+
} catch {
|
|
4565
|
+
}
|
|
4358
4566
|
});
|
|
4359
4567
|
return true;
|
|
4360
4568
|
}
|
|
@@ -4688,18 +4896,36 @@ function injectMeshSystemMessage(components, args) {
|
|
|
4688
4896
|
LOG.info("MeshEvents", `Suppressed ${args.event} for intentionally cleanup-stopped session ${eventSessionId || "(unknown session)"}`);
|
|
4689
4897
|
return { success: true, forwarded: 0, suppressed: true, intentionalCleanupStop: true };
|
|
4690
4898
|
}
|
|
4899
|
+
const eventTimestamp = readEventTimestamp(args.metadataEvent.timestamp);
|
|
4900
|
+
if (args.event === "agent:generating_completed" && eventSessionId) {
|
|
4901
|
+
const duplicateCompletion = isDuplicateMeshCompletionEvent({
|
|
4902
|
+
meshId: args.meshId,
|
|
4903
|
+
event: args.event,
|
|
4904
|
+
sessionId: eventSessionId,
|
|
4905
|
+
providerType: readNonEmptyString(args.metadataEvent.providerType) || void 0,
|
|
4906
|
+
providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0,
|
|
4907
|
+
timestamp: eventTimestamp,
|
|
4908
|
+
finalSummary: readNonEmptyString(args.metadataEvent.finalSummary) || void 0
|
|
4909
|
+
});
|
|
4910
|
+
if (duplicateCompletion) {
|
|
4911
|
+
LOG.info("MeshEvents", `Suppressed duplicate completion for mesh ${args.meshId} session ${eventSessionId}`);
|
|
4912
|
+
return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true };
|
|
4913
|
+
}
|
|
4914
|
+
}
|
|
4691
4915
|
let completedTaskForLedger = null;
|
|
4692
4916
|
if (args.event === "agent:generating_completed") {
|
|
4693
4917
|
const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
4694
4918
|
const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
|
|
4695
4919
|
const providerType = readNonEmptyString(args.metadataEvent.providerType);
|
|
4696
4920
|
if (sessionId) {
|
|
4697
|
-
const completedTask = updateSessionTaskStatus(args.meshId, sessionId, "completed"
|
|
4921
|
+
const completedTask = updateSessionTaskStatus(args.meshId, sessionId, "completed", {
|
|
4922
|
+
occurredAt: eventTimestamp !== null ? new Date(eventTimestamp).toISOString() : void 0
|
|
4923
|
+
});
|
|
4698
4924
|
completedTaskForLedger = completedTask ? { id: completedTask.id } : null;
|
|
4699
4925
|
if (nodeId && providerType) {
|
|
4700
|
-
|
|
4926
|
+
setImmediate(() => {
|
|
4701
4927
|
tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
|
|
4702
|
-
}
|
|
4928
|
+
});
|
|
4703
4929
|
}
|
|
4704
4930
|
}
|
|
4705
4931
|
} else if (args.event === "agent:ready") {
|
|
@@ -4737,13 +4963,17 @@ function injectMeshSystemMessage(components, args) {
|
|
|
4737
4963
|
}
|
|
4738
4964
|
}
|
|
4739
4965
|
if (sessionId && nodeId && providerType) {
|
|
4740
|
-
|
|
4741
|
-
|
|
4966
|
+
sweepExpiredRemoteIdleSessions();
|
|
4967
|
+
remoteIdleSessions.set(`${nodeId}:${sessionId}`, {
|
|
4968
|
+
nodeId,
|
|
4969
|
+
sessionId,
|
|
4970
|
+
providerType,
|
|
4971
|
+
expiresAt: Date.now() + REMOTE_IDLE_SESSION_TTL_MS
|
|
4972
|
+
});
|
|
4973
|
+
setImmediate(() => {
|
|
4742
4974
|
const assigned = tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
|
|
4743
|
-
if (assigned) {
|
|
4744
|
-
|
|
4745
|
-
}
|
|
4746
|
-
}, 500);
|
|
4975
|
+
if (assigned) remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
|
|
4976
|
+
});
|
|
4747
4977
|
}
|
|
4748
4978
|
} else if (args.event === "agent:generating_started") {
|
|
4749
4979
|
const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
@@ -4854,17 +5084,18 @@ function injectMeshSystemMessage(components, args) {
|
|
|
4854
5084
|
return true;
|
|
4855
5085
|
});
|
|
4856
5086
|
if (coordinatorInstances.length === 0) {
|
|
4857
|
-
if (
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
}
|
|
4866
|
-
|
|
4867
|
-
|
|
5087
|
+
if (queuePendingMeshCoordinatorEvent({
|
|
5088
|
+
event: args.event,
|
|
5089
|
+
meshId: args.meshId,
|
|
5090
|
+
nodeLabel: args.nodeLabel,
|
|
5091
|
+
nodeId: args.nodeId || void 0,
|
|
5092
|
+
workspace: readNonEmptyString(args.metadataEvent.workspace),
|
|
5093
|
+
metadataEvent: {
|
|
5094
|
+
...args.metadataEvent,
|
|
5095
|
+
...recoveryContext ? { recoveryContext } : {}
|
|
5096
|
+
},
|
|
5097
|
+
queuedAt: Date.now()
|
|
5098
|
+
})) {
|
|
4868
5099
|
LOG.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId})`);
|
|
4869
5100
|
}
|
|
4870
5101
|
return { success: true, forwarded: 0 };
|
|
@@ -4903,6 +5134,7 @@ function handleMeshForwardEvent(components, payload) {
|
|
|
4903
5134
|
providerType: readNonEmptyString(payload.providerType),
|
|
4904
5135
|
providerSessionId: readNonEmptyString(payload.providerSessionId),
|
|
4905
5136
|
finalSummary: readNonEmptyString(payload.finalSummary) || readNonEmptyString(payload.summary),
|
|
5137
|
+
...payload.timestamp !== void 0 ? { timestamp: payload.timestamp } : {},
|
|
4906
5138
|
intentional: payload.intentional === true,
|
|
4907
5139
|
intentionalStop: payload.intentionalStop === true,
|
|
4908
5140
|
operatorCleanup: payload.operatorCleanup === true,
|
|
@@ -4945,19 +5177,20 @@ function setupMeshEventForwarding(components) {
|
|
|
4945
5177
|
});
|
|
4946
5178
|
});
|
|
4947
5179
|
}
|
|
4948
|
-
var
|
|
5180
|
+
var import_fs6, import_path5, 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;
|
|
4949
5181
|
var init_mesh_events = __esm({
|
|
4950
5182
|
"../../oss/packages/daemon-core/src/mesh/mesh-events.ts"() {
|
|
4951
5183
|
"use strict";
|
|
5184
|
+
import_fs6 = require("fs");
|
|
5185
|
+
import_path5 = require("path");
|
|
4952
5186
|
init_config();
|
|
4953
5187
|
init_mesh_config();
|
|
4954
5188
|
init_cli_detector();
|
|
4955
5189
|
init_logger();
|
|
4956
5190
|
init_mesh_ledger();
|
|
4957
5191
|
init_mesh_work_queue();
|
|
5192
|
+
REMOTE_IDLE_SESSION_TTL_MS = 5 * 60 * 1e3;
|
|
4958
5193
|
remoteIdleSessions = /* @__PURE__ */ new Map();
|
|
4959
|
-
MAX_PENDING_EVENTS = 50;
|
|
4960
|
-
pendingMeshCoordinatorEvents = [];
|
|
4961
5194
|
MESH_COORDINATOR_EVENTS = /* @__PURE__ */ new Set([
|
|
4962
5195
|
"agent:generating_started",
|
|
4963
5196
|
"agent:generating_completed",
|
|
@@ -4973,6 +5206,8 @@ var init_mesh_events = __esm({
|
|
|
4973
5206
|
"monitor:long_generating": "task_stalled"
|
|
4974
5207
|
};
|
|
4975
5208
|
INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS = 30 * 60 * 1e3;
|
|
5209
|
+
RECENT_COMPLETION_FINGERPRINT_TTL_MS = 10 * 60 * 1e3;
|
|
5210
|
+
recentCompletionFingerprints = /* @__PURE__ */ new Map();
|
|
4976
5211
|
autoLaunchInProgress = /* @__PURE__ */ new Set();
|
|
4977
5212
|
autoLaunchCooldownUntil = /* @__PURE__ */ new Map();
|
|
4978
5213
|
AUTO_LAUNCH_COOLDOWN_MS = 5e3;
|
|
@@ -5100,7 +5335,7 @@ function isPlainObject2(value) {
|
|
|
5100
5335
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
5101
5336
|
}
|
|
5102
5337
|
function getStatePath() {
|
|
5103
|
-
return (0,
|
|
5338
|
+
return (0, import_path6.join)(getConfigDir(), "state.json");
|
|
5104
5339
|
}
|
|
5105
5340
|
function normalizeState(raw) {
|
|
5106
5341
|
const parsed = isPlainObject2(raw) ? raw : {};
|
|
@@ -5136,11 +5371,11 @@ function normalizeState(raw) {
|
|
|
5136
5371
|
}
|
|
5137
5372
|
function loadState() {
|
|
5138
5373
|
const statePath = getStatePath();
|
|
5139
|
-
if (!(0,
|
|
5374
|
+
if (!(0, import_fs7.existsSync)(statePath)) {
|
|
5140
5375
|
return { ...DEFAULT_STATE };
|
|
5141
5376
|
}
|
|
5142
5377
|
try {
|
|
5143
|
-
const raw = (0,
|
|
5378
|
+
const raw = (0, import_fs7.readFileSync)(statePath, "utf-8");
|
|
5144
5379
|
return normalizeState(JSON.parse(raw));
|
|
5145
5380
|
} catch {
|
|
5146
5381
|
return { ...DEFAULT_STATE };
|
|
@@ -5149,17 +5384,17 @@ function loadState() {
|
|
|
5149
5384
|
function saveState(state) {
|
|
5150
5385
|
const statePath = getStatePath();
|
|
5151
5386
|
const normalized = normalizeState(state);
|
|
5152
|
-
(0,
|
|
5387
|
+
(0, import_fs7.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
|
|
5153
5388
|
}
|
|
5154
5389
|
function resetState() {
|
|
5155
5390
|
saveState({ ...DEFAULT_STATE });
|
|
5156
5391
|
}
|
|
5157
|
-
var
|
|
5392
|
+
var import_fs7, import_path6, DEFAULT_STATE;
|
|
5158
5393
|
var init_state_store = __esm({
|
|
5159
5394
|
"../../oss/packages/daemon-core/src/config/state-store.ts"() {
|
|
5160
5395
|
"use strict";
|
|
5161
|
-
|
|
5162
|
-
|
|
5396
|
+
import_fs7 = require("fs");
|
|
5397
|
+
import_path6 = require("path");
|
|
5163
5398
|
init_config();
|
|
5164
5399
|
DEFAULT_STATE = {
|
|
5165
5400
|
recentActivity: [],
|
|
@@ -5192,7 +5427,7 @@ function findCliCommand(command) {
|
|
|
5192
5427
|
if (path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
5193
5428
|
const candidate = trimmed.startsWith("~") ? path10.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
|
|
5194
5429
|
const resolved = path10.isAbsolute(candidate) ? candidate : path10.resolve(candidate);
|
|
5195
|
-
return (0,
|
|
5430
|
+
return (0, import_fs8.existsSync)(resolved) ? resolved : null;
|
|
5196
5431
|
}
|
|
5197
5432
|
try {
|
|
5198
5433
|
const result = (0, import_child_process2.execSync)(
|
|
@@ -5223,9 +5458,9 @@ function checkPathExists(paths) {
|
|
|
5223
5458
|
if (normalized.includes("*")) {
|
|
5224
5459
|
const username = home.split(/[\\/]/).pop() || "";
|
|
5225
5460
|
const resolved = normalized.replace("*", username);
|
|
5226
|
-
if ((0,
|
|
5461
|
+
if ((0, import_fs8.existsSync)(resolved)) return resolved;
|
|
5227
5462
|
} else {
|
|
5228
|
-
if ((0,
|
|
5463
|
+
if ((0, import_fs8.existsSync)(normalized)) return normalized;
|
|
5229
5464
|
}
|
|
5230
5465
|
}
|
|
5231
5466
|
return null;
|
|
@@ -5239,7 +5474,7 @@ async function detectIDEs(providerLoader) {
|
|
|
5239
5474
|
let resolvedCli = cliPath;
|
|
5240
5475
|
if (!resolvedCli && appPath && os32 === "darwin") {
|
|
5241
5476
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
5242
|
-
if ((0,
|
|
5477
|
+
if ((0, import_fs8.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
5243
5478
|
}
|
|
5244
5479
|
if (!resolvedCli && appPath && os32 === "win32") {
|
|
5245
5480
|
const { dirname: dirname13 } = await import("path");
|
|
@@ -5252,7 +5487,7 @@ async function detectIDEs(providerLoader) {
|
|
|
5252
5487
|
`${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
|
|
5253
5488
|
];
|
|
5254
5489
|
for (const c of candidates) {
|
|
5255
|
-
if ((0,
|
|
5490
|
+
if ((0, import_fs8.existsSync)(c)) {
|
|
5256
5491
|
resolvedCli = c;
|
|
5257
5492
|
break;
|
|
5258
5493
|
}
|
|
@@ -5273,12 +5508,12 @@ async function detectIDEs(providerLoader) {
|
|
|
5273
5508
|
}
|
|
5274
5509
|
return results;
|
|
5275
5510
|
}
|
|
5276
|
-
var import_child_process2,
|
|
5511
|
+
var import_child_process2, import_fs8, import_os2, path10, BUILTIN_IDE_DEFINITIONS, registeredIDEs;
|
|
5277
5512
|
var init_ide_detector = __esm({
|
|
5278
5513
|
"../../oss/packages/daemon-core/src/detection/ide-detector.ts"() {
|
|
5279
5514
|
"use strict";
|
|
5280
5515
|
import_child_process2 = require("child_process");
|
|
5281
|
-
|
|
5516
|
+
import_fs8 = require("fs");
|
|
5282
5517
|
import_os2 = require("os");
|
|
5283
5518
|
path10 = __toESM(require("path"));
|
|
5284
5519
|
BUILTIN_IDE_DEFINITIONS = [];
|
|
@@ -7199,7 +7434,7 @@ var init_status_monitor = __esm({
|
|
|
7199
7434
|
});
|
|
7200
7435
|
|
|
7201
7436
|
// ../../oss/packages/daemon-core/src/providers/chat-message-normalization.ts
|
|
7202
|
-
function extractFinalSummaryFromMessages(messages, maxChars =
|
|
7437
|
+
function extractFinalSummaryFromMessages(messages, maxChars = DEFAULT_FINAL_SUMMARY_MAX_CHARS) {
|
|
7203
7438
|
if (!Array.isArray(messages) || messages.length === 0) return "";
|
|
7204
7439
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
7205
7440
|
const msg = messages[i];
|
|
@@ -7501,11 +7736,12 @@ function filterInternalChatMessages(messages) {
|
|
|
7501
7736
|
function filterChatMessagesByVisibility(messages, surface) {
|
|
7502
7737
|
return (Array.isArray(messages) ? messages : []).filter((message) => classifyChatMessageVisibility(message).surface === surface);
|
|
7503
7738
|
}
|
|
7504
|
-
var BUILTIN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_VISIBILITIES, CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES, CHAT_MESSAGE_AUDIENCES, CHAT_MESSAGE_SOURCES, CHAT_MESSAGE_ACTIVITY_SOURCES, CHAT_MESSAGE_INTERNAL_SOURCES, KNOWN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_KIND_ALIASES, EXPLICIT_HIDDEN_VISIBILITIES, EXPLICIT_VISIBLE_VISIBILITIES, HIDDEN_AUDIENCES, ACTIVITY_SOURCE_SET, INTERNAL_SOURCE_SET;
|
|
7739
|
+
var DEFAULT_FINAL_SUMMARY_MAX_CHARS, BUILTIN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_VISIBILITIES, CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES, CHAT_MESSAGE_AUDIENCES, CHAT_MESSAGE_SOURCES, CHAT_MESSAGE_ACTIVITY_SOURCES, CHAT_MESSAGE_INTERNAL_SOURCES, KNOWN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_KIND_ALIASES, EXPLICIT_HIDDEN_VISIBILITIES, EXPLICIT_VISIBLE_VISIBILITIES, HIDDEN_AUDIENCES, ACTIVITY_SOURCE_SET, INTERNAL_SOURCE_SET;
|
|
7505
7740
|
var init_chat_message_normalization = __esm({
|
|
7506
7741
|
"../../oss/packages/daemon-core/src/providers/chat-message-normalization.ts"() {
|
|
7507
7742
|
"use strict";
|
|
7508
7743
|
init_contracts();
|
|
7744
|
+
DEFAULT_FINAL_SUMMARY_MAX_CHARS = 4e3;
|
|
7509
7745
|
BUILTIN_CHAT_MESSAGE_KINDS = ["standard", "thought", "tool", "terminal", "system"];
|
|
7510
7746
|
CHAT_MESSAGE_VISIBILITIES = ["user", "debug", "internal", "hidden"];
|
|
7511
7747
|
CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES = ["visible", "chat", "user", "debug", "internal", "hidden"];
|
|
@@ -37725,7 +37961,7 @@ function commandExists(command) {
|
|
|
37725
37961
|
const trimmed = command.trim();
|
|
37726
37962
|
if (!trimmed) return false;
|
|
37727
37963
|
if (isExplicitCommand(trimmed)) {
|
|
37728
|
-
return (0,
|
|
37964
|
+
return (0, import_fs9.existsSync)(expandExecutable(trimmed));
|
|
37729
37965
|
}
|
|
37730
37966
|
try {
|
|
37731
37967
|
(0, import_child_process6.execFileSync)(process.platform === "win32" ? "where" : "which", [trimmed], {
|
|
@@ -37746,10 +37982,10 @@ function hasCliArg(args, flag) {
|
|
|
37746
37982
|
}
|
|
37747
37983
|
function ensureEmptyDelegatedMcpConfig(workspace) {
|
|
37748
37984
|
const baseDir = path19.join(os16.tmpdir(), "adhdev-delegated-agent-empty-mcp");
|
|
37749
|
-
(0,
|
|
37985
|
+
(0, import_fs9.mkdirSync)(baseDir, { recursive: true });
|
|
37750
37986
|
const workspaceHash = crypto4.createHash("sha256").update(path19.resolve(workspace || os16.tmpdir())).digest("hex").slice(0, 16);
|
|
37751
37987
|
const filePath = path19.join(baseDir, `${workspaceHash}.json`);
|
|
37752
|
-
(0,
|
|
37988
|
+
(0, import_fs9.writeFileSync)(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
|
|
37753
37989
|
return filePath;
|
|
37754
37990
|
}
|
|
37755
37991
|
function buildCoordinatorDelegatedCliLaunchOptions(input) {
|
|
@@ -37876,14 +38112,14 @@ function resolveCliSessionBinding(provider, normalizedType, cliArgs, requestedRe
|
|
|
37876
38112
|
launchMode: "new"
|
|
37877
38113
|
};
|
|
37878
38114
|
}
|
|
37879
|
-
var os16, path19, crypto4,
|
|
38115
|
+
var os16, path19, crypto4, import_fs9, import_child_process6, chalkModule, chalkApi, COORDINATOR_DELEGATED_ENV_UNSETS, DaemonCliManager;
|
|
37880
38116
|
var init_cli_manager = __esm({
|
|
37881
38117
|
"../../oss/packages/daemon-core/src/commands/cli-manager.ts"() {
|
|
37882
38118
|
"use strict";
|
|
37883
38119
|
os16 = __toESM(require("os"));
|
|
37884
38120
|
path19 = __toESM(require("path"));
|
|
37885
38121
|
crypto4 = __toESM(require("crypto"));
|
|
37886
|
-
|
|
38122
|
+
import_fs9 = require("fs");
|
|
37887
38123
|
import_child_process6 = require("child_process");
|
|
37888
38124
|
init_source2();
|
|
37889
38125
|
init_provider_cli_adapter();
|
|
@@ -38797,7 +39033,7 @@ function createFsWatchInstance(path42, options, listener, errHandler, emitRaw) {
|
|
|
38797
39033
|
}
|
|
38798
39034
|
};
|
|
38799
39035
|
try {
|
|
38800
|
-
return (0,
|
|
39036
|
+
return (0, import_fs10.watch)(path42, {
|
|
38801
39037
|
persistent: options.persistent
|
|
38802
39038
|
}, handleEvent);
|
|
38803
39039
|
} catch (error48) {
|
|
@@ -38805,11 +39041,11 @@ function createFsWatchInstance(path42, options, listener, errHandler, emitRaw) {
|
|
|
38805
39041
|
return void 0;
|
|
38806
39042
|
}
|
|
38807
39043
|
}
|
|
38808
|
-
var
|
|
39044
|
+
var import_fs10, import_promises5, sysPath, import_os3, STR_DATA, STR_END, STR_CLOSE, EMPTY_FN, pl, isWindows, isMacos, isLinux, isFreeBSD, isIBMi, EVENTS, EV, THROTTLE_MODE_WATCH, statMethods, KEY_LISTENERS, KEY_ERR, KEY_RAW, HANDLER_KEYS, binaryExtensions, isBinaryPath, foreach, addAndConvert, clearItem, delFromSet, isEmptySet, FsWatchInstances, fsWatchBroadcast, setFsWatchListener, FsWatchFileInstances, setFsWatchFileListener, NodeFsHandler;
|
|
38809
39045
|
var init_handler2 = __esm({
|
|
38810
39046
|
"../../oss/node_modules/chokidar/esm/handler.js"() {
|
|
38811
39047
|
"use strict";
|
|
38812
|
-
|
|
39048
|
+
import_fs10 = require("fs");
|
|
38813
39049
|
import_promises5 = require("fs/promises");
|
|
38814
39050
|
sysPath = __toESM(require("path"), 1);
|
|
38815
39051
|
import_os3 = require("os");
|
|
@@ -39213,7 +39449,7 @@ var init_handler2 = __esm({
|
|
|
39213
39449
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
39214
39450
|
const copts = cont && cont.options;
|
|
39215
39451
|
if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
|
|
39216
|
-
(0,
|
|
39452
|
+
(0, import_fs10.unwatchFile)(fullPath);
|
|
39217
39453
|
cont = void 0;
|
|
39218
39454
|
}
|
|
39219
39455
|
if (cont) {
|
|
@@ -39224,7 +39460,7 @@ var init_handler2 = __esm({
|
|
|
39224
39460
|
listeners: listener,
|
|
39225
39461
|
rawEmitters: rawEmitter,
|
|
39226
39462
|
options,
|
|
39227
|
-
watcher: (0,
|
|
39463
|
+
watcher: (0, import_fs10.watchFile)(fullPath, options, (curr, prev) => {
|
|
39228
39464
|
foreach(cont.rawEmitters, (rawEmitter2) => {
|
|
39229
39465
|
rawEmitter2(EV.CHANGE, fullPath, { curr, prev });
|
|
39230
39466
|
});
|
|
@@ -39241,7 +39477,7 @@ var init_handler2 = __esm({
|
|
|
39241
39477
|
delFromSet(cont, KEY_RAW, rawEmitter);
|
|
39242
39478
|
if (isEmptySet(cont.listeners)) {
|
|
39243
39479
|
FsWatchFileInstances.delete(fullPath);
|
|
39244
|
-
(0,
|
|
39480
|
+
(0, import_fs10.unwatchFile)(fullPath);
|
|
39245
39481
|
cont.options = cont.watcher = void 0;
|
|
39246
39482
|
Object.freeze(cont);
|
|
39247
39483
|
}
|
|
@@ -39619,11 +39855,11 @@ function watch(paths, options = {}) {
|
|
|
39619
39855
|
watcher.add(paths);
|
|
39620
39856
|
return watcher;
|
|
39621
39857
|
}
|
|
39622
|
-
var
|
|
39858
|
+
var import_fs11, import_promises6, import_events2, sysPath2, SLASH, SLASH_SLASH, ONE_DOT, TWO_DOTS, STRING_TYPE, BACK_SLASH_RE, DOUBLE_SLASH_RE, DOT_RE, REPLACER_RE, isMatcherObject, unifyPaths, toUnix, normalizePathToUnix, normalizeIgnored, getAbsolutePath, EMPTY_SET, DirEntry, STAT_METHOD_F, STAT_METHOD_L, WatchHelper, FSWatcher;
|
|
39623
39859
|
var init_esm2 = __esm({
|
|
39624
39860
|
"../../oss/node_modules/chokidar/esm/index.js"() {
|
|
39625
39861
|
"use strict";
|
|
39626
|
-
|
|
39862
|
+
import_fs11 = require("fs");
|
|
39627
39863
|
import_promises6 = require("fs/promises");
|
|
39628
39864
|
import_events2 = require("events");
|
|
39629
39865
|
sysPath2 = __toESM(require("path"), 1);
|
|
@@ -40101,7 +40337,7 @@ var init_esm2 = __esm({
|
|
|
40101
40337
|
const now = /* @__PURE__ */ new Date();
|
|
40102
40338
|
const writes = this._pendingWrites;
|
|
40103
40339
|
function awaitWriteFinishFn(prevStat) {
|
|
40104
|
-
(0,
|
|
40340
|
+
(0, import_fs11.stat)(fullPath, (err, curStat) => {
|
|
40105
40341
|
if (err || !writes.has(path42)) {
|
|
40106
40342
|
if (err && err.code !== "ENOENT")
|
|
40107
40343
|
awfEmit(err);
|
|
@@ -46402,55 +46638,45 @@ function readBooleanValue(...values) {
|
|
|
46402
46638
|
}
|
|
46403
46639
|
return void 0;
|
|
46404
46640
|
}
|
|
46405
|
-
function
|
|
46406
|
-
const
|
|
46407
|
-
const
|
|
46408
|
-
if (
|
|
46409
|
-
|
|
46410
|
-
|
|
46411
|
-
|
|
46412
|
-
|
|
46413
|
-
|
|
46414
|
-
|
|
46415
|
-
|
|
46416
|
-
|
|
46417
|
-
|
|
46418
|
-
|
|
46419
|
-
|
|
46420
|
-
|
|
46421
|
-
|
|
46422
|
-
|
|
46423
|
-
|
|
46424
|
-
|
|
46425
|
-
|
|
46426
|
-
|
|
46427
|
-
|
|
46428
|
-
|
|
46429
|
-
|
|
46430
|
-
|
|
46431
|
-
|
|
46432
|
-
|
|
46433
|
-
|
|
46434
|
-
}
|
|
46435
|
-
}
|
|
46436
|
-
const rawGit = readObjectRecord(node?.lastGit ?? node?.last_git);
|
|
46437
|
-
const gitResult = readObjectRecord(rawGit.result);
|
|
46438
|
-
const directStatus = readObjectRecord(rawGit.status);
|
|
46439
|
-
const nestedStatus = readObjectRecord(gitResult.status);
|
|
46440
|
-
const rawProbe = readObjectRecord(node?.lastProbe ?? node?.last_probe);
|
|
46441
|
-
const probeGit = readObjectRecord(rawProbe.git);
|
|
46442
|
-
const probeGitResult = readObjectRecord(probeGit.result);
|
|
46443
|
-
const probeDirectStatus = readObjectRecord(probeGit.status);
|
|
46444
|
-
const probeNestedStatus = readObjectRecord(probeGitResult.status);
|
|
46445
|
-
const status = Object.keys(directStatus).length ? directStatus : Object.keys(nestedStatus).length ? nestedStatus : Object.keys(probeDirectStatus).length ? probeDirectStatus : Object.keys(probeNestedStatus).length ? probeNestedStatus : {};
|
|
46641
|
+
function joinRepoPath(root, relativePath) {
|
|
46642
|
+
const normalizedRoot = typeof root === "string" ? root.trim().replace(/[\\/]+$/, "") : "";
|
|
46643
|
+
const normalizedPath = typeof relativePath === "string" ? relativePath.trim() : "";
|
|
46644
|
+
if (!normalizedPath) return void 0;
|
|
46645
|
+
if (/^(?:[A-Za-z]:[\\/]|\/)/.test(normalizedPath)) return normalizedPath;
|
|
46646
|
+
if (!normalizedRoot) return void 0;
|
|
46647
|
+
return `${normalizedRoot}/${normalizedPath.replace(/^[\\/]+/, "")}`;
|
|
46648
|
+
}
|
|
46649
|
+
function readGitSubmodules(value, parentRepoRoot) {
|
|
46650
|
+
if (!Array.isArray(value)) return void 0;
|
|
46651
|
+
const submodules = value.map((entry) => {
|
|
46652
|
+
const submodule = readObjectRecord(entry);
|
|
46653
|
+
const path42 = readStringValue(submodule.path);
|
|
46654
|
+
const commit = readStringValue(submodule.commit);
|
|
46655
|
+
const repoPath = readStringValue(submodule.repoPath, submodule.repo_root) ?? joinRepoPath(parentRepoRoot, path42);
|
|
46656
|
+
if (!path42 || !commit || !repoPath) return null;
|
|
46657
|
+
return {
|
|
46658
|
+
path: path42,
|
|
46659
|
+
commit,
|
|
46660
|
+
repoPath,
|
|
46661
|
+
dirty: readBooleanValue(submodule.dirty) ?? false,
|
|
46662
|
+
outOfSync: readBooleanValue(submodule.outOfSync, submodule.out_of_sync) ?? false,
|
|
46663
|
+
lastCheckedAt: readNumberValue(submodule.lastCheckedAt, submodule.last_checked_at) ?? Date.now(),
|
|
46664
|
+
...readStringValue(submodule.error) ? { error: readStringValue(submodule.error) } : {}
|
|
46665
|
+
};
|
|
46666
|
+
}).filter((entry) => entry !== null);
|
|
46667
|
+
return submodules.length > 0 ? submodules : void 0;
|
|
46668
|
+
}
|
|
46669
|
+
function normalizeInlineMeshGitStatus(status, node, options) {
|
|
46446
46670
|
const isGitRepo = readBooleanValue(status.isGitRepo);
|
|
46447
46671
|
if (!Object.keys(status).length || isGitRepo === void 0) return void 0;
|
|
46448
46672
|
const conflictFiles = Array.isArray(status.conflictFiles) ? status.conflictFiles.filter((value) => typeof value === "string") : [];
|
|
46449
46673
|
const conflictCount = readNumberValue(status.conflicts) ?? conflictFiles.length;
|
|
46450
46674
|
const hasConflicts = readBooleanValue(status.hasConflicts) ?? conflictCount > 0;
|
|
46675
|
+
const repoRoot = readStringValue(status.repoRoot, status.repo_root, node?.repoRoot, node?.repo_root, status.workspace, node?.workspace) || void 0;
|
|
46676
|
+
const submodules = readGitSubmodules(status.submodules, repoRoot);
|
|
46451
46677
|
return {
|
|
46452
46678
|
workspace: readStringValue(status.workspace, node?.workspace) || "",
|
|
46453
|
-
repoRoot:
|
|
46679
|
+
repoRoot: repoRoot ?? null,
|
|
46454
46680
|
isGitRepo,
|
|
46455
46681
|
branch: readStringValue(status.branch) ?? null,
|
|
46456
46682
|
headCommit: readStringValue(status.headCommit) ?? null,
|
|
@@ -46466,29 +46692,412 @@ function buildCachedInlineMeshGitStatus(node) {
|
|
|
46466
46692
|
hasConflicts,
|
|
46467
46693
|
conflictFiles,
|
|
46468
46694
|
stashCount: readNumberValue(status.stashCount) ?? 0,
|
|
46469
|
-
lastCheckedAt: Date.now()
|
|
46695
|
+
lastCheckedAt: options?.lastCheckedAt ?? readNumberValue(status.lastCheckedAt) ?? Date.now(),
|
|
46696
|
+
...submodules ? { submodules } : {}
|
|
46470
46697
|
};
|
|
46471
46698
|
}
|
|
46472
|
-
function
|
|
46699
|
+
function buildInlineMeshTransitGitStatus(node) {
|
|
46700
|
+
const rawGit = readObjectRecord(node?.lastGit ?? node?.last_git);
|
|
46701
|
+
const gitResult = readObjectRecord(rawGit.result);
|
|
46702
|
+
const directStatus = readObjectRecord(rawGit.status);
|
|
46703
|
+
const nestedStatus = readObjectRecord(gitResult.status);
|
|
46704
|
+
const rawProbe = readObjectRecord(node?.lastProbe ?? node?.last_probe);
|
|
46705
|
+
const probeGit = readObjectRecord(rawProbe.git);
|
|
46706
|
+
const probeGitResult = readObjectRecord(probeGit.result);
|
|
46707
|
+
const probeDirectStatus = readObjectRecord(probeGit.status);
|
|
46708
|
+
const probeNestedStatus = readObjectRecord(probeGitResult.status);
|
|
46709
|
+
const status = Object.keys(directStatus).length ? directStatus : Object.keys(nestedStatus).length ? nestedStatus : Object.keys(probeDirectStatus).length ? probeDirectStatus : Object.keys(probeNestedStatus).length ? probeNestedStatus : {};
|
|
46710
|
+
return normalizeInlineMeshGitStatus(status, node, { lastCheckedAt: Date.now() });
|
|
46711
|
+
}
|
|
46712
|
+
function recordInlineMeshDirectGitTruth(node, git, source) {
|
|
46713
|
+
if (!node || typeof node !== "object" || Array.isArray(node)) return;
|
|
46714
|
+
const checkedAt = readNumberValue(git.lastCheckedAt) ?? Date.now();
|
|
46715
|
+
const updatedAt = new Date(checkedAt).toISOString();
|
|
46716
|
+
const nextGit = {
|
|
46717
|
+
...git,
|
|
46718
|
+
lastCheckedAt: checkedAt
|
|
46719
|
+
};
|
|
46720
|
+
node.lastGit = {
|
|
46721
|
+
source,
|
|
46722
|
+
checkedAt,
|
|
46723
|
+
status: nextGit
|
|
46724
|
+
};
|
|
46725
|
+
node.last_git = node.lastGit;
|
|
46726
|
+
node.machineStatus = "online";
|
|
46727
|
+
node.updatedAt = updatedAt;
|
|
46728
|
+
node.lastSeenAt = updatedAt;
|
|
46729
|
+
const repoRoot = readStringValue(nextGit.repoRoot);
|
|
46730
|
+
if (repoRoot && !readStringValue(node.repoRoot)) node.repoRoot = repoRoot;
|
|
46731
|
+
}
|
|
46732
|
+
function buildCachedInlineMeshGitStatus(node) {
|
|
46733
|
+
const liveGit = buildInlineMeshTransitGitStatus(node);
|
|
46734
|
+
if (liveGit) return liveGit;
|
|
46473
46735
|
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46474
|
-
const
|
|
46475
|
-
|
|
46476
|
-
|
|
46736
|
+
const cachedGit = readObjectRecord(cachedStatus.git);
|
|
46737
|
+
if (!Object.keys(cachedGit).length) return void 0;
|
|
46738
|
+
return normalizeInlineMeshGitStatus(cachedGit, node);
|
|
46739
|
+
}
|
|
46740
|
+
function shouldDiscardCachedInlineMeshStatus(node) {
|
|
46741
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46742
|
+
if (!Object.keys(cachedStatus).length) return false;
|
|
46743
|
+
const cachedGit = readObjectRecord(cachedStatus.git);
|
|
46744
|
+
const workspaceError = readStringValue(cachedStatus.error, node?.error);
|
|
46745
|
+
if (workspaceError && /workspace must be an existing directory/i.test(workspaceError)) return true;
|
|
46746
|
+
const isGitRepo = readBooleanValue(cachedGit.isGitRepo);
|
|
46747
|
+
const branch = readStringValue(cachedGit.branch);
|
|
46748
|
+
const headCommit = readStringValue(cachedGit.headCommit);
|
|
46749
|
+
return isGitRepo === false && !branch && !headCommit;
|
|
46750
|
+
}
|
|
46751
|
+
function stripInlineMeshTransientNodeState(node) {
|
|
46752
|
+
if (!node || typeof node !== "object" || Array.isArray(node)) return node;
|
|
46753
|
+
const {
|
|
46754
|
+
cachedStatus,
|
|
46755
|
+
lastGit: _lastGit,
|
|
46756
|
+
last_git: _lastGitLegacy,
|
|
46757
|
+
lastProbe: _lastProbe,
|
|
46758
|
+
last_probe: _lastProbeLegacy,
|
|
46759
|
+
error: _error,
|
|
46760
|
+
health: _health,
|
|
46761
|
+
machineStatus: _machineStatus,
|
|
46762
|
+
lastSeenAt: _lastSeenAt,
|
|
46763
|
+
last_seen_at: _lastSeenAtLegacy,
|
|
46764
|
+
updatedAt: _updatedAt,
|
|
46765
|
+
updated_at: _updatedAtLegacy,
|
|
46766
|
+
activeSession: _activeSession,
|
|
46767
|
+
active_session: _activeSessionLegacy,
|
|
46768
|
+
activeSessionId: _activeSessionId,
|
|
46769
|
+
active_session_id: _activeSessionIdLegacy,
|
|
46770
|
+
sessionId: _sessionId,
|
|
46771
|
+
session_id: _sessionIdLegacy,
|
|
46772
|
+
providerType: _providerType,
|
|
46773
|
+
provider_type: _providerTypeLegacy,
|
|
46774
|
+
...rest
|
|
46775
|
+
} = node;
|
|
46776
|
+
if (cachedStatus && !shouldDiscardCachedInlineMeshStatus(node)) {
|
|
46777
|
+
return { ...rest, cachedStatus };
|
|
46778
|
+
}
|
|
46779
|
+
return rest;
|
|
46780
|
+
}
|
|
46781
|
+
function hasInlineMeshTransientNodeState(node) {
|
|
46782
|
+
if (!node || typeof node !== "object" || Array.isArray(node)) return false;
|
|
46783
|
+
return "cachedStatus" in node || "lastGit" in node || "last_git" in node || "lastProbe" in node || "last_probe" in node || "error" in node || "health" in node || "machineStatus" in node || "lastSeenAt" in node || "last_seen_at" in node || "updatedAt" in node || "updated_at" in node || "activeSession" in node || "active_session" in node || "activeSessionId" in node || "active_session_id" in node || "sessionId" in node || "session_id" in node || "providerType" in node || "provider_type" in node;
|
|
46784
|
+
}
|
|
46785
|
+
function inlineMeshCarriesTransientNodeTruth(inlineMesh) {
|
|
46786
|
+
if (!inlineMesh || typeof inlineMesh !== "object" || Array.isArray(inlineMesh)) return false;
|
|
46787
|
+
if (!Array.isArray(inlineMesh.nodes) || inlineMesh.nodes.length === 0) return false;
|
|
46788
|
+
return inlineMesh.nodes.some((node) => hasInlineMeshTransientNodeState(node));
|
|
46789
|
+
}
|
|
46790
|
+
function readInlineMeshNodeId(node) {
|
|
46791
|
+
return readStringValue(node?.id, node?.nodeId) || "";
|
|
46792
|
+
}
|
|
46793
|
+
function sanitizeInlineMesh(inlineMesh) {
|
|
46794
|
+
if (!inlineMesh || typeof inlineMesh !== "object" || Array.isArray(inlineMesh)) return inlineMesh;
|
|
46795
|
+
if (!Array.isArray(inlineMesh.nodes)) return inlineMesh;
|
|
46796
|
+
let changed = false;
|
|
46797
|
+
const nodes = inlineMesh.nodes.map((node) => {
|
|
46798
|
+
if (!hasInlineMeshTransientNodeState(node)) return node;
|
|
46799
|
+
changed = true;
|
|
46800
|
+
return stripInlineMeshTransientNodeState(node);
|
|
46801
|
+
});
|
|
46802
|
+
if (!changed) return inlineMesh;
|
|
46803
|
+
return {
|
|
46804
|
+
...inlineMesh,
|
|
46805
|
+
nodes
|
|
46806
|
+
};
|
|
46807
|
+
}
|
|
46808
|
+
function reconcileInlineMeshCache(cached2, incoming) {
|
|
46809
|
+
if (!cached2 || typeof cached2 !== "object" || Array.isArray(cached2)) return incoming;
|
|
46810
|
+
if (!incoming || typeof incoming !== "object" || Array.isArray(incoming)) return cached2;
|
|
46811
|
+
const cachedNodes = Array.isArray(cached2.nodes) ? cached2.nodes : [];
|
|
46812
|
+
const incomingNodes = Array.isArray(incoming.nodes) ? incoming.nodes : [];
|
|
46813
|
+
if (!cachedNodes.length || !incomingNodes.length) return { ...cached2, ...incoming };
|
|
46814
|
+
const incomingById = /* @__PURE__ */ new Map();
|
|
46815
|
+
for (const node of incomingNodes) {
|
|
46816
|
+
const nodeId = readInlineMeshNodeId(node);
|
|
46817
|
+
if (nodeId) incomingById.set(nodeId, node);
|
|
46818
|
+
}
|
|
46819
|
+
const nodes = cachedNodes.map((cachedNode) => {
|
|
46820
|
+
const nodeId = readInlineMeshNodeId(cachedNode);
|
|
46821
|
+
const incomingNode = nodeId ? incomingById.get(nodeId) : void 0;
|
|
46822
|
+
if (!incomingNode) return cachedNode;
|
|
46823
|
+
if (hasInlineMeshTransientNodeState(incomingNode)) {
|
|
46824
|
+
return { ...cachedNode, ...incomingNode };
|
|
46825
|
+
}
|
|
46826
|
+
return { ...stripInlineMeshTransientNodeState(cachedNode), ...incomingNode };
|
|
46827
|
+
});
|
|
46828
|
+
return {
|
|
46829
|
+
...cached2,
|
|
46830
|
+
...incoming,
|
|
46831
|
+
nodes
|
|
46832
|
+
};
|
|
46833
|
+
}
|
|
46834
|
+
function hasGitWorktreeChanges(git) {
|
|
46835
|
+
if (!git) return false;
|
|
46836
|
+
return Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
|
|
46837
|
+
}
|
|
46838
|
+
function getGitSubmoduleDriftState(git) {
|
|
46839
|
+
const submodules = Array.isArray(git?.submodules) ? git.submodules : [];
|
|
46840
|
+
let dirty = false;
|
|
46841
|
+
let outOfSync = false;
|
|
46842
|
+
for (const entry of submodules) {
|
|
46843
|
+
const submodule = readObjectRecord(entry);
|
|
46844
|
+
if (readBooleanValue(submodule.dirty) === true) dirty = true;
|
|
46845
|
+
if (readBooleanValue(submodule.outOfSync) === true || !!readStringValue(submodule.error)) outOfSync = true;
|
|
46846
|
+
}
|
|
46847
|
+
return { dirty, outOfSync };
|
|
46848
|
+
}
|
|
46849
|
+
function deriveMeshNodeHealthFromGit(git) {
|
|
46850
|
+
if (!git || readBooleanValue(git.isGitRepo) === false) return "degraded";
|
|
46851
|
+
const branch = readStringValue(git.branch);
|
|
46852
|
+
if (!branch) return "degraded";
|
|
46853
|
+
const submoduleDrift = getGitSubmoduleDriftState(git);
|
|
46854
|
+
if (submoduleDrift.outOfSync) return "degraded";
|
|
46855
|
+
if (submoduleDrift.dirty || hasGitWorktreeChanges(git)) return "dirty";
|
|
46856
|
+
return "online";
|
|
46857
|
+
}
|
|
46858
|
+
function readCachedInlineMeshActiveSessions(node) {
|
|
46859
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46860
|
+
const activeSession = readObjectRecord(cachedStatus.activeSession);
|
|
46861
|
+
const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
|
|
46862
|
+
const sessionId = readStringValue(fallbackSession.id, fallbackSession.sessionId, fallbackSession.session_id, node?.activeSessionId, node?.active_session_id, node?.sessionId, node?.session_id);
|
|
46863
|
+
return sessionId ? [sessionId] : [];
|
|
46864
|
+
}
|
|
46865
|
+
function readCachedInlineMeshActiveSessionDetails(node) {
|
|
46866
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46867
|
+
const activeSession = readObjectRecord(cachedStatus.activeSession);
|
|
46868
|
+
const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
|
|
46869
|
+
const sessionId = readStringValue(
|
|
46870
|
+
fallbackSession.id,
|
|
46871
|
+
fallbackSession.sessionId,
|
|
46872
|
+
fallbackSession.session_id,
|
|
46873
|
+
node?.activeSessionId,
|
|
46874
|
+
node?.active_session_id,
|
|
46875
|
+
node?.sessionId,
|
|
46876
|
+
node?.session_id
|
|
46877
|
+
);
|
|
46878
|
+
if (!sessionId) return [];
|
|
46879
|
+
return [{
|
|
46880
|
+
sessionId,
|
|
46881
|
+
providerType: readStringValue(
|
|
46882
|
+
fallbackSession.providerType,
|
|
46883
|
+
fallbackSession.provider_type,
|
|
46884
|
+
fallbackSession.cliType,
|
|
46885
|
+
fallbackSession.cli_type,
|
|
46886
|
+
fallbackSession.provider,
|
|
46887
|
+
node?.providerType,
|
|
46888
|
+
node?.provider_type
|
|
46889
|
+
),
|
|
46890
|
+
state: readStringValue(fallbackSession.status, fallbackSession.state, fallbackSession.lifecycle),
|
|
46891
|
+
lifecycle: readStringValue(fallbackSession.lifecycle),
|
|
46892
|
+
title: readStringValue(fallbackSession.title, fallbackSession.displayName, fallbackSession.display_name) ?? null,
|
|
46893
|
+
workspace: readStringValue(fallbackSession.workspace, node?.workspace) ?? null,
|
|
46894
|
+
lastActivityAt: readStringValue(fallbackSession.lastActivityAt, fallbackSession.last_activity_at) ?? null,
|
|
46895
|
+
recoveryState: readStringValue(fallbackSession.recoveryState, fallbackSession.recovery_state) ?? null,
|
|
46896
|
+
isCached: true
|
|
46897
|
+
}];
|
|
46898
|
+
}
|
|
46899
|
+
function readLiveMeshSessionState(record2) {
|
|
46900
|
+
return readStringValue(
|
|
46901
|
+
record2?.meta?.sessionStatus,
|
|
46902
|
+
record2?.meta?.status,
|
|
46903
|
+
record2?.meta?.providerStatus,
|
|
46904
|
+
record2?.status,
|
|
46905
|
+
record2?.state,
|
|
46906
|
+
record2?.lifecycle
|
|
46907
|
+
);
|
|
46908
|
+
}
|
|
46909
|
+
function toIsoTimestamp(value) {
|
|
46910
|
+
if (typeof value === "number" && Number.isFinite(value)) return new Date(value).toISOString();
|
|
46911
|
+
const stringValue = readStringValue(value);
|
|
46912
|
+
return stringValue || null;
|
|
46913
|
+
}
|
|
46914
|
+
function synthesizeMeshNodeFreshnessFromConnection(status) {
|
|
46915
|
+
const connection = readObjectRecord(status.connection);
|
|
46916
|
+
const connectionFreshAt = toIsoTimestamp(connection.lastCommandAt ?? connection.lastConnectedAt ?? connection.lastStateChangeAt);
|
|
46917
|
+
const git = readObjectRecord(status.git);
|
|
46918
|
+
const gitCheckedAt = toIsoTimestamp(git.lastCheckedAt);
|
|
46919
|
+
if (!status.lastSeenAt && connectionFreshAt) status.lastSeenAt = connectionFreshAt;
|
|
46920
|
+
if (!status.updatedAt && (gitCheckedAt || connectionFreshAt)) {
|
|
46921
|
+
status.updatedAt = gitCheckedAt ?? connectionFreshAt;
|
|
46922
|
+
}
|
|
46923
|
+
}
|
|
46924
|
+
function finalizeMeshNodeStatus(args) {
|
|
46925
|
+
const { status, node, daemonId, isSelfNode } = args;
|
|
46926
|
+
if (!readStringValue(status.machineStatus)) {
|
|
46927
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46928
|
+
const machineStatus = readStringValue(cachedStatus.machineStatus, cachedStatus.machine_status, node?.machineStatus);
|
|
46929
|
+
if (machineStatus) status.machineStatus = machineStatus;
|
|
46930
|
+
}
|
|
46931
|
+
synthesizeMeshNodeFreshnessFromConnection(status);
|
|
46932
|
+
const connectionState = readStringValue(readObjectRecord(status.connection).state);
|
|
46933
|
+
status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || connectionState === "connected" || isSelfNode);
|
|
46934
|
+
}
|
|
46935
|
+
async function probeRemoteMeshGitStatus(args) {
|
|
46936
|
+
if (!args.dispatchMeshCommand) return null;
|
|
46937
|
+
const remoteResult = await Promise.race([
|
|
46938
|
+
args.dispatchMeshCommand(args.daemonId, "git_status", { workspace: args.workspace }),
|
|
46939
|
+
new Promise((_2, reject) => setTimeout(() => reject(new Error("timeout")), args.timeoutMs))
|
|
46940
|
+
]);
|
|
46941
|
+
const remoteGit = remoteResult?.status ?? remoteResult?.git ?? remoteResult;
|
|
46942
|
+
return remoteGit && typeof remoteGit === "object" && typeof remoteGit.isGitRepo === "boolean" ? remoteGit : null;
|
|
46943
|
+
}
|
|
46944
|
+
async function hydrateInlineMeshDirectTruth(args) {
|
|
46945
|
+
const nodes = Array.isArray(args.mesh?.nodes) ? args.mesh.nodes : [];
|
|
46946
|
+
if (!nodes.length) {
|
|
46947
|
+
return {
|
|
46948
|
+
directEvidenceCount: 0,
|
|
46949
|
+
localConfirmedCount: 0,
|
|
46950
|
+
peerAttemptedCount: 0,
|
|
46951
|
+
peerConfirmedCount: 0,
|
|
46952
|
+
unavailableNodeIds: []
|
|
46953
|
+
};
|
|
46954
|
+
}
|
|
46955
|
+
const selectedCoordinatorNodeId = readStringValue(
|
|
46956
|
+
args.mesh?.coordinator?.preferredNodeId,
|
|
46957
|
+
nodes[0]?.id,
|
|
46958
|
+
nodes[0]?.nodeId
|
|
46959
|
+
);
|
|
46960
|
+
let localConfirmedCount = 0;
|
|
46961
|
+
let peerAttemptedCount = 0;
|
|
46962
|
+
let peerConfirmedCount = 0;
|
|
46963
|
+
const unavailableNodeIds = [];
|
|
46964
|
+
for (const [nodeIndex, node] of nodes.entries()) {
|
|
46965
|
+
const nodeId = readStringValue(node?.id, node?.nodeId) || `node_${nodeIndex}`;
|
|
46966
|
+
const workspace = readStringValue(node?.workspace);
|
|
46967
|
+
const daemonId = readStringValue(node?.daemonId);
|
|
46968
|
+
const isSelfNode = Boolean(
|
|
46969
|
+
nodeId && selectedCoordinatorNodeId && nodeId === selectedCoordinatorNodeId
|
|
46970
|
+
) || Boolean(
|
|
46971
|
+
daemonId && (daemonId === args.localMachineId || daemonId === args.statusInstanceId)
|
|
46972
|
+
) || Boolean(args.meshSource !== "local_config" && nodeIndex === 0);
|
|
46973
|
+
if (!workspace) {
|
|
46974
|
+
if (!isSelfNode && daemonId) unavailableNodeIds.push(nodeId);
|
|
46975
|
+
continue;
|
|
46976
|
+
}
|
|
46977
|
+
if (isSelfNode && fs10.existsSync(workspace)) {
|
|
46978
|
+
try {
|
|
46979
|
+
const localGit = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
46980
|
+
if (localGit?.isGitRepo) {
|
|
46981
|
+
recordInlineMeshDirectGitTruth(node, localGit, "selected_coordinator_local_git");
|
|
46982
|
+
localConfirmedCount += 1;
|
|
46983
|
+
continue;
|
|
46984
|
+
}
|
|
46985
|
+
} catch {
|
|
46986
|
+
}
|
|
46987
|
+
}
|
|
46988
|
+
if (!daemonId || !args.dispatchMeshCommand) {
|
|
46989
|
+
if (!isSelfNode) unavailableNodeIds.push(nodeId);
|
|
46990
|
+
continue;
|
|
46991
|
+
}
|
|
46992
|
+
peerAttemptedCount += 1;
|
|
46993
|
+
try {
|
|
46994
|
+
const remoteGit = await probeRemoteMeshGitStatus({
|
|
46995
|
+
dispatchMeshCommand: args.dispatchMeshCommand,
|
|
46996
|
+
daemonId,
|
|
46997
|
+
workspace,
|
|
46998
|
+
timeoutMs: 8e3
|
|
46999
|
+
});
|
|
47000
|
+
if (remoteGit) {
|
|
47001
|
+
recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
|
|
47002
|
+
peerConfirmedCount += 1;
|
|
47003
|
+
continue;
|
|
47004
|
+
}
|
|
47005
|
+
} catch {
|
|
47006
|
+
}
|
|
47007
|
+
unavailableNodeIds.push(nodeId);
|
|
47008
|
+
}
|
|
47009
|
+
return {
|
|
47010
|
+
directEvidenceCount: localConfirmedCount + peerConfirmedCount,
|
|
47011
|
+
localConfirmedCount,
|
|
47012
|
+
peerAttemptedCount,
|
|
47013
|
+
peerConfirmedCount,
|
|
47014
|
+
unavailableNodeIds
|
|
47015
|
+
};
|
|
47016
|
+
}
|
|
47017
|
+
function summarizeMeshSessionRecord(record2) {
|
|
47018
|
+
return {
|
|
47019
|
+
sessionId: readStringValue(record2?.sessionId) || "unknown",
|
|
47020
|
+
providerType: readStringValue(record2?.providerType),
|
|
47021
|
+
state: readLiveMeshSessionState(record2),
|
|
47022
|
+
lifecycle: readStringValue(record2?.lifecycle),
|
|
47023
|
+
surfaceKind: getSessionHostSurfaceKind(record2),
|
|
47024
|
+
recoveryState: readStringValue(record2?.meta?.runtimeRecoveryState) ?? null,
|
|
47025
|
+
workspace: readStringValue(record2?.workspace) ?? null,
|
|
47026
|
+
title: readStringValue(record2?.displayName, record2?.workspaceLabel) ?? null,
|
|
47027
|
+
lastActivityAt: toIsoTimestamp(record2?.updatedAt ?? record2?.lastActivityAt ?? record2?.last_activity_at),
|
|
47028
|
+
isCached: false
|
|
47029
|
+
};
|
|
47030
|
+
}
|
|
47031
|
+
function liveSessionRecordMatchesMeshNode(record2, meshId, nodeId) {
|
|
47032
|
+
const recordNodeId = readStringValue(record2?.meta?.meshNodeId);
|
|
47033
|
+
if (!recordNodeId || recordNodeId !== nodeId) return false;
|
|
47034
|
+
const recordMeshId = readStringValue(record2?.meta?.meshNodeFor);
|
|
47035
|
+
return !recordMeshId || recordMeshId === meshId;
|
|
47036
|
+
}
|
|
47037
|
+
function liveSessionRecordMatchesMeshWorkspace(record2, meshId, workspace) {
|
|
47038
|
+
const recordWorkspace = readStringValue(record2?.workspace);
|
|
47039
|
+
if (!recordWorkspace || !workspace || recordWorkspace !== workspace) return false;
|
|
47040
|
+
const recordMeshId = readStringValue(record2?.meta?.meshNodeFor);
|
|
47041
|
+
if (recordMeshId) return recordMeshId === meshId;
|
|
47042
|
+
return record2?.meta?.launchedByCoordinator === true || !!readStringValue(record2?.meta?.meshNodeId);
|
|
47043
|
+
}
|
|
47044
|
+
function readLiveMeshNodeWorkspace(args) {
|
|
47045
|
+
const directNodeWorkspace = args.liveSessionRecords.find((record2) => liveSessionRecordMatchesMeshNode(record2, args.meshId, args.nodeId) && readStringValue(record2?.workspace));
|
|
47046
|
+
if (directNodeWorkspace) {
|
|
47047
|
+
return readStringValue(directNodeWorkspace.workspace) || "";
|
|
47048
|
+
}
|
|
47049
|
+
if (args.allowCoordinatorSession) {
|
|
47050
|
+
const coordinatorWorkspace = args.liveSessionRecords.find((record2) => readStringValue(record2?.meta?.meshCoordinatorFor) === args.meshId && readStringValue(record2?.workspace));
|
|
47051
|
+
if (coordinatorWorkspace) {
|
|
47052
|
+
return readStringValue(coordinatorWorkspace.workspace) || "";
|
|
47053
|
+
}
|
|
47054
|
+
}
|
|
47055
|
+
return "";
|
|
47056
|
+
}
|
|
47057
|
+
function collectLiveMeshSessionRecords(args) {
|
|
47058
|
+
const matches = args.liveSessionRecords.filter((record2) => {
|
|
47059
|
+
const nodeWorkspace = readStringValue(args.node?.workspace);
|
|
47060
|
+
if (liveSessionRecordMatchesMeshNode(record2, args.meshId, args.nodeId)) return true;
|
|
47061
|
+
return !!nodeWorkspace && liveSessionRecordMatchesMeshWorkspace(record2, args.meshId, nodeWorkspace);
|
|
47062
|
+
});
|
|
47063
|
+
if (args.allowCoordinatorSession) {
|
|
47064
|
+
for (const record2 of args.liveSessionRecords) {
|
|
47065
|
+
if (readStringValue(record2?.meta?.meshCoordinatorFor) !== args.meshId) continue;
|
|
47066
|
+
const sessionId = readStringValue(record2?.sessionId);
|
|
47067
|
+
if (sessionId && matches.some((entry) => readStringValue(entry?.sessionId) === sessionId)) continue;
|
|
47068
|
+
matches.push(record2);
|
|
47069
|
+
}
|
|
47070
|
+
}
|
|
47071
|
+
return matches;
|
|
47072
|
+
}
|
|
47073
|
+
function applyCachedInlineMeshNodeStatus(status, node, options) {
|
|
47074
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
47075
|
+
const liveGit = buildInlineMeshTransitGitStatus(node);
|
|
47076
|
+
const git = options?.skipGit ? void 0 : liveGit ?? buildCachedInlineMeshGitStatus(node);
|
|
47077
|
+
const error48 = options?.skipError ? void 0 : liveGit ? void 0 : readStringValue(cachedStatus.error, node?.error);
|
|
47078
|
+
const health = options?.skipHealth ? void 0 : liveGit ? void 0 : readStringValue(cachedStatus.health, node?.health);
|
|
46477
47079
|
const machineStatus = readStringValue(cachedStatus.machineStatus, node?.machineStatus);
|
|
46478
|
-
|
|
46479
|
-
|
|
47080
|
+
const lastSeenAt = toIsoTimestamp(cachedStatus.lastSeenAt ?? cachedStatus.last_seen_at ?? node?.lastSeenAt ?? node?.last_seen_at);
|
|
47081
|
+
const updatedAt = toIsoTimestamp(cachedStatus.updatedAt ?? cachedStatus.updated_at ?? node?.updatedAt ?? node?.updated_at);
|
|
47082
|
+
const activeSessions = readCachedInlineMeshActiveSessions(node);
|
|
47083
|
+
const activeSessionDetails = readCachedInlineMeshActiveSessionDetails(node);
|
|
47084
|
+
if (!git && !error48 && !health && !machineStatus && !lastSeenAt && !updatedAt && activeSessions.length === 0) return false;
|
|
46480
47085
|
if (git) status.git = git;
|
|
46481
47086
|
if (error48) status.error = error48;
|
|
47087
|
+
if (machineStatus) status.machineStatus = machineStatus;
|
|
47088
|
+
if (lastSeenAt) status.lastSeenAt = lastSeenAt;
|
|
47089
|
+
if (updatedAt) status.updatedAt = updatedAt;
|
|
47090
|
+
if (activeSessions.length > 0) status.activeSessions = activeSessions;
|
|
47091
|
+
if (activeSessionDetails.length > 0) status.activeSessionDetails = activeSessionDetails;
|
|
46482
47092
|
if (health) {
|
|
46483
47093
|
status.health = health;
|
|
46484
47094
|
return true;
|
|
46485
47095
|
}
|
|
46486
47096
|
if (git) {
|
|
46487
|
-
|
|
46488
|
-
status.health = git.isGitRepo === false ? "degraded" : dirty ? "dirty" : "online";
|
|
47097
|
+
status.health = deriveMeshNodeHealthFromGit(git);
|
|
46489
47098
|
return true;
|
|
46490
47099
|
}
|
|
46491
|
-
return
|
|
47100
|
+
return activeSessions.length > 0 || !!machineStatus || !!lastSeenAt || !!updatedAt;
|
|
46492
47101
|
}
|
|
46493
47102
|
async function resolveProviderTypeFromPriority(args) {
|
|
46494
47103
|
if (!args.providerPriority.length) {
|
|
@@ -46519,9 +47128,85 @@ function truncateValidationOutput(value) {
|
|
|
46519
47128
|
return `${text.slice(0, REFINE_VALIDATION_SUMMARY_CHARS)}
|
|
46520
47129
|
[truncated ${text.length - REFINE_VALIDATION_SUMMARY_CHARS} chars]`;
|
|
46521
47130
|
}
|
|
47131
|
+
function recordMeshRefineStage(stages, stage, status, startedAt, details) {
|
|
47132
|
+
stages.push({
|
|
47133
|
+
stage,
|
|
47134
|
+
status,
|
|
47135
|
+
durationMs: Date.now() - startedAt,
|
|
47136
|
+
...details || {}
|
|
47137
|
+
});
|
|
47138
|
+
}
|
|
47139
|
+
async function computeGitPatchId(cwd, fromRef, toRef) {
|
|
47140
|
+
const { execFileSync: execFileSync7 } = await import("child_process");
|
|
47141
|
+
const diff = execFileSync7("git", ["diff", "--patch", "--full-index", fromRef, toRef], {
|
|
47142
|
+
cwd,
|
|
47143
|
+
encoding: "utf8",
|
|
47144
|
+
maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
|
|
47145
|
+
});
|
|
47146
|
+
if (!diff.trim()) return "";
|
|
47147
|
+
const patchId = execFileSync7("git", ["patch-id", "--stable"], {
|
|
47148
|
+
cwd,
|
|
47149
|
+
input: diff,
|
|
47150
|
+
encoding: "utf8",
|
|
47151
|
+
maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
|
|
47152
|
+
}).trim();
|
|
47153
|
+
return patchId.split(/\s+/)[0] || "";
|
|
47154
|
+
}
|
|
47155
|
+
async function runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead) {
|
|
47156
|
+
const startedAt = Date.now();
|
|
47157
|
+
try {
|
|
47158
|
+
const { execFileSync: execFileSync7 } = await import("child_process");
|
|
47159
|
+
const git = (args) => execFileSync7("git", args, {
|
|
47160
|
+
cwd: repoRoot,
|
|
47161
|
+
encoding: "utf8",
|
|
47162
|
+
maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
|
|
47163
|
+
});
|
|
47164
|
+
const mergeBase = git(["merge-base", baseHead, branchHead]).trim();
|
|
47165
|
+
const mergeTreeStdout = git(["merge-tree", "--write-tree", baseHead, branchHead]);
|
|
47166
|
+
const mergedTree = mergeTreeStdout.trim().split(/\s+/)[0] || "";
|
|
47167
|
+
if (!mergeBase || !mergedTree) {
|
|
47168
|
+
return {
|
|
47169
|
+
status: "failed",
|
|
47170
|
+
equivalent: false,
|
|
47171
|
+
baseHead,
|
|
47172
|
+
branchHead,
|
|
47173
|
+
mergeBase: mergeBase || void 0,
|
|
47174
|
+
mergedTree: mergedTree || void 0,
|
|
47175
|
+
durationMs: Date.now() - startedAt,
|
|
47176
|
+
error: "patch equivalence preflight could not resolve merge-base or synthetic merge tree",
|
|
47177
|
+
stdout: truncateValidationOutput(mergeTreeStdout)
|
|
47178
|
+
};
|
|
47179
|
+
}
|
|
47180
|
+
const expectedPatchId = await computeGitPatchId(repoRoot, mergeBase, branchHead);
|
|
47181
|
+
const actualPatchId = await computeGitPatchId(repoRoot, baseHead, mergedTree);
|
|
47182
|
+
const equivalent = expectedPatchId === actualPatchId;
|
|
47183
|
+
return {
|
|
47184
|
+
status: equivalent ? "passed" : "failed",
|
|
47185
|
+
equivalent,
|
|
47186
|
+
baseHead,
|
|
47187
|
+
branchHead,
|
|
47188
|
+
mergeBase,
|
|
47189
|
+
mergedTree,
|
|
47190
|
+
expectedPatchId,
|
|
47191
|
+
actualPatchId,
|
|
47192
|
+
durationMs: Date.now() - startedAt
|
|
47193
|
+
};
|
|
47194
|
+
} catch (e) {
|
|
47195
|
+
return {
|
|
47196
|
+
status: "failed",
|
|
47197
|
+
equivalent: false,
|
|
47198
|
+
baseHead,
|
|
47199
|
+
branchHead,
|
|
47200
|
+
durationMs: Date.now() - startedAt,
|
|
47201
|
+
error: e?.message || String(e),
|
|
47202
|
+
stdout: truncateValidationOutput(e?.stdout),
|
|
47203
|
+
stderr: truncateValidationOutput(e?.stderr)
|
|
47204
|
+
};
|
|
47205
|
+
}
|
|
47206
|
+
}
|
|
46522
47207
|
function readPackageScripts(workspace) {
|
|
46523
47208
|
try {
|
|
46524
|
-
const packageJsonPath = (0,
|
|
47209
|
+
const packageJsonPath = (0, import_path7.join)(workspace, "package.json");
|
|
46525
47210
|
const parsed = JSON.parse(fs10.readFileSync(packageJsonPath, "utf-8"));
|
|
46526
47211
|
return parsed?.scripts && typeof parsed.scripts === "object" && !Array.isArray(parsed.scripts) ? parsed.scripts : {};
|
|
46527
47212
|
} catch {
|
|
@@ -46729,13 +47414,13 @@ function serializeMeshCoordinatorMcpConfig(config2, format) {
|
|
|
46729
47414
|
}
|
|
46730
47415
|
function resolveHermesUserHome() {
|
|
46731
47416
|
const explicitHome = process.env.HERMES_HOME?.trim();
|
|
46732
|
-
return explicitHome || (0,
|
|
47417
|
+
return explicitHome || (0, import_path7.join)((0, import_os4.homedir)(), ".hermes");
|
|
46733
47418
|
}
|
|
46734
47419
|
function loadHermesCoordinatorBaseConfig(targetConfigPath) {
|
|
46735
47420
|
const sourceHome = resolveHermesUserHome();
|
|
46736
|
-
const sourceConfigPath = (0,
|
|
47421
|
+
const sourceConfigPath = (0, import_path7.join)(sourceHome, "config.yaml");
|
|
46737
47422
|
if (!fs10.existsSync(sourceConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
46738
|
-
if ((0,
|
|
47423
|
+
if ((0, import_path7.resolve)(sourceConfigPath) === (0, import_path7.resolve)(targetConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
46739
47424
|
const parsed = parseMeshCoordinatorMcpConfig(fs10.readFileSync(sourceConfigPath, "utf-8"), "hermes_config_yaml");
|
|
46740
47425
|
const { mcp_servers: _mcpServers, ...baseConfig } = parsed;
|
|
46741
47426
|
return { config: baseConfig, sourceHome, sourceConfigPath };
|
|
@@ -46769,10 +47454,10 @@ function stripHermesCoordinatorTempModelProviderOverrides(config2) {
|
|
|
46769
47454
|
return sanitized;
|
|
46770
47455
|
}
|
|
46771
47456
|
function copyHermesCoordinatorCredentialFiles(sourceHome, targetHome) {
|
|
46772
|
-
if ((0,
|
|
47457
|
+
if ((0, import_path7.resolve)(sourceHome) === (0, import_path7.resolve)(targetHome)) return;
|
|
46773
47458
|
for (const fileName of [".env", "auth.json"]) {
|
|
46774
|
-
const sourcePath = (0,
|
|
46775
|
-
const targetPath = (0,
|
|
47459
|
+
const sourcePath = (0, import_path7.join)(sourceHome, fileName);
|
|
47460
|
+
const targetPath = (0, import_path7.join)(targetHome, fileName);
|
|
46776
47461
|
if (!fs10.existsSync(sourcePath)) continue;
|
|
46777
47462
|
try {
|
|
46778
47463
|
fs10.copyFileSync(sourcePath, targetPath);
|
|
@@ -46862,7 +47547,7 @@ function summarizeSessionHostPruneResult(result) {
|
|
|
46862
47547
|
keptCount: Array.isArray(value.keptSessionIds) ? value.keptSessionIds.length : void 0
|
|
46863
47548
|
};
|
|
46864
47549
|
}
|
|
46865
|
-
var import_os4,
|
|
47550
|
+
var import_os4, import_path7, fs10, CHANNEL_NPM_TAG, CHANNEL_SERVER_URL, REFINE_VALIDATION_CATEGORIES, REFINE_VALIDATION_TIMEOUT_MS, REFINE_VALIDATION_OUTPUT_LIMIT_BYTES, REFINE_VALIDATION_SUMMARY_CHARS, REFINE_VALIDATION_MAX_COMMANDS, REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES, CHAT_COMMANDS, READ_DEBUG_ENABLED2, DaemonCommandRouter;
|
|
46866
47551
|
var init_router = __esm({
|
|
46867
47552
|
"../../oss/packages/daemon-core/src/commands/router.ts"() {
|
|
46868
47553
|
"use strict";
|
|
@@ -46878,6 +47563,7 @@ var init_router = __esm({
|
|
|
46878
47563
|
init_chat_history();
|
|
46879
47564
|
init_ide_detector();
|
|
46880
47565
|
init_cli_detector();
|
|
47566
|
+
init_git_status();
|
|
46881
47567
|
init_logger();
|
|
46882
47568
|
init_command_log();
|
|
46883
47569
|
init_js_yaml();
|
|
@@ -46891,7 +47577,7 @@ var init_router = __esm({
|
|
|
46891
47577
|
init_snapshot();
|
|
46892
47578
|
init_upgrade_helper();
|
|
46893
47579
|
import_os4 = require("os");
|
|
46894
|
-
|
|
47580
|
+
import_path7 = require("path");
|
|
46895
47581
|
fs10 = __toESM(require("fs"));
|
|
46896
47582
|
CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
|
|
46897
47583
|
CHANNEL_SERVER_URL = {
|
|
@@ -46903,6 +47589,7 @@ var init_router = __esm({
|
|
|
46903
47589
|
REFINE_VALIDATION_OUTPUT_LIMIT_BYTES = 128 * 1024;
|
|
46904
47590
|
REFINE_VALIDATION_SUMMARY_CHARS = 2e3;
|
|
46905
47591
|
REFINE_VALIDATION_MAX_COMMANDS = 4;
|
|
47592
|
+
REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES = 4 * 1024 * 1024;
|
|
46906
47593
|
CHAT_COMMANDS = [
|
|
46907
47594
|
"send_chat",
|
|
46908
47595
|
"new_chat",
|
|
@@ -46917,30 +47604,97 @@ var init_router = __esm({
|
|
|
46917
47604
|
* Allows the MCP server to query mesh data via get_mesh even when
|
|
46918
47605
|
* the mesh doesn't exist in the local meshes.json file. */
|
|
46919
47606
|
inlineMeshCache = /* @__PURE__ */ new Map();
|
|
47607
|
+
/** Coordinator-owned whole-mesh aggregate status snapshots. Browser callers read this by default. */
|
|
47608
|
+
aggregateMeshStatusCache = /* @__PURE__ */ new Map();
|
|
46920
47609
|
constructor(deps) {
|
|
46921
47610
|
this.deps = deps;
|
|
46922
47611
|
}
|
|
47612
|
+
cloneJsonValue(value) {
|
|
47613
|
+
if (typeof structuredClone === "function") return structuredClone(value);
|
|
47614
|
+
return JSON.parse(JSON.stringify(value));
|
|
47615
|
+
}
|
|
47616
|
+
getCachedAggregateMeshStatus(meshId) {
|
|
47617
|
+
const cached2 = this.aggregateMeshStatusCache.get(meshId);
|
|
47618
|
+
if (!cached2?.snapshot || cached2.snapshot.success !== true || !Array.isArray(cached2.snapshot.nodes)) return null;
|
|
47619
|
+
const snapshot = this.cloneJsonValue(cached2.snapshot);
|
|
47620
|
+
const ageMs = Math.max(0, Date.now() - cached2.builtAt);
|
|
47621
|
+
const sourceOfTruth = snapshot.sourceOfTruth && typeof snapshot.sourceOfTruth === "object" ? snapshot.sourceOfTruth : {};
|
|
47622
|
+
snapshot.sourceOfTruth = {
|
|
47623
|
+
...sourceOfTruth,
|
|
47624
|
+
aggregateSnapshot: {
|
|
47625
|
+
...sourceOfTruth.aggregateSnapshot && typeof sourceOfTruth.aggregateSnapshot === "object" ? sourceOfTruth.aggregateSnapshot : {},
|
|
47626
|
+
owner: "coordinator_daemon_memory",
|
|
47627
|
+
cached: true,
|
|
47628
|
+
source: "memory",
|
|
47629
|
+
refreshReason: "memory_cache_hit",
|
|
47630
|
+
ageMs,
|
|
47631
|
+
cachedAt: new Date(cached2.builtAt).toISOString(),
|
|
47632
|
+
returnedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
47633
|
+
}
|
|
47634
|
+
};
|
|
47635
|
+
return snapshot;
|
|
47636
|
+
}
|
|
47637
|
+
rememberAggregateMeshStatus(meshId, snapshot, refreshReason) {
|
|
47638
|
+
if (!snapshot || typeof snapshot !== "object" || snapshot.success !== true || !Array.isArray(snapshot.nodes)) return snapshot;
|
|
47639
|
+
const builtAt = Date.now();
|
|
47640
|
+
const next = this.cloneJsonValue(snapshot);
|
|
47641
|
+
const sourceOfTruth = next.sourceOfTruth && typeof next.sourceOfTruth === "object" ? next.sourceOfTruth : {};
|
|
47642
|
+
next.sourceOfTruth = {
|
|
47643
|
+
...sourceOfTruth,
|
|
47644
|
+
aggregateSnapshot: {
|
|
47645
|
+
owner: "coordinator_daemon_memory",
|
|
47646
|
+
cached: false,
|
|
47647
|
+
source: "live_refresh",
|
|
47648
|
+
refreshReason,
|
|
47649
|
+
ageMs: 0,
|
|
47650
|
+
cachedAt: new Date(builtAt).toISOString(),
|
|
47651
|
+
returnedAt: new Date(builtAt).toISOString()
|
|
47652
|
+
}
|
|
47653
|
+
};
|
|
47654
|
+
this.aggregateMeshStatusCache.set(meshId, { builtAt, snapshot: this.cloneJsonValue(next) });
|
|
47655
|
+
return next;
|
|
47656
|
+
}
|
|
46923
47657
|
getCachedInlineMesh(meshId, inlineMesh) {
|
|
46924
47658
|
if (inlineMesh && typeof inlineMesh === "object") {
|
|
46925
|
-
this.
|
|
46926
|
-
return inlineMesh;
|
|
47659
|
+
return this.warmInlineMeshCache(meshId, inlineMesh);
|
|
46927
47660
|
}
|
|
46928
47661
|
return this.inlineMeshCache.get(meshId);
|
|
46929
47662
|
}
|
|
47663
|
+
warmInlineMeshCache(meshId, inlineMesh) {
|
|
47664
|
+
if (!inlineMesh || typeof inlineMesh !== "object") return void 0;
|
|
47665
|
+
const sanitizedInlineMesh = sanitizeInlineMesh(inlineMesh);
|
|
47666
|
+
const cached2 = this.inlineMeshCache.get(meshId);
|
|
47667
|
+
if (cached2) {
|
|
47668
|
+
const merged = reconcileInlineMeshCache(cached2, sanitizedInlineMesh);
|
|
47669
|
+
this.inlineMeshCache.set(meshId, merged);
|
|
47670
|
+
return merged;
|
|
47671
|
+
}
|
|
47672
|
+
this.inlineMeshCache.set(meshId, sanitizedInlineMesh);
|
|
47673
|
+
return sanitizedInlineMesh;
|
|
47674
|
+
}
|
|
46930
47675
|
async getMeshForCommand(meshId, inlineMesh, options) {
|
|
46931
47676
|
const preferInline = options?.preferInline === true;
|
|
46932
47677
|
if (preferInline) {
|
|
46933
|
-
const cached3 = this.getCachedInlineMesh(meshId
|
|
46934
|
-
if (cached3) return { mesh: cached3, inline: true };
|
|
47678
|
+
const cached3 = this.getCachedInlineMesh(meshId);
|
|
47679
|
+
if (cached3) return { mesh: cached3, inline: true, source: "inline_cache" };
|
|
47680
|
+
if (inlineMeshCarriesTransientNodeTruth(inlineMesh)) {
|
|
47681
|
+
this.warmInlineMeshCache(meshId, inlineMesh);
|
|
47682
|
+
return { mesh: inlineMesh, inline: true, source: "inline_bootstrap" };
|
|
47683
|
+
}
|
|
46935
47684
|
}
|
|
46936
47685
|
try {
|
|
46937
47686
|
const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
46938
47687
|
const mesh = getMesh3(meshId);
|
|
46939
|
-
if (mesh) return { mesh, inline: false };
|
|
47688
|
+
if (mesh) return { mesh, inline: false, source: "local_config" };
|
|
46940
47689
|
} catch {
|
|
46941
47690
|
}
|
|
46942
|
-
const cached2 = this.getCachedInlineMesh(meshId
|
|
46943
|
-
|
|
47691
|
+
const cached2 = this.getCachedInlineMesh(meshId);
|
|
47692
|
+
if (cached2) return { mesh: cached2, inline: true, source: "inline_cache" };
|
|
47693
|
+
const warmedInline = this.warmInlineMeshCache(meshId, inlineMesh);
|
|
47694
|
+
return warmedInline ? { mesh: warmedInline, inline: true, source: "inline_bootstrap" } : null;
|
|
47695
|
+
}
|
|
47696
|
+
invalidateAggregateMeshStatus(meshId) {
|
|
47697
|
+
this.aggregateMeshStatusCache.delete(meshId);
|
|
46944
47698
|
}
|
|
46945
47699
|
updateInlineMeshNode(meshId, mesh, node) {
|
|
46946
47700
|
if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
|
|
@@ -46949,6 +47703,7 @@ var init_router = __esm({
|
|
|
46949
47703
|
else mesh.nodes.push(node);
|
|
46950
47704
|
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
46951
47705
|
this.inlineMeshCache.set(meshId, mesh);
|
|
47706
|
+
this.invalidateAggregateMeshStatus(meshId);
|
|
46952
47707
|
}
|
|
46953
47708
|
removeInlineMeshNode(meshId, mesh, nodeId) {
|
|
46954
47709
|
if (!mesh || !Array.isArray(mesh.nodes)) return false;
|
|
@@ -46957,6 +47712,7 @@ var init_router = __esm({
|
|
|
46957
47712
|
mesh.nodes.splice(idx, 1);
|
|
46958
47713
|
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
46959
47714
|
this.inlineMeshCache.set(meshId, mesh);
|
|
47715
|
+
this.invalidateAggregateMeshStatus(meshId);
|
|
46960
47716
|
return true;
|
|
46961
47717
|
}
|
|
46962
47718
|
normalizeMeshSessionCleanupMode(value) {
|
|
@@ -47005,7 +47761,7 @@ var init_router = __esm({
|
|
|
47005
47761
|
}
|
|
47006
47762
|
const { resolveWorktreePath: resolveWorktreePath2, listWorktrees: listWorktrees2, removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
47007
47763
|
const normalizePath3 = (value) => {
|
|
47008
|
-
const resolved = (0,
|
|
47764
|
+
const resolved = (0, import_path7.resolve)(value);
|
|
47009
47765
|
try {
|
|
47010
47766
|
return fs10.realpathSync(resolved);
|
|
47011
47767
|
} catch {
|
|
@@ -47169,6 +47925,7 @@ var init_router = __esm({
|
|
|
47169
47925
|
const deletedSessionIds = [];
|
|
47170
47926
|
const skippedSessionIds = [];
|
|
47171
47927
|
const skippedLiveSessionIds = [];
|
|
47928
|
+
const skippedCoordinatorSessionIds = [];
|
|
47172
47929
|
const deleteUnsupportedSessionIds = [];
|
|
47173
47930
|
const recordsRemainSessionIds = [];
|
|
47174
47931
|
const errors = [];
|
|
@@ -47201,6 +47958,12 @@ var init_router = __esm({
|
|
|
47201
47958
|
const completed = this.isCompletedHostedSession(record2);
|
|
47202
47959
|
const surfaceKind = getSessionHostSurfaceKind(record2);
|
|
47203
47960
|
const liveRuntime = surfaceKind === "live_runtime";
|
|
47961
|
+
const coordinatorSession = readStringValue(record2?.meta?.meshCoordinatorFor) === args.meshId;
|
|
47962
|
+
if (!hasExplicitSessionIds && coordinatorSession) {
|
|
47963
|
+
skippedSessionIds.push(sessionId);
|
|
47964
|
+
skippedCoordinatorSessionIds.push(sessionId);
|
|
47965
|
+
continue;
|
|
47966
|
+
}
|
|
47204
47967
|
if (!hasExplicitSessionIds && liveRuntime) {
|
|
47205
47968
|
skippedSessionIds.push(sessionId);
|
|
47206
47969
|
skippedLiveSessionIds.push(sessionId);
|
|
@@ -47266,6 +48029,7 @@ var init_router = __esm({
|
|
|
47266
48029
|
deletedSessionIds,
|
|
47267
48030
|
skippedSessionIds,
|
|
47268
48031
|
skippedLiveSessionIds,
|
|
48032
|
+
skippedCoordinatorSessionIds,
|
|
47269
48033
|
...deleteUnsupported ? {
|
|
47270
48034
|
deleteUnsupported: true,
|
|
47271
48035
|
effectiveCleanup: args.mode === "stop_and_delete" ? "stopped_only_records_remain" : "delete_unsupported_records_remain",
|
|
@@ -47398,7 +48162,8 @@ var init_router = __esm({
|
|
|
47398
48162
|
return handleMeshForwardEvent({ instanceManager: this.deps.instanceManager }, args);
|
|
47399
48163
|
}
|
|
47400
48164
|
case "get_pending_mesh_events": {
|
|
47401
|
-
const
|
|
48165
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
48166
|
+
const events = drainPendingMeshCoordinatorEvents(meshId || void 0);
|
|
47402
48167
|
return { success: true, events };
|
|
47403
48168
|
}
|
|
47404
48169
|
case "launch_cli":
|
|
@@ -47927,15 +48692,39 @@ var init_router = __esm({
|
|
|
47927
48692
|
case "get_mesh": {
|
|
47928
48693
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
47929
48694
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
47930
|
-
|
|
47931
|
-
|
|
47932
|
-
|
|
47933
|
-
|
|
47934
|
-
|
|
48695
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
48696
|
+
if (!meshRecord?.mesh) return { success: false, error: "Mesh not found" };
|
|
48697
|
+
const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
|
|
48698
|
+
const directTruth = await hydrateInlineMeshDirectTruth({
|
|
48699
|
+
mesh: meshRecord.mesh,
|
|
48700
|
+
meshSource: meshRecord.source,
|
|
48701
|
+
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
48702
|
+
statusInstanceId: this.deps.statusInstanceId,
|
|
48703
|
+
localMachineId: loadConfig().machineId || ""
|
|
48704
|
+
});
|
|
48705
|
+
const directTruthSatisfied = meshRecord.source !== "inline_bootstrap" || directTruth.directEvidenceCount > 0;
|
|
48706
|
+
const sourceOfTruth = {
|
|
48707
|
+
membership: meshRecord.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
|
|
48708
|
+
coordinatorOwnsLiveTruth: directTruthSatisfied,
|
|
48709
|
+
directPeerTruth: {
|
|
48710
|
+
required: requireDirectPeerTruth,
|
|
48711
|
+
satisfied: directTruthSatisfied,
|
|
48712
|
+
directEvidenceCount: directTruth.directEvidenceCount,
|
|
48713
|
+
localConfirmedCount: directTruth.localConfirmedCount,
|
|
48714
|
+
peerAttemptedCount: directTruth.peerAttemptedCount,
|
|
48715
|
+
peerConfirmedCount: directTruth.peerConfirmedCount,
|
|
48716
|
+
unavailableNodeIds: directTruth.unavailableNodeIds
|
|
48717
|
+
}
|
|
48718
|
+
};
|
|
48719
|
+
if (requireDirectPeerTruth && !directTruthSatisfied) {
|
|
48720
|
+
return {
|
|
48721
|
+
success: false,
|
|
48722
|
+
code: "mesh_direct_peer_truth_unavailable",
|
|
48723
|
+
error: "Selected coordinator could not confirm direct mesh truth yet. Bootstrap inventory stays unavailable until direct get_mesh probes succeed.",
|
|
48724
|
+
sourceOfTruth
|
|
48725
|
+
};
|
|
47935
48726
|
}
|
|
47936
|
-
|
|
47937
|
-
if (cached2) return { success: true, mesh: cached2 };
|
|
47938
|
-
return { success: false, error: "Mesh not found" };
|
|
48727
|
+
return { success: true, mesh: meshRecord.mesh, sourceOfTruth };
|
|
47939
48728
|
}
|
|
47940
48729
|
case "create_mesh": {
|
|
47941
48730
|
const name = typeof args?.name === "string" ? args.name.trim() : "";
|
|
@@ -47965,6 +48754,7 @@ var init_router = __esm({
|
|
|
47965
48754
|
const mesh = updateMesh2(meshId, patch);
|
|
47966
48755
|
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
47967
48756
|
this.inlineMeshCache.set(meshId, mesh);
|
|
48757
|
+
this.invalidateAggregateMeshStatus(meshId);
|
|
47968
48758
|
return { success: true, mesh };
|
|
47969
48759
|
} catch (e) {
|
|
47970
48760
|
return { success: false, error: e.message };
|
|
@@ -48154,26 +48944,41 @@ var init_router = __esm({
|
|
|
48154
48944
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
48155
48945
|
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
48156
48946
|
if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
|
|
48947
|
+
const refineStages = [];
|
|
48157
48948
|
try {
|
|
48158
48949
|
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
48159
48950
|
const mesh = meshRecord?.mesh;
|
|
48160
48951
|
const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
|
|
48161
|
-
if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh
|
|
48952
|
+
if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh`, refineStages };
|
|
48162
48953
|
if (!node.isLocalWorktree || !node.workspace) {
|
|
48163
|
-
return { success: false, error: `Refinery requires a local worktree node
|
|
48954
|
+
return { success: false, error: `Refinery requires a local worktree node`, refineStages };
|
|
48164
48955
|
}
|
|
48165
48956
|
const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
|
|
48166
48957
|
const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
|
|
48167
|
-
if (!repoRoot) return { success: false, error: "Source node repoRoot not found" };
|
|
48958
|
+
if (!repoRoot) return { success: false, error: "Source node repoRoot not found", refineStages };
|
|
48168
48959
|
const { execFile: execFile3 } = await import("child_process");
|
|
48169
48960
|
const { promisify: promisify3 } = await import("util");
|
|
48170
48961
|
const execFileAsync3 = promisify3(execFile3);
|
|
48962
|
+
const resolveStarted = Date.now();
|
|
48171
48963
|
const { stdout: branchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: node.workspace, encoding: "utf8" });
|
|
48172
48964
|
const branch = branchStdout.trim();
|
|
48173
|
-
if (!branch) return { success: false, error: "Could not determine branch of the worktree node" };
|
|
48965
|
+
if (!branch) return { success: false, error: "Could not determine branch of the worktree node", refineStages };
|
|
48174
48966
|
const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
|
|
48175
48967
|
const baseBranch = baseBranchStdout.trim();
|
|
48968
|
+
const { stdout: baseHeadStdout } = await execFileAsync3("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf8" });
|
|
48969
|
+
const { stdout: branchHeadStdout } = await execFileAsync3("git", ["rev-parse", branch], { cwd: node.workspace, encoding: "utf8" });
|
|
48970
|
+
const baseHead = baseHeadStdout.trim();
|
|
48971
|
+
const branchHead = branchHeadStdout.trim();
|
|
48972
|
+
recordMeshRefineStage(refineStages, "resolve_refs", "passed", resolveStarted, { branch, baseBranch, baseHead, branchHead });
|
|
48973
|
+
const validationStarted = Date.now();
|
|
48176
48974
|
const validationSummary = await runMeshRefineValidationGate(mesh, node.workspace);
|
|
48975
|
+
recordMeshRefineStage(
|
|
48976
|
+
refineStages,
|
|
48977
|
+
"validation",
|
|
48978
|
+
validationSummary.status === "passed" ? "passed" : validationSummary.status === "failed" ? "failed" : "skipped",
|
|
48979
|
+
validationStarted,
|
|
48980
|
+
{ validationStatus: validationSummary.status, commandsRun: validationSummary.commandsRun.length }
|
|
48981
|
+
);
|
|
48177
48982
|
if (validationSummary.status === "failed") {
|
|
48178
48983
|
return {
|
|
48179
48984
|
success: false,
|
|
@@ -48183,6 +48988,7 @@ var init_router = __esm({
|
|
|
48183
48988
|
branch,
|
|
48184
48989
|
into: baseBranch,
|
|
48185
48990
|
validationSummary,
|
|
48991
|
+
refineStages,
|
|
48186
48992
|
finalBranchConvergenceState: {
|
|
48187
48993
|
branch,
|
|
48188
48994
|
baseBranch,
|
|
@@ -48202,6 +49008,7 @@ var init_router = __esm({
|
|
|
48202
49008
|
branch,
|
|
48203
49009
|
into: baseBranch,
|
|
48204
49010
|
validationSummary,
|
|
49011
|
+
refineStages,
|
|
48205
49012
|
finalBranchConvergenceState: {
|
|
48206
49013
|
branch,
|
|
48207
49014
|
baseBranch,
|
|
@@ -48212,37 +49019,121 @@ var init_router = __esm({
|
|
|
48212
49019
|
}
|
|
48213
49020
|
};
|
|
48214
49021
|
}
|
|
49022
|
+
const patchEquivalenceStarted = Date.now();
|
|
49023
|
+
const patchEquivalence = await runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead);
|
|
49024
|
+
recordMeshRefineStage(refineStages, "patch_equivalence", patchEquivalence.status, patchEquivalenceStarted, {
|
|
49025
|
+
equivalent: patchEquivalence.equivalent,
|
|
49026
|
+
expectedPatchId: patchEquivalence.expectedPatchId,
|
|
49027
|
+
actualPatchId: patchEquivalence.actualPatchId,
|
|
49028
|
+
error: patchEquivalence.error
|
|
49029
|
+
});
|
|
49030
|
+
if (!patchEquivalence.equivalent) {
|
|
49031
|
+
return {
|
|
49032
|
+
success: false,
|
|
49033
|
+
code: "patch_equivalence_failed",
|
|
49034
|
+
convergenceStatus: "blocked_review",
|
|
49035
|
+
error: "Refinery patch-equivalence preflight failed; merge/refine was not attempted.",
|
|
49036
|
+
branch,
|
|
49037
|
+
into: baseBranch,
|
|
49038
|
+
validationSummary,
|
|
49039
|
+
patchEquivalence,
|
|
49040
|
+
refineStages,
|
|
49041
|
+
finalBranchConvergenceState: {
|
|
49042
|
+
branch,
|
|
49043
|
+
baseBranch,
|
|
49044
|
+
merged: false,
|
|
49045
|
+
removed: false,
|
|
49046
|
+
validation: "passed",
|
|
49047
|
+
patchEquivalence: "failed",
|
|
49048
|
+
status: "blocked_review"
|
|
49049
|
+
}
|
|
49050
|
+
};
|
|
49051
|
+
}
|
|
49052
|
+
let mergeResult;
|
|
49053
|
+
const mergeStarted = Date.now();
|
|
48215
49054
|
try {
|
|
48216
|
-
await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
|
|
49055
|
+
const result = await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
|
|
49056
|
+
mergeResult = {
|
|
49057
|
+
stdout: truncateValidationOutput(result.stdout),
|
|
49058
|
+
stderr: truncateValidationOutput(result.stderr),
|
|
49059
|
+
durationMs: Date.now() - mergeStarted
|
|
49060
|
+
};
|
|
49061
|
+
recordMeshRefineStage(refineStages, "merge", "passed", mergeStarted, mergeResult);
|
|
48217
49062
|
} catch (e) {
|
|
49063
|
+
recordMeshRefineStage(refineStages, "merge", "failed", mergeStarted, {
|
|
49064
|
+
error: e?.message || String(e),
|
|
49065
|
+
stdout: truncateValidationOutput(e?.stdout),
|
|
49066
|
+
stderr: truncateValidationOutput(e?.stderr)
|
|
49067
|
+
});
|
|
48218
49068
|
return {
|
|
48219
49069
|
success: false,
|
|
48220
49070
|
error: `Merge failed (conflicts?): ${e.message}`,
|
|
48221
49071
|
validationSummary,
|
|
49072
|
+
patchEquivalence,
|
|
49073
|
+
refineStages,
|
|
48222
49074
|
finalBranchConvergenceState: {
|
|
48223
49075
|
branch,
|
|
48224
49076
|
baseBranch,
|
|
48225
49077
|
merged: false,
|
|
48226
49078
|
removed: false,
|
|
48227
49079
|
validation: "passed",
|
|
49080
|
+
patchEquivalence: "passed",
|
|
48228
49081
|
status: "not_mergeable"
|
|
48229
49082
|
}
|
|
48230
49083
|
};
|
|
48231
49084
|
}
|
|
49085
|
+
const cleanupStarted = Date.now();
|
|
48232
49086
|
const removeResult = await this.execute("remove_mesh_node", {
|
|
48233
49087
|
meshId,
|
|
48234
49088
|
nodeId,
|
|
48235
|
-
sessionCleanupMode: "
|
|
49089
|
+
sessionCleanupMode: "preserve",
|
|
48236
49090
|
inlineMesh: args?.inlineMesh
|
|
48237
49091
|
});
|
|
49092
|
+
recordMeshRefineStage(refineStages, "cleanup", removeResult?.success === false ? "failed" : "passed", cleanupStarted, {
|
|
49093
|
+
removed: removeResult?.removed,
|
|
49094
|
+
code: removeResult?.code,
|
|
49095
|
+
error: removeResult?.error
|
|
49096
|
+
});
|
|
49097
|
+
let ledgerError;
|
|
49098
|
+
const ledgerStarted = Date.now();
|
|
48238
49099
|
try {
|
|
48239
49100
|
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
48240
49101
|
appendLedgerEntry2(meshId, {
|
|
48241
49102
|
kind: "node_removed",
|
|
48242
49103
|
nodeId,
|
|
48243
|
-
payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary }
|
|
49104
|
+
payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary, patchEquivalence }
|
|
48244
49105
|
});
|
|
48245
|
-
|
|
49106
|
+
recordMeshRefineStage(refineStages, "ledger", "passed", ledgerStarted);
|
|
49107
|
+
} catch (e) {
|
|
49108
|
+
ledgerError = e?.message || String(e);
|
|
49109
|
+
recordMeshRefineStage(refineStages, "ledger", "failed", ledgerStarted, { error: ledgerError });
|
|
49110
|
+
}
|
|
49111
|
+
const finalBranchConvergenceState = {
|
|
49112
|
+
branch: baseBranch,
|
|
49113
|
+
mergedBranch: branch,
|
|
49114
|
+
baseBranch,
|
|
49115
|
+
merged: true,
|
|
49116
|
+
removed: removeResult?.success !== false,
|
|
49117
|
+
validation: "passed",
|
|
49118
|
+
patchEquivalence: "passed",
|
|
49119
|
+
status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
|
|
49120
|
+
};
|
|
49121
|
+
if (removeResult?.success === false) {
|
|
49122
|
+
return {
|
|
49123
|
+
success: false,
|
|
49124
|
+
code: "cleanup_failed",
|
|
49125
|
+
error: "Refinery merge completed but worktree cleanup failed; manual cleanup/retry is required.",
|
|
49126
|
+
merged: true,
|
|
49127
|
+
branch,
|
|
49128
|
+
into: baseBranch,
|
|
49129
|
+
removeResult,
|
|
49130
|
+
validationSummary,
|
|
49131
|
+
patchEquivalence,
|
|
49132
|
+
mergeResult,
|
|
49133
|
+
refineStages,
|
|
49134
|
+
...ledgerError ? { ledgerError } : {},
|
|
49135
|
+
finalBranchConvergenceState
|
|
49136
|
+
};
|
|
48246
49137
|
}
|
|
48247
49138
|
return {
|
|
48248
49139
|
success: true,
|
|
@@ -48251,18 +49142,14 @@ var init_router = __esm({
|
|
|
48251
49142
|
into: baseBranch,
|
|
48252
49143
|
removeResult,
|
|
48253
49144
|
validationSummary,
|
|
48254
|
-
|
|
48255
|
-
|
|
48256
|
-
|
|
48257
|
-
|
|
48258
|
-
|
|
48259
|
-
removed: removeResult?.success !== false,
|
|
48260
|
-
validation: "passed",
|
|
48261
|
-
status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
|
|
48262
|
-
}
|
|
49145
|
+
patchEquivalence,
|
|
49146
|
+
mergeResult,
|
|
49147
|
+
refineStages,
|
|
49148
|
+
...ledgerError ? { ledgerError } : {},
|
|
49149
|
+
finalBranchConvergenceState
|
|
48263
49150
|
};
|
|
48264
49151
|
} catch (e) {
|
|
48265
|
-
return { success: false, error: e.message };
|
|
49152
|
+
return { success: false, error: e.message, refineStages };
|
|
48266
49153
|
}
|
|
48267
49154
|
}
|
|
48268
49155
|
case "remove_mesh_node": {
|
|
@@ -48303,6 +49190,7 @@ var init_router = __esm({
|
|
|
48303
49190
|
} else {
|
|
48304
49191
|
const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
48305
49192
|
removed = removeNode3(meshId, nodeId);
|
|
49193
|
+
if (removed) this.invalidateAggregateMeshStatus(meshId);
|
|
48306
49194
|
}
|
|
48307
49195
|
if (removed) {
|
|
48308
49196
|
try {
|
|
@@ -48381,6 +49269,7 @@ var init_router = __esm({
|
|
|
48381
49269
|
policy: { ...sourceNode.policy || {} }
|
|
48382
49270
|
});
|
|
48383
49271
|
if (!node) return { success: false, error: "Failed to register worktree node" };
|
|
49272
|
+
this.invalidateAggregateMeshStatus(meshId);
|
|
48384
49273
|
}
|
|
48385
49274
|
const initSubmodules = sourceNode.policy?.initSubmodulesOnClone !== false;
|
|
48386
49275
|
if (initSubmodules) {
|
|
@@ -48456,7 +49345,14 @@ var init_router = __esm({
|
|
|
48456
49345
|
cliType
|
|
48457
49346
|
};
|
|
48458
49347
|
}
|
|
48459
|
-
const
|
|
49348
|
+
const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
|
|
49349
|
+
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
49350
|
+
const workspace = readLiveMeshNodeWorkspace({
|
|
49351
|
+
meshId,
|
|
49352
|
+
nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || ""),
|
|
49353
|
+
liveSessionRecords: liveMeshSessions,
|
|
49354
|
+
allowCoordinatorSession: true
|
|
49355
|
+
}) || (typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "");
|
|
48460
49356
|
if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
|
|
48461
49357
|
if (!cliType) {
|
|
48462
49358
|
const resolved = await resolveProviderTypeFromPriority({
|
|
@@ -48618,7 +49514,7 @@ ${block}`);
|
|
|
48618
49514
|
workspace
|
|
48619
49515
|
};
|
|
48620
49516
|
}
|
|
48621
|
-
const { existsSync:
|
|
49517
|
+
const { existsSync: existsSync33, readFileSync: readFileSync24, writeFileSync: writeFileSync18, copyFileSync: copyFileSync5, mkdirSync: mkdirSync22 } = await import("fs");
|
|
48622
49518
|
const { dirname: dirname13 } = await import("path");
|
|
48623
49519
|
const mcpConfigPath = coordinatorSetup.configPath;
|
|
48624
49520
|
const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
|
|
@@ -48661,14 +49557,14 @@ ${block}`);
|
|
|
48661
49557
|
if (hermesManualFallback) return returnManualFallback(message);
|
|
48662
49558
|
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
48663
49559
|
}
|
|
48664
|
-
const hadExistingMcpConfig =
|
|
49560
|
+
const hadExistingMcpConfig = existsSync33(mcpConfigPath);
|
|
48665
49561
|
let existingMcpConfig = hermesBaseConfig?.config || {};
|
|
48666
49562
|
if (hermesBaseConfig) {
|
|
48667
49563
|
copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname13(mcpConfigPath));
|
|
48668
49564
|
}
|
|
48669
49565
|
if (hadExistingMcpConfig) {
|
|
48670
49566
|
try {
|
|
48671
|
-
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(
|
|
49567
|
+
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync24(mcpConfigPath, "utf-8"), configFormat);
|
|
48672
49568
|
const existingCoordinatorConfig = hermesManualFallback ? stripHermesCoordinatorTempModelProviderOverrides(parsedExistingMcpConfig) : parsedExistingMcpConfig;
|
|
48673
49569
|
existingMcpConfig = { ...existingMcpConfig, ...existingCoordinatorConfig };
|
|
48674
49570
|
copyFileSync5(mcpConfigPath, mcpConfigPath + ".backup");
|
|
@@ -48758,110 +49654,264 @@ ${block}`);
|
|
|
48758
49654
|
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
48759
49655
|
const mesh = meshRecord?.mesh;
|
|
48760
49656
|
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
49657
|
+
const refreshRequested = args?.refresh === true || args?.forceRefresh === true;
|
|
49658
|
+
if (!refreshRequested) {
|
|
49659
|
+
const cachedStatus = this.getCachedAggregateMeshStatus(meshId);
|
|
49660
|
+
if (cachedStatus) return cachedStatus;
|
|
49661
|
+
}
|
|
49662
|
+
const refreshReason = refreshRequested ? "explicit_refresh" : "cold_cache_miss";
|
|
48761
49663
|
const { getMeshQueueStats: getMeshQueueStats2, getQueue: getQueue2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
48762
49664
|
const queue = getQueue2(meshId);
|
|
48763
49665
|
const queueSummary = getMeshQueueStats2(meshId);
|
|
48764
49666
|
const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
48765
49667
|
const ledgerEntries = readLedgerEntries2(meshId, { tail: 20 });
|
|
48766
49668
|
const ledgerSummary = getLedgerSummary2(meshId);
|
|
49669
|
+
const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
|
|
49670
|
+
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
49671
|
+
const localMachineId = loadConfig().machineId || "";
|
|
49672
|
+
const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
|
|
49673
|
+
const directTruth = requireDirectPeerTruth ? await hydrateInlineMeshDirectTruth({
|
|
49674
|
+
mesh,
|
|
49675
|
+
meshSource: meshRecord.source,
|
|
49676
|
+
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
49677
|
+
statusInstanceId: this.deps.statusInstanceId,
|
|
49678
|
+
localMachineId
|
|
49679
|
+
}) : {
|
|
49680
|
+
directEvidenceCount: 0,
|
|
49681
|
+
localConfirmedCount: 0,
|
|
49682
|
+
peerAttemptedCount: 0,
|
|
49683
|
+
peerConfirmedCount: 0,
|
|
49684
|
+
unavailableNodeIds: []
|
|
49685
|
+
};
|
|
49686
|
+
const directTruthSatisfied = meshRecord.source !== "inline_bootstrap" || directTruth.directEvidenceCount > 0;
|
|
49687
|
+
if (requireDirectPeerTruth && !directTruthSatisfied) {
|
|
49688
|
+
return {
|
|
49689
|
+
success: false,
|
|
49690
|
+
code: "mesh_direct_peer_truth_unavailable",
|
|
49691
|
+
error: "Selected coordinator could not confirm direct mesh truth yet. Bootstrap inventory stays unavailable until direct mesh_status probes succeed.",
|
|
49692
|
+
sourceOfTruth: {
|
|
49693
|
+
membership: meshRecord.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
|
|
49694
|
+
coordinatorOwnsLiveTruth: false,
|
|
49695
|
+
currentStatus: "direct_peer_truth_unavailable",
|
|
49696
|
+
directPeerTruth: {
|
|
49697
|
+
required: true,
|
|
49698
|
+
satisfied: false,
|
|
49699
|
+
directEvidenceCount: directTruth.directEvidenceCount,
|
|
49700
|
+
localConfirmedCount: directTruth.localConfirmedCount,
|
|
49701
|
+
peerAttemptedCount: directTruth.peerAttemptedCount,
|
|
49702
|
+
peerConfirmedCount: directTruth.peerConfirmedCount,
|
|
49703
|
+
unavailableNodeIds: directTruth.unavailableNodeIds
|
|
49704
|
+
}
|
|
49705
|
+
}
|
|
49706
|
+
};
|
|
49707
|
+
}
|
|
49708
|
+
const directTruthUnavailableNodeIds = new Set(directTruth.unavailableNodeIds);
|
|
49709
|
+
const selectedCoordinatorNodeId = readStringValue(
|
|
49710
|
+
mesh.coordinator?.preferredNodeId,
|
|
49711
|
+
mesh.nodes?.[0]?.id,
|
|
49712
|
+
mesh.nodes?.[0]?.nodeId
|
|
49713
|
+
);
|
|
49714
|
+
const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? selectedCoordinatorNodeId : void 0;
|
|
49715
|
+
const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
48767
49716
|
const nodeStatuses = [];
|
|
48768
|
-
for (const node of mesh.nodes || []) {
|
|
49717
|
+
for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
|
|
49718
|
+
const nodeId = String(node.id || node.nodeId || "");
|
|
49719
|
+
const daemonId = readStringValue(node.daemonId);
|
|
49720
|
+
const providerPriority = readProviderPriorityFromPolicy(node.policy);
|
|
49721
|
+
const isSelfNode = Boolean(
|
|
49722
|
+
nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId
|
|
49723
|
+
) || Boolean(
|
|
49724
|
+
daemonId && (daemonId === localMachineId || daemonId === this.deps.statusInstanceId)
|
|
49725
|
+
) || Boolean(meshRecord?.inline && nodeIndex === 0);
|
|
48769
49726
|
const status = {
|
|
48770
|
-
nodeId
|
|
49727
|
+
nodeId,
|
|
48771
49728
|
machineLabel: node.machineLabel || node.id || node.nodeId,
|
|
48772
49729
|
workspace: node.workspace,
|
|
48773
49730
|
repoRoot: node.repoRoot,
|
|
48774
49731
|
isLocalWorktree: node.isLocalWorktree,
|
|
48775
49732
|
worktreeBranch: node.worktreeBranch,
|
|
48776
|
-
daemonId
|
|
49733
|
+
daemonId,
|
|
48777
49734
|
machineId: node.machineId,
|
|
49735
|
+
machineStatus: node.machineStatus,
|
|
48778
49736
|
health: "unknown",
|
|
48779
49737
|
providers: node.providers || [],
|
|
48780
|
-
|
|
49738
|
+
providerPriority,
|
|
49739
|
+
activeSessions: [],
|
|
49740
|
+
activeSessionDetails: [],
|
|
49741
|
+
launchReady: false
|
|
48781
49742
|
};
|
|
48782
|
-
if (
|
|
48783
|
-
|
|
48784
|
-
|
|
48785
|
-
|
|
49743
|
+
if (isSelfNode) {
|
|
49744
|
+
status.connection = {
|
|
49745
|
+
perspective: "selected_coordinator",
|
|
49746
|
+
source: "mesh_peer_status",
|
|
49747
|
+
state: "self",
|
|
49748
|
+
transport: "local",
|
|
49749
|
+
reported: true,
|
|
49750
|
+
reason: "Selected coordinator daemon",
|
|
49751
|
+
lastStateChangeAt: refreshedAt
|
|
49752
|
+
};
|
|
49753
|
+
} else if (daemonId) {
|
|
49754
|
+
const connection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
|
|
49755
|
+
status.connection = connection ?? {
|
|
49756
|
+
perspective: "selected_coordinator",
|
|
49757
|
+
source: "not_reported",
|
|
49758
|
+
state: "unknown",
|
|
49759
|
+
transport: "unknown",
|
|
49760
|
+
reported: false,
|
|
49761
|
+
reason: "No live mesh peer telemetry reported by the selected coordinator yet."
|
|
49762
|
+
};
|
|
49763
|
+
} else {
|
|
49764
|
+
status.connection = {
|
|
49765
|
+
perspective: "selected_coordinator",
|
|
49766
|
+
source: "not_reported",
|
|
49767
|
+
state: "unknown",
|
|
49768
|
+
transport: "unknown",
|
|
49769
|
+
reported: false,
|
|
49770
|
+
reason: "Node has no daemon id, so mesh transport cannot be reported from the selected coordinator."
|
|
49771
|
+
};
|
|
49772
|
+
}
|
|
49773
|
+
const matchedLiveSessionRecords = collectLiveMeshSessionRecords({
|
|
49774
|
+
meshId,
|
|
49775
|
+
node,
|
|
49776
|
+
nodeId,
|
|
49777
|
+
liveSessionRecords: liveMeshSessions,
|
|
49778
|
+
allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
|
|
49779
|
+
});
|
|
49780
|
+
const workspace = readLiveMeshNodeWorkspace({
|
|
49781
|
+
meshId,
|
|
49782
|
+
nodeId,
|
|
49783
|
+
liveSessionRecords: matchedLiveSessionRecords,
|
|
49784
|
+
allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
|
|
49785
|
+
}) || (typeof node.workspace === "string" ? node.workspace : "");
|
|
49786
|
+
status.workspace = workspace || node.workspace;
|
|
49787
|
+
if (matchedLiveSessionRecords.length > 0) {
|
|
49788
|
+
const sessionIds = matchedLiveSessionRecords.map((record2) => typeof record2?.sessionId === "string" ? record2.sessionId : "").filter(Boolean);
|
|
49789
|
+
const providerTypes = matchedLiveSessionRecords.map((record2) => readStringValue(record2?.providerType)).filter(Boolean);
|
|
49790
|
+
status.activeSessions = sessionIds;
|
|
49791
|
+
status.activeSessionDetails = matchedLiveSessionRecords.map(summarizeMeshSessionRecord);
|
|
49792
|
+
if (providerTypes.length > 0) {
|
|
49793
|
+
status.providers = Array.from(/* @__PURE__ */ new Set([...Array.isArray(status.providers) ? status.providers : [], ...providerTypes]));
|
|
48786
49794
|
}
|
|
48787
|
-
|
|
48788
|
-
|
|
48789
|
-
|
|
48790
|
-
const
|
|
48791
|
-
|
|
48792
|
-
|
|
48793
|
-
|
|
48794
|
-
|
|
48795
|
-
|
|
48796
|
-
|
|
48797
|
-
|
|
48798
|
-
|
|
48799
|
-
|
|
48800
|
-
|
|
48801
|
-
|
|
48802
|
-
|
|
48803
|
-
|
|
48804
|
-
|
|
48805
|
-
|
|
48806
|
-
|
|
48807
|
-
|
|
48808
|
-
|
|
48809
|
-
|
|
48810
|
-
|
|
49795
|
+
}
|
|
49796
|
+
if (workspace) {
|
|
49797
|
+
if (!fs10.existsSync(workspace)) {
|
|
49798
|
+
const inlineTransitGit = buildInlineMeshTransitGitStatus(node);
|
|
49799
|
+
let remoteProbeApplied = false;
|
|
49800
|
+
if (inlineTransitGit) {
|
|
49801
|
+
status.git = inlineTransitGit;
|
|
49802
|
+
status.health = inlineTransitGit.isGitRepo ? deriveMeshNodeHealthFromGit(inlineTransitGit) : "degraded";
|
|
49803
|
+
remoteProbeApplied = true;
|
|
49804
|
+
} else if (!isSelfNode && daemonId && this.deps.dispatchMeshCommand && !directTruthUnavailableNodeIds.has(nodeId)) {
|
|
49805
|
+
try {
|
|
49806
|
+
const remoteGit = await probeRemoteMeshGitStatus({
|
|
49807
|
+
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
49808
|
+
daemonId,
|
|
49809
|
+
workspace,
|
|
49810
|
+
timeoutMs: 8e3
|
|
49811
|
+
});
|
|
49812
|
+
if (remoteGit) {
|
|
49813
|
+
status.git = remoteGit;
|
|
49814
|
+
status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
|
|
49815
|
+
recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
|
|
49816
|
+
remoteProbeApplied = true;
|
|
49817
|
+
}
|
|
49818
|
+
} catch {
|
|
49819
|
+
const refreshedConnection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
|
|
49820
|
+
const refreshedConnectionState = readStringValue(refreshedConnection?.state);
|
|
49821
|
+
if (refreshedConnection && refreshedConnectionState === "connected") {
|
|
49822
|
+
status.connection = refreshedConnection;
|
|
49823
|
+
try {
|
|
49824
|
+
const remoteGit = await probeRemoteMeshGitStatus({
|
|
49825
|
+
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
49826
|
+
daemonId,
|
|
49827
|
+
workspace,
|
|
49828
|
+
timeoutMs: 12e3
|
|
49829
|
+
});
|
|
49830
|
+
if (remoteGit) {
|
|
49831
|
+
status.git = remoteGit;
|
|
49832
|
+
status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
|
|
49833
|
+
recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
|
|
49834
|
+
remoteProbeApplied = true;
|
|
49835
|
+
}
|
|
49836
|
+
} catch {
|
|
49837
|
+
}
|
|
49838
|
+
}
|
|
48811
49839
|
}
|
|
48812
49840
|
}
|
|
48813
|
-
|
|
48814
|
-
|
|
48815
|
-
|
|
48816
|
-
|
|
48817
|
-
|
|
48818
|
-
|
|
48819
|
-
|
|
48820
|
-
if (
|
|
48821
|
-
|
|
48822
|
-
|
|
49841
|
+
if (!remoteProbeApplied) {
|
|
49842
|
+
const connectionState = readStringValue(status.connection?.state);
|
|
49843
|
+
const pendingPeerGitProbe = !inlineTransitGit && !isSelfNode && !!daemonId && (readStringValue(status.machineStatus) === "online" || readStringValue(status.health) === "online" || connectionState === "connecting" || connectionState === "connected" || connectionState === "unknown");
|
|
49844
|
+
if (pendingPeerGitProbe) {
|
|
49845
|
+
status.gitProbePending = true;
|
|
49846
|
+
status.health = "unknown";
|
|
49847
|
+
}
|
|
49848
|
+
if (applyCachedInlineMeshNodeStatus(
|
|
49849
|
+
status,
|
|
49850
|
+
node,
|
|
49851
|
+
pendingPeerGitProbe ? { skipGit: true, skipError: true, skipHealth: true } : void 0
|
|
49852
|
+
)) {
|
|
49853
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
49854
|
+
nodeStatuses.push(status);
|
|
49855
|
+
continue;
|
|
49856
|
+
}
|
|
49857
|
+
if (meshRecord?.source === "inline_cache" && !isSelfNode) {
|
|
49858
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
49859
|
+
nodeStatuses.push(status);
|
|
49860
|
+
continue;
|
|
49861
|
+
}
|
|
48823
49862
|
}
|
|
48824
|
-
|
|
48825
|
-
|
|
48826
|
-
|
|
48827
|
-
|
|
48828
|
-
|
|
48829
|
-
|
|
48830
|
-
|
|
48831
|
-
|
|
48832
|
-
|
|
48833
|
-
|
|
48834
|
-
|
|
48835
|
-
|
|
48836
|
-
|
|
48837
|
-
|
|
48838
|
-
|
|
48839
|
-
hasConflicts: false,
|
|
48840
|
-
conflictFiles: [],
|
|
48841
|
-
stashCount: stashCount ? stashCount.split("\n").filter(Boolean).length : 0,
|
|
48842
|
-
lastCheckedAt: Date.now()
|
|
48843
|
-
};
|
|
48844
|
-
status.health = branch ? dirty ? "dirty" : "online" : "degraded";
|
|
48845
|
-
} catch {
|
|
48846
|
-
if (!applyCachedInlineMeshNodeStatus(status, node)) {
|
|
48847
|
-
status.health = "degraded";
|
|
49863
|
+
} else {
|
|
49864
|
+
try {
|
|
49865
|
+
const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
49866
|
+
status.git = gitStatus;
|
|
49867
|
+
recordInlineMeshDirectGitTruth(node, gitStatus, "selected_coordinator_local_git");
|
|
49868
|
+
if (gitStatus.isGitRepo) {
|
|
49869
|
+
status.health = deriveMeshNodeHealthFromGit(gitStatus);
|
|
49870
|
+
} else {
|
|
49871
|
+
status.health = "degraded";
|
|
49872
|
+
if (gitStatus.error && !status.error) status.error = gitStatus.error;
|
|
49873
|
+
}
|
|
49874
|
+
} catch {
|
|
49875
|
+
if (!applyCachedInlineMeshNodeStatus(status, node)) {
|
|
49876
|
+
status.health = "degraded";
|
|
49877
|
+
}
|
|
48848
49878
|
}
|
|
48849
49879
|
}
|
|
48850
49880
|
} else {
|
|
48851
49881
|
applyCachedInlineMeshNodeStatus(status, node);
|
|
48852
49882
|
}
|
|
49883
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
48853
49884
|
nodeStatuses.push(status);
|
|
48854
49885
|
}
|
|
48855
|
-
|
|
49886
|
+
const statusResult = {
|
|
48856
49887
|
success: true,
|
|
48857
49888
|
meshId: mesh.id,
|
|
48858
49889
|
meshName: mesh.name,
|
|
48859
49890
|
repoIdentity: mesh.repoIdentity,
|
|
48860
49891
|
defaultBranch: mesh.defaultBranch,
|
|
49892
|
+
refreshedAt,
|
|
49893
|
+
sourceOfTruth: {
|
|
49894
|
+
membership: meshRecord?.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord?.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
|
|
49895
|
+
coordinatorOwnsLiveTruth: directTruthSatisfied,
|
|
49896
|
+
...requireDirectPeerTruth ? {
|
|
49897
|
+
currentStatus: directTruthSatisfied ? "live_git_and_session_probes" : "direct_peer_truth_unavailable",
|
|
49898
|
+
directPeerTruth: {
|
|
49899
|
+
required: true,
|
|
49900
|
+
satisfied: directTruthSatisfied,
|
|
49901
|
+
directEvidenceCount: directTruth.directEvidenceCount,
|
|
49902
|
+
localConfirmedCount: directTruth.localConfirmedCount,
|
|
49903
|
+
peerAttemptedCount: directTruth.peerAttemptedCount,
|
|
49904
|
+
peerConfirmedCount: directTruth.peerConfirmedCount,
|
|
49905
|
+
unavailableNodeIds: directTruth.unavailableNodeIds
|
|
49906
|
+
}
|
|
49907
|
+
} : {},
|
|
49908
|
+
historicalEvidenceOnly: ["recoveryHints", "ledger.summary", "queue.summary"]
|
|
49909
|
+
},
|
|
48861
49910
|
nodes: nodeStatuses,
|
|
48862
49911
|
queue: { tasks: queue, summary: queueSummary },
|
|
48863
49912
|
ledger: { entries: ledgerEntries, summary: ledgerSummary }
|
|
48864
49913
|
};
|
|
49914
|
+
return this.rememberAggregateMeshStatus(meshId, statusResult, refreshReason);
|
|
48865
49915
|
} catch (e) {
|
|
48866
49916
|
return { success: false, error: e.message };
|
|
48867
49917
|
}
|
|
@@ -56936,6 +57986,7 @@ async function initDaemonComponents(config2) {
|
|
|
56936
57986
|
sessionHostControl: config2.sessionHostControl,
|
|
56937
57987
|
statusInstanceId: config2.statusInstanceId,
|
|
56938
57988
|
statusVersion: config2.statusVersion,
|
|
57989
|
+
getMeshPeerConnectionStatus: config2.getMeshPeerConnectionStatus,
|
|
56939
57990
|
getCdpLogFn: config2.getCdpLogFn || ((ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn())
|
|
56940
57991
|
});
|
|
56941
57992
|
poller = new AgentStreamPoller({
|
|
@@ -57237,6 +58288,7 @@ __export(src_exports, {
|
|
|
57237
58288
|
prepareSessionChatTailUpdate: () => prepareSessionChatTailUpdate,
|
|
57238
58289
|
prepareSessionModalUpdate: () => prepareSessionModalUpdate,
|
|
57239
58290
|
probeCdpPort: () => probeCdpPort,
|
|
58291
|
+
queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
|
|
57240
58292
|
readChatHistory: () => readChatHistory,
|
|
57241
58293
|
readLedgerEntries: () => readLedgerEntries,
|
|
57242
58294
|
readLedgerSlice: () => readLedgerSlice,
|
|
@@ -72139,7 +73191,7 @@ var require_buffer_list = __commonJS({
|
|
|
72139
73191
|
}
|
|
72140
73192
|
}, {
|
|
72141
73193
|
key: "join",
|
|
72142
|
-
value: function
|
|
73194
|
+
value: function join40(s) {
|
|
72143
73195
|
if (this.length === 0) return "";
|
|
72144
73196
|
var p = this.head;
|
|
72145
73197
|
var ret = "" + p.data;
|
|
@@ -86198,13 +87250,13 @@ function splitStringBySpace(str2) {
|
|
|
86198
87250
|
}
|
|
86199
87251
|
return pieces;
|
|
86200
87252
|
}
|
|
86201
|
-
var import_chardet, import_child_process12,
|
|
87253
|
+
var import_chardet, import_child_process12, import_fs12, import_node_path3, import_node_os3, import_node_crypto3, import_iconv_lite, ExternalEditor;
|
|
86202
87254
|
var init_esm4 = __esm({
|
|
86203
87255
|
"../../node_modules/@inquirer/external-editor/dist/esm/index.js"() {
|
|
86204
87256
|
"use strict";
|
|
86205
87257
|
import_chardet = __toESM(require_lib(), 1);
|
|
86206
87258
|
import_child_process12 = require("child_process");
|
|
86207
|
-
|
|
87259
|
+
import_fs12 = require("fs");
|
|
86208
87260
|
import_node_path3 = __toESM(require("path"), 1);
|
|
86209
87261
|
import_node_os3 = __toESM(require("os"), 1);
|
|
86210
87262
|
import_node_crypto3 = require("crypto");
|
|
@@ -86280,14 +87332,14 @@ var init_esm4 = __esm({
|
|
|
86280
87332
|
if (Object.prototype.hasOwnProperty.call(this.fileOptions, "mode")) {
|
|
86281
87333
|
opt.mode = this.fileOptions.mode;
|
|
86282
87334
|
}
|
|
86283
|
-
(0,
|
|
87335
|
+
(0, import_fs12.writeFileSync)(this.tempFile, this.text, opt);
|
|
86284
87336
|
} catch (createFileError) {
|
|
86285
87337
|
throw new CreateFileError(createFileError);
|
|
86286
87338
|
}
|
|
86287
87339
|
}
|
|
86288
87340
|
readTemporaryFile() {
|
|
86289
87341
|
try {
|
|
86290
|
-
const tempFileBuffer = (0,
|
|
87342
|
+
const tempFileBuffer = (0, import_fs12.readFileSync)(this.tempFile);
|
|
86291
87343
|
if (tempFileBuffer.length === 0) {
|
|
86292
87344
|
this.text = "";
|
|
86293
87345
|
} else {
|
|
@@ -86303,7 +87355,7 @@ var init_esm4 = __esm({
|
|
|
86303
87355
|
}
|
|
86304
87356
|
removeTemporaryFile() {
|
|
86305
87357
|
try {
|
|
86306
|
-
(0,
|
|
87358
|
+
(0, import_fs12.unlinkSync)(this.tempFile);
|
|
86307
87359
|
} catch (removeFileError) {
|
|
86308
87360
|
throw new RemoveFileError(removeFileError);
|
|
86309
87361
|
}
|
|
@@ -88005,25 +89057,25 @@ function resolvePackageVersion(options) {
|
|
|
88005
89057
|
const injectedVersion = options?.injectedVersion || "unknown";
|
|
88006
89058
|
const dir = options?.dirname || __dirname;
|
|
88007
89059
|
const possiblePaths = [
|
|
88008
|
-
(0,
|
|
88009
|
-
(0,
|
|
88010
|
-
(0,
|
|
89060
|
+
(0, import_path8.join)(dir, "..", "..", "package.json"),
|
|
89061
|
+
(0, import_path8.join)(dir, "..", "package.json"),
|
|
89062
|
+
(0, import_path8.join)(dir, "package.json")
|
|
88011
89063
|
];
|
|
88012
89064
|
for (const p of possiblePaths) {
|
|
88013
89065
|
try {
|
|
88014
|
-
const data = JSON.parse((0,
|
|
89066
|
+
const data = JSON.parse((0, import_fs13.readFileSync)(p, "utf-8"));
|
|
88015
89067
|
if (data.version) return data.version;
|
|
88016
89068
|
} catch {
|
|
88017
89069
|
}
|
|
88018
89070
|
}
|
|
88019
89071
|
return injectedVersion;
|
|
88020
89072
|
}
|
|
88021
|
-
var
|
|
89073
|
+
var import_fs13, import_path8;
|
|
88022
89074
|
var init_version = __esm({
|
|
88023
89075
|
"src/version.ts"() {
|
|
88024
89076
|
"use strict";
|
|
88025
|
-
|
|
88026
|
-
|
|
89077
|
+
import_fs13 = require("fs");
|
|
89078
|
+
import_path8 = require("path");
|
|
88027
89079
|
}
|
|
88028
89080
|
});
|
|
88029
89081
|
|
|
@@ -88144,7 +89196,9 @@ var init_server_connection = __esm({
|
|
|
88144
89196
|
const requestId = `mesh_${crypto.randomUUID()}`;
|
|
88145
89197
|
const timer = setTimeout(() => {
|
|
88146
89198
|
this.off("daemon_mesh_result", handler);
|
|
88147
|
-
reject(new Error(
|
|
89199
|
+
reject(new Error(
|
|
89200
|
+
`Mesh command '${command}' to ${targetDaemonId.slice(0, 12)} timed out after ${timeoutMs}ms (requestId=${requestId})`
|
|
89201
|
+
));
|
|
88148
89202
|
}, timeoutMs);
|
|
88149
89203
|
const handler = (msg) => {
|
|
88150
89204
|
const body = msg.payload && typeof msg.payload === "object" ? { ...msg, ...msg.payload } : msg;
|
|
@@ -89959,7 +91013,7 @@ var require_filesystem = __commonJS({
|
|
|
89959
91013
|
var LDD_PATH = "/usr/bin/ldd";
|
|
89960
91014
|
var SELF_PATH = "/proc/self/exe";
|
|
89961
91015
|
var MAX_LENGTH = 2048;
|
|
89962
|
-
var
|
|
91016
|
+
var readFileSync24 = (path42) => {
|
|
89963
91017
|
const fd = fs24.openSync(path42, "r");
|
|
89964
91018
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
89965
91019
|
const bytesRead = fs24.readSync(fd, buffer, 0, MAX_LENGTH, 0);
|
|
@@ -89984,7 +91038,7 @@ var require_filesystem = __commonJS({
|
|
|
89984
91038
|
module2.exports = {
|
|
89985
91039
|
LDD_PATH,
|
|
89986
91040
|
SELF_PATH,
|
|
89987
|
-
readFileSync:
|
|
91041
|
+
readFileSync: readFileSync24,
|
|
89988
91042
|
readFile: readFile2
|
|
89989
91043
|
};
|
|
89990
91044
|
}
|
|
@@ -90033,7 +91087,7 @@ var require_detect_libc = __commonJS({
|
|
|
90033
91087
|
"use strict";
|
|
90034
91088
|
var childProcess = require("child_process");
|
|
90035
91089
|
var { isLinux: isLinux2, getReport } = require_process();
|
|
90036
|
-
var { LDD_PATH, SELF_PATH, readFile: readFile2, readFileSync:
|
|
91090
|
+
var { LDD_PATH, SELF_PATH, readFile: readFile2, readFileSync: readFileSync24 } = require_filesystem();
|
|
90037
91091
|
var { interpreterPath } = require_elf();
|
|
90038
91092
|
var cachedFamilyInterpreter;
|
|
90039
91093
|
var cachedFamilyFilesystem;
|
|
@@ -90125,7 +91179,7 @@ var require_detect_libc = __commonJS({
|
|
|
90125
91179
|
}
|
|
90126
91180
|
cachedFamilyFilesystem = null;
|
|
90127
91181
|
try {
|
|
90128
|
-
const lddContent =
|
|
91182
|
+
const lddContent = readFileSync24(LDD_PATH);
|
|
90129
91183
|
cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
|
|
90130
91184
|
} catch (e) {
|
|
90131
91185
|
}
|
|
@@ -90150,7 +91204,7 @@ var require_detect_libc = __commonJS({
|
|
|
90150
91204
|
}
|
|
90151
91205
|
cachedFamilyInterpreter = null;
|
|
90152
91206
|
try {
|
|
90153
|
-
const selfContent =
|
|
91207
|
+
const selfContent = readFileSync24(SELF_PATH);
|
|
90154
91208
|
const path42 = interpreterPath(selfContent);
|
|
90155
91209
|
cachedFamilyInterpreter = familyFromInterpreterPath(path42);
|
|
90156
91210
|
} catch (e) {
|
|
@@ -90214,7 +91268,7 @@ var require_detect_libc = __commonJS({
|
|
|
90214
91268
|
}
|
|
90215
91269
|
cachedVersionFilesystem = null;
|
|
90216
91270
|
try {
|
|
90217
|
-
const lddContent =
|
|
91271
|
+
const lddContent = readFileSync24(LDD_PATH);
|
|
90218
91272
|
const versionMatch = lddContent.match(RE_GLIBC_VERSION);
|
|
90219
91273
|
if (versionMatch) {
|
|
90220
91274
|
cachedVersionFilesystem = versionMatch[1];
|
|
@@ -97213,11 +98267,37 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97213
98267
|
nodeDatachannel = null;
|
|
97214
98268
|
peers = /* @__PURE__ */ new Map();
|
|
97215
98269
|
// Map<targetDaemonId, PeerEntry>
|
|
98270
|
+
peerSnapshots = /* @__PURE__ */ new Map();
|
|
97216
98271
|
pendingRequests = /* @__PURE__ */ new Map();
|
|
97217
98272
|
commandCallback;
|
|
97218
98273
|
p2pFailure(message, command, targetDaemonId) {
|
|
97219
98274
|
return new P2pRelayFailureError(message, { command, targetDaemonId });
|
|
97220
98275
|
}
|
|
98276
|
+
logMeshCommandEvent(event, fields) {
|
|
98277
|
+
try {
|
|
98278
|
+
LOG.info("Mesh", `[MeshCommand] ${JSON.stringify({ event, ...fields })}`);
|
|
98279
|
+
} catch {
|
|
98280
|
+
LOG.info("Mesh", `[MeshCommand] ${event}`);
|
|
98281
|
+
}
|
|
98282
|
+
}
|
|
98283
|
+
updatePeerSnapshot(targetDaemonId, state, patch = {}) {
|
|
98284
|
+
const previous = this.peerSnapshots.get(targetDaemonId);
|
|
98285
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
98286
|
+
this.peerSnapshots.set(targetDaemonId, {
|
|
98287
|
+
perspective: "selected_coordinator",
|
|
98288
|
+
source: "mesh_peer_status",
|
|
98289
|
+
reported: true,
|
|
98290
|
+
state,
|
|
98291
|
+
transport: patch.transport ?? previous?.transport ?? "unknown",
|
|
98292
|
+
reason: patch.reason ?? previous?.reason,
|
|
98293
|
+
lastStateChangeAt: now,
|
|
98294
|
+
lastConnectedAt: patch.lastConnectedAt ?? previous?.lastConnectedAt,
|
|
98295
|
+
lastCommandAt: patch.lastCommandAt ?? previous?.lastCommandAt
|
|
98296
|
+
});
|
|
98297
|
+
}
|
|
98298
|
+
getPeerConnectionStatus(targetDaemonId) {
|
|
98299
|
+
return this.peerSnapshots.get(targetDaemonId) ?? null;
|
|
98300
|
+
}
|
|
97221
98301
|
invalidatePeer(targetDaemonId, reason, options = {}) {
|
|
97222
98302
|
const peer = this.peers.get(targetDaemonId);
|
|
97223
98303
|
if (peer?.commandQueue) {
|
|
@@ -97232,6 +98312,11 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97232
98312
|
pending.reject(this.p2pFailure(reason, pending.command, targetDaemonId));
|
|
97233
98313
|
}
|
|
97234
98314
|
}
|
|
98315
|
+
const snapshotState = peer?.state === "closed" ? "closed" : peer?.state === "disconnected" ? "disconnected" : "failed";
|
|
98316
|
+
this.updatePeerSnapshot(targetDaemonId, snapshotState, {
|
|
98317
|
+
reason,
|
|
98318
|
+
transport: peer?.isRelay === true ? "relay" : peer?.isRelay === false ? "direct" : "unknown"
|
|
98319
|
+
});
|
|
97235
98320
|
if (options.closeResources !== false && peer) {
|
|
97236
98321
|
try {
|
|
97237
98322
|
peer.dataChannel?.close?.();
|
|
@@ -97264,6 +98349,7 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97264
98349
|
"send_chat",
|
|
97265
98350
|
"read_chat",
|
|
97266
98351
|
"get_chat_debug_bundle",
|
|
98352
|
+
"get_pending_mesh_events",
|
|
97267
98353
|
"git_status",
|
|
97268
98354
|
"git_diff_summary",
|
|
97269
98355
|
"launch_cli",
|
|
@@ -97324,6 +98410,13 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97324
98410
|
const peer = this.peers.get(targetDaemonId);
|
|
97325
98411
|
if (!peer || peer.state !== "connected" || !peer.dataChannel?.isOpen()) {
|
|
97326
98412
|
LOG.warn("Mesh", `[Mesh] Cannot send result for ${requestId}, P2P not open with ${targetDaemonId.slice(0, 12)}`);
|
|
98413
|
+
this.logMeshCommandEvent("response_send_failed", {
|
|
98414
|
+
requestId,
|
|
98415
|
+
targetDaemonId,
|
|
98416
|
+
sentAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
98417
|
+
peerState: peer?.state ?? "missing",
|
|
98418
|
+
error: "P2P not open"
|
|
98419
|
+
});
|
|
97327
98420
|
return;
|
|
97328
98421
|
}
|
|
97329
98422
|
try {
|
|
@@ -97334,8 +98427,22 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97334
98427
|
result,
|
|
97335
98428
|
error: error48
|
|
97336
98429
|
}));
|
|
98430
|
+
this.logMeshCommandEvent("response_sent", {
|
|
98431
|
+
requestId,
|
|
98432
|
+
targetDaemonId,
|
|
98433
|
+
sentAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
98434
|
+
peerState: peer.state,
|
|
98435
|
+
success: !error48
|
|
98436
|
+
});
|
|
97337
98437
|
} catch (err) {
|
|
97338
98438
|
LOG.warn("Mesh", `[Mesh] Failed to send command result: ${err.message}`);
|
|
98439
|
+
this.logMeshCommandEvent("response_send_failed", {
|
|
98440
|
+
requestId,
|
|
98441
|
+
targetDaemonId,
|
|
98442
|
+
sentAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
98443
|
+
peerState: peer.state,
|
|
98444
|
+
error: err?.message || "Failed to send command result"
|
|
98445
|
+
});
|
|
97339
98446
|
}
|
|
97340
98447
|
}
|
|
97341
98448
|
/** Convenience: send a one-off mesh command without a rule. */
|
|
@@ -97351,11 +98458,37 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97351
98458
|
if (!peer) {
|
|
97352
98459
|
throw this.p2pFailure("Failed to initiate P2P connection entry", command, targetDaemonId);
|
|
97353
98460
|
}
|
|
98461
|
+
const lastCommandAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
98462
|
+
if (peer.state === "connected") {
|
|
98463
|
+
this.updatePeerSnapshot(targetDaemonId, "connected", {
|
|
98464
|
+
transport: peer.isRelay === true ? "relay" : peer.isRelay === false ? "direct" : "unknown",
|
|
98465
|
+
lastConnectedAt: this.peerSnapshots.get(targetDaemonId)?.lastConnectedAt,
|
|
98466
|
+
lastCommandAt
|
|
98467
|
+
});
|
|
98468
|
+
} else {
|
|
98469
|
+
this.updatePeerSnapshot(targetDaemonId, "connecting", {
|
|
98470
|
+
transport: peer.isRelay === true ? "relay" : peer.isRelay === false ? "direct" : "unknown",
|
|
98471
|
+
reason: "Waiting for mesh DataChannel to open.",
|
|
98472
|
+
lastCommandAt
|
|
98473
|
+
});
|
|
98474
|
+
}
|
|
97354
98475
|
return new Promise((resolve23, reject) => {
|
|
97355
98476
|
const requestId = `req_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
98477
|
+
const queuedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
97356
98478
|
const timer = setTimeout(() => {
|
|
98479
|
+
const pending = this.pendingRequests.get(requestId);
|
|
97357
98480
|
this.pendingRequests.delete(requestId);
|
|
98481
|
+
const timedOutAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
97358
98482
|
const message = `P2P DataChannel command '${command}' to ${targetDaemonId.slice(0, 12)} timed out after 30s`;
|
|
98483
|
+
this.logMeshCommandEvent("timeout", {
|
|
98484
|
+
requestId,
|
|
98485
|
+
command,
|
|
98486
|
+
targetDaemonId,
|
|
98487
|
+
queuedAt: pending?.queuedAt ?? queuedAt,
|
|
98488
|
+
sentAt: pending?.sentAt,
|
|
98489
|
+
timedOutAt,
|
|
98490
|
+
peerState: peer?.state
|
|
98491
|
+
});
|
|
97359
98492
|
this.invalidatePeer(targetDaemonId, message, { rejectPending: true, excludeRequestId: requestId });
|
|
97360
98493
|
reject(this.p2pFailure(message, command, targetDaemonId));
|
|
97361
98494
|
}, 3e4);
|
|
@@ -97372,7 +98505,8 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97372
98505
|
},
|
|
97373
98506
|
timer,
|
|
97374
98507
|
targetDaemonId,
|
|
97375
|
-
command
|
|
98508
|
+
command,
|
|
98509
|
+
queuedAt
|
|
97376
98510
|
});
|
|
97377
98511
|
const payload = {
|
|
97378
98512
|
type: "mesh_command",
|
|
@@ -97381,18 +98515,47 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97381
98515
|
args
|
|
97382
98516
|
};
|
|
97383
98517
|
if (peer.state === "connected" && peer.dataChannel?.isOpen()) {
|
|
98518
|
+
const sentAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
98519
|
+
const pending = this.pendingRequests.get(requestId);
|
|
98520
|
+
if (pending) pending.sentAt = sentAt;
|
|
97384
98521
|
LOG.info("Mesh", `[Mesh] Sending '${command}' via P2P DataChannel to ${targetDaemonId.slice(0, 12)}`);
|
|
98522
|
+
this.logMeshCommandEvent("sent", {
|
|
98523
|
+
requestId,
|
|
98524
|
+
command,
|
|
98525
|
+
targetDaemonId,
|
|
98526
|
+
queuedAt,
|
|
98527
|
+
sentAt,
|
|
98528
|
+
peerState: peer.state,
|
|
98529
|
+
transport: peer.isRelay === true ? "relay" : peer.isRelay === false ? "direct" : "unknown"
|
|
98530
|
+
});
|
|
97385
98531
|
try {
|
|
97386
98532
|
peer.dataChannel.sendMessage(JSON.stringify(payload));
|
|
97387
98533
|
} catch (err) {
|
|
97388
98534
|
const req = this.pendingRequests.get(requestId);
|
|
97389
98535
|
const message = err?.message || "P2P DataChannel send failed";
|
|
98536
|
+
this.logMeshCommandEvent("send_failed", {
|
|
98537
|
+
requestId,
|
|
98538
|
+
command,
|
|
98539
|
+
targetDaemonId,
|
|
98540
|
+
queuedAt,
|
|
98541
|
+
sentAt,
|
|
98542
|
+
failedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
98543
|
+
error: message
|
|
98544
|
+
});
|
|
97390
98545
|
this.invalidatePeer(targetDaemonId, message, { rejectPending: true, excludeRequestId: requestId });
|
|
97391
98546
|
if (req) req.reject(this.p2pFailure(message, command, targetDaemonId));
|
|
97392
98547
|
}
|
|
97393
98548
|
return;
|
|
97394
98549
|
}
|
|
97395
98550
|
LOG.info("Mesh", `[Mesh] Queuing '${command}' for ${targetDaemonId.slice(0, 12)} (state: ${peer.state})`);
|
|
98551
|
+
this.logMeshCommandEvent("queued", {
|
|
98552
|
+
requestId,
|
|
98553
|
+
command,
|
|
98554
|
+
targetDaemonId,
|
|
98555
|
+
queuedAt,
|
|
98556
|
+
peerState: peer.state,
|
|
98557
|
+
transport: peer.isRelay === true ? "relay" : peer.isRelay === false ? "direct" : "unknown"
|
|
98558
|
+
});
|
|
97396
98559
|
if (!peer.commandQueue) {
|
|
97397
98560
|
peer.commandQueue = [];
|
|
97398
98561
|
}
|
|
@@ -97400,6 +98563,7 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97400
98563
|
command,
|
|
97401
98564
|
args,
|
|
97402
98565
|
requestId,
|
|
98566
|
+
queuedAt,
|
|
97403
98567
|
reject: (err) => {
|
|
97404
98568
|
const req = this.pendingRequests.get(requestId);
|
|
97405
98569
|
if (req) req.reject(err);
|
|
@@ -97438,7 +98602,18 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97438
98602
|
peer.pendingCandidates = [];
|
|
97439
98603
|
}
|
|
97440
98604
|
} catch (err) {
|
|
97441
|
-
|
|
98605
|
+
const errorMessage = err?.message || "Failed to set remote description";
|
|
98606
|
+
const isDuplicateStableAnswer = type2 === "mesh_p2p_answer" && /Unexpected remote answer description in signaling state stable/i.test(errorMessage);
|
|
98607
|
+
this.logMeshCommandEvent(isDuplicateStableAnswer ? "remote_desc_duplicate_ignored" : "remote_desc_failed", {
|
|
98608
|
+
targetDaemonId,
|
|
98609
|
+
signalType: type2,
|
|
98610
|
+
receivedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
98611
|
+
peerState: peer.state,
|
|
98612
|
+
error: errorMessage
|
|
98613
|
+
});
|
|
98614
|
+
if (isDuplicateStableAnswer) return;
|
|
98615
|
+
LOG.warn("Mesh", `[Mesh] Failed to set remote desc for ${type2} from ${targetDaemonId.slice(0, 12)}: ${errorMessage}`);
|
|
98616
|
+
this.invalidatePeer(targetDaemonId, `P2P remote description failed: ${errorMessage}`, { rejectPending: true, closeResources: true });
|
|
97442
98617
|
}
|
|
97443
98618
|
} else if (type2 === "mesh_p2p_ice") {
|
|
97444
98619
|
try {
|
|
@@ -97494,6 +98669,9 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97494
98669
|
remoteDescriptionSet: false
|
|
97495
98670
|
};
|
|
97496
98671
|
this.peers.set(targetDaemonId, entry);
|
|
98672
|
+
this.updatePeerSnapshot(targetDaemonId, "connecting", {
|
|
98673
|
+
reason: isInitiator ? "P2P mesh connection initiated by the selected coordinator." : "Waiting for the remote daemon to finish the mesh DataChannel handshake."
|
|
98674
|
+
});
|
|
97497
98675
|
pc.onLocalDescription((sdp, type2) => {
|
|
97498
98676
|
this.serverConn.sendMeshCommand(targetDaemonId, type2 === "offer" ? "mesh_p2p_offer" : "mesh_p2p_answer", { sdp, type: type2 });
|
|
97499
98677
|
});
|
|
@@ -97504,7 +98682,26 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97504
98682
|
LOG.info("Mesh", `[Mesh] P2P state with ${targetDaemonId.slice(0, 12)}: ${state}`);
|
|
97505
98683
|
if (state === "connected") {
|
|
97506
98684
|
entry.state = "connected";
|
|
98685
|
+
let transport = "unknown";
|
|
98686
|
+
try {
|
|
98687
|
+
const pair = pc.getSelectedCandidatePair?.();
|
|
98688
|
+
if (pair) {
|
|
98689
|
+
const localType = pair.local?.type || "unknown";
|
|
98690
|
+
const remoteType = pair.remote?.type || "unknown";
|
|
98691
|
+
entry.isRelay = localType === "relay" || remoteType === "relay";
|
|
98692
|
+
transport = entry.isRelay ? "relay" : "direct";
|
|
98693
|
+
LOG.info("Mesh", `[Mesh] Candidate pair with ${targetDaemonId.slice(0, 12)}: local=${localType} remote=${remoteType} \u2192 ${transport}`);
|
|
98694
|
+
}
|
|
98695
|
+
} catch {
|
|
98696
|
+
transport = entry.isRelay === true ? "relay" : entry.isRelay === false ? "direct" : "unknown";
|
|
98697
|
+
}
|
|
98698
|
+
this.updatePeerSnapshot(targetDaemonId, "connected", {
|
|
98699
|
+
transport,
|
|
98700
|
+
reason: transport === "relay" ? "Connected over TURN relay." : transport === "direct" ? "Connected directly peer-to-peer." : "Connected, but selected candidate pair details are unavailable.",
|
|
98701
|
+
lastConnectedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
98702
|
+
});
|
|
97507
98703
|
} else if (state === "failed" || state === "closed" || state === "disconnected") {
|
|
98704
|
+
entry.state = state;
|
|
97508
98705
|
this.invalidatePeer(targetDaemonId, `P2P state changed to ${state}`, { rejectPending: true, closeResources: false });
|
|
97509
98706
|
}
|
|
97510
98707
|
});
|
|
@@ -97522,12 +98719,30 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97522
98719
|
dc.onOpen(() => {
|
|
97523
98720
|
LOG.info("Mesh", `[Mesh] DataChannel OPEN with ${targetDaemonId.slice(0, 12)}`);
|
|
97524
98721
|
entry.state = "connected";
|
|
98722
|
+
this.updatePeerSnapshot(targetDaemonId, "connected", {
|
|
98723
|
+
transport: entry.isRelay === true ? "relay" : entry.isRelay === false ? "direct" : "unknown",
|
|
98724
|
+
reason: entry.isRelay === true ? "Connected over TURN relay." : entry.isRelay === false ? "Connected directly peer-to-peer." : "DataChannel open; transport details not reported yet.",
|
|
98725
|
+
lastConnectedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
98726
|
+
});
|
|
97525
98727
|
if (entry.commandQueue) {
|
|
97526
98728
|
const queue = entry.commandQueue;
|
|
97527
98729
|
entry.commandQueue = [];
|
|
97528
98730
|
for (const item of queue) {
|
|
97529
98731
|
try {
|
|
98732
|
+
const sentAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
98733
|
+
const pending = this.pendingRequests.get(item.requestId);
|
|
98734
|
+
if (pending) pending.sentAt = sentAt;
|
|
97530
98735
|
LOG.info("Mesh", `[Mesh] Flushing queued '${item.command}' to ${targetDaemonId.slice(0, 12)}`);
|
|
98736
|
+
this.logMeshCommandEvent("sent", {
|
|
98737
|
+
requestId: item.requestId,
|
|
98738
|
+
command: item.command,
|
|
98739
|
+
targetDaemonId,
|
|
98740
|
+
queuedAt: item.queuedAt,
|
|
98741
|
+
sentAt,
|
|
98742
|
+
peerState: entry.state,
|
|
98743
|
+
transport: entry.isRelay === true ? "relay" : entry.isRelay === false ? "direct" : "unknown",
|
|
98744
|
+
flushed: true
|
|
98745
|
+
});
|
|
97531
98746
|
dc.sendMessage(JSON.stringify({
|
|
97532
98747
|
type: "mesh_command",
|
|
97533
98748
|
requestId: item.requestId,
|
|
@@ -97535,6 +98750,14 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97535
98750
|
args: item.args
|
|
97536
98751
|
}));
|
|
97537
98752
|
} catch (err) {
|
|
98753
|
+
this.logMeshCommandEvent("send_failed", {
|
|
98754
|
+
requestId: item.requestId,
|
|
98755
|
+
command: item.command,
|
|
98756
|
+
targetDaemonId,
|
|
98757
|
+
queuedAt: item.queuedAt,
|
|
98758
|
+
failedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
98759
|
+
error: err?.message || "P2P DataChannel send failed while flushing command queue"
|
|
98760
|
+
});
|
|
97538
98761
|
item.reject(this.p2pFailure(err?.message || "P2P DataChannel send failed while flushing command queue", item.command, targetDaemonId));
|
|
97539
98762
|
}
|
|
97540
98763
|
}
|
|
@@ -97549,6 +98772,12 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97549
98772
|
const str2 = typeof msg === "string" ? msg : msg.toString("utf8");
|
|
97550
98773
|
const data = JSON.parse(str2);
|
|
97551
98774
|
if (data.type === "mesh_command" && data.command) {
|
|
98775
|
+
this.logMeshCommandEvent("incoming", {
|
|
98776
|
+
requestId: data.requestId,
|
|
98777
|
+
command: data.command,
|
|
98778
|
+
senderDaemonId: targetDaemonId,
|
|
98779
|
+
receivedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
98780
|
+
});
|
|
97552
98781
|
if (this.commandCallback) {
|
|
97553
98782
|
this.commandCallback(targetDaemonId, data.command, data.args, data.requestId).catch((e) => {
|
|
97554
98783
|
LOG.warn("Mesh", `[Mesh] Error handling incoming P2P command: ${e.message}`);
|
|
@@ -97557,11 +98786,27 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97557
98786
|
} else if (data.type === "mesh_command_result" && data.requestId) {
|
|
97558
98787
|
const pending = this.pendingRequests.get(data.requestId);
|
|
97559
98788
|
if (pending) {
|
|
98789
|
+
this.logMeshCommandEvent("response_received", {
|
|
98790
|
+
requestId: data.requestId,
|
|
98791
|
+
command: pending.command,
|
|
98792
|
+
targetDaemonId: pending.targetDaemonId,
|
|
98793
|
+
queuedAt: pending.queuedAt,
|
|
98794
|
+
sentAt: pending.sentAt,
|
|
98795
|
+
receivedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
98796
|
+
success: data.success === true
|
|
98797
|
+
});
|
|
97560
98798
|
if (data.success) {
|
|
97561
98799
|
pending.resolve(data.result);
|
|
97562
98800
|
} else {
|
|
97563
98801
|
pending.reject(new Error(data.error || "P2P Command failed"));
|
|
97564
98802
|
}
|
|
98803
|
+
} else {
|
|
98804
|
+
this.logMeshCommandEvent("response_orphan", {
|
|
98805
|
+
requestId: data.requestId,
|
|
98806
|
+
targetDaemonId,
|
|
98807
|
+
receivedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
98808
|
+
success: data.success === true
|
|
98809
|
+
});
|
|
97565
98810
|
}
|
|
97566
98811
|
}
|
|
97567
98812
|
} catch (e) {
|
|
@@ -97801,6 +99046,7 @@ var init_adhdev_daemon = __esm({
|
|
|
97801
99046
|
"use strict";
|
|
97802
99047
|
init_server_connection();
|
|
97803
99048
|
init_src();
|
|
99049
|
+
init_mesh_events();
|
|
97804
99050
|
init_daemon_p2p2();
|
|
97805
99051
|
init_screenshot_controller();
|
|
97806
99052
|
init_session_host();
|
|
@@ -97817,7 +99063,7 @@ var init_adhdev_daemon = __esm({
|
|
|
97817
99063
|
init_version();
|
|
97818
99064
|
init_src();
|
|
97819
99065
|
init_runtime_defaults();
|
|
97820
|
-
pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.82-rc.
|
|
99066
|
+
pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.82-rc.41" });
|
|
97821
99067
|
AdhdevDaemon = class _AdhdevDaemon {
|
|
97822
99068
|
localHttpServer = null;
|
|
97823
99069
|
localWss = null;
|
|
@@ -98341,6 +99587,7 @@ ${err?.stack || ""}`);
|
|
|
98341
99587
|
if (!this.meshManager) throw new Error("Mesh manager not initialized");
|
|
98342
99588
|
return this.meshManager.sendCommand(daemonId, command, args);
|
|
98343
99589
|
},
|
|
99590
|
+
getMeshPeerConnectionStatus: (daemonId) => this.meshManager?.getPeerConnectionStatus(daemonId) ?? null,
|
|
98344
99591
|
onStatusChange: () => {
|
|
98345
99592
|
this.invalidateHotChatSnapshotCache();
|
|
98346
99593
|
this.statusReporter?.onStatusChange();
|
|
@@ -98710,6 +99957,7 @@ ${err?.stack || ""}`);
|
|
|
98710
99957
|
const meshId = this.readMeshString(settings.meshNodeFor);
|
|
98711
99958
|
const coordinatorDaemonId = this.readMeshString(settings.meshCoordinatorDaemonId);
|
|
98712
99959
|
if (!meshId || !coordinatorDaemonId) return;
|
|
99960
|
+
const relayTimestamp = typeof event.timestamp === "number" && Number.isFinite(event.timestamp) ? event.timestamp : this.readMeshString(event.timestamp) || void 0;
|
|
98713
99961
|
const payload = {
|
|
98714
99962
|
event: this.readMeshString(event.event),
|
|
98715
99963
|
meshId,
|
|
@@ -98718,7 +99966,8 @@ ${err?.stack || ""}`);
|
|
|
98718
99966
|
targetSessionId: this.readMeshString(event.targetSessionId) || instanceId,
|
|
98719
99967
|
providerType: this.readMeshString(event.providerType),
|
|
98720
99968
|
providerSessionId: this.readMeshString(event.providerSessionId),
|
|
98721
|
-
finalSummary: this.readMeshString(event.finalSummary) || this.readMeshString(event.summary)
|
|
99969
|
+
finalSummary: this.readMeshString(event.finalSummary) || this.readMeshString(event.summary),
|
|
99970
|
+
...relayTimestamp !== void 0 ? { timestamp: relayTimestamp } : {}
|
|
98722
99971
|
};
|
|
98723
99972
|
if (coordinatorDaemonId === localDaemonId) {
|
|
98724
99973
|
try {
|
|
@@ -98733,6 +99982,22 @@ ${err?.stack || ""}`);
|
|
|
98733
99982
|
await this.meshManager.sendCommand(coordinatorDaemonId, "mesh_forward_event", payload);
|
|
98734
99983
|
LOG.info("MeshEvents", `Relayed ${payload.event} for mesh ${meshId} to coordinator daemon ${coordinatorDaemonId.slice(0, 12)}\u2026`);
|
|
98735
99984
|
} catch (error48) {
|
|
99985
|
+
queuePendingMeshCoordinatorEvent({
|
|
99986
|
+
event: payload.event,
|
|
99987
|
+
meshId,
|
|
99988
|
+
nodeLabel: payload.nodeId ? `Node '${payload.nodeId}'` : payload.workspace ? `Agent at ${payload.workspace}` : "Remote agent",
|
|
99989
|
+
nodeId: payload.nodeId || void 0,
|
|
99990
|
+
workspace: payload.workspace || void 0,
|
|
99991
|
+
metadataEvent: {
|
|
99992
|
+
targetSessionId: payload.targetSessionId,
|
|
99993
|
+
providerType: payload.providerType,
|
|
99994
|
+
providerSessionId: payload.providerSessionId,
|
|
99995
|
+
finalSummary: payload.finalSummary,
|
|
99996
|
+
workspace: payload.workspace,
|
|
99997
|
+
...payload.timestamp !== void 0 ? { timestamp: payload.timestamp } : {}
|
|
99998
|
+
},
|
|
99999
|
+
queuedAt: Date.now()
|
|
100000
|
+
});
|
|
98736
100001
|
LOG.warn("MeshEvents", `Failed to relay ${payload.event} for mesh ${meshId}: ${error48?.message || error48}`);
|
|
98737
100002
|
}
|
|
98738
100003
|
}
|
|
@@ -99639,6 +100904,420 @@ var init_runtime_target_trace = __esm({
|
|
|
99639
100904
|
}
|
|
99640
100905
|
});
|
|
99641
100906
|
|
|
100907
|
+
// src/cli/service-commands.ts
|
|
100908
|
+
var service_commands_exports = {};
|
|
100909
|
+
__export(service_commands_exports, {
|
|
100910
|
+
buildPlist: () => buildPlist,
|
|
100911
|
+
installAutoStartServiceForCurrentProcess: () => installAutoStartServiceForCurrentProcess,
|
|
100912
|
+
isAutoStartServiceInstalled: () => isAutoStartServiceInstalled,
|
|
100913
|
+
registerServiceCommands: () => registerServiceCommands
|
|
100914
|
+
});
|
|
100915
|
+
function getDarwinPlistPath() {
|
|
100916
|
+
return import_node_path5.default.join(import_node_os4.default.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
|
|
100917
|
+
}
|
|
100918
|
+
function getWindowsStartupDir() {
|
|
100919
|
+
const appData = process.env.APPDATA || import_node_path5.default.join(import_node_os4.default.homedir(), "AppData", "Roaming");
|
|
100920
|
+
return import_node_path5.default.join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "Startup");
|
|
100921
|
+
}
|
|
100922
|
+
function getWindowsVbsPath() {
|
|
100923
|
+
return import_node_path5.default.join(getWindowsStartupDir(), "adhdev-daemon.vbs");
|
|
100924
|
+
}
|
|
100925
|
+
function resolveCliPath() {
|
|
100926
|
+
return import_node_fs4.default.realpathSync(process.argv[1]);
|
|
100927
|
+
}
|
|
100928
|
+
function ensureDir(dir) {
|
|
100929
|
+
if (!import_node_fs4.default.existsSync(dir)) import_node_fs4.default.mkdirSync(dir, { recursive: true });
|
|
100930
|
+
}
|
|
100931
|
+
async function fetchHealth() {
|
|
100932
|
+
const controller = new AbortController();
|
|
100933
|
+
const timer = setTimeout(() => controller.abort(), DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS2);
|
|
100934
|
+
try {
|
|
100935
|
+
const res = await fetch(`http://127.0.0.1:${DEFAULT_DAEMON_PORT}/health`, { signal: controller.signal });
|
|
100936
|
+
if (!res.ok) return null;
|
|
100937
|
+
return await res.json();
|
|
100938
|
+
} catch {
|
|
100939
|
+
return null;
|
|
100940
|
+
} finally {
|
|
100941
|
+
clearTimeout(timer);
|
|
100942
|
+
}
|
|
100943
|
+
}
|
|
100944
|
+
function getProcessInfo(pid) {
|
|
100945
|
+
try {
|
|
100946
|
+
if (process.platform === "win32") {
|
|
100947
|
+
const out = (0, import_node_child_process4.execSync)(`tasklist /FI "PID eq ${pid}" /FO CSV /NH`, { encoding: "utf-8" });
|
|
100948
|
+
const match = out.match(/"(\d[\d,]+)\sK"/);
|
|
100949
|
+
const memKB = match ? parseInt(match[1].replace(/,/g, ""), 10) : 0;
|
|
100950
|
+
return { uptime: "-", memMB: Math.round(memKB / 1024) };
|
|
100951
|
+
} else {
|
|
100952
|
+
const out = (0, import_node_child_process4.execSync)(`ps -o etime=,rss= -p ${pid}`, { encoding: "utf-8" }).trim();
|
|
100953
|
+
const parts = out.split(/\s+/);
|
|
100954
|
+
const etime = parts[0] || "-";
|
|
100955
|
+
const rssKB = parseInt(parts[1] || "0", 10);
|
|
100956
|
+
return { uptime: formatElapsed(etime), memMB: Math.round(rssKB / 1024) };
|
|
100957
|
+
}
|
|
100958
|
+
} catch {
|
|
100959
|
+
return null;
|
|
100960
|
+
}
|
|
100961
|
+
}
|
|
100962
|
+
function formatElapsed(etime) {
|
|
100963
|
+
const parts = etime.replace("-", ":").split(":").map(Number);
|
|
100964
|
+
if (parts.length === 4) return `${parts[0]}d ${parts[1]}h ${parts[2]}m`;
|
|
100965
|
+
if (parts.length === 3) return `${parts[0]}h ${parts[1]}m`;
|
|
100966
|
+
if (parts.length === 2) return `${parts[0]}m ${parts[1]}s`;
|
|
100967
|
+
return etime;
|
|
100968
|
+
}
|
|
100969
|
+
function rotateLogIfNeeded(logPath) {
|
|
100970
|
+
try {
|
|
100971
|
+
if (!import_node_fs4.default.existsSync(logPath)) return;
|
|
100972
|
+
const stat5 = import_node_fs4.default.statSync(logPath);
|
|
100973
|
+
if (stat5.size > MAX_LOG_SIZE2) {
|
|
100974
|
+
const rotated = logPath + ".old";
|
|
100975
|
+
if (import_node_fs4.default.existsSync(rotated)) import_node_fs4.default.unlinkSync(rotated);
|
|
100976
|
+
import_node_fs4.default.renameSync(logPath, rotated);
|
|
100977
|
+
import_node_fs4.default.writeFileSync(logPath, `[log rotated at ${(/* @__PURE__ */ new Date()).toISOString()}]
|
|
100978
|
+
`, "utf-8");
|
|
100979
|
+
}
|
|
100980
|
+
} catch {
|
|
100981
|
+
}
|
|
100982
|
+
}
|
|
100983
|
+
function rotateLogs() {
|
|
100984
|
+
rotateLogIfNeeded(LOG_OUT);
|
|
100985
|
+
rotateLogIfNeeded(LOG_ERR);
|
|
100986
|
+
}
|
|
100987
|
+
function normalizeLaunchdPathEntry(entry) {
|
|
100988
|
+
const trimmed = String(entry || "").trim();
|
|
100989
|
+
if (!trimmed) return null;
|
|
100990
|
+
if (trimmed.startsWith("~")) {
|
|
100991
|
+
return import_node_path5.default.join(import_node_os4.default.homedir(), trimmed.slice(1));
|
|
100992
|
+
}
|
|
100993
|
+
return import_node_path5.default.isAbsolute(trimmed) ? trimmed : null;
|
|
100994
|
+
}
|
|
100995
|
+
function buildLaunchdPath(nodeExe, currentPath = process.env.PATH || "") {
|
|
100996
|
+
const brewPrefix = import_node_fs4.default.existsSync("/opt/homebrew/bin") ? "/opt/homebrew/bin" : "/usr/local/bin";
|
|
100997
|
+
const entries = [];
|
|
100998
|
+
const seen = /* @__PURE__ */ new Set();
|
|
100999
|
+
const addEntry = (value) => {
|
|
101000
|
+
if (!value) return;
|
|
101001
|
+
const normalized = normalizeLaunchdPathEntry(value);
|
|
101002
|
+
if (!normalized || seen.has(normalized)) return;
|
|
101003
|
+
seen.add(normalized);
|
|
101004
|
+
entries.push(normalized);
|
|
101005
|
+
};
|
|
101006
|
+
addEntry(import_node_path5.default.dirname(nodeExe));
|
|
101007
|
+
for (const entry of String(currentPath || "").split(import_node_path5.default.delimiter)) {
|
|
101008
|
+
addEntry(entry);
|
|
101009
|
+
}
|
|
101010
|
+
for (const entry of [brewPrefix, "/usr/local/bin", "/usr/bin", "/bin", "/usr/sbin", "/sbin"]) {
|
|
101011
|
+
addEntry(entry);
|
|
101012
|
+
}
|
|
101013
|
+
return entries.join(":");
|
|
101014
|
+
}
|
|
101015
|
+
function buildPlist(nodeExe, cliExe, currentPath = process.env.PATH || "") {
|
|
101016
|
+
const pathValue = buildLaunchdPath(nodeExe, currentPath);
|
|
101017
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
101018
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
101019
|
+
<plist version="1.0">
|
|
101020
|
+
<dict>
|
|
101021
|
+
<key>Label</key>
|
|
101022
|
+
<string>${LAUNCHD_LABEL}</string>
|
|
101023
|
+
<key>ProgramArguments</key>
|
|
101024
|
+
<array>
|
|
101025
|
+
<string>${nodeExe}</string>
|
|
101026
|
+
<string>${cliExe}</string>
|
|
101027
|
+
<string>daemon</string>
|
|
101028
|
+
</array>
|
|
101029
|
+
<key>RunAtLoad</key>
|
|
101030
|
+
<true/>
|
|
101031
|
+
<key>KeepAlive</key>
|
|
101032
|
+
<dict>
|
|
101033
|
+
<key>SuccessfulExit</key>
|
|
101034
|
+
<false/>
|
|
101035
|
+
</dict>
|
|
101036
|
+
<key>ThrottleInterval</key>
|
|
101037
|
+
<integer>30</integer>
|
|
101038
|
+
<key>StandardOutPath</key>
|
|
101039
|
+
<string>${LOG_OUT}</string>
|
|
101040
|
+
<key>StandardErrorPath</key>
|
|
101041
|
+
<string>${LOG_ERR}</string>
|
|
101042
|
+
<key>EnvironmentVariables</key>
|
|
101043
|
+
<dict>
|
|
101044
|
+
<key>PATH</key>
|
|
101045
|
+
<string>${pathValue}</string>
|
|
101046
|
+
</dict>
|
|
101047
|
+
</dict>
|
|
101048
|
+
</plist>`;
|
|
101049
|
+
}
|
|
101050
|
+
function installDarwin(nodeExe, cliExe) {
|
|
101051
|
+
const plistPath = getDarwinPlistPath();
|
|
101052
|
+
ensureDir(ADHDEV_DIR);
|
|
101053
|
+
ensureDir(import_node_path5.default.dirname(plistPath));
|
|
101054
|
+
import_node_fs4.default.writeFileSync(plistPath, buildPlist(nodeExe, cliExe), "utf-8");
|
|
101055
|
+
console.log(source_default.gray(` Plist: ${plistPath}`));
|
|
101056
|
+
try {
|
|
101057
|
+
(0, import_node_child_process4.execSync)(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" });
|
|
101058
|
+
} catch {
|
|
101059
|
+
}
|
|
101060
|
+
try {
|
|
101061
|
+
(0, import_node_child_process4.execSync)(`launchctl load -w "${plistPath}"`, { stdio: "ignore" });
|
|
101062
|
+
console.log(source_default.green("\n \u2713 Registered as LaunchAgent \u2014 daemon will start on login."));
|
|
101063
|
+
console.log(source_default.gray(` Logs: ~/.adhdev/daemon-launchd.{out,err}`));
|
|
101064
|
+
} catch (e) {
|
|
101065
|
+
console.log(source_default.red(`
|
|
101066
|
+
\u2717 launchctl load failed: ${e.message}`));
|
|
101067
|
+
}
|
|
101068
|
+
}
|
|
101069
|
+
function uninstallDarwin() {
|
|
101070
|
+
const plistPath = getDarwinPlistPath();
|
|
101071
|
+
if (!import_node_fs4.default.existsSync(plistPath)) {
|
|
101072
|
+
console.log(source_default.yellow("\n \u26A0 Service is not installed."));
|
|
101073
|
+
return;
|
|
101074
|
+
}
|
|
101075
|
+
try {
|
|
101076
|
+
(0, import_node_child_process4.execSync)(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" });
|
|
101077
|
+
} catch {
|
|
101078
|
+
}
|
|
101079
|
+
import_node_fs4.default.unlinkSync(plistPath);
|
|
101080
|
+
console.log(source_default.green("\n \u2713 Removed LaunchAgent. Daemon will no longer auto-start."));
|
|
101081
|
+
}
|
|
101082
|
+
function isInstalledDarwin() {
|
|
101083
|
+
return import_node_fs4.default.existsSync(getDarwinPlistPath());
|
|
101084
|
+
}
|
|
101085
|
+
function buildVbs(nodeExe, cliExe) {
|
|
101086
|
+
const logFile = import_node_path5.default.join(ADHDEV_DIR, "daemon-service.log").replace(/\\/g, "\\\\");
|
|
101087
|
+
const escapedNodeExe = nodeExe.replace(/\\/g, "\\\\");
|
|
101088
|
+
const escapedCliExe = cliExe.replace(/\\/g, "\\\\");
|
|
101089
|
+
return `' ADHDev Daemon Auto-Start (generated by adhdev service install)
|
|
101090
|
+
Set WshShell = CreateObject("WScript.Shell")
|
|
101091
|
+
WshShell.Run "cmd.exe /c """"${escapedNodeExe}"""" """"${escapedCliExe}"""" daemon >> """"${logFile}"""" 2>&1", 0, False
|
|
101092
|
+
`;
|
|
101093
|
+
}
|
|
101094
|
+
function installWindows(nodeExe, cliExe) {
|
|
101095
|
+
const vbsPath = getWindowsVbsPath();
|
|
101096
|
+
ensureDir(ADHDEV_DIR);
|
|
101097
|
+
ensureDir(import_node_path5.default.dirname(vbsPath));
|
|
101098
|
+
import_node_fs4.default.writeFileSync(vbsPath, buildVbs(nodeExe, cliExe), "utf-8");
|
|
101099
|
+
console.log(source_default.gray(` Startup script: ${vbsPath}`));
|
|
101100
|
+
console.log(source_default.green("\n \u2713 Registered in Startup folder \u2014 daemon will start on login (hidden)."));
|
|
101101
|
+
console.log(source_default.gray(` Logs: ${import_node_path5.default.join(ADHDEV_DIR, "daemon-service.log")}`));
|
|
101102
|
+
console.log(source_default.gray(" To start now without rebooting, run: adhdev daemon"));
|
|
101103
|
+
}
|
|
101104
|
+
function uninstallWindows() {
|
|
101105
|
+
const vbsPath = getWindowsVbsPath();
|
|
101106
|
+
if (!import_node_fs4.default.existsSync(vbsPath)) {
|
|
101107
|
+
console.log(source_default.yellow("\n \u26A0 Service is not installed."));
|
|
101108
|
+
return;
|
|
101109
|
+
}
|
|
101110
|
+
import_node_fs4.default.unlinkSync(vbsPath);
|
|
101111
|
+
console.log(source_default.green("\n \u2713 Removed Startup script. Daemon will no longer auto-start."));
|
|
101112
|
+
console.log(source_default.gray(" Note: a currently running daemon is not affected. Stop with: adhdev daemon:stop"));
|
|
101113
|
+
}
|
|
101114
|
+
function isInstalledWindows() {
|
|
101115
|
+
return import_node_fs4.default.existsSync(getWindowsVbsPath());
|
|
101116
|
+
}
|
|
101117
|
+
function isAutoStartServiceInstalled(platform12 = import_node_os4.default.platform()) {
|
|
101118
|
+
if (platform12 === "darwin") return isInstalledDarwin();
|
|
101119
|
+
if (platform12 === "win32") return isInstalledWindows();
|
|
101120
|
+
return false;
|
|
101121
|
+
}
|
|
101122
|
+
function installAutoStartServiceForCurrentProcess(platform12 = import_node_os4.default.platform()) {
|
|
101123
|
+
const nodeExe = process.execPath;
|
|
101124
|
+
const cliExe = resolveCliPath();
|
|
101125
|
+
if (platform12 === "darwin") {
|
|
101126
|
+
installDarwin(nodeExe, cliExe);
|
|
101127
|
+
return true;
|
|
101128
|
+
}
|
|
101129
|
+
if (platform12 === "win32") {
|
|
101130
|
+
installWindows(nodeExe, cliExe);
|
|
101131
|
+
return true;
|
|
101132
|
+
}
|
|
101133
|
+
return false;
|
|
101134
|
+
}
|
|
101135
|
+
function registerServiceCommands(program2) {
|
|
101136
|
+
const svc = program2.command("service").description("\u{1F50C} Manage ADHDev as an OS background auto-start service");
|
|
101137
|
+
svc.command("install").description("Register ADHDev daemon to start automatically on login").action(async () => {
|
|
101138
|
+
console.log(source_default.bold("\n \u{1F680} Installing ADHDev Background Service"));
|
|
101139
|
+
const platform12 = import_node_os4.default.platform();
|
|
101140
|
+
const nodeExe = process.execPath;
|
|
101141
|
+
const cliExe = resolveCliPath();
|
|
101142
|
+
console.log(source_default.gray(` Node: ${nodeExe}`));
|
|
101143
|
+
console.log(source_default.gray(` CLI: ${cliExe}`));
|
|
101144
|
+
console.log(source_default.gray(` Platform: ${platform12}`));
|
|
101145
|
+
if (!installAutoStartServiceForCurrentProcess(platform12)) {
|
|
101146
|
+
console.log(source_default.yellow("\n \u26A0 Auto-start service install is not supported on this platform."));
|
|
101147
|
+
console.log(source_default.gray(" On Linux, create a systemd user unit manually:"));
|
|
101148
|
+
console.log(source_default.gray(" ~/.config/systemd/user/adhdev-daemon.service"));
|
|
101149
|
+
}
|
|
101150
|
+
console.log();
|
|
101151
|
+
});
|
|
101152
|
+
svc.command("uninstall").description("Remove the OS background service").action(async () => {
|
|
101153
|
+
console.log(source_default.bold("\n \u{1F5D1}\uFE0F Removing ADHDev Background Service"));
|
|
101154
|
+
const platform12 = import_node_os4.default.platform();
|
|
101155
|
+
if (platform12 === "darwin") {
|
|
101156
|
+
uninstallDarwin();
|
|
101157
|
+
} else if (platform12 === "win32") {
|
|
101158
|
+
uninstallWindows();
|
|
101159
|
+
} else {
|
|
101160
|
+
console.log(source_default.yellow("\n \u26A0 Not supported on this platform."));
|
|
101161
|
+
}
|
|
101162
|
+
console.log();
|
|
101163
|
+
});
|
|
101164
|
+
svc.command("status").description("Show service installation state and live daemon health").action(async () => {
|
|
101165
|
+
const platform12 = import_node_os4.default.platform();
|
|
101166
|
+
const installed = isAutoStartServiceInstalled(platform12);
|
|
101167
|
+
if (installed) {
|
|
101168
|
+
console.log(source_default.green("\n \u2713 Service is installed."));
|
|
101169
|
+
if (platform12 === "darwin") console.log(source_default.gray(` Plist: ${getDarwinPlistPath()}`));
|
|
101170
|
+
else console.log(source_default.gray(` Script: ${getWindowsVbsPath()}`));
|
|
101171
|
+
} else {
|
|
101172
|
+
console.log(source_default.gray("\n \u2717 Service is not installed. Run: adhdev service install"));
|
|
101173
|
+
}
|
|
101174
|
+
const health = await fetchHealth();
|
|
101175
|
+
if (health?.ok && health.pid) {
|
|
101176
|
+
const info = getProcessInfo(health.pid);
|
|
101177
|
+
if (info) {
|
|
101178
|
+
console.log(source_default.green(` \u2713 Daemon running \u2014 PID ${health.pid}, uptime ${info.uptime}, ${info.memMB} MB`));
|
|
101179
|
+
} else {
|
|
101180
|
+
console.log(source_default.green(` \u2713 Daemon running \u2014 PID ${health.pid}`));
|
|
101181
|
+
}
|
|
101182
|
+
} else {
|
|
101183
|
+
console.log(source_default.yellow(" \u2717 Daemon is not running."));
|
|
101184
|
+
}
|
|
101185
|
+
const outSize = import_node_fs4.default.existsSync(LOG_OUT) ? import_node_fs4.default.statSync(LOG_OUT).size : 0;
|
|
101186
|
+
const errSize = import_node_fs4.default.existsSync(LOG_ERR) ? import_node_fs4.default.statSync(LOG_ERR).size : 0;
|
|
101187
|
+
if (outSize > 0 || errSize > 0) {
|
|
101188
|
+
console.log(source_default.gray(` Logs: stdout ${formatBytes(outSize)}, stderr ${formatBytes(errSize)}`));
|
|
101189
|
+
}
|
|
101190
|
+
console.log();
|
|
101191
|
+
});
|
|
101192
|
+
svc.command("logs").description("View daemon service logs").option("--err", "Show stderr log instead of stdout").option("--clear", "Truncate all log files").option("-n, --lines <count>", "Number of lines to show", "30").action(async (options) => {
|
|
101193
|
+
if (options.clear) {
|
|
101194
|
+
for (const f of [LOG_OUT, LOG_ERR]) {
|
|
101195
|
+
if (import_node_fs4.default.existsSync(f)) import_node_fs4.default.writeFileSync(f, "", "utf-8");
|
|
101196
|
+
}
|
|
101197
|
+
console.log(source_default.green("\n \u2713 Logs cleared.\n"));
|
|
101198
|
+
return;
|
|
101199
|
+
}
|
|
101200
|
+
const logFile = options.err ? LOG_ERR : LOG_OUT;
|
|
101201
|
+
if (!import_node_fs4.default.existsSync(logFile)) {
|
|
101202
|
+
console.log(source_default.gray(`
|
|
101203
|
+
No log file found: ${logFile}
|
|
101204
|
+
`));
|
|
101205
|
+
return;
|
|
101206
|
+
}
|
|
101207
|
+
const lines = parseInt(options.lines, 10) || 30;
|
|
101208
|
+
console.log(source_default.gray(`
|
|
101209
|
+
\u2500\u2500 ${options.err ? "stderr" : "stdout"}: ${logFile} (last ${lines} lines) \u2500\u2500
|
|
101210
|
+
`));
|
|
101211
|
+
const content = import_node_fs4.default.readFileSync(logFile, "utf-8");
|
|
101212
|
+
const allLines = content.split("\n");
|
|
101213
|
+
const lastLines = allLines.slice(-lines).join("\n");
|
|
101214
|
+
if (lastLines.trim()) console.log(lastLines);
|
|
101215
|
+
console.log(source_default.gray("\n (watching for new output, Ctrl+C to stop)\n"));
|
|
101216
|
+
let offset = Buffer.byteLength(content, "utf-8");
|
|
101217
|
+
const watcher = import_node_fs4.default.watchFile(logFile, { interval: 500 }, () => {
|
|
101218
|
+
try {
|
|
101219
|
+
const stat5 = import_node_fs4.default.statSync(logFile);
|
|
101220
|
+
if (stat5.size > offset) {
|
|
101221
|
+
const fd = import_node_fs4.default.openSync(logFile, "r");
|
|
101222
|
+
const buf = Buffer.alloc(stat5.size - offset);
|
|
101223
|
+
import_node_fs4.default.readSync(fd, buf, 0, buf.length, offset);
|
|
101224
|
+
import_node_fs4.default.closeSync(fd);
|
|
101225
|
+
process.stdout.write(buf.toString("utf-8"));
|
|
101226
|
+
offset = stat5.size;
|
|
101227
|
+
} else if (stat5.size < offset) {
|
|
101228
|
+
offset = 0;
|
|
101229
|
+
}
|
|
101230
|
+
} catch {
|
|
101231
|
+
}
|
|
101232
|
+
});
|
|
101233
|
+
const cleanup = () => {
|
|
101234
|
+
import_node_fs4.default.unwatchFile(logFile);
|
|
101235
|
+
process.exit(0);
|
|
101236
|
+
};
|
|
101237
|
+
process.on("SIGINT", cleanup);
|
|
101238
|
+
process.on("SIGTERM", cleanup);
|
|
101239
|
+
});
|
|
101240
|
+
svc.command("restart").description("Restart the daemon process (service will auto-relaunch)").action(async () => {
|
|
101241
|
+
const platform12 = import_node_os4.default.platform();
|
|
101242
|
+
const installed = isAutoStartServiceInstalled(platform12);
|
|
101243
|
+
if (!installed) {
|
|
101244
|
+
console.log(source_default.yellow("\n \u26A0 Service is not installed. Use `adhdev daemon:restart` for manual restart."));
|
|
101245
|
+
console.log(source_default.gray(" Or install the service first: adhdev service install\n"));
|
|
101246
|
+
return;
|
|
101247
|
+
}
|
|
101248
|
+
rotateLogs();
|
|
101249
|
+
if (platform12 === "darwin") {
|
|
101250
|
+
console.log(source_default.cyan("\n Refreshing LaunchAgent definition and reloading service..."));
|
|
101251
|
+
installAutoStartServiceForCurrentProcess(platform12);
|
|
101252
|
+
console.log();
|
|
101253
|
+
return;
|
|
101254
|
+
}
|
|
101255
|
+
const health = await fetchHealth();
|
|
101256
|
+
if (!health?.pid) {
|
|
101257
|
+
console.log(source_default.yellow("\n \u26A0 Daemon is not currently running."));
|
|
101258
|
+
console.log(source_default.gray(" Start with: adhdev daemon\n"));
|
|
101259
|
+
return;
|
|
101260
|
+
}
|
|
101261
|
+
console.log(source_default.cyan(`
|
|
101262
|
+
Stopping daemon (PID ${health.pid})...`));
|
|
101263
|
+
try {
|
|
101264
|
+
process.kill(health.pid, "SIGTERM");
|
|
101265
|
+
} catch {
|
|
101266
|
+
console.log(source_default.yellow(" Could not send SIGTERM. Process may have already exited."));
|
|
101267
|
+
}
|
|
101268
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
101269
|
+
if (platform12 === "win32") {
|
|
101270
|
+
const vbsPath = getWindowsVbsPath();
|
|
101271
|
+
if (import_node_fs4.default.existsSync(vbsPath)) {
|
|
101272
|
+
try {
|
|
101273
|
+
(0, import_node_child_process4.execSync)(`wscript.exe "${vbsPath}"`, { stdio: "ignore", windowsHide: true });
|
|
101274
|
+
} catch {
|
|
101275
|
+
}
|
|
101276
|
+
}
|
|
101277
|
+
}
|
|
101278
|
+
let restarted = false;
|
|
101279
|
+
for (let i = 0; i < 8; i++) {
|
|
101280
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
101281
|
+
const newHealth = await fetchHealth();
|
|
101282
|
+
if (newHealth?.ok && newHealth.pid !== health.pid) {
|
|
101283
|
+
restarted = true;
|
|
101284
|
+
const info = getProcessInfo(newHealth.pid);
|
|
101285
|
+
console.log(source_default.green(` \u2713 Daemon restarted \u2014 new PID ${newHealth.pid}${info ? `, ${info.memMB} MB` : ""}`));
|
|
101286
|
+
break;
|
|
101287
|
+
}
|
|
101288
|
+
}
|
|
101289
|
+
if (!restarted) {
|
|
101290
|
+
console.log(source_default.yellow(" \u26A0 Daemon did not restart within 10s."));
|
|
101291
|
+
console.log(source_default.gray(" Check: adhdev service logs --err"));
|
|
101292
|
+
}
|
|
101293
|
+
console.log();
|
|
101294
|
+
});
|
|
101295
|
+
}
|
|
101296
|
+
function formatBytes(bytes) {
|
|
101297
|
+
if (bytes === 0) return "0 B";
|
|
101298
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
101299
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
101300
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
101301
|
+
}
|
|
101302
|
+
var import_node_fs4, import_node_path5, import_node_os4, import_node_child_process4, DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS2, LAUNCHD_LABEL, ADHDEV_DIR, LOG_OUT, LOG_ERR, MAX_LOG_SIZE2;
|
|
101303
|
+
var init_service_commands = __esm({
|
|
101304
|
+
"src/cli/service-commands.ts"() {
|
|
101305
|
+
"use strict";
|
|
101306
|
+
import_node_fs4 = __toESM(require("fs"));
|
|
101307
|
+
import_node_path5 = __toESM(require("path"));
|
|
101308
|
+
import_node_os4 = __toESM(require("os"));
|
|
101309
|
+
import_node_child_process4 = require("child_process");
|
|
101310
|
+
init_source();
|
|
101311
|
+
init_src();
|
|
101312
|
+
DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS2 = 1500;
|
|
101313
|
+
LAUNCHD_LABEL = "dev.adhf.daemon";
|
|
101314
|
+
ADHDEV_DIR = import_node_path5.default.join(import_node_os4.default.homedir(), ".adhdev");
|
|
101315
|
+
LOG_OUT = import_node_path5.default.join(ADHDEV_DIR, "daemon-launchd.out");
|
|
101316
|
+
LOG_ERR = import_node_path5.default.join(ADHDEV_DIR, "daemon-launchd.err");
|
|
101317
|
+
MAX_LOG_SIZE2 = 10 * 1024 * 1024;
|
|
101318
|
+
}
|
|
101319
|
+
});
|
|
101320
|
+
|
|
99642
101321
|
// ../../oss/packages/web-core/src/constants/supported.ts
|
|
99643
101322
|
var supported_exports = {};
|
|
99644
101323
|
__export(supported_exports, {
|
|
@@ -101612,7 +103291,7 @@ function formatDebugTraceEntryLine(entry) {
|
|
|
101612
103291
|
}
|
|
101613
103292
|
|
|
101614
103293
|
// src/cli/daemon-commands.ts
|
|
101615
|
-
var
|
|
103294
|
+
var DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS3 = 1500;
|
|
101616
103295
|
var DEFAULT_TRACE_FOLLOW_INTERVAL_MS = 1500;
|
|
101617
103296
|
var DEFAULT_DAEMON_PORT_TEXT = String(DEFAULT_DAEMON_PORT);
|
|
101618
103297
|
var DEV_SERVER_PORT2 = 19280;
|
|
@@ -101640,6 +103319,15 @@ async function resolveConfiguredUpdateChannel() {
|
|
|
101640
103319
|
function releaseChannelLabel(channel) {
|
|
101641
103320
|
return `${channel} (${CHANNEL_NPM_TAG3[channel]})`;
|
|
101642
103321
|
}
|
|
103322
|
+
function buildDaemonRestartCommandArgv(options = {}) {
|
|
103323
|
+
const cliPath = options.cliPath || process.argv[1];
|
|
103324
|
+
const daemonPort = options.daemonPort || DEFAULT_DAEMON_PORT_TEXT;
|
|
103325
|
+
const platform12 = options.platform || process.platform;
|
|
103326
|
+
if (platform12 === "darwin" && options.serviceInstalled) {
|
|
103327
|
+
return [cliPath, "service", "install"];
|
|
103328
|
+
}
|
|
103329
|
+
return [cliPath, "daemon", "-p", daemonPort];
|
|
103330
|
+
}
|
|
101643
103331
|
async function persistReleaseChannel(channel) {
|
|
101644
103332
|
const { updateConfig: updateConfig2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
101645
103333
|
updateConfig2({ updateChannel: channel, serverUrl: CHANNEL_SERVER_URL3[channel] });
|
|
@@ -101650,7 +103338,7 @@ function hideCommand(command) {
|
|
|
101650
103338
|
}
|
|
101651
103339
|
async function fetchLocalDaemonHealth(port) {
|
|
101652
103340
|
const controller = new AbortController();
|
|
101653
|
-
const timer = setTimeout(() => controller.abort(),
|
|
103341
|
+
const timer = setTimeout(() => controller.abort(), DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS3);
|
|
101654
103342
|
try {
|
|
101655
103343
|
const res = await fetch(`http://127.0.0.1:${port}/health`, { signal: controller.signal });
|
|
101656
103344
|
if (!res.ok) return null;
|
|
@@ -102016,6 +103704,9 @@ async function runDaemonUpgrade(options, pkgVersion3) {
|
|
|
102016
103704
|
} else {
|
|
102017
103705
|
console.log(source_default.cyan(`
|
|
102018
103706
|
Upgrading v${currentVersion} \u2192 v${latest}...`));
|
|
103707
|
+
const { isAutoStartServiceInstalled: isAutoStartServiceInstalled2 } = await Promise.resolve().then(() => (init_service_commands(), service_commands_exports));
|
|
103708
|
+
const serviceInstalled = isAutoStartServiceInstalled2();
|
|
103709
|
+
const shouldRefreshInstalledService = options.restart !== false && process.platform === "darwin" && serviceInstalled;
|
|
102019
103710
|
const daemonWasRunning = options.restart !== false && isDaemonRunning2();
|
|
102020
103711
|
if (daemonWasRunning) {
|
|
102021
103712
|
stopDaemon2();
|
|
@@ -102027,10 +103718,22 @@ async function runDaemonUpgrade(options, pkgVersion3) {
|
|
|
102027
103718
|
packageName: "adhdev",
|
|
102028
103719
|
targetVersion: latest,
|
|
102029
103720
|
parentPid: process.pid,
|
|
102030
|
-
restartArgv:
|
|
103721
|
+
restartArgv: shouldRefreshInstalledService ? buildDaemonRestartCommandArgv({
|
|
103722
|
+
cliPath: process.argv[1],
|
|
103723
|
+
daemonPort: DEFAULT_DAEMON_PORT_TEXT,
|
|
103724
|
+
platform: process.platform,
|
|
103725
|
+
serviceInstalled
|
|
103726
|
+
}) : daemonWasRunning ? buildDaemonRestartCommandArgv({
|
|
103727
|
+
cliPath: process.argv[1],
|
|
103728
|
+
daemonPort: DEFAULT_DAEMON_PORT_TEXT,
|
|
103729
|
+
platform: process.platform,
|
|
103730
|
+
serviceInstalled
|
|
103731
|
+
}) : [],
|
|
102031
103732
|
cwd: process.cwd()
|
|
102032
103733
|
});
|
|
102033
|
-
if (
|
|
103734
|
+
if (shouldRefreshInstalledService) {
|
|
103735
|
+
console.log(source_default.cyan(" Upgrading and refreshing background service in background..."));
|
|
103736
|
+
} else if (daemonWasRunning) {
|
|
102034
103737
|
console.log(source_default.cyan(" Upgrading and restarting daemon in background..."));
|
|
102035
103738
|
} else {
|
|
102036
103739
|
console.log(source_default.cyan(" Upgrading in background..."));
|
|
@@ -102042,29 +103745,44 @@ async function runDaemonUpgrade(options, pkgVersion3) {
|
|
|
102042
103745
|
return;
|
|
102043
103746
|
}
|
|
102044
103747
|
}
|
|
102045
|
-
if (options.restart !== false
|
|
102046
|
-
|
|
102047
|
-
|
|
102048
|
-
|
|
102049
|
-
|
|
102050
|
-
|
|
102051
|
-
|
|
102052
|
-
|
|
102053
|
-
|
|
102054
|
-
windowsHide: true,
|
|
102055
|
-
env: { ...process.env }
|
|
102056
|
-
});
|
|
102057
|
-
child.unref();
|
|
102058
|
-
await new Promise((r) => setTimeout(r, 3e3));
|
|
103748
|
+
if (options.restart !== false) {
|
|
103749
|
+
const { installAutoStartServiceForCurrentProcess: installAutoStartServiceForCurrentProcess2, isAutoStartServiceInstalled: isAutoStartServiceInstalled2 } = await Promise.resolve().then(() => (init_service_commands(), service_commands_exports));
|
|
103750
|
+
const serviceInstalled = isAutoStartServiceInstalled2();
|
|
103751
|
+
if (process.platform === "darwin" && serviceInstalled) {
|
|
103752
|
+
console.log(source_default.yellow("\n Refreshing LaunchAgent definition..."));
|
|
103753
|
+
installAutoStartServiceForCurrentProcess2(process.platform);
|
|
103754
|
+
console.log();
|
|
103755
|
+
return;
|
|
103756
|
+
}
|
|
102059
103757
|
if (isDaemonRunning2()) {
|
|
102060
|
-
console.log(source_default.
|
|
103758
|
+
console.log(source_default.yellow("\n Restarting daemon..."));
|
|
103759
|
+
stopDaemon2();
|
|
103760
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
103761
|
+
stopManagedSessionHostProcess2();
|
|
103762
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
103763
|
+
const child = spawn7(process.execPath, buildDaemonRestartCommandArgv({
|
|
103764
|
+
cliPath: process.argv[1],
|
|
103765
|
+
daemonPort: DEFAULT_DAEMON_PORT_TEXT,
|
|
103766
|
+
platform: process.platform,
|
|
103767
|
+
serviceInstalled
|
|
103768
|
+
}), {
|
|
103769
|
+
detached: true,
|
|
103770
|
+
stdio: "ignore",
|
|
103771
|
+
windowsHide: true,
|
|
103772
|
+
env: { ...process.env }
|
|
103773
|
+
});
|
|
103774
|
+
child.unref();
|
|
103775
|
+
await new Promise((r) => setTimeout(r, 3e3));
|
|
103776
|
+
if (isDaemonRunning2()) {
|
|
103777
|
+
console.log(source_default.green(` \u2713 Daemon restarted with new version
|
|
102061
103778
|
`));
|
|
102062
|
-
|
|
102063
|
-
|
|
103779
|
+
} else {
|
|
103780
|
+
console.log(source_default.yellow(` \u26A0 Daemon not detected. Start manually: adhdev daemon
|
|
102064
103781
|
`));
|
|
103782
|
+
}
|
|
103783
|
+
} else {
|
|
103784
|
+
console.log(source_default.gray("\n Daemon was not running. Start with: adhdev daemon\n"));
|
|
102065
103785
|
}
|
|
102066
|
-
} else if (options.restart !== false) {
|
|
102067
|
-
console.log(source_default.gray("\n Daemon was not running. Start with: adhdev daemon\n"));
|
|
102068
103786
|
} else {
|
|
102069
103787
|
console.log(source_default.green("\n \u2713 Upgrade complete (daemon not restarted)\n"));
|
|
102070
103788
|
}
|
|
@@ -102235,7 +103953,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
|
|
|
102235
103953
|
}
|
|
102236
103954
|
try {
|
|
102237
103955
|
const controller = new AbortController();
|
|
102238
|
-
const timer = setTimeout(() => controller.abort(),
|
|
103956
|
+
const timer = setTimeout(() => controller.abort(), DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS3);
|
|
102239
103957
|
const res = await fetch(`${DEV_SERVER_BASE_URL}/api/status`, { signal: controller.signal });
|
|
102240
103958
|
clearTimeout(timer);
|
|
102241
103959
|
if (res.ok) {
|
|
@@ -102782,373 +104500,8 @@ function buildDoctorAdvice(input) {
|
|
|
102782
104500
|
return advice;
|
|
102783
104501
|
}
|
|
102784
104502
|
|
|
102785
|
-
// src/cli/service-commands.ts
|
|
102786
|
-
var import_node_fs4 = __toESM(require("fs"));
|
|
102787
|
-
var import_node_path5 = __toESM(require("path"));
|
|
102788
|
-
var import_node_os4 = __toESM(require("os"));
|
|
102789
|
-
var import_node_child_process4 = require("child_process");
|
|
102790
|
-
init_source();
|
|
102791
|
-
init_src();
|
|
102792
|
-
var DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS3 = 1500;
|
|
102793
|
-
var LAUNCHD_LABEL = "dev.adhf.daemon";
|
|
102794
|
-
var ADHDEV_DIR = import_node_path5.default.join(import_node_os4.default.homedir(), ".adhdev");
|
|
102795
|
-
var LOG_OUT = import_node_path5.default.join(ADHDEV_DIR, "daemon-launchd.out");
|
|
102796
|
-
var LOG_ERR = import_node_path5.default.join(ADHDEV_DIR, "daemon-launchd.err");
|
|
102797
|
-
var MAX_LOG_SIZE2 = 10 * 1024 * 1024;
|
|
102798
|
-
function getDarwinPlistPath() {
|
|
102799
|
-
return import_node_path5.default.join(import_node_os4.default.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
|
|
102800
|
-
}
|
|
102801
|
-
function getWindowsStartupDir() {
|
|
102802
|
-
const appData = process.env.APPDATA || import_node_path5.default.join(import_node_os4.default.homedir(), "AppData", "Roaming");
|
|
102803
|
-
return import_node_path5.default.join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "Startup");
|
|
102804
|
-
}
|
|
102805
|
-
function getWindowsVbsPath() {
|
|
102806
|
-
return import_node_path5.default.join(getWindowsStartupDir(), "adhdev-daemon.vbs");
|
|
102807
|
-
}
|
|
102808
|
-
function resolveCliPath() {
|
|
102809
|
-
return import_node_fs4.default.realpathSync(process.argv[1]);
|
|
102810
|
-
}
|
|
102811
|
-
function ensureDir(dir) {
|
|
102812
|
-
if (!import_node_fs4.default.existsSync(dir)) import_node_fs4.default.mkdirSync(dir, { recursive: true });
|
|
102813
|
-
}
|
|
102814
|
-
async function fetchHealth() {
|
|
102815
|
-
const controller = new AbortController();
|
|
102816
|
-
const timer = setTimeout(() => controller.abort(), DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS3);
|
|
102817
|
-
try {
|
|
102818
|
-
const res = await fetch(`http://127.0.0.1:${DEFAULT_DAEMON_PORT}/health`, { signal: controller.signal });
|
|
102819
|
-
if (!res.ok) return null;
|
|
102820
|
-
return await res.json();
|
|
102821
|
-
} catch {
|
|
102822
|
-
return null;
|
|
102823
|
-
} finally {
|
|
102824
|
-
clearTimeout(timer);
|
|
102825
|
-
}
|
|
102826
|
-
}
|
|
102827
|
-
function getProcessInfo(pid) {
|
|
102828
|
-
try {
|
|
102829
|
-
if (process.platform === "win32") {
|
|
102830
|
-
const out = (0, import_node_child_process4.execSync)(`tasklist /FI "PID eq ${pid}" /FO CSV /NH`, { encoding: "utf-8" });
|
|
102831
|
-
const match = out.match(/"(\d[\d,]+)\sK"/);
|
|
102832
|
-
const memKB = match ? parseInt(match[1].replace(/,/g, ""), 10) : 0;
|
|
102833
|
-
return { uptime: "-", memMB: Math.round(memKB / 1024) };
|
|
102834
|
-
} else {
|
|
102835
|
-
const out = (0, import_node_child_process4.execSync)(`ps -o etime=,rss= -p ${pid}`, { encoding: "utf-8" }).trim();
|
|
102836
|
-
const parts = out.split(/\s+/);
|
|
102837
|
-
const etime = parts[0] || "-";
|
|
102838
|
-
const rssKB = parseInt(parts[1] || "0", 10);
|
|
102839
|
-
return { uptime: formatElapsed(etime), memMB: Math.round(rssKB / 1024) };
|
|
102840
|
-
}
|
|
102841
|
-
} catch {
|
|
102842
|
-
return null;
|
|
102843
|
-
}
|
|
102844
|
-
}
|
|
102845
|
-
function formatElapsed(etime) {
|
|
102846
|
-
const parts = etime.replace("-", ":").split(":").map(Number);
|
|
102847
|
-
if (parts.length === 4) return `${parts[0]}d ${parts[1]}h ${parts[2]}m`;
|
|
102848
|
-
if (parts.length === 3) return `${parts[0]}h ${parts[1]}m`;
|
|
102849
|
-
if (parts.length === 2) return `${parts[0]}m ${parts[1]}s`;
|
|
102850
|
-
return etime;
|
|
102851
|
-
}
|
|
102852
|
-
function rotateLogIfNeeded(logPath) {
|
|
102853
|
-
try {
|
|
102854
|
-
if (!import_node_fs4.default.existsSync(logPath)) return;
|
|
102855
|
-
const stat5 = import_node_fs4.default.statSync(logPath);
|
|
102856
|
-
if (stat5.size > MAX_LOG_SIZE2) {
|
|
102857
|
-
const rotated = logPath + ".old";
|
|
102858
|
-
if (import_node_fs4.default.existsSync(rotated)) import_node_fs4.default.unlinkSync(rotated);
|
|
102859
|
-
import_node_fs4.default.renameSync(logPath, rotated);
|
|
102860
|
-
import_node_fs4.default.writeFileSync(logPath, `[log rotated at ${(/* @__PURE__ */ new Date()).toISOString()}]
|
|
102861
|
-
`, "utf-8");
|
|
102862
|
-
}
|
|
102863
|
-
} catch {
|
|
102864
|
-
}
|
|
102865
|
-
}
|
|
102866
|
-
function rotateLogs() {
|
|
102867
|
-
rotateLogIfNeeded(LOG_OUT);
|
|
102868
|
-
rotateLogIfNeeded(LOG_ERR);
|
|
102869
|
-
}
|
|
102870
|
-
function buildPlist(nodeExe, cliExe) {
|
|
102871
|
-
const brewPrefix = import_node_fs4.default.existsSync("/opt/homebrew/bin") ? "/opt/homebrew/bin" : "/usr/local/bin";
|
|
102872
|
-
const nodeDir = import_node_path5.default.dirname(nodeExe);
|
|
102873
|
-
const pathEntries = /* @__PURE__ */ new Set([nodeDir, brewPrefix, "/usr/local/bin", "/usr/bin", "/bin", "/usr/sbin", "/sbin"]);
|
|
102874
|
-
const pathValue = Array.from(pathEntries).join(":");
|
|
102875
|
-
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
102876
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
102877
|
-
<plist version="1.0">
|
|
102878
|
-
<dict>
|
|
102879
|
-
<key>Label</key>
|
|
102880
|
-
<string>${LAUNCHD_LABEL}</string>
|
|
102881
|
-
<key>ProgramArguments</key>
|
|
102882
|
-
<array>
|
|
102883
|
-
<string>${nodeExe}</string>
|
|
102884
|
-
<string>${cliExe}</string>
|
|
102885
|
-
<string>daemon</string>
|
|
102886
|
-
</array>
|
|
102887
|
-
<key>RunAtLoad</key>
|
|
102888
|
-
<true/>
|
|
102889
|
-
<key>KeepAlive</key>
|
|
102890
|
-
<dict>
|
|
102891
|
-
<key>SuccessfulExit</key>
|
|
102892
|
-
<false/>
|
|
102893
|
-
</dict>
|
|
102894
|
-
<key>ThrottleInterval</key>
|
|
102895
|
-
<integer>30</integer>
|
|
102896
|
-
<key>StandardOutPath</key>
|
|
102897
|
-
<string>${LOG_OUT}</string>
|
|
102898
|
-
<key>StandardErrorPath</key>
|
|
102899
|
-
<string>${LOG_ERR}</string>
|
|
102900
|
-
<key>EnvironmentVariables</key>
|
|
102901
|
-
<dict>
|
|
102902
|
-
<key>PATH</key>
|
|
102903
|
-
<string>${pathValue}</string>
|
|
102904
|
-
</dict>
|
|
102905
|
-
</dict>
|
|
102906
|
-
</plist>`;
|
|
102907
|
-
}
|
|
102908
|
-
function installDarwin(nodeExe, cliExe) {
|
|
102909
|
-
const plistPath = getDarwinPlistPath();
|
|
102910
|
-
ensureDir(ADHDEV_DIR);
|
|
102911
|
-
ensureDir(import_node_path5.default.dirname(plistPath));
|
|
102912
|
-
import_node_fs4.default.writeFileSync(plistPath, buildPlist(nodeExe, cliExe), "utf-8");
|
|
102913
|
-
console.log(source_default.gray(` Plist: ${plistPath}`));
|
|
102914
|
-
try {
|
|
102915
|
-
(0, import_node_child_process4.execSync)(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" });
|
|
102916
|
-
} catch {
|
|
102917
|
-
}
|
|
102918
|
-
try {
|
|
102919
|
-
(0, import_node_child_process4.execSync)(`launchctl load -w "${plistPath}"`, { stdio: "ignore" });
|
|
102920
|
-
console.log(source_default.green("\n \u2713 Registered as LaunchAgent \u2014 daemon will start on login."));
|
|
102921
|
-
console.log(source_default.gray(` Logs: ~/.adhdev/daemon-launchd.{out,err}`));
|
|
102922
|
-
} catch (e) {
|
|
102923
|
-
console.log(source_default.red(`
|
|
102924
|
-
\u2717 launchctl load failed: ${e.message}`));
|
|
102925
|
-
}
|
|
102926
|
-
}
|
|
102927
|
-
function uninstallDarwin() {
|
|
102928
|
-
const plistPath = getDarwinPlistPath();
|
|
102929
|
-
if (!import_node_fs4.default.existsSync(plistPath)) {
|
|
102930
|
-
console.log(source_default.yellow("\n \u26A0 Service is not installed."));
|
|
102931
|
-
return;
|
|
102932
|
-
}
|
|
102933
|
-
try {
|
|
102934
|
-
(0, import_node_child_process4.execSync)(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" });
|
|
102935
|
-
} catch {
|
|
102936
|
-
}
|
|
102937
|
-
import_node_fs4.default.unlinkSync(plistPath);
|
|
102938
|
-
console.log(source_default.green("\n \u2713 Removed LaunchAgent. Daemon will no longer auto-start."));
|
|
102939
|
-
}
|
|
102940
|
-
function isInstalledDarwin() {
|
|
102941
|
-
return import_node_fs4.default.existsSync(getDarwinPlistPath());
|
|
102942
|
-
}
|
|
102943
|
-
function buildVbs(nodeExe, cliExe) {
|
|
102944
|
-
const logFile = import_node_path5.default.join(ADHDEV_DIR, "daemon-service.log").replace(/\\/g, "\\\\");
|
|
102945
|
-
const escapedNodeExe = nodeExe.replace(/\\/g, "\\\\");
|
|
102946
|
-
const escapedCliExe = cliExe.replace(/\\/g, "\\\\");
|
|
102947
|
-
return `' ADHDev Daemon Auto-Start (generated by adhdev service install)
|
|
102948
|
-
Set WshShell = CreateObject("WScript.Shell")
|
|
102949
|
-
WshShell.Run "cmd.exe /c """"${escapedNodeExe}"""" """"${escapedCliExe}"""" daemon >> """"${logFile}"""" 2>&1", 0, False
|
|
102950
|
-
`;
|
|
102951
|
-
}
|
|
102952
|
-
function installWindows(nodeExe, cliExe) {
|
|
102953
|
-
const vbsPath = getWindowsVbsPath();
|
|
102954
|
-
ensureDir(ADHDEV_DIR);
|
|
102955
|
-
ensureDir(import_node_path5.default.dirname(vbsPath));
|
|
102956
|
-
import_node_fs4.default.writeFileSync(vbsPath, buildVbs(nodeExe, cliExe), "utf-8");
|
|
102957
|
-
console.log(source_default.gray(` Startup script: ${vbsPath}`));
|
|
102958
|
-
console.log(source_default.green("\n \u2713 Registered in Startup folder \u2014 daemon will start on login (hidden)."));
|
|
102959
|
-
console.log(source_default.gray(` Logs: ${import_node_path5.default.join(ADHDEV_DIR, "daemon-service.log")}`));
|
|
102960
|
-
console.log(source_default.gray(" To start now without rebooting, run: adhdev daemon"));
|
|
102961
|
-
}
|
|
102962
|
-
function uninstallWindows() {
|
|
102963
|
-
const vbsPath = getWindowsVbsPath();
|
|
102964
|
-
if (!import_node_fs4.default.existsSync(vbsPath)) {
|
|
102965
|
-
console.log(source_default.yellow("\n \u26A0 Service is not installed."));
|
|
102966
|
-
return;
|
|
102967
|
-
}
|
|
102968
|
-
import_node_fs4.default.unlinkSync(vbsPath);
|
|
102969
|
-
console.log(source_default.green("\n \u2713 Removed Startup script. Daemon will no longer auto-start."));
|
|
102970
|
-
console.log(source_default.gray(" Note: a currently running daemon is not affected. Stop with: adhdev daemon:stop"));
|
|
102971
|
-
}
|
|
102972
|
-
function isInstalledWindows() {
|
|
102973
|
-
return import_node_fs4.default.existsSync(getWindowsVbsPath());
|
|
102974
|
-
}
|
|
102975
|
-
function registerServiceCommands(program2) {
|
|
102976
|
-
const svc = program2.command("service").description("\u{1F50C} Manage ADHDev as an OS background auto-start service");
|
|
102977
|
-
svc.command("install").description("Register ADHDev daemon to start automatically on login").action(async () => {
|
|
102978
|
-
console.log(source_default.bold("\n \u{1F680} Installing ADHDev Background Service"));
|
|
102979
|
-
const platform12 = import_node_os4.default.platform();
|
|
102980
|
-
const nodeExe = process.execPath;
|
|
102981
|
-
const cliExe = resolveCliPath();
|
|
102982
|
-
console.log(source_default.gray(` Node: ${nodeExe}`));
|
|
102983
|
-
console.log(source_default.gray(` CLI: ${cliExe}`));
|
|
102984
|
-
console.log(source_default.gray(` Platform: ${platform12}`));
|
|
102985
|
-
if (platform12 === "darwin") {
|
|
102986
|
-
installDarwin(nodeExe, cliExe);
|
|
102987
|
-
} else if (platform12 === "win32") {
|
|
102988
|
-
installWindows(nodeExe, cliExe);
|
|
102989
|
-
} else {
|
|
102990
|
-
console.log(source_default.yellow("\n \u26A0 Auto-start service install is not supported on this platform."));
|
|
102991
|
-
console.log(source_default.gray(" On Linux, create a systemd user unit manually:"));
|
|
102992
|
-
console.log(source_default.gray(" ~/.config/systemd/user/adhdev-daemon.service"));
|
|
102993
|
-
}
|
|
102994
|
-
console.log();
|
|
102995
|
-
});
|
|
102996
|
-
svc.command("uninstall").description("Remove the OS background service").action(async () => {
|
|
102997
|
-
console.log(source_default.bold("\n \u{1F5D1}\uFE0F Removing ADHDev Background Service"));
|
|
102998
|
-
const platform12 = import_node_os4.default.platform();
|
|
102999
|
-
if (platform12 === "darwin") {
|
|
103000
|
-
uninstallDarwin();
|
|
103001
|
-
} else if (platform12 === "win32") {
|
|
103002
|
-
uninstallWindows();
|
|
103003
|
-
} else {
|
|
103004
|
-
console.log(source_default.yellow("\n \u26A0 Not supported on this platform."));
|
|
103005
|
-
}
|
|
103006
|
-
console.log();
|
|
103007
|
-
});
|
|
103008
|
-
svc.command("status").description("Show service installation state and live daemon health").action(async () => {
|
|
103009
|
-
const platform12 = import_node_os4.default.platform();
|
|
103010
|
-
const installed = platform12 === "darwin" ? isInstalledDarwin() : platform12 === "win32" ? isInstalledWindows() : false;
|
|
103011
|
-
if (installed) {
|
|
103012
|
-
console.log(source_default.green("\n \u2713 Service is installed."));
|
|
103013
|
-
if (platform12 === "darwin") console.log(source_default.gray(` Plist: ${getDarwinPlistPath()}`));
|
|
103014
|
-
else console.log(source_default.gray(` Script: ${getWindowsVbsPath()}`));
|
|
103015
|
-
} else {
|
|
103016
|
-
console.log(source_default.gray("\n \u2717 Service is not installed. Run: adhdev service install"));
|
|
103017
|
-
}
|
|
103018
|
-
const health = await fetchHealth();
|
|
103019
|
-
if (health?.ok && health.pid) {
|
|
103020
|
-
const info = getProcessInfo(health.pid);
|
|
103021
|
-
if (info) {
|
|
103022
|
-
console.log(source_default.green(` \u2713 Daemon running \u2014 PID ${health.pid}, uptime ${info.uptime}, ${info.memMB} MB`));
|
|
103023
|
-
} else {
|
|
103024
|
-
console.log(source_default.green(` \u2713 Daemon running \u2014 PID ${health.pid}`));
|
|
103025
|
-
}
|
|
103026
|
-
} else {
|
|
103027
|
-
console.log(source_default.yellow(" \u2717 Daemon is not running."));
|
|
103028
|
-
}
|
|
103029
|
-
const outSize = import_node_fs4.default.existsSync(LOG_OUT) ? import_node_fs4.default.statSync(LOG_OUT).size : 0;
|
|
103030
|
-
const errSize = import_node_fs4.default.existsSync(LOG_ERR) ? import_node_fs4.default.statSync(LOG_ERR).size : 0;
|
|
103031
|
-
if (outSize > 0 || errSize > 0) {
|
|
103032
|
-
console.log(source_default.gray(` Logs: stdout ${formatBytes(outSize)}, stderr ${formatBytes(errSize)}`));
|
|
103033
|
-
}
|
|
103034
|
-
console.log();
|
|
103035
|
-
});
|
|
103036
|
-
svc.command("logs").description("View daemon service logs").option("--err", "Show stderr log instead of stdout").option("--clear", "Truncate all log files").option("-n, --lines <count>", "Number of lines to show", "30").action(async (options) => {
|
|
103037
|
-
if (options.clear) {
|
|
103038
|
-
for (const f of [LOG_OUT, LOG_ERR]) {
|
|
103039
|
-
if (import_node_fs4.default.existsSync(f)) import_node_fs4.default.writeFileSync(f, "", "utf-8");
|
|
103040
|
-
}
|
|
103041
|
-
console.log(source_default.green("\n \u2713 Logs cleared.\n"));
|
|
103042
|
-
return;
|
|
103043
|
-
}
|
|
103044
|
-
const logFile = options.err ? LOG_ERR : LOG_OUT;
|
|
103045
|
-
if (!import_node_fs4.default.existsSync(logFile)) {
|
|
103046
|
-
console.log(source_default.gray(`
|
|
103047
|
-
No log file found: ${logFile}
|
|
103048
|
-
`));
|
|
103049
|
-
return;
|
|
103050
|
-
}
|
|
103051
|
-
const lines = parseInt(options.lines, 10) || 30;
|
|
103052
|
-
console.log(source_default.gray(`
|
|
103053
|
-
\u2500\u2500 ${options.err ? "stderr" : "stdout"}: ${logFile} (last ${lines} lines) \u2500\u2500
|
|
103054
|
-
`));
|
|
103055
|
-
const content = import_node_fs4.default.readFileSync(logFile, "utf-8");
|
|
103056
|
-
const allLines = content.split("\n");
|
|
103057
|
-
const lastLines = allLines.slice(-lines).join("\n");
|
|
103058
|
-
if (lastLines.trim()) console.log(lastLines);
|
|
103059
|
-
console.log(source_default.gray("\n (watching for new output, Ctrl+C to stop)\n"));
|
|
103060
|
-
let offset = Buffer.byteLength(content, "utf-8");
|
|
103061
|
-
const watcher = import_node_fs4.default.watchFile(logFile, { interval: 500 }, () => {
|
|
103062
|
-
try {
|
|
103063
|
-
const stat5 = import_node_fs4.default.statSync(logFile);
|
|
103064
|
-
if (stat5.size > offset) {
|
|
103065
|
-
const fd = import_node_fs4.default.openSync(logFile, "r");
|
|
103066
|
-
const buf = Buffer.alloc(stat5.size - offset);
|
|
103067
|
-
import_node_fs4.default.readSync(fd, buf, 0, buf.length, offset);
|
|
103068
|
-
import_node_fs4.default.closeSync(fd);
|
|
103069
|
-
process.stdout.write(buf.toString("utf-8"));
|
|
103070
|
-
offset = stat5.size;
|
|
103071
|
-
} else if (stat5.size < offset) {
|
|
103072
|
-
offset = 0;
|
|
103073
|
-
}
|
|
103074
|
-
} catch {
|
|
103075
|
-
}
|
|
103076
|
-
});
|
|
103077
|
-
const cleanup = () => {
|
|
103078
|
-
import_node_fs4.default.unwatchFile(logFile);
|
|
103079
|
-
process.exit(0);
|
|
103080
|
-
};
|
|
103081
|
-
process.on("SIGINT", cleanup);
|
|
103082
|
-
process.on("SIGTERM", cleanup);
|
|
103083
|
-
});
|
|
103084
|
-
svc.command("restart").description("Restart the daemon process (service will auto-relaunch)").action(async () => {
|
|
103085
|
-
const platform12 = import_node_os4.default.platform();
|
|
103086
|
-
const installed = platform12 === "darwin" ? isInstalledDarwin() : platform12 === "win32" ? isInstalledWindows() : false;
|
|
103087
|
-
if (!installed) {
|
|
103088
|
-
console.log(source_default.yellow("\n \u26A0 Service is not installed. Use `adhdev daemon:restart` for manual restart."));
|
|
103089
|
-
console.log(source_default.gray(" Or install the service first: adhdev service install\n"));
|
|
103090
|
-
return;
|
|
103091
|
-
}
|
|
103092
|
-
rotateLogs();
|
|
103093
|
-
const health = await fetchHealth();
|
|
103094
|
-
if (!health?.pid) {
|
|
103095
|
-
console.log(source_default.yellow("\n \u26A0 Daemon is not currently running."));
|
|
103096
|
-
if (platform12 === "darwin") {
|
|
103097
|
-
console.log(source_default.gray(" Starting via launchctl..."));
|
|
103098
|
-
try {
|
|
103099
|
-
(0, import_node_child_process4.execSync)(`launchctl start ${LAUNCHD_LABEL}`, { stdio: "ignore" });
|
|
103100
|
-
console.log(source_default.green(" \u2713 Started.\n"));
|
|
103101
|
-
} catch {
|
|
103102
|
-
console.log(source_default.red(" \u2717 Failed to start. Check: adhdev service logs --err\n"));
|
|
103103
|
-
}
|
|
103104
|
-
} else {
|
|
103105
|
-
console.log(source_default.gray(" Start with: adhdev daemon\n"));
|
|
103106
|
-
}
|
|
103107
|
-
return;
|
|
103108
|
-
}
|
|
103109
|
-
console.log(source_default.cyan(`
|
|
103110
|
-
Stopping daemon (PID ${health.pid})...`));
|
|
103111
|
-
try {
|
|
103112
|
-
process.kill(health.pid, "SIGTERM");
|
|
103113
|
-
} catch {
|
|
103114
|
-
console.log(source_default.yellow(" Could not send SIGTERM. Process may have already exited."));
|
|
103115
|
-
}
|
|
103116
|
-
await new Promise((r) => setTimeout(r, 2e3));
|
|
103117
|
-
if (platform12 === "win32") {
|
|
103118
|
-
const vbsPath = getWindowsVbsPath();
|
|
103119
|
-
if (import_node_fs4.default.existsSync(vbsPath)) {
|
|
103120
|
-
try {
|
|
103121
|
-
(0, import_node_child_process4.execSync)(`wscript.exe "${vbsPath}"`, { stdio: "ignore", windowsHide: true });
|
|
103122
|
-
} catch {
|
|
103123
|
-
}
|
|
103124
|
-
}
|
|
103125
|
-
}
|
|
103126
|
-
let restarted = false;
|
|
103127
|
-
for (let i = 0; i < 8; i++) {
|
|
103128
|
-
await new Promise((r) => setTimeout(r, 1e3));
|
|
103129
|
-
const newHealth = await fetchHealth();
|
|
103130
|
-
if (newHealth?.ok && newHealth.pid !== health.pid) {
|
|
103131
|
-
restarted = true;
|
|
103132
|
-
const info = getProcessInfo(newHealth.pid);
|
|
103133
|
-
console.log(source_default.green(` \u2713 Daemon restarted \u2014 new PID ${newHealth.pid}${info ? `, ${info.memMB} MB` : ""}`));
|
|
103134
|
-
break;
|
|
103135
|
-
}
|
|
103136
|
-
}
|
|
103137
|
-
if (!restarted) {
|
|
103138
|
-
console.log(source_default.yellow(" \u26A0 Daemon did not restart within 10s."));
|
|
103139
|
-
console.log(source_default.gray(" Check: adhdev service logs --err"));
|
|
103140
|
-
}
|
|
103141
|
-
console.log();
|
|
103142
|
-
});
|
|
103143
|
-
}
|
|
103144
|
-
function formatBytes(bytes) {
|
|
103145
|
-
if (bytes === 0) return "0 B";
|
|
103146
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
103147
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
103148
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
103149
|
-
}
|
|
103150
|
-
|
|
103151
104503
|
// src/cli/doctor-commands.ts
|
|
104504
|
+
init_service_commands();
|
|
103152
104505
|
function resolvePackageRoot() {
|
|
103153
104506
|
return path39.resolve(__dirname, "..", "..");
|
|
103154
104507
|
}
|
|
@@ -104640,6 +105993,9 @@ function registerCdpCommands(program2) {
|
|
|
104640
105993
|
});
|
|
104641
105994
|
}
|
|
104642
105995
|
|
|
105996
|
+
// src/cli/index.ts
|
|
105997
|
+
init_service_commands();
|
|
105998
|
+
|
|
104643
105999
|
// src/cli/mcp-commands.ts
|
|
104644
106000
|
var import_node_child_process5 = require("child_process");
|
|
104645
106001
|
var fs23 = __toESM(require("fs"));
|