adhdev 0.9.82-rc.3 → 0.9.82-rc.31
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 +1654 -717
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +1173 -327
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/vendor/mcp-server/index.js +324 -31
- 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`);
|
|
4406
|
+
}
|
|
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
|
+
}
|
|
4288
4436
|
}
|
|
4289
|
-
function getPendingMeshCoordinatorEvents() {
|
|
4290
|
-
|
|
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,407 @@ 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 } : {}
|
|
46697
|
+
};
|
|
46698
|
+
}
|
|
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
|
|
46470
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;
|
|
46735
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46736
|
+
const cachedGit = readObjectRecord(cachedStatus.git);
|
|
46737
|
+
if (!Object.keys(cachedGit).length) return void 0;
|
|
46738
|
+
return normalizeInlineMeshGitStatus(cachedGit, node);
|
|
46471
46739
|
}
|
|
46472
|
-
function
|
|
46740
|
+
function shouldDiscardCachedInlineMeshStatus(node) {
|
|
46473
46741
|
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46474
|
-
|
|
46475
|
-
const
|
|
46476
|
-
const
|
|
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 readInlineMeshNodeId(node) {
|
|
46786
|
+
return readStringValue(node?.id, node?.nodeId) || "";
|
|
46787
|
+
}
|
|
46788
|
+
function sanitizeInlineMesh(inlineMesh) {
|
|
46789
|
+
if (!inlineMesh || typeof inlineMesh !== "object" || Array.isArray(inlineMesh)) return inlineMesh;
|
|
46790
|
+
if (!Array.isArray(inlineMesh.nodes)) return inlineMesh;
|
|
46791
|
+
let changed = false;
|
|
46792
|
+
const nodes = inlineMesh.nodes.map((node) => {
|
|
46793
|
+
if (!hasInlineMeshTransientNodeState(node)) return node;
|
|
46794
|
+
changed = true;
|
|
46795
|
+
return stripInlineMeshTransientNodeState(node);
|
|
46796
|
+
});
|
|
46797
|
+
if (!changed) return inlineMesh;
|
|
46798
|
+
return {
|
|
46799
|
+
...inlineMesh,
|
|
46800
|
+
nodes
|
|
46801
|
+
};
|
|
46802
|
+
}
|
|
46803
|
+
function reconcileInlineMeshCache(cached2, incoming) {
|
|
46804
|
+
if (!cached2 || typeof cached2 !== "object" || Array.isArray(cached2)) return incoming;
|
|
46805
|
+
if (!incoming || typeof incoming !== "object" || Array.isArray(incoming)) return cached2;
|
|
46806
|
+
const cachedNodes = Array.isArray(cached2.nodes) ? cached2.nodes : [];
|
|
46807
|
+
const incomingNodes = Array.isArray(incoming.nodes) ? incoming.nodes : [];
|
|
46808
|
+
if (!cachedNodes.length || !incomingNodes.length) return { ...cached2, ...incoming };
|
|
46809
|
+
const incomingById = /* @__PURE__ */ new Map();
|
|
46810
|
+
for (const node of incomingNodes) {
|
|
46811
|
+
const nodeId = readInlineMeshNodeId(node);
|
|
46812
|
+
if (nodeId) incomingById.set(nodeId, node);
|
|
46813
|
+
}
|
|
46814
|
+
const nodes = cachedNodes.map((cachedNode) => {
|
|
46815
|
+
const nodeId = readInlineMeshNodeId(cachedNode);
|
|
46816
|
+
const incomingNode = nodeId ? incomingById.get(nodeId) : void 0;
|
|
46817
|
+
if (!incomingNode) return cachedNode;
|
|
46818
|
+
if (hasInlineMeshTransientNodeState(incomingNode)) {
|
|
46819
|
+
return { ...cachedNode, ...incomingNode };
|
|
46820
|
+
}
|
|
46821
|
+
return { ...stripInlineMeshTransientNodeState(cachedNode), ...incomingNode };
|
|
46822
|
+
});
|
|
46823
|
+
return {
|
|
46824
|
+
...cached2,
|
|
46825
|
+
...incoming,
|
|
46826
|
+
nodes
|
|
46827
|
+
};
|
|
46828
|
+
}
|
|
46829
|
+
function hasGitWorktreeChanges(git) {
|
|
46830
|
+
if (!git) return false;
|
|
46831
|
+
return Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
|
|
46832
|
+
}
|
|
46833
|
+
function getGitSubmoduleDriftState(git) {
|
|
46834
|
+
const submodules = Array.isArray(git?.submodules) ? git.submodules : [];
|
|
46835
|
+
let dirty = false;
|
|
46836
|
+
let outOfSync = false;
|
|
46837
|
+
for (const entry of submodules) {
|
|
46838
|
+
const submodule = readObjectRecord(entry);
|
|
46839
|
+
if (readBooleanValue(submodule.dirty) === true) dirty = true;
|
|
46840
|
+
if (readBooleanValue(submodule.outOfSync) === true || !!readStringValue(submodule.error)) outOfSync = true;
|
|
46841
|
+
}
|
|
46842
|
+
return { dirty, outOfSync };
|
|
46843
|
+
}
|
|
46844
|
+
function deriveMeshNodeHealthFromGit(git) {
|
|
46845
|
+
if (!git || readBooleanValue(git.isGitRepo) === false) return "degraded";
|
|
46846
|
+
const branch = readStringValue(git.branch);
|
|
46847
|
+
if (!branch) return "degraded";
|
|
46848
|
+
const submoduleDrift = getGitSubmoduleDriftState(git);
|
|
46849
|
+
if (submoduleDrift.outOfSync) return "degraded";
|
|
46850
|
+
if (submoduleDrift.dirty || hasGitWorktreeChanges(git)) return "dirty";
|
|
46851
|
+
return "online";
|
|
46852
|
+
}
|
|
46853
|
+
function readCachedInlineMeshActiveSessions(node) {
|
|
46854
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46855
|
+
const activeSession = readObjectRecord(cachedStatus.activeSession);
|
|
46856
|
+
const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
|
|
46857
|
+
const sessionId = readStringValue(fallbackSession.id, fallbackSession.sessionId, fallbackSession.session_id, node?.activeSessionId, node?.active_session_id, node?.sessionId, node?.session_id);
|
|
46858
|
+
return sessionId ? [sessionId] : [];
|
|
46859
|
+
}
|
|
46860
|
+
function readCachedInlineMeshActiveSessionDetails(node) {
|
|
46861
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46862
|
+
const activeSession = readObjectRecord(cachedStatus.activeSession);
|
|
46863
|
+
const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
|
|
46864
|
+
const sessionId = readStringValue(
|
|
46865
|
+
fallbackSession.id,
|
|
46866
|
+
fallbackSession.sessionId,
|
|
46867
|
+
fallbackSession.session_id,
|
|
46868
|
+
node?.activeSessionId,
|
|
46869
|
+
node?.active_session_id,
|
|
46870
|
+
node?.sessionId,
|
|
46871
|
+
node?.session_id
|
|
46872
|
+
);
|
|
46873
|
+
if (!sessionId) return [];
|
|
46874
|
+
return [{
|
|
46875
|
+
sessionId,
|
|
46876
|
+
providerType: readStringValue(
|
|
46877
|
+
fallbackSession.providerType,
|
|
46878
|
+
fallbackSession.provider_type,
|
|
46879
|
+
fallbackSession.cliType,
|
|
46880
|
+
fallbackSession.cli_type,
|
|
46881
|
+
fallbackSession.provider,
|
|
46882
|
+
node?.providerType,
|
|
46883
|
+
node?.provider_type
|
|
46884
|
+
),
|
|
46885
|
+
state: readStringValue(fallbackSession.status, fallbackSession.state, fallbackSession.lifecycle),
|
|
46886
|
+
lifecycle: readStringValue(fallbackSession.lifecycle),
|
|
46887
|
+
title: readStringValue(fallbackSession.title, fallbackSession.displayName, fallbackSession.display_name) ?? null,
|
|
46888
|
+
workspace: readStringValue(fallbackSession.workspace, node?.workspace) ?? null,
|
|
46889
|
+
lastActivityAt: readStringValue(fallbackSession.lastActivityAt, fallbackSession.last_activity_at) ?? null,
|
|
46890
|
+
recoveryState: readStringValue(fallbackSession.recoveryState, fallbackSession.recovery_state) ?? null,
|
|
46891
|
+
isCached: true
|
|
46892
|
+
}];
|
|
46893
|
+
}
|
|
46894
|
+
function readLiveMeshSessionState(record2) {
|
|
46895
|
+
return readStringValue(
|
|
46896
|
+
record2?.meta?.sessionStatus,
|
|
46897
|
+
record2?.meta?.status,
|
|
46898
|
+
record2?.meta?.providerStatus,
|
|
46899
|
+
record2?.status,
|
|
46900
|
+
record2?.state,
|
|
46901
|
+
record2?.lifecycle
|
|
46902
|
+
);
|
|
46903
|
+
}
|
|
46904
|
+
function toIsoTimestamp(value) {
|
|
46905
|
+
if (typeof value === "number" && Number.isFinite(value)) return new Date(value).toISOString();
|
|
46906
|
+
const stringValue = readStringValue(value);
|
|
46907
|
+
return stringValue || null;
|
|
46908
|
+
}
|
|
46909
|
+
function synthesizeMeshNodeFreshnessFromConnection(status) {
|
|
46910
|
+
const connection = readObjectRecord(status.connection);
|
|
46911
|
+
const connectionFreshAt = toIsoTimestamp(connection.lastCommandAt ?? connection.lastConnectedAt ?? connection.lastStateChangeAt);
|
|
46912
|
+
const git = readObjectRecord(status.git);
|
|
46913
|
+
const gitCheckedAt = toIsoTimestamp(git.lastCheckedAt);
|
|
46914
|
+
if (!status.lastSeenAt && connectionFreshAt) status.lastSeenAt = connectionFreshAt;
|
|
46915
|
+
if (!status.updatedAt && (gitCheckedAt || connectionFreshAt)) {
|
|
46916
|
+
status.updatedAt = gitCheckedAt ?? connectionFreshAt;
|
|
46917
|
+
}
|
|
46918
|
+
}
|
|
46919
|
+
function finalizeMeshNodeStatus(args) {
|
|
46920
|
+
const { status, node, daemonId, isSelfNode } = args;
|
|
46921
|
+
if (!readStringValue(status.machineStatus)) {
|
|
46922
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46923
|
+
const machineStatus = readStringValue(cachedStatus.machineStatus, cachedStatus.machine_status, node?.machineStatus);
|
|
46924
|
+
if (machineStatus) status.machineStatus = machineStatus;
|
|
46925
|
+
}
|
|
46926
|
+
synthesizeMeshNodeFreshnessFromConnection(status);
|
|
46927
|
+
const connectionState = readStringValue(readObjectRecord(status.connection).state);
|
|
46928
|
+
status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || connectionState === "connected" || isSelfNode);
|
|
46929
|
+
}
|
|
46930
|
+
async function probeRemoteMeshGitStatus(args) {
|
|
46931
|
+
if (!args.dispatchMeshCommand) return null;
|
|
46932
|
+
const remoteResult = await Promise.race([
|
|
46933
|
+
args.dispatchMeshCommand(args.daemonId, "git_status", { workspace: args.workspace }),
|
|
46934
|
+
new Promise((_2, reject) => setTimeout(() => reject(new Error("timeout")), args.timeoutMs))
|
|
46935
|
+
]);
|
|
46936
|
+
const remoteGit = remoteResult?.status ?? remoteResult?.git ?? remoteResult;
|
|
46937
|
+
return remoteGit && typeof remoteGit === "object" && typeof remoteGit.isGitRepo === "boolean" ? remoteGit : null;
|
|
46938
|
+
}
|
|
46939
|
+
async function hydrateInlineMeshDirectTruth(args) {
|
|
46940
|
+
const nodes = Array.isArray(args.mesh?.nodes) ? args.mesh.nodes : [];
|
|
46941
|
+
if (!nodes.length) {
|
|
46942
|
+
return {
|
|
46943
|
+
directEvidenceCount: 0,
|
|
46944
|
+
localConfirmedCount: 0,
|
|
46945
|
+
peerAttemptedCount: 0,
|
|
46946
|
+
peerConfirmedCount: 0,
|
|
46947
|
+
unavailableNodeIds: []
|
|
46948
|
+
};
|
|
46949
|
+
}
|
|
46950
|
+
const selectedCoordinatorNodeId = readStringValue(
|
|
46951
|
+
args.mesh?.coordinator?.preferredNodeId,
|
|
46952
|
+
nodes[0]?.id,
|
|
46953
|
+
nodes[0]?.nodeId
|
|
46954
|
+
);
|
|
46955
|
+
let localConfirmedCount = 0;
|
|
46956
|
+
let peerAttemptedCount = 0;
|
|
46957
|
+
let peerConfirmedCount = 0;
|
|
46958
|
+
const unavailableNodeIds = [];
|
|
46959
|
+
for (const [nodeIndex, node] of nodes.entries()) {
|
|
46960
|
+
const nodeId = readStringValue(node?.id, node?.nodeId) || `node_${nodeIndex}`;
|
|
46961
|
+
const workspace = readStringValue(node?.workspace);
|
|
46962
|
+
const daemonId = readStringValue(node?.daemonId);
|
|
46963
|
+
const isSelfNode = Boolean(
|
|
46964
|
+
nodeId && selectedCoordinatorNodeId && nodeId === selectedCoordinatorNodeId
|
|
46965
|
+
) || Boolean(
|
|
46966
|
+
daemonId && (daemonId === args.localMachineId || daemonId === args.statusInstanceId)
|
|
46967
|
+
) || Boolean(args.meshSource !== "local_config" && nodeIndex === 0);
|
|
46968
|
+
if (!workspace) {
|
|
46969
|
+
if (!isSelfNode && daemonId) unavailableNodeIds.push(nodeId);
|
|
46970
|
+
continue;
|
|
46971
|
+
}
|
|
46972
|
+
if (isSelfNode && fs10.existsSync(workspace)) {
|
|
46973
|
+
try {
|
|
46974
|
+
const localGit = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
46975
|
+
if (localGit?.isGitRepo) {
|
|
46976
|
+
recordInlineMeshDirectGitTruth(node, localGit, "selected_coordinator_local_git");
|
|
46977
|
+
localConfirmedCount += 1;
|
|
46978
|
+
continue;
|
|
46979
|
+
}
|
|
46980
|
+
} catch {
|
|
46981
|
+
}
|
|
46982
|
+
}
|
|
46983
|
+
if (!daemonId || !args.dispatchMeshCommand) {
|
|
46984
|
+
if (!isSelfNode) unavailableNodeIds.push(nodeId);
|
|
46985
|
+
continue;
|
|
46986
|
+
}
|
|
46987
|
+
peerAttemptedCount += 1;
|
|
46988
|
+
try {
|
|
46989
|
+
const remoteGit = await probeRemoteMeshGitStatus({
|
|
46990
|
+
dispatchMeshCommand: args.dispatchMeshCommand,
|
|
46991
|
+
daemonId,
|
|
46992
|
+
workspace,
|
|
46993
|
+
timeoutMs: 8e3
|
|
46994
|
+
});
|
|
46995
|
+
if (remoteGit) {
|
|
46996
|
+
recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
|
|
46997
|
+
peerConfirmedCount += 1;
|
|
46998
|
+
continue;
|
|
46999
|
+
}
|
|
47000
|
+
} catch {
|
|
47001
|
+
}
|
|
47002
|
+
unavailableNodeIds.push(nodeId);
|
|
47003
|
+
}
|
|
47004
|
+
return {
|
|
47005
|
+
directEvidenceCount: localConfirmedCount + peerConfirmedCount,
|
|
47006
|
+
localConfirmedCount,
|
|
47007
|
+
peerAttemptedCount,
|
|
47008
|
+
peerConfirmedCount,
|
|
47009
|
+
unavailableNodeIds
|
|
47010
|
+
};
|
|
47011
|
+
}
|
|
47012
|
+
function summarizeMeshSessionRecord(record2) {
|
|
47013
|
+
return {
|
|
47014
|
+
sessionId: readStringValue(record2?.sessionId) || "unknown",
|
|
47015
|
+
providerType: readStringValue(record2?.providerType),
|
|
47016
|
+
state: readLiveMeshSessionState(record2),
|
|
47017
|
+
lifecycle: readStringValue(record2?.lifecycle),
|
|
47018
|
+
surfaceKind: getSessionHostSurfaceKind(record2),
|
|
47019
|
+
recoveryState: readStringValue(record2?.meta?.runtimeRecoveryState) ?? null,
|
|
47020
|
+
workspace: readStringValue(record2?.workspace) ?? null,
|
|
47021
|
+
title: readStringValue(record2?.displayName, record2?.workspaceLabel) ?? null,
|
|
47022
|
+
lastActivityAt: toIsoTimestamp(record2?.updatedAt ?? record2?.lastActivityAt ?? record2?.last_activity_at),
|
|
47023
|
+
isCached: false
|
|
47024
|
+
};
|
|
47025
|
+
}
|
|
47026
|
+
function liveSessionRecordMatchesMeshNode(record2, meshId, nodeId) {
|
|
47027
|
+
const recordNodeId = readStringValue(record2?.meta?.meshNodeId);
|
|
47028
|
+
if (!recordNodeId || recordNodeId !== nodeId) return false;
|
|
47029
|
+
const recordMeshId = readStringValue(record2?.meta?.meshNodeFor);
|
|
47030
|
+
return !recordMeshId || recordMeshId === meshId;
|
|
47031
|
+
}
|
|
47032
|
+
function liveSessionRecordMatchesMeshWorkspace(record2, meshId, workspace) {
|
|
47033
|
+
const recordWorkspace = readStringValue(record2?.workspace);
|
|
47034
|
+
if (!recordWorkspace || !workspace || recordWorkspace !== workspace) return false;
|
|
47035
|
+
const recordMeshId = readStringValue(record2?.meta?.meshNodeFor);
|
|
47036
|
+
if (recordMeshId) return recordMeshId === meshId;
|
|
47037
|
+
return record2?.meta?.launchedByCoordinator === true || !!readStringValue(record2?.meta?.meshNodeId);
|
|
47038
|
+
}
|
|
47039
|
+
function readLiveMeshNodeWorkspace(args) {
|
|
47040
|
+
const directNodeWorkspace = args.liveSessionRecords.find((record2) => liveSessionRecordMatchesMeshNode(record2, args.meshId, args.nodeId) && readStringValue(record2?.workspace));
|
|
47041
|
+
if (directNodeWorkspace) {
|
|
47042
|
+
return readStringValue(directNodeWorkspace.workspace) || "";
|
|
47043
|
+
}
|
|
47044
|
+
if (args.allowCoordinatorSession) {
|
|
47045
|
+
const coordinatorWorkspace = args.liveSessionRecords.find((record2) => readStringValue(record2?.meta?.meshCoordinatorFor) === args.meshId && readStringValue(record2?.workspace));
|
|
47046
|
+
if (coordinatorWorkspace) {
|
|
47047
|
+
return readStringValue(coordinatorWorkspace.workspace) || "";
|
|
47048
|
+
}
|
|
47049
|
+
}
|
|
47050
|
+
return "";
|
|
47051
|
+
}
|
|
47052
|
+
function collectLiveMeshSessionRecords(args) {
|
|
47053
|
+
const matches = args.liveSessionRecords.filter((record2) => {
|
|
47054
|
+
const nodeWorkspace = readStringValue(args.node?.workspace);
|
|
47055
|
+
if (liveSessionRecordMatchesMeshNode(record2, args.meshId, args.nodeId)) return true;
|
|
47056
|
+
return !!nodeWorkspace && liveSessionRecordMatchesMeshWorkspace(record2, args.meshId, nodeWorkspace);
|
|
47057
|
+
});
|
|
47058
|
+
if (args.allowCoordinatorSession) {
|
|
47059
|
+
for (const record2 of args.liveSessionRecords) {
|
|
47060
|
+
if (readStringValue(record2?.meta?.meshCoordinatorFor) !== args.meshId) continue;
|
|
47061
|
+
const sessionId = readStringValue(record2?.sessionId);
|
|
47062
|
+
if (sessionId && matches.some((entry) => readStringValue(entry?.sessionId) === sessionId)) continue;
|
|
47063
|
+
matches.push(record2);
|
|
47064
|
+
}
|
|
47065
|
+
}
|
|
47066
|
+
return matches;
|
|
47067
|
+
}
|
|
47068
|
+
function applyCachedInlineMeshNodeStatus(status, node, options) {
|
|
47069
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
47070
|
+
const liveGit = buildInlineMeshTransitGitStatus(node);
|
|
47071
|
+
const git = options?.skipGit ? void 0 : liveGit ?? buildCachedInlineMeshGitStatus(node);
|
|
47072
|
+
const error48 = options?.skipError ? void 0 : liveGit ? void 0 : readStringValue(cachedStatus.error, node?.error);
|
|
47073
|
+
const health = options?.skipHealth ? void 0 : liveGit ? void 0 : readStringValue(cachedStatus.health, node?.health);
|
|
46477
47074
|
const machineStatus = readStringValue(cachedStatus.machineStatus, node?.machineStatus);
|
|
46478
|
-
|
|
46479
|
-
|
|
47075
|
+
const lastSeenAt = toIsoTimestamp(cachedStatus.lastSeenAt ?? cachedStatus.last_seen_at ?? node?.lastSeenAt ?? node?.last_seen_at);
|
|
47076
|
+
const updatedAt = toIsoTimestamp(cachedStatus.updatedAt ?? cachedStatus.updated_at ?? node?.updatedAt ?? node?.updated_at);
|
|
47077
|
+
const activeSessions = readCachedInlineMeshActiveSessions(node);
|
|
47078
|
+
const activeSessionDetails = readCachedInlineMeshActiveSessionDetails(node);
|
|
47079
|
+
if (!git && !error48 && !health && !machineStatus && !lastSeenAt && !updatedAt && activeSessions.length === 0) return false;
|
|
46480
47080
|
if (git) status.git = git;
|
|
46481
47081
|
if (error48) status.error = error48;
|
|
47082
|
+
if (machineStatus) status.machineStatus = machineStatus;
|
|
47083
|
+
if (lastSeenAt) status.lastSeenAt = lastSeenAt;
|
|
47084
|
+
if (updatedAt) status.updatedAt = updatedAt;
|
|
47085
|
+
if (activeSessions.length > 0) status.activeSessions = activeSessions;
|
|
47086
|
+
if (activeSessionDetails.length > 0) status.activeSessionDetails = activeSessionDetails;
|
|
46482
47087
|
if (health) {
|
|
46483
47088
|
status.health = health;
|
|
46484
47089
|
return true;
|
|
46485
47090
|
}
|
|
46486
47091
|
if (git) {
|
|
46487
|
-
|
|
46488
|
-
status.health = git.isGitRepo === false ? "degraded" : dirty ? "dirty" : "online";
|
|
47092
|
+
status.health = deriveMeshNodeHealthFromGit(git);
|
|
46489
47093
|
return true;
|
|
46490
47094
|
}
|
|
46491
|
-
return
|
|
47095
|
+
return activeSessions.length > 0 || !!machineStatus || !!lastSeenAt || !!updatedAt;
|
|
46492
47096
|
}
|
|
46493
47097
|
async function resolveProviderTypeFromPriority(args) {
|
|
46494
47098
|
if (!args.providerPriority.length) {
|
|
@@ -46521,7 +47125,7 @@ function truncateValidationOutput(value) {
|
|
|
46521
47125
|
}
|
|
46522
47126
|
function readPackageScripts(workspace) {
|
|
46523
47127
|
try {
|
|
46524
|
-
const packageJsonPath = (0,
|
|
47128
|
+
const packageJsonPath = (0, import_path7.join)(workspace, "package.json");
|
|
46525
47129
|
const parsed = JSON.parse(fs10.readFileSync(packageJsonPath, "utf-8"));
|
|
46526
47130
|
return parsed?.scripts && typeof parsed.scripts === "object" && !Array.isArray(parsed.scripts) ? parsed.scripts : {};
|
|
46527
47131
|
} catch {
|
|
@@ -46729,13 +47333,13 @@ function serializeMeshCoordinatorMcpConfig(config2, format) {
|
|
|
46729
47333
|
}
|
|
46730
47334
|
function resolveHermesUserHome() {
|
|
46731
47335
|
const explicitHome = process.env.HERMES_HOME?.trim();
|
|
46732
|
-
return explicitHome || (0,
|
|
47336
|
+
return explicitHome || (0, import_path7.join)((0, import_os4.homedir)(), ".hermes");
|
|
46733
47337
|
}
|
|
46734
47338
|
function loadHermesCoordinatorBaseConfig(targetConfigPath) {
|
|
46735
47339
|
const sourceHome = resolveHermesUserHome();
|
|
46736
|
-
const sourceConfigPath = (0,
|
|
47340
|
+
const sourceConfigPath = (0, import_path7.join)(sourceHome, "config.yaml");
|
|
46737
47341
|
if (!fs10.existsSync(sourceConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
46738
|
-
if ((0,
|
|
47342
|
+
if ((0, import_path7.resolve)(sourceConfigPath) === (0, import_path7.resolve)(targetConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
46739
47343
|
const parsed = parseMeshCoordinatorMcpConfig(fs10.readFileSync(sourceConfigPath, "utf-8"), "hermes_config_yaml");
|
|
46740
47344
|
const { mcp_servers: _mcpServers, ...baseConfig } = parsed;
|
|
46741
47345
|
return { config: baseConfig, sourceHome, sourceConfigPath };
|
|
@@ -46769,10 +47373,10 @@ function stripHermesCoordinatorTempModelProviderOverrides(config2) {
|
|
|
46769
47373
|
return sanitized;
|
|
46770
47374
|
}
|
|
46771
47375
|
function copyHermesCoordinatorCredentialFiles(sourceHome, targetHome) {
|
|
46772
|
-
if ((0,
|
|
47376
|
+
if ((0, import_path7.resolve)(sourceHome) === (0, import_path7.resolve)(targetHome)) return;
|
|
46773
47377
|
for (const fileName of [".env", "auth.json"]) {
|
|
46774
|
-
const sourcePath = (0,
|
|
46775
|
-
const targetPath = (0,
|
|
47378
|
+
const sourcePath = (0, import_path7.join)(sourceHome, fileName);
|
|
47379
|
+
const targetPath = (0, import_path7.join)(targetHome, fileName);
|
|
46776
47380
|
if (!fs10.existsSync(sourcePath)) continue;
|
|
46777
47381
|
try {
|
|
46778
47382
|
fs10.copyFileSync(sourcePath, targetPath);
|
|
@@ -46862,7 +47466,7 @@ function summarizeSessionHostPruneResult(result) {
|
|
|
46862
47466
|
keptCount: Array.isArray(value.keptSessionIds) ? value.keptSessionIds.length : void 0
|
|
46863
47467
|
};
|
|
46864
47468
|
}
|
|
46865
|
-
var import_os4,
|
|
47469
|
+
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, CHAT_COMMANDS, READ_DEBUG_ENABLED2, DaemonCommandRouter;
|
|
46866
47470
|
var init_router = __esm({
|
|
46867
47471
|
"../../oss/packages/daemon-core/src/commands/router.ts"() {
|
|
46868
47472
|
"use strict";
|
|
@@ -46878,6 +47482,7 @@ var init_router = __esm({
|
|
|
46878
47482
|
init_chat_history();
|
|
46879
47483
|
init_ide_detector();
|
|
46880
47484
|
init_cli_detector();
|
|
47485
|
+
init_git_status();
|
|
46881
47486
|
init_logger();
|
|
46882
47487
|
init_command_log();
|
|
46883
47488
|
init_js_yaml();
|
|
@@ -46891,7 +47496,7 @@ var init_router = __esm({
|
|
|
46891
47496
|
init_snapshot();
|
|
46892
47497
|
init_upgrade_helper();
|
|
46893
47498
|
import_os4 = require("os");
|
|
46894
|
-
|
|
47499
|
+
import_path7 = require("path");
|
|
46895
47500
|
fs10 = __toESM(require("fs"));
|
|
46896
47501
|
CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
|
|
46897
47502
|
CHANNEL_SERVER_URL = {
|
|
@@ -46922,25 +47527,40 @@ var init_router = __esm({
|
|
|
46922
47527
|
}
|
|
46923
47528
|
getCachedInlineMesh(meshId, inlineMesh) {
|
|
46924
47529
|
if (inlineMesh && typeof inlineMesh === "object") {
|
|
46925
|
-
this.
|
|
46926
|
-
return inlineMesh;
|
|
47530
|
+
return this.warmInlineMeshCache(meshId, inlineMesh);
|
|
46927
47531
|
}
|
|
46928
47532
|
return this.inlineMeshCache.get(meshId);
|
|
46929
47533
|
}
|
|
47534
|
+
warmInlineMeshCache(meshId, inlineMesh) {
|
|
47535
|
+
if (!inlineMesh || typeof inlineMesh !== "object") return void 0;
|
|
47536
|
+
const sanitizedInlineMesh = sanitizeInlineMesh(inlineMesh);
|
|
47537
|
+
const cached2 = this.inlineMeshCache.get(meshId);
|
|
47538
|
+
if (cached2) {
|
|
47539
|
+
const merged = reconcileInlineMeshCache(cached2, sanitizedInlineMesh);
|
|
47540
|
+
this.inlineMeshCache.set(meshId, merged);
|
|
47541
|
+
return merged;
|
|
47542
|
+
}
|
|
47543
|
+
this.inlineMeshCache.set(meshId, sanitizedInlineMesh);
|
|
47544
|
+
return sanitizedInlineMesh;
|
|
47545
|
+
}
|
|
46930
47546
|
async getMeshForCommand(meshId, inlineMesh, options) {
|
|
46931
47547
|
const preferInline = options?.preferInline === true;
|
|
46932
47548
|
if (preferInline) {
|
|
46933
|
-
const cached3 = this.getCachedInlineMesh(meshId
|
|
46934
|
-
if (cached3) return { mesh: cached3, inline: true };
|
|
47549
|
+
const cached3 = this.getCachedInlineMesh(meshId);
|
|
47550
|
+
if (cached3) return { mesh: cached3, inline: true, source: "inline_cache" };
|
|
47551
|
+
const warmedInline2 = this.warmInlineMeshCache(meshId, inlineMesh);
|
|
47552
|
+
if (warmedInline2) return { mesh: warmedInline2, inline: true, source: "inline_bootstrap" };
|
|
46935
47553
|
}
|
|
46936
47554
|
try {
|
|
46937
47555
|
const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
46938
47556
|
const mesh = getMesh3(meshId);
|
|
46939
|
-
if (mesh) return { mesh, inline: false };
|
|
47557
|
+
if (mesh) return { mesh, inline: false, source: "local_config" };
|
|
46940
47558
|
} catch {
|
|
46941
47559
|
}
|
|
46942
|
-
const cached2 = this.getCachedInlineMesh(meshId
|
|
46943
|
-
|
|
47560
|
+
const cached2 = this.getCachedInlineMesh(meshId);
|
|
47561
|
+
if (cached2) return { mesh: cached2, inline: true, source: "inline_cache" };
|
|
47562
|
+
const warmedInline = this.warmInlineMeshCache(meshId, inlineMesh);
|
|
47563
|
+
return warmedInline ? { mesh: warmedInline, inline: true, source: "inline_bootstrap" } : null;
|
|
46944
47564
|
}
|
|
46945
47565
|
updateInlineMeshNode(meshId, mesh, node) {
|
|
46946
47566
|
if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
|
|
@@ -47005,7 +47625,7 @@ var init_router = __esm({
|
|
|
47005
47625
|
}
|
|
47006
47626
|
const { resolveWorktreePath: resolveWorktreePath2, listWorktrees: listWorktrees2, removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
47007
47627
|
const normalizePath3 = (value) => {
|
|
47008
|
-
const resolved = (0,
|
|
47628
|
+
const resolved = (0, import_path7.resolve)(value);
|
|
47009
47629
|
try {
|
|
47010
47630
|
return fs10.realpathSync(resolved);
|
|
47011
47631
|
} catch {
|
|
@@ -47169,6 +47789,7 @@ var init_router = __esm({
|
|
|
47169
47789
|
const deletedSessionIds = [];
|
|
47170
47790
|
const skippedSessionIds = [];
|
|
47171
47791
|
const skippedLiveSessionIds = [];
|
|
47792
|
+
const skippedCoordinatorSessionIds = [];
|
|
47172
47793
|
const deleteUnsupportedSessionIds = [];
|
|
47173
47794
|
const recordsRemainSessionIds = [];
|
|
47174
47795
|
const errors = [];
|
|
@@ -47201,6 +47822,12 @@ var init_router = __esm({
|
|
|
47201
47822
|
const completed = this.isCompletedHostedSession(record2);
|
|
47202
47823
|
const surfaceKind = getSessionHostSurfaceKind(record2);
|
|
47203
47824
|
const liveRuntime = surfaceKind === "live_runtime";
|
|
47825
|
+
const coordinatorSession = readStringValue(record2?.meta?.meshCoordinatorFor) === args.meshId;
|
|
47826
|
+
if (!hasExplicitSessionIds && coordinatorSession) {
|
|
47827
|
+
skippedSessionIds.push(sessionId);
|
|
47828
|
+
skippedCoordinatorSessionIds.push(sessionId);
|
|
47829
|
+
continue;
|
|
47830
|
+
}
|
|
47204
47831
|
if (!hasExplicitSessionIds && liveRuntime) {
|
|
47205
47832
|
skippedSessionIds.push(sessionId);
|
|
47206
47833
|
skippedLiveSessionIds.push(sessionId);
|
|
@@ -47266,6 +47893,7 @@ var init_router = __esm({
|
|
|
47266
47893
|
deletedSessionIds,
|
|
47267
47894
|
skippedSessionIds,
|
|
47268
47895
|
skippedLiveSessionIds,
|
|
47896
|
+
skippedCoordinatorSessionIds,
|
|
47269
47897
|
...deleteUnsupported ? {
|
|
47270
47898
|
deleteUnsupported: true,
|
|
47271
47899
|
effectiveCleanup: args.mode === "stop_and_delete" ? "stopped_only_records_remain" : "delete_unsupported_records_remain",
|
|
@@ -47398,7 +48026,8 @@ var init_router = __esm({
|
|
|
47398
48026
|
return handleMeshForwardEvent({ instanceManager: this.deps.instanceManager }, args);
|
|
47399
48027
|
}
|
|
47400
48028
|
case "get_pending_mesh_events": {
|
|
47401
|
-
const
|
|
48029
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
48030
|
+
const events = drainPendingMeshCoordinatorEvents(meshId || void 0);
|
|
47402
48031
|
return { success: true, events };
|
|
47403
48032
|
}
|
|
47404
48033
|
case "launch_cli":
|
|
@@ -47927,15 +48556,39 @@ var init_router = __esm({
|
|
|
47927
48556
|
case "get_mesh": {
|
|
47928
48557
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
47929
48558
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
47930
|
-
|
|
47931
|
-
|
|
47932
|
-
|
|
47933
|
-
|
|
47934
|
-
|
|
48559
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
48560
|
+
if (!meshRecord?.mesh) return { success: false, error: "Mesh not found" };
|
|
48561
|
+
const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
|
|
48562
|
+
const directTruth = await hydrateInlineMeshDirectTruth({
|
|
48563
|
+
mesh: meshRecord.mesh,
|
|
48564
|
+
meshSource: meshRecord.source,
|
|
48565
|
+
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
48566
|
+
statusInstanceId: this.deps.statusInstanceId,
|
|
48567
|
+
localMachineId: loadConfig().machineId || ""
|
|
48568
|
+
});
|
|
48569
|
+
const directTruthSatisfied = meshRecord.source !== "inline_bootstrap" || directTruth.directEvidenceCount > 0;
|
|
48570
|
+
const sourceOfTruth = {
|
|
48571
|
+
membership: meshRecord.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
|
|
48572
|
+
coordinatorOwnsLiveTruth: directTruthSatisfied,
|
|
48573
|
+
directPeerTruth: {
|
|
48574
|
+
required: requireDirectPeerTruth,
|
|
48575
|
+
satisfied: directTruthSatisfied,
|
|
48576
|
+
directEvidenceCount: directTruth.directEvidenceCount,
|
|
48577
|
+
localConfirmedCount: directTruth.localConfirmedCount,
|
|
48578
|
+
peerAttemptedCount: directTruth.peerAttemptedCount,
|
|
48579
|
+
peerConfirmedCount: directTruth.peerConfirmedCount,
|
|
48580
|
+
unavailableNodeIds: directTruth.unavailableNodeIds
|
|
48581
|
+
}
|
|
48582
|
+
};
|
|
48583
|
+
if (requireDirectPeerTruth && !directTruthSatisfied) {
|
|
48584
|
+
return {
|
|
48585
|
+
success: false,
|
|
48586
|
+
code: "mesh_direct_peer_truth_unavailable",
|
|
48587
|
+
error: "Selected coordinator could not confirm direct mesh truth yet. Bootstrap inventory stays unavailable until direct get_mesh probes succeed.",
|
|
48588
|
+
sourceOfTruth
|
|
48589
|
+
};
|
|
47935
48590
|
}
|
|
47936
|
-
|
|
47937
|
-
if (cached2) return { success: true, mesh: cached2 };
|
|
47938
|
-
return { success: false, error: "Mesh not found" };
|
|
48591
|
+
return { success: true, mesh: meshRecord.mesh, sourceOfTruth };
|
|
47939
48592
|
}
|
|
47940
48593
|
case "create_mesh": {
|
|
47941
48594
|
const name = typeof args?.name === "string" ? args.name.trim() : "";
|
|
@@ -48456,7 +49109,14 @@ var init_router = __esm({
|
|
|
48456
49109
|
cliType
|
|
48457
49110
|
};
|
|
48458
49111
|
}
|
|
48459
|
-
const
|
|
49112
|
+
const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
|
|
49113
|
+
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
49114
|
+
const workspace = readLiveMeshNodeWorkspace({
|
|
49115
|
+
meshId,
|
|
49116
|
+
nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || ""),
|
|
49117
|
+
liveSessionRecords: liveMeshSessions,
|
|
49118
|
+
allowCoordinatorSession: true
|
|
49119
|
+
}) || (typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "");
|
|
48460
49120
|
if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
|
|
48461
49121
|
if (!cliType) {
|
|
48462
49122
|
const resolved = await resolveProviderTypeFromPriority({
|
|
@@ -48618,7 +49278,7 @@ ${block}`);
|
|
|
48618
49278
|
workspace
|
|
48619
49279
|
};
|
|
48620
49280
|
}
|
|
48621
|
-
const { existsSync:
|
|
49281
|
+
const { existsSync: existsSync33, readFileSync: readFileSync24, writeFileSync: writeFileSync18, copyFileSync: copyFileSync5, mkdirSync: mkdirSync22 } = await import("fs");
|
|
48622
49282
|
const { dirname: dirname13 } = await import("path");
|
|
48623
49283
|
const mcpConfigPath = coordinatorSetup.configPath;
|
|
48624
49284
|
const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
|
|
@@ -48661,14 +49321,14 @@ ${block}`);
|
|
|
48661
49321
|
if (hermesManualFallback) return returnManualFallback(message);
|
|
48662
49322
|
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
48663
49323
|
}
|
|
48664
|
-
const hadExistingMcpConfig =
|
|
49324
|
+
const hadExistingMcpConfig = existsSync33(mcpConfigPath);
|
|
48665
49325
|
let existingMcpConfig = hermesBaseConfig?.config || {};
|
|
48666
49326
|
if (hermesBaseConfig) {
|
|
48667
49327
|
copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname13(mcpConfigPath));
|
|
48668
49328
|
}
|
|
48669
49329
|
if (hadExistingMcpConfig) {
|
|
48670
49330
|
try {
|
|
48671
|
-
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(
|
|
49331
|
+
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync24(mcpConfigPath, "utf-8"), configFormat);
|
|
48672
49332
|
const existingCoordinatorConfig = hermesManualFallback ? stripHermesCoordinatorTempModelProviderOverrides(parsedExistingMcpConfig) : parsedExistingMcpConfig;
|
|
48673
49333
|
existingMcpConfig = { ...existingMcpConfig, ...existingCoordinatorConfig };
|
|
48674
49334
|
copyFileSync5(mcpConfigPath, mcpConfigPath + ".backup");
|
|
@@ -48764,92 +49424,184 @@ ${block}`);
|
|
|
48764
49424
|
const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
48765
49425
|
const ledgerEntries = readLedgerEntries2(meshId, { tail: 20 });
|
|
48766
49426
|
const ledgerSummary = getLedgerSummary2(meshId);
|
|
49427
|
+
const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
|
|
49428
|
+
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
49429
|
+
const localMachineId = loadConfig().machineId || "";
|
|
49430
|
+
const selectedCoordinatorNodeId = readStringValue(
|
|
49431
|
+
mesh.coordinator?.preferredNodeId,
|
|
49432
|
+
mesh.nodes?.[0]?.id,
|
|
49433
|
+
mesh.nodes?.[0]?.nodeId
|
|
49434
|
+
);
|
|
49435
|
+
const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? selectedCoordinatorNodeId : void 0;
|
|
49436
|
+
const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
48767
49437
|
const nodeStatuses = [];
|
|
48768
|
-
for (const node of mesh.nodes || []) {
|
|
49438
|
+
for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
|
|
49439
|
+
const nodeId = String(node.id || node.nodeId || "");
|
|
49440
|
+
const daemonId = readStringValue(node.daemonId);
|
|
49441
|
+
const providerPriority = readProviderPriorityFromPolicy(node.policy);
|
|
49442
|
+
const isSelfNode = Boolean(
|
|
49443
|
+
nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId
|
|
49444
|
+
) || Boolean(
|
|
49445
|
+
daemonId && (daemonId === localMachineId || daemonId === this.deps.statusInstanceId)
|
|
49446
|
+
) || Boolean(meshRecord?.inline && nodeIndex === 0);
|
|
48769
49447
|
const status = {
|
|
48770
|
-
nodeId
|
|
49448
|
+
nodeId,
|
|
48771
49449
|
machineLabel: node.machineLabel || node.id || node.nodeId,
|
|
48772
49450
|
workspace: node.workspace,
|
|
48773
49451
|
repoRoot: node.repoRoot,
|
|
48774
49452
|
isLocalWorktree: node.isLocalWorktree,
|
|
48775
49453
|
worktreeBranch: node.worktreeBranch,
|
|
48776
|
-
daemonId
|
|
49454
|
+
daemonId,
|
|
48777
49455
|
machineId: node.machineId,
|
|
49456
|
+
machineStatus: node.machineStatus,
|
|
48778
49457
|
health: "unknown",
|
|
48779
49458
|
providers: node.providers || [],
|
|
48780
|
-
|
|
49459
|
+
providerPriority,
|
|
49460
|
+
activeSessions: [],
|
|
49461
|
+
activeSessionDetails: [],
|
|
49462
|
+
launchReady: false
|
|
48781
49463
|
};
|
|
48782
|
-
if (
|
|
48783
|
-
|
|
48784
|
-
|
|
48785
|
-
|
|
49464
|
+
if (isSelfNode) {
|
|
49465
|
+
status.connection = {
|
|
49466
|
+
perspective: "selected_coordinator",
|
|
49467
|
+
source: "mesh_peer_status",
|
|
49468
|
+
state: "self",
|
|
49469
|
+
transport: "local",
|
|
49470
|
+
reported: true,
|
|
49471
|
+
reason: "Selected coordinator daemon",
|
|
49472
|
+
lastStateChangeAt: refreshedAt
|
|
49473
|
+
};
|
|
49474
|
+
} else if (daemonId) {
|
|
49475
|
+
const connection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
|
|
49476
|
+
status.connection = connection ?? {
|
|
49477
|
+
perspective: "selected_coordinator",
|
|
49478
|
+
source: "not_reported",
|
|
49479
|
+
state: "unknown",
|
|
49480
|
+
transport: "unknown",
|
|
49481
|
+
reported: false,
|
|
49482
|
+
reason: "No live mesh peer telemetry reported by the selected coordinator yet."
|
|
49483
|
+
};
|
|
49484
|
+
} else {
|
|
49485
|
+
status.connection = {
|
|
49486
|
+
perspective: "selected_coordinator",
|
|
49487
|
+
source: "not_reported",
|
|
49488
|
+
state: "unknown",
|
|
49489
|
+
transport: "unknown",
|
|
49490
|
+
reported: false,
|
|
49491
|
+
reason: "Node has no daemon id, so mesh transport cannot be reported from the selected coordinator."
|
|
49492
|
+
};
|
|
49493
|
+
}
|
|
49494
|
+
const matchedLiveSessionRecords = collectLiveMeshSessionRecords({
|
|
49495
|
+
meshId,
|
|
49496
|
+
node,
|
|
49497
|
+
nodeId,
|
|
49498
|
+
liveSessionRecords: liveMeshSessions,
|
|
49499
|
+
allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
|
|
49500
|
+
});
|
|
49501
|
+
const workspace = readLiveMeshNodeWorkspace({
|
|
49502
|
+
meshId,
|
|
49503
|
+
nodeId,
|
|
49504
|
+
liveSessionRecords: matchedLiveSessionRecords,
|
|
49505
|
+
allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
|
|
49506
|
+
}) || (typeof node.workspace === "string" ? node.workspace : "");
|
|
49507
|
+
status.workspace = workspace || node.workspace;
|
|
49508
|
+
if (matchedLiveSessionRecords.length > 0) {
|
|
49509
|
+
const sessionIds = matchedLiveSessionRecords.map((record2) => typeof record2?.sessionId === "string" ? record2.sessionId : "").filter(Boolean);
|
|
49510
|
+
const providerTypes = matchedLiveSessionRecords.map((record2) => readStringValue(record2?.providerType)).filter(Boolean);
|
|
49511
|
+
status.activeSessions = sessionIds;
|
|
49512
|
+
status.activeSessionDetails = matchedLiveSessionRecords.map(summarizeMeshSessionRecord);
|
|
49513
|
+
if (providerTypes.length > 0) {
|
|
49514
|
+
status.providers = Array.from(/* @__PURE__ */ new Set([...Array.isArray(status.providers) ? status.providers : [], ...providerTypes]));
|
|
48786
49515
|
}
|
|
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
|
-
|
|
49516
|
+
}
|
|
49517
|
+
if (workspace) {
|
|
49518
|
+
if (!fs10.existsSync(workspace)) {
|
|
49519
|
+
const inlineTransitGit = buildInlineMeshTransitGitStatus(node);
|
|
49520
|
+
let remoteProbeApplied = false;
|
|
49521
|
+
if (inlineTransitGit) {
|
|
49522
|
+
status.git = inlineTransitGit;
|
|
49523
|
+
status.health = inlineTransitGit.isGitRepo ? deriveMeshNodeHealthFromGit(inlineTransitGit) : "degraded";
|
|
49524
|
+
remoteProbeApplied = true;
|
|
49525
|
+
} else if (!isSelfNode && daemonId && this.deps.dispatchMeshCommand) {
|
|
49526
|
+
try {
|
|
49527
|
+
const remoteGit = await probeRemoteMeshGitStatus({
|
|
49528
|
+
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
49529
|
+
daemonId,
|
|
49530
|
+
workspace,
|
|
49531
|
+
timeoutMs: 8e3
|
|
49532
|
+
});
|
|
49533
|
+
if (remoteGit) {
|
|
49534
|
+
status.git = remoteGit;
|
|
49535
|
+
status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
|
|
49536
|
+
recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
|
|
49537
|
+
remoteProbeApplied = true;
|
|
49538
|
+
}
|
|
49539
|
+
} catch {
|
|
49540
|
+
const refreshedConnection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
|
|
49541
|
+
const refreshedConnectionState = readStringValue(refreshedConnection?.state);
|
|
49542
|
+
if (refreshedConnection && refreshedConnectionState === "connected") {
|
|
49543
|
+
status.connection = refreshedConnection;
|
|
49544
|
+
try {
|
|
49545
|
+
const remoteGit = await probeRemoteMeshGitStatus({
|
|
49546
|
+
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
49547
|
+
daemonId,
|
|
49548
|
+
workspace,
|
|
49549
|
+
timeoutMs: 12e3
|
|
49550
|
+
});
|
|
49551
|
+
if (remoteGit) {
|
|
49552
|
+
status.git = remoteGit;
|
|
49553
|
+
status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
|
|
49554
|
+
recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
|
|
49555
|
+
remoteProbeApplied = true;
|
|
49556
|
+
}
|
|
49557
|
+
} catch {
|
|
49558
|
+
}
|
|
49559
|
+
}
|
|
48811
49560
|
}
|
|
48812
49561
|
}
|
|
48813
|
-
|
|
48814
|
-
|
|
48815
|
-
|
|
48816
|
-
|
|
48817
|
-
|
|
48818
|
-
|
|
48819
|
-
|
|
48820
|
-
if (
|
|
48821
|
-
|
|
48822
|
-
|
|
49562
|
+
if (!remoteProbeApplied) {
|
|
49563
|
+
const connectionState = readStringValue(status.connection?.state);
|
|
49564
|
+
const pendingPeerGitProbe = !inlineTransitGit && !isSelfNode && !!daemonId && (readStringValue(status.machineStatus) === "online" || readStringValue(status.health) === "online" || connectionState === "connecting" || connectionState === "connected" || connectionState === "unknown");
|
|
49565
|
+
if (pendingPeerGitProbe) {
|
|
49566
|
+
status.gitProbePending = true;
|
|
49567
|
+
status.health = "unknown";
|
|
49568
|
+
}
|
|
49569
|
+
if (applyCachedInlineMeshNodeStatus(
|
|
49570
|
+
status,
|
|
49571
|
+
node,
|
|
49572
|
+
pendingPeerGitProbe ? { skipGit: true, skipError: true, skipHealth: true } : void 0
|
|
49573
|
+
)) {
|
|
49574
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
49575
|
+
nodeStatuses.push(status);
|
|
49576
|
+
continue;
|
|
49577
|
+
}
|
|
49578
|
+
if (meshRecord?.source === "inline_cache" && !isSelfNode) {
|
|
49579
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
49580
|
+
nodeStatuses.push(status);
|
|
49581
|
+
continue;
|
|
49582
|
+
}
|
|
48823
49583
|
}
|
|
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";
|
|
49584
|
+
} else {
|
|
49585
|
+
try {
|
|
49586
|
+
const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
49587
|
+
status.git = gitStatus;
|
|
49588
|
+
recordInlineMeshDirectGitTruth(node, gitStatus, "selected_coordinator_local_git");
|
|
49589
|
+
if (gitStatus.isGitRepo) {
|
|
49590
|
+
status.health = deriveMeshNodeHealthFromGit(gitStatus);
|
|
49591
|
+
} else {
|
|
49592
|
+
status.health = "degraded";
|
|
49593
|
+
if (gitStatus.error && !status.error) status.error = gitStatus.error;
|
|
49594
|
+
}
|
|
49595
|
+
} catch {
|
|
49596
|
+
if (!applyCachedInlineMeshNodeStatus(status, node)) {
|
|
49597
|
+
status.health = "degraded";
|
|
49598
|
+
}
|
|
48848
49599
|
}
|
|
48849
49600
|
}
|
|
48850
49601
|
} else {
|
|
48851
49602
|
applyCachedInlineMeshNodeStatus(status, node);
|
|
48852
49603
|
}
|
|
49604
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
48853
49605
|
nodeStatuses.push(status);
|
|
48854
49606
|
}
|
|
48855
49607
|
return {
|
|
@@ -48858,6 +49610,12 @@ ${block}`);
|
|
|
48858
49610
|
meshName: mesh.name,
|
|
48859
49611
|
repoIdentity: mesh.repoIdentity,
|
|
48860
49612
|
defaultBranch: mesh.defaultBranch,
|
|
49613
|
+
refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
49614
|
+
sourceOfTruth: {
|
|
49615
|
+
membership: meshRecord?.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord?.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
|
|
49616
|
+
coordinatorOwnsLiveTruth: meshRecord?.source !== "inline_bootstrap",
|
|
49617
|
+
historicalEvidenceOnly: ["recoveryHints", "ledger.summary", "queue.summary"]
|
|
49618
|
+
},
|
|
48861
49619
|
nodes: nodeStatuses,
|
|
48862
49620
|
queue: { tasks: queue, summary: queueSummary },
|
|
48863
49621
|
ledger: { entries: ledgerEntries, summary: ledgerSummary }
|
|
@@ -56936,6 +57694,7 @@ async function initDaemonComponents(config2) {
|
|
|
56936
57694
|
sessionHostControl: config2.sessionHostControl,
|
|
56937
57695
|
statusInstanceId: config2.statusInstanceId,
|
|
56938
57696
|
statusVersion: config2.statusVersion,
|
|
57697
|
+
getMeshPeerConnectionStatus: config2.getMeshPeerConnectionStatus,
|
|
56939
57698
|
getCdpLogFn: config2.getCdpLogFn || ((ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn())
|
|
56940
57699
|
});
|
|
56941
57700
|
poller = new AgentStreamPoller({
|
|
@@ -57237,6 +57996,7 @@ __export(src_exports, {
|
|
|
57237
57996
|
prepareSessionChatTailUpdate: () => prepareSessionChatTailUpdate,
|
|
57238
57997
|
prepareSessionModalUpdate: () => prepareSessionModalUpdate,
|
|
57239
57998
|
probeCdpPort: () => probeCdpPort,
|
|
57999
|
+
queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
|
|
57240
58000
|
readChatHistory: () => readChatHistory,
|
|
57241
58001
|
readLedgerEntries: () => readLedgerEntries,
|
|
57242
58002
|
readLedgerSlice: () => readLedgerSlice,
|
|
@@ -72139,7 +72899,7 @@ var require_buffer_list = __commonJS({
|
|
|
72139
72899
|
}
|
|
72140
72900
|
}, {
|
|
72141
72901
|
key: "join",
|
|
72142
|
-
value: function
|
|
72902
|
+
value: function join40(s) {
|
|
72143
72903
|
if (this.length === 0) return "";
|
|
72144
72904
|
var p = this.head;
|
|
72145
72905
|
var ret = "" + p.data;
|
|
@@ -86198,13 +86958,13 @@ function splitStringBySpace(str2) {
|
|
|
86198
86958
|
}
|
|
86199
86959
|
return pieces;
|
|
86200
86960
|
}
|
|
86201
|
-
var import_chardet, import_child_process12,
|
|
86961
|
+
var import_chardet, import_child_process12, import_fs12, import_node_path3, import_node_os3, import_node_crypto3, import_iconv_lite, ExternalEditor;
|
|
86202
86962
|
var init_esm4 = __esm({
|
|
86203
86963
|
"../../node_modules/@inquirer/external-editor/dist/esm/index.js"() {
|
|
86204
86964
|
"use strict";
|
|
86205
86965
|
import_chardet = __toESM(require_lib(), 1);
|
|
86206
86966
|
import_child_process12 = require("child_process");
|
|
86207
|
-
|
|
86967
|
+
import_fs12 = require("fs");
|
|
86208
86968
|
import_node_path3 = __toESM(require("path"), 1);
|
|
86209
86969
|
import_node_os3 = __toESM(require("os"), 1);
|
|
86210
86970
|
import_node_crypto3 = require("crypto");
|
|
@@ -86280,14 +87040,14 @@ var init_esm4 = __esm({
|
|
|
86280
87040
|
if (Object.prototype.hasOwnProperty.call(this.fileOptions, "mode")) {
|
|
86281
87041
|
opt.mode = this.fileOptions.mode;
|
|
86282
87042
|
}
|
|
86283
|
-
(0,
|
|
87043
|
+
(0, import_fs12.writeFileSync)(this.tempFile, this.text, opt);
|
|
86284
87044
|
} catch (createFileError) {
|
|
86285
87045
|
throw new CreateFileError(createFileError);
|
|
86286
87046
|
}
|
|
86287
87047
|
}
|
|
86288
87048
|
readTemporaryFile() {
|
|
86289
87049
|
try {
|
|
86290
|
-
const tempFileBuffer = (0,
|
|
87050
|
+
const tempFileBuffer = (0, import_fs12.readFileSync)(this.tempFile);
|
|
86291
87051
|
if (tempFileBuffer.length === 0) {
|
|
86292
87052
|
this.text = "";
|
|
86293
87053
|
} else {
|
|
@@ -86303,7 +87063,7 @@ var init_esm4 = __esm({
|
|
|
86303
87063
|
}
|
|
86304
87064
|
removeTemporaryFile() {
|
|
86305
87065
|
try {
|
|
86306
|
-
(0,
|
|
87066
|
+
(0, import_fs12.unlinkSync)(this.tempFile);
|
|
86307
87067
|
} catch (removeFileError) {
|
|
86308
87068
|
throw new RemoveFileError(removeFileError);
|
|
86309
87069
|
}
|
|
@@ -88005,25 +88765,25 @@ function resolvePackageVersion(options) {
|
|
|
88005
88765
|
const injectedVersion = options?.injectedVersion || "unknown";
|
|
88006
88766
|
const dir = options?.dirname || __dirname;
|
|
88007
88767
|
const possiblePaths = [
|
|
88008
|
-
(0,
|
|
88009
|
-
(0,
|
|
88010
|
-
(0,
|
|
88768
|
+
(0, import_path8.join)(dir, "..", "..", "package.json"),
|
|
88769
|
+
(0, import_path8.join)(dir, "..", "package.json"),
|
|
88770
|
+
(0, import_path8.join)(dir, "package.json")
|
|
88011
88771
|
];
|
|
88012
88772
|
for (const p of possiblePaths) {
|
|
88013
88773
|
try {
|
|
88014
|
-
const data = JSON.parse((0,
|
|
88774
|
+
const data = JSON.parse((0, import_fs13.readFileSync)(p, "utf-8"));
|
|
88015
88775
|
if (data.version) return data.version;
|
|
88016
88776
|
} catch {
|
|
88017
88777
|
}
|
|
88018
88778
|
}
|
|
88019
88779
|
return injectedVersion;
|
|
88020
88780
|
}
|
|
88021
|
-
var
|
|
88781
|
+
var import_fs13, import_path8;
|
|
88022
88782
|
var init_version = __esm({
|
|
88023
88783
|
"src/version.ts"() {
|
|
88024
88784
|
"use strict";
|
|
88025
|
-
|
|
88026
|
-
|
|
88785
|
+
import_fs13 = require("fs");
|
|
88786
|
+
import_path8 = require("path");
|
|
88027
88787
|
}
|
|
88028
88788
|
});
|
|
88029
88789
|
|
|
@@ -89959,7 +90719,7 @@ var require_filesystem = __commonJS({
|
|
|
89959
90719
|
var LDD_PATH = "/usr/bin/ldd";
|
|
89960
90720
|
var SELF_PATH = "/proc/self/exe";
|
|
89961
90721
|
var MAX_LENGTH = 2048;
|
|
89962
|
-
var
|
|
90722
|
+
var readFileSync24 = (path42) => {
|
|
89963
90723
|
const fd = fs24.openSync(path42, "r");
|
|
89964
90724
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
89965
90725
|
const bytesRead = fs24.readSync(fd, buffer, 0, MAX_LENGTH, 0);
|
|
@@ -89984,7 +90744,7 @@ var require_filesystem = __commonJS({
|
|
|
89984
90744
|
module2.exports = {
|
|
89985
90745
|
LDD_PATH,
|
|
89986
90746
|
SELF_PATH,
|
|
89987
|
-
readFileSync:
|
|
90747
|
+
readFileSync: readFileSync24,
|
|
89988
90748
|
readFile: readFile2
|
|
89989
90749
|
};
|
|
89990
90750
|
}
|
|
@@ -90033,7 +90793,7 @@ var require_detect_libc = __commonJS({
|
|
|
90033
90793
|
"use strict";
|
|
90034
90794
|
var childProcess = require("child_process");
|
|
90035
90795
|
var { isLinux: isLinux2, getReport } = require_process();
|
|
90036
|
-
var { LDD_PATH, SELF_PATH, readFile: readFile2, readFileSync:
|
|
90796
|
+
var { LDD_PATH, SELF_PATH, readFile: readFile2, readFileSync: readFileSync24 } = require_filesystem();
|
|
90037
90797
|
var { interpreterPath } = require_elf();
|
|
90038
90798
|
var cachedFamilyInterpreter;
|
|
90039
90799
|
var cachedFamilyFilesystem;
|
|
@@ -90125,7 +90885,7 @@ var require_detect_libc = __commonJS({
|
|
|
90125
90885
|
}
|
|
90126
90886
|
cachedFamilyFilesystem = null;
|
|
90127
90887
|
try {
|
|
90128
|
-
const lddContent =
|
|
90888
|
+
const lddContent = readFileSync24(LDD_PATH);
|
|
90129
90889
|
cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
|
|
90130
90890
|
} catch (e) {
|
|
90131
90891
|
}
|
|
@@ -90150,7 +90910,7 @@ var require_detect_libc = __commonJS({
|
|
|
90150
90910
|
}
|
|
90151
90911
|
cachedFamilyInterpreter = null;
|
|
90152
90912
|
try {
|
|
90153
|
-
const selfContent =
|
|
90913
|
+
const selfContent = readFileSync24(SELF_PATH);
|
|
90154
90914
|
const path42 = interpreterPath(selfContent);
|
|
90155
90915
|
cachedFamilyInterpreter = familyFromInterpreterPath(path42);
|
|
90156
90916
|
} catch (e) {
|
|
@@ -90214,7 +90974,7 @@ var require_detect_libc = __commonJS({
|
|
|
90214
90974
|
}
|
|
90215
90975
|
cachedVersionFilesystem = null;
|
|
90216
90976
|
try {
|
|
90217
|
-
const lddContent =
|
|
90977
|
+
const lddContent = readFileSync24(LDD_PATH);
|
|
90218
90978
|
const versionMatch = lddContent.match(RE_GLIBC_VERSION);
|
|
90219
90979
|
if (versionMatch) {
|
|
90220
90980
|
cachedVersionFilesystem = versionMatch[1];
|
|
@@ -97213,11 +97973,30 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97213
97973
|
nodeDatachannel = null;
|
|
97214
97974
|
peers = /* @__PURE__ */ new Map();
|
|
97215
97975
|
// Map<targetDaemonId, PeerEntry>
|
|
97976
|
+
peerSnapshots = /* @__PURE__ */ new Map();
|
|
97216
97977
|
pendingRequests = /* @__PURE__ */ new Map();
|
|
97217
97978
|
commandCallback;
|
|
97218
97979
|
p2pFailure(message, command, targetDaemonId) {
|
|
97219
97980
|
return new P2pRelayFailureError(message, { command, targetDaemonId });
|
|
97220
97981
|
}
|
|
97982
|
+
updatePeerSnapshot(targetDaemonId, state, patch = {}) {
|
|
97983
|
+
const previous = this.peerSnapshots.get(targetDaemonId);
|
|
97984
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
97985
|
+
this.peerSnapshots.set(targetDaemonId, {
|
|
97986
|
+
perspective: "selected_coordinator",
|
|
97987
|
+
source: "mesh_peer_status",
|
|
97988
|
+
reported: true,
|
|
97989
|
+
state,
|
|
97990
|
+
transport: patch.transport ?? previous?.transport ?? "unknown",
|
|
97991
|
+
reason: patch.reason ?? previous?.reason,
|
|
97992
|
+
lastStateChangeAt: now,
|
|
97993
|
+
lastConnectedAt: patch.lastConnectedAt ?? previous?.lastConnectedAt,
|
|
97994
|
+
lastCommandAt: patch.lastCommandAt ?? previous?.lastCommandAt
|
|
97995
|
+
});
|
|
97996
|
+
}
|
|
97997
|
+
getPeerConnectionStatus(targetDaemonId) {
|
|
97998
|
+
return this.peerSnapshots.get(targetDaemonId) ?? null;
|
|
97999
|
+
}
|
|
97221
98000
|
invalidatePeer(targetDaemonId, reason, options = {}) {
|
|
97222
98001
|
const peer = this.peers.get(targetDaemonId);
|
|
97223
98002
|
if (peer?.commandQueue) {
|
|
@@ -97232,6 +98011,11 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97232
98011
|
pending.reject(this.p2pFailure(reason, pending.command, targetDaemonId));
|
|
97233
98012
|
}
|
|
97234
98013
|
}
|
|
98014
|
+
const snapshotState = peer?.state === "closed" ? "closed" : peer?.state === "disconnected" ? "disconnected" : "failed";
|
|
98015
|
+
this.updatePeerSnapshot(targetDaemonId, snapshotState, {
|
|
98016
|
+
reason,
|
|
98017
|
+
transport: peer?.isRelay === true ? "relay" : peer?.isRelay === false ? "direct" : "unknown"
|
|
98018
|
+
});
|
|
97235
98019
|
if (options.closeResources !== false && peer) {
|
|
97236
98020
|
try {
|
|
97237
98021
|
peer.dataChannel?.close?.();
|
|
@@ -97264,6 +98048,7 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97264
98048
|
"send_chat",
|
|
97265
98049
|
"read_chat",
|
|
97266
98050
|
"get_chat_debug_bundle",
|
|
98051
|
+
"get_pending_mesh_events",
|
|
97267
98052
|
"git_status",
|
|
97268
98053
|
"git_diff_summary",
|
|
97269
98054
|
"launch_cli",
|
|
@@ -97351,6 +98136,20 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97351
98136
|
if (!peer) {
|
|
97352
98137
|
throw this.p2pFailure("Failed to initiate P2P connection entry", command, targetDaemonId);
|
|
97353
98138
|
}
|
|
98139
|
+
const lastCommandAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
98140
|
+
if (peer.state === "connected") {
|
|
98141
|
+
this.updatePeerSnapshot(targetDaemonId, "connected", {
|
|
98142
|
+
transport: peer.isRelay === true ? "relay" : peer.isRelay === false ? "direct" : "unknown",
|
|
98143
|
+
lastConnectedAt: this.peerSnapshots.get(targetDaemonId)?.lastConnectedAt,
|
|
98144
|
+
lastCommandAt
|
|
98145
|
+
});
|
|
98146
|
+
} else {
|
|
98147
|
+
this.updatePeerSnapshot(targetDaemonId, "connecting", {
|
|
98148
|
+
transport: peer.isRelay === true ? "relay" : peer.isRelay === false ? "direct" : "unknown",
|
|
98149
|
+
reason: "Waiting for mesh DataChannel to open.",
|
|
98150
|
+
lastCommandAt
|
|
98151
|
+
});
|
|
98152
|
+
}
|
|
97354
98153
|
return new Promise((resolve23, reject) => {
|
|
97355
98154
|
const requestId = `req_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
97356
98155
|
const timer = setTimeout(() => {
|
|
@@ -97494,6 +98293,9 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97494
98293
|
remoteDescriptionSet: false
|
|
97495
98294
|
};
|
|
97496
98295
|
this.peers.set(targetDaemonId, entry);
|
|
98296
|
+
this.updatePeerSnapshot(targetDaemonId, "connecting", {
|
|
98297
|
+
reason: isInitiator ? "P2P mesh connection initiated by the selected coordinator." : "Waiting for the remote daemon to finish the mesh DataChannel handshake."
|
|
98298
|
+
});
|
|
97497
98299
|
pc.onLocalDescription((sdp, type2) => {
|
|
97498
98300
|
this.serverConn.sendMeshCommand(targetDaemonId, type2 === "offer" ? "mesh_p2p_offer" : "mesh_p2p_answer", { sdp, type: type2 });
|
|
97499
98301
|
});
|
|
@@ -97504,7 +98306,26 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97504
98306
|
LOG.info("Mesh", `[Mesh] P2P state with ${targetDaemonId.slice(0, 12)}: ${state}`);
|
|
97505
98307
|
if (state === "connected") {
|
|
97506
98308
|
entry.state = "connected";
|
|
98309
|
+
let transport = "unknown";
|
|
98310
|
+
try {
|
|
98311
|
+
const pair = pc.getSelectedCandidatePair?.();
|
|
98312
|
+
if (pair) {
|
|
98313
|
+
const localType = pair.local?.type || "unknown";
|
|
98314
|
+
const remoteType = pair.remote?.type || "unknown";
|
|
98315
|
+
entry.isRelay = localType === "relay" || remoteType === "relay";
|
|
98316
|
+
transport = entry.isRelay ? "relay" : "direct";
|
|
98317
|
+
LOG.info("Mesh", `[Mesh] Candidate pair with ${targetDaemonId.slice(0, 12)}: local=${localType} remote=${remoteType} \u2192 ${transport}`);
|
|
98318
|
+
}
|
|
98319
|
+
} catch {
|
|
98320
|
+
transport = entry.isRelay === true ? "relay" : entry.isRelay === false ? "direct" : "unknown";
|
|
98321
|
+
}
|
|
98322
|
+
this.updatePeerSnapshot(targetDaemonId, "connected", {
|
|
98323
|
+
transport,
|
|
98324
|
+
reason: transport === "relay" ? "Connected over TURN relay." : transport === "direct" ? "Connected directly peer-to-peer." : "Connected, but selected candidate pair details are unavailable.",
|
|
98325
|
+
lastConnectedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
98326
|
+
});
|
|
97507
98327
|
} else if (state === "failed" || state === "closed" || state === "disconnected") {
|
|
98328
|
+
entry.state = state;
|
|
97508
98329
|
this.invalidatePeer(targetDaemonId, `P2P state changed to ${state}`, { rejectPending: true, closeResources: false });
|
|
97509
98330
|
}
|
|
97510
98331
|
});
|
|
@@ -97522,6 +98343,11 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97522
98343
|
dc.onOpen(() => {
|
|
97523
98344
|
LOG.info("Mesh", `[Mesh] DataChannel OPEN with ${targetDaemonId.slice(0, 12)}`);
|
|
97524
98345
|
entry.state = "connected";
|
|
98346
|
+
this.updatePeerSnapshot(targetDaemonId, "connected", {
|
|
98347
|
+
transport: entry.isRelay === true ? "relay" : entry.isRelay === false ? "direct" : "unknown",
|
|
98348
|
+
reason: entry.isRelay === true ? "Connected over TURN relay." : entry.isRelay === false ? "Connected directly peer-to-peer." : "DataChannel open; transport details not reported yet.",
|
|
98349
|
+
lastConnectedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
98350
|
+
});
|
|
97525
98351
|
if (entry.commandQueue) {
|
|
97526
98352
|
const queue = entry.commandQueue;
|
|
97527
98353
|
entry.commandQueue = [];
|
|
@@ -97801,6 +98627,7 @@ var init_adhdev_daemon = __esm({
|
|
|
97801
98627
|
"use strict";
|
|
97802
98628
|
init_server_connection();
|
|
97803
98629
|
init_src();
|
|
98630
|
+
init_mesh_events();
|
|
97804
98631
|
init_daemon_p2p2();
|
|
97805
98632
|
init_screenshot_controller();
|
|
97806
98633
|
init_session_host();
|
|
@@ -97817,7 +98644,7 @@ var init_adhdev_daemon = __esm({
|
|
|
97817
98644
|
init_version();
|
|
97818
98645
|
init_src();
|
|
97819
98646
|
init_runtime_defaults();
|
|
97820
|
-
pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.82-rc.
|
|
98647
|
+
pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.82-rc.31" });
|
|
97821
98648
|
AdhdevDaemon = class _AdhdevDaemon {
|
|
97822
98649
|
localHttpServer = null;
|
|
97823
98650
|
localWss = null;
|
|
@@ -98341,6 +99168,7 @@ ${err?.stack || ""}`);
|
|
|
98341
99168
|
if (!this.meshManager) throw new Error("Mesh manager not initialized");
|
|
98342
99169
|
return this.meshManager.sendCommand(daemonId, command, args);
|
|
98343
99170
|
},
|
|
99171
|
+
getMeshPeerConnectionStatus: (daemonId) => this.meshManager?.getPeerConnectionStatus(daemonId) ?? null,
|
|
98344
99172
|
onStatusChange: () => {
|
|
98345
99173
|
this.invalidateHotChatSnapshotCache();
|
|
98346
99174
|
this.statusReporter?.onStatusChange();
|
|
@@ -98710,6 +99538,7 @@ ${err?.stack || ""}`);
|
|
|
98710
99538
|
const meshId = this.readMeshString(settings.meshNodeFor);
|
|
98711
99539
|
const coordinatorDaemonId = this.readMeshString(settings.meshCoordinatorDaemonId);
|
|
98712
99540
|
if (!meshId || !coordinatorDaemonId) return;
|
|
99541
|
+
const relayTimestamp = typeof event.timestamp === "number" && Number.isFinite(event.timestamp) ? event.timestamp : this.readMeshString(event.timestamp) || void 0;
|
|
98713
99542
|
const payload = {
|
|
98714
99543
|
event: this.readMeshString(event.event),
|
|
98715
99544
|
meshId,
|
|
@@ -98718,7 +99547,8 @@ ${err?.stack || ""}`);
|
|
|
98718
99547
|
targetSessionId: this.readMeshString(event.targetSessionId) || instanceId,
|
|
98719
99548
|
providerType: this.readMeshString(event.providerType),
|
|
98720
99549
|
providerSessionId: this.readMeshString(event.providerSessionId),
|
|
98721
|
-
finalSummary: this.readMeshString(event.finalSummary) || this.readMeshString(event.summary)
|
|
99550
|
+
finalSummary: this.readMeshString(event.finalSummary) || this.readMeshString(event.summary),
|
|
99551
|
+
...relayTimestamp !== void 0 ? { timestamp: relayTimestamp } : {}
|
|
98722
99552
|
};
|
|
98723
99553
|
if (coordinatorDaemonId === localDaemonId) {
|
|
98724
99554
|
try {
|
|
@@ -98733,6 +99563,22 @@ ${err?.stack || ""}`);
|
|
|
98733
99563
|
await this.meshManager.sendCommand(coordinatorDaemonId, "mesh_forward_event", payload);
|
|
98734
99564
|
LOG.info("MeshEvents", `Relayed ${payload.event} for mesh ${meshId} to coordinator daemon ${coordinatorDaemonId.slice(0, 12)}\u2026`);
|
|
98735
99565
|
} catch (error48) {
|
|
99566
|
+
queuePendingMeshCoordinatorEvent({
|
|
99567
|
+
event: payload.event,
|
|
99568
|
+
meshId,
|
|
99569
|
+
nodeLabel: payload.nodeId ? `Node '${payload.nodeId}'` : payload.workspace ? `Agent at ${payload.workspace}` : "Remote agent",
|
|
99570
|
+
nodeId: payload.nodeId || void 0,
|
|
99571
|
+
workspace: payload.workspace || void 0,
|
|
99572
|
+
metadataEvent: {
|
|
99573
|
+
targetSessionId: payload.targetSessionId,
|
|
99574
|
+
providerType: payload.providerType,
|
|
99575
|
+
providerSessionId: payload.providerSessionId,
|
|
99576
|
+
finalSummary: payload.finalSummary,
|
|
99577
|
+
workspace: payload.workspace,
|
|
99578
|
+
...payload.timestamp !== void 0 ? { timestamp: payload.timestamp } : {}
|
|
99579
|
+
},
|
|
99580
|
+
queuedAt: Date.now()
|
|
99581
|
+
});
|
|
98736
99582
|
LOG.warn("MeshEvents", `Failed to relay ${payload.event} for mesh ${meshId}: ${error48?.message || error48}`);
|
|
98737
99583
|
}
|
|
98738
99584
|
}
|
|
@@ -99639,6 +100485,420 @@ var init_runtime_target_trace = __esm({
|
|
|
99639
100485
|
}
|
|
99640
100486
|
});
|
|
99641
100487
|
|
|
100488
|
+
// src/cli/service-commands.ts
|
|
100489
|
+
var service_commands_exports = {};
|
|
100490
|
+
__export(service_commands_exports, {
|
|
100491
|
+
buildPlist: () => buildPlist,
|
|
100492
|
+
installAutoStartServiceForCurrentProcess: () => installAutoStartServiceForCurrentProcess,
|
|
100493
|
+
isAutoStartServiceInstalled: () => isAutoStartServiceInstalled,
|
|
100494
|
+
registerServiceCommands: () => registerServiceCommands
|
|
100495
|
+
});
|
|
100496
|
+
function getDarwinPlistPath() {
|
|
100497
|
+
return import_node_path5.default.join(import_node_os4.default.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
|
|
100498
|
+
}
|
|
100499
|
+
function getWindowsStartupDir() {
|
|
100500
|
+
const appData = process.env.APPDATA || import_node_path5.default.join(import_node_os4.default.homedir(), "AppData", "Roaming");
|
|
100501
|
+
return import_node_path5.default.join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "Startup");
|
|
100502
|
+
}
|
|
100503
|
+
function getWindowsVbsPath() {
|
|
100504
|
+
return import_node_path5.default.join(getWindowsStartupDir(), "adhdev-daemon.vbs");
|
|
100505
|
+
}
|
|
100506
|
+
function resolveCliPath() {
|
|
100507
|
+
return import_node_fs4.default.realpathSync(process.argv[1]);
|
|
100508
|
+
}
|
|
100509
|
+
function ensureDir(dir) {
|
|
100510
|
+
if (!import_node_fs4.default.existsSync(dir)) import_node_fs4.default.mkdirSync(dir, { recursive: true });
|
|
100511
|
+
}
|
|
100512
|
+
async function fetchHealth() {
|
|
100513
|
+
const controller = new AbortController();
|
|
100514
|
+
const timer = setTimeout(() => controller.abort(), DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS2);
|
|
100515
|
+
try {
|
|
100516
|
+
const res = await fetch(`http://127.0.0.1:${DEFAULT_DAEMON_PORT}/health`, { signal: controller.signal });
|
|
100517
|
+
if (!res.ok) return null;
|
|
100518
|
+
return await res.json();
|
|
100519
|
+
} catch {
|
|
100520
|
+
return null;
|
|
100521
|
+
} finally {
|
|
100522
|
+
clearTimeout(timer);
|
|
100523
|
+
}
|
|
100524
|
+
}
|
|
100525
|
+
function getProcessInfo(pid) {
|
|
100526
|
+
try {
|
|
100527
|
+
if (process.platform === "win32") {
|
|
100528
|
+
const out = (0, import_node_child_process4.execSync)(`tasklist /FI "PID eq ${pid}" /FO CSV /NH`, { encoding: "utf-8" });
|
|
100529
|
+
const match = out.match(/"(\d[\d,]+)\sK"/);
|
|
100530
|
+
const memKB = match ? parseInt(match[1].replace(/,/g, ""), 10) : 0;
|
|
100531
|
+
return { uptime: "-", memMB: Math.round(memKB / 1024) };
|
|
100532
|
+
} else {
|
|
100533
|
+
const out = (0, import_node_child_process4.execSync)(`ps -o etime=,rss= -p ${pid}`, { encoding: "utf-8" }).trim();
|
|
100534
|
+
const parts = out.split(/\s+/);
|
|
100535
|
+
const etime = parts[0] || "-";
|
|
100536
|
+
const rssKB = parseInt(parts[1] || "0", 10);
|
|
100537
|
+
return { uptime: formatElapsed(etime), memMB: Math.round(rssKB / 1024) };
|
|
100538
|
+
}
|
|
100539
|
+
} catch {
|
|
100540
|
+
return null;
|
|
100541
|
+
}
|
|
100542
|
+
}
|
|
100543
|
+
function formatElapsed(etime) {
|
|
100544
|
+
const parts = etime.replace("-", ":").split(":").map(Number);
|
|
100545
|
+
if (parts.length === 4) return `${parts[0]}d ${parts[1]}h ${parts[2]}m`;
|
|
100546
|
+
if (parts.length === 3) return `${parts[0]}h ${parts[1]}m`;
|
|
100547
|
+
if (parts.length === 2) return `${parts[0]}m ${parts[1]}s`;
|
|
100548
|
+
return etime;
|
|
100549
|
+
}
|
|
100550
|
+
function rotateLogIfNeeded(logPath) {
|
|
100551
|
+
try {
|
|
100552
|
+
if (!import_node_fs4.default.existsSync(logPath)) return;
|
|
100553
|
+
const stat5 = import_node_fs4.default.statSync(logPath);
|
|
100554
|
+
if (stat5.size > MAX_LOG_SIZE2) {
|
|
100555
|
+
const rotated = logPath + ".old";
|
|
100556
|
+
if (import_node_fs4.default.existsSync(rotated)) import_node_fs4.default.unlinkSync(rotated);
|
|
100557
|
+
import_node_fs4.default.renameSync(logPath, rotated);
|
|
100558
|
+
import_node_fs4.default.writeFileSync(logPath, `[log rotated at ${(/* @__PURE__ */ new Date()).toISOString()}]
|
|
100559
|
+
`, "utf-8");
|
|
100560
|
+
}
|
|
100561
|
+
} catch {
|
|
100562
|
+
}
|
|
100563
|
+
}
|
|
100564
|
+
function rotateLogs() {
|
|
100565
|
+
rotateLogIfNeeded(LOG_OUT);
|
|
100566
|
+
rotateLogIfNeeded(LOG_ERR);
|
|
100567
|
+
}
|
|
100568
|
+
function normalizeLaunchdPathEntry(entry) {
|
|
100569
|
+
const trimmed = String(entry || "").trim();
|
|
100570
|
+
if (!trimmed) return null;
|
|
100571
|
+
if (trimmed.startsWith("~")) {
|
|
100572
|
+
return import_node_path5.default.join(import_node_os4.default.homedir(), trimmed.slice(1));
|
|
100573
|
+
}
|
|
100574
|
+
return import_node_path5.default.isAbsolute(trimmed) ? trimmed : null;
|
|
100575
|
+
}
|
|
100576
|
+
function buildLaunchdPath(nodeExe, currentPath = process.env.PATH || "") {
|
|
100577
|
+
const brewPrefix = import_node_fs4.default.existsSync("/opt/homebrew/bin") ? "/opt/homebrew/bin" : "/usr/local/bin";
|
|
100578
|
+
const entries = [];
|
|
100579
|
+
const seen = /* @__PURE__ */ new Set();
|
|
100580
|
+
const addEntry = (value) => {
|
|
100581
|
+
if (!value) return;
|
|
100582
|
+
const normalized = normalizeLaunchdPathEntry(value);
|
|
100583
|
+
if (!normalized || seen.has(normalized)) return;
|
|
100584
|
+
seen.add(normalized);
|
|
100585
|
+
entries.push(normalized);
|
|
100586
|
+
};
|
|
100587
|
+
addEntry(import_node_path5.default.dirname(nodeExe));
|
|
100588
|
+
for (const entry of String(currentPath || "").split(import_node_path5.default.delimiter)) {
|
|
100589
|
+
addEntry(entry);
|
|
100590
|
+
}
|
|
100591
|
+
for (const entry of [brewPrefix, "/usr/local/bin", "/usr/bin", "/bin", "/usr/sbin", "/sbin"]) {
|
|
100592
|
+
addEntry(entry);
|
|
100593
|
+
}
|
|
100594
|
+
return entries.join(":");
|
|
100595
|
+
}
|
|
100596
|
+
function buildPlist(nodeExe, cliExe, currentPath = process.env.PATH || "") {
|
|
100597
|
+
const pathValue = buildLaunchdPath(nodeExe, currentPath);
|
|
100598
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
100599
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
100600
|
+
<plist version="1.0">
|
|
100601
|
+
<dict>
|
|
100602
|
+
<key>Label</key>
|
|
100603
|
+
<string>${LAUNCHD_LABEL}</string>
|
|
100604
|
+
<key>ProgramArguments</key>
|
|
100605
|
+
<array>
|
|
100606
|
+
<string>${nodeExe}</string>
|
|
100607
|
+
<string>${cliExe}</string>
|
|
100608
|
+
<string>daemon</string>
|
|
100609
|
+
</array>
|
|
100610
|
+
<key>RunAtLoad</key>
|
|
100611
|
+
<true/>
|
|
100612
|
+
<key>KeepAlive</key>
|
|
100613
|
+
<dict>
|
|
100614
|
+
<key>SuccessfulExit</key>
|
|
100615
|
+
<false/>
|
|
100616
|
+
</dict>
|
|
100617
|
+
<key>ThrottleInterval</key>
|
|
100618
|
+
<integer>30</integer>
|
|
100619
|
+
<key>StandardOutPath</key>
|
|
100620
|
+
<string>${LOG_OUT}</string>
|
|
100621
|
+
<key>StandardErrorPath</key>
|
|
100622
|
+
<string>${LOG_ERR}</string>
|
|
100623
|
+
<key>EnvironmentVariables</key>
|
|
100624
|
+
<dict>
|
|
100625
|
+
<key>PATH</key>
|
|
100626
|
+
<string>${pathValue}</string>
|
|
100627
|
+
</dict>
|
|
100628
|
+
</dict>
|
|
100629
|
+
</plist>`;
|
|
100630
|
+
}
|
|
100631
|
+
function installDarwin(nodeExe, cliExe) {
|
|
100632
|
+
const plistPath = getDarwinPlistPath();
|
|
100633
|
+
ensureDir(ADHDEV_DIR);
|
|
100634
|
+
ensureDir(import_node_path5.default.dirname(plistPath));
|
|
100635
|
+
import_node_fs4.default.writeFileSync(plistPath, buildPlist(nodeExe, cliExe), "utf-8");
|
|
100636
|
+
console.log(source_default.gray(` Plist: ${plistPath}`));
|
|
100637
|
+
try {
|
|
100638
|
+
(0, import_node_child_process4.execSync)(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" });
|
|
100639
|
+
} catch {
|
|
100640
|
+
}
|
|
100641
|
+
try {
|
|
100642
|
+
(0, import_node_child_process4.execSync)(`launchctl load -w "${plistPath}"`, { stdio: "ignore" });
|
|
100643
|
+
console.log(source_default.green("\n \u2713 Registered as LaunchAgent \u2014 daemon will start on login."));
|
|
100644
|
+
console.log(source_default.gray(` Logs: ~/.adhdev/daemon-launchd.{out,err}`));
|
|
100645
|
+
} catch (e) {
|
|
100646
|
+
console.log(source_default.red(`
|
|
100647
|
+
\u2717 launchctl load failed: ${e.message}`));
|
|
100648
|
+
}
|
|
100649
|
+
}
|
|
100650
|
+
function uninstallDarwin() {
|
|
100651
|
+
const plistPath = getDarwinPlistPath();
|
|
100652
|
+
if (!import_node_fs4.default.existsSync(plistPath)) {
|
|
100653
|
+
console.log(source_default.yellow("\n \u26A0 Service is not installed."));
|
|
100654
|
+
return;
|
|
100655
|
+
}
|
|
100656
|
+
try {
|
|
100657
|
+
(0, import_node_child_process4.execSync)(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" });
|
|
100658
|
+
} catch {
|
|
100659
|
+
}
|
|
100660
|
+
import_node_fs4.default.unlinkSync(plistPath);
|
|
100661
|
+
console.log(source_default.green("\n \u2713 Removed LaunchAgent. Daemon will no longer auto-start."));
|
|
100662
|
+
}
|
|
100663
|
+
function isInstalledDarwin() {
|
|
100664
|
+
return import_node_fs4.default.existsSync(getDarwinPlistPath());
|
|
100665
|
+
}
|
|
100666
|
+
function buildVbs(nodeExe, cliExe) {
|
|
100667
|
+
const logFile = import_node_path5.default.join(ADHDEV_DIR, "daemon-service.log").replace(/\\/g, "\\\\");
|
|
100668
|
+
const escapedNodeExe = nodeExe.replace(/\\/g, "\\\\");
|
|
100669
|
+
const escapedCliExe = cliExe.replace(/\\/g, "\\\\");
|
|
100670
|
+
return `' ADHDev Daemon Auto-Start (generated by adhdev service install)
|
|
100671
|
+
Set WshShell = CreateObject("WScript.Shell")
|
|
100672
|
+
WshShell.Run "cmd.exe /c """"${escapedNodeExe}"""" """"${escapedCliExe}"""" daemon >> """"${logFile}"""" 2>&1", 0, False
|
|
100673
|
+
`;
|
|
100674
|
+
}
|
|
100675
|
+
function installWindows(nodeExe, cliExe) {
|
|
100676
|
+
const vbsPath = getWindowsVbsPath();
|
|
100677
|
+
ensureDir(ADHDEV_DIR);
|
|
100678
|
+
ensureDir(import_node_path5.default.dirname(vbsPath));
|
|
100679
|
+
import_node_fs4.default.writeFileSync(vbsPath, buildVbs(nodeExe, cliExe), "utf-8");
|
|
100680
|
+
console.log(source_default.gray(` Startup script: ${vbsPath}`));
|
|
100681
|
+
console.log(source_default.green("\n \u2713 Registered in Startup folder \u2014 daemon will start on login (hidden)."));
|
|
100682
|
+
console.log(source_default.gray(` Logs: ${import_node_path5.default.join(ADHDEV_DIR, "daemon-service.log")}`));
|
|
100683
|
+
console.log(source_default.gray(" To start now without rebooting, run: adhdev daemon"));
|
|
100684
|
+
}
|
|
100685
|
+
function uninstallWindows() {
|
|
100686
|
+
const vbsPath = getWindowsVbsPath();
|
|
100687
|
+
if (!import_node_fs4.default.existsSync(vbsPath)) {
|
|
100688
|
+
console.log(source_default.yellow("\n \u26A0 Service is not installed."));
|
|
100689
|
+
return;
|
|
100690
|
+
}
|
|
100691
|
+
import_node_fs4.default.unlinkSync(vbsPath);
|
|
100692
|
+
console.log(source_default.green("\n \u2713 Removed Startup script. Daemon will no longer auto-start."));
|
|
100693
|
+
console.log(source_default.gray(" Note: a currently running daemon is not affected. Stop with: adhdev daemon:stop"));
|
|
100694
|
+
}
|
|
100695
|
+
function isInstalledWindows() {
|
|
100696
|
+
return import_node_fs4.default.existsSync(getWindowsVbsPath());
|
|
100697
|
+
}
|
|
100698
|
+
function isAutoStartServiceInstalled(platform12 = import_node_os4.default.platform()) {
|
|
100699
|
+
if (platform12 === "darwin") return isInstalledDarwin();
|
|
100700
|
+
if (platform12 === "win32") return isInstalledWindows();
|
|
100701
|
+
return false;
|
|
100702
|
+
}
|
|
100703
|
+
function installAutoStartServiceForCurrentProcess(platform12 = import_node_os4.default.platform()) {
|
|
100704
|
+
const nodeExe = process.execPath;
|
|
100705
|
+
const cliExe = resolveCliPath();
|
|
100706
|
+
if (platform12 === "darwin") {
|
|
100707
|
+
installDarwin(nodeExe, cliExe);
|
|
100708
|
+
return true;
|
|
100709
|
+
}
|
|
100710
|
+
if (platform12 === "win32") {
|
|
100711
|
+
installWindows(nodeExe, cliExe);
|
|
100712
|
+
return true;
|
|
100713
|
+
}
|
|
100714
|
+
return false;
|
|
100715
|
+
}
|
|
100716
|
+
function registerServiceCommands(program2) {
|
|
100717
|
+
const svc = program2.command("service").description("\u{1F50C} Manage ADHDev as an OS background auto-start service");
|
|
100718
|
+
svc.command("install").description("Register ADHDev daemon to start automatically on login").action(async () => {
|
|
100719
|
+
console.log(source_default.bold("\n \u{1F680} Installing ADHDev Background Service"));
|
|
100720
|
+
const platform12 = import_node_os4.default.platform();
|
|
100721
|
+
const nodeExe = process.execPath;
|
|
100722
|
+
const cliExe = resolveCliPath();
|
|
100723
|
+
console.log(source_default.gray(` Node: ${nodeExe}`));
|
|
100724
|
+
console.log(source_default.gray(` CLI: ${cliExe}`));
|
|
100725
|
+
console.log(source_default.gray(` Platform: ${platform12}`));
|
|
100726
|
+
if (!installAutoStartServiceForCurrentProcess(platform12)) {
|
|
100727
|
+
console.log(source_default.yellow("\n \u26A0 Auto-start service install is not supported on this platform."));
|
|
100728
|
+
console.log(source_default.gray(" On Linux, create a systemd user unit manually:"));
|
|
100729
|
+
console.log(source_default.gray(" ~/.config/systemd/user/adhdev-daemon.service"));
|
|
100730
|
+
}
|
|
100731
|
+
console.log();
|
|
100732
|
+
});
|
|
100733
|
+
svc.command("uninstall").description("Remove the OS background service").action(async () => {
|
|
100734
|
+
console.log(source_default.bold("\n \u{1F5D1}\uFE0F Removing ADHDev Background Service"));
|
|
100735
|
+
const platform12 = import_node_os4.default.platform();
|
|
100736
|
+
if (platform12 === "darwin") {
|
|
100737
|
+
uninstallDarwin();
|
|
100738
|
+
} else if (platform12 === "win32") {
|
|
100739
|
+
uninstallWindows();
|
|
100740
|
+
} else {
|
|
100741
|
+
console.log(source_default.yellow("\n \u26A0 Not supported on this platform."));
|
|
100742
|
+
}
|
|
100743
|
+
console.log();
|
|
100744
|
+
});
|
|
100745
|
+
svc.command("status").description("Show service installation state and live daemon health").action(async () => {
|
|
100746
|
+
const platform12 = import_node_os4.default.platform();
|
|
100747
|
+
const installed = isAutoStartServiceInstalled(platform12);
|
|
100748
|
+
if (installed) {
|
|
100749
|
+
console.log(source_default.green("\n \u2713 Service is installed."));
|
|
100750
|
+
if (platform12 === "darwin") console.log(source_default.gray(` Plist: ${getDarwinPlistPath()}`));
|
|
100751
|
+
else console.log(source_default.gray(` Script: ${getWindowsVbsPath()}`));
|
|
100752
|
+
} else {
|
|
100753
|
+
console.log(source_default.gray("\n \u2717 Service is not installed. Run: adhdev service install"));
|
|
100754
|
+
}
|
|
100755
|
+
const health = await fetchHealth();
|
|
100756
|
+
if (health?.ok && health.pid) {
|
|
100757
|
+
const info = getProcessInfo(health.pid);
|
|
100758
|
+
if (info) {
|
|
100759
|
+
console.log(source_default.green(` \u2713 Daemon running \u2014 PID ${health.pid}, uptime ${info.uptime}, ${info.memMB} MB`));
|
|
100760
|
+
} else {
|
|
100761
|
+
console.log(source_default.green(` \u2713 Daemon running \u2014 PID ${health.pid}`));
|
|
100762
|
+
}
|
|
100763
|
+
} else {
|
|
100764
|
+
console.log(source_default.yellow(" \u2717 Daemon is not running."));
|
|
100765
|
+
}
|
|
100766
|
+
const outSize = import_node_fs4.default.existsSync(LOG_OUT) ? import_node_fs4.default.statSync(LOG_OUT).size : 0;
|
|
100767
|
+
const errSize = import_node_fs4.default.existsSync(LOG_ERR) ? import_node_fs4.default.statSync(LOG_ERR).size : 0;
|
|
100768
|
+
if (outSize > 0 || errSize > 0) {
|
|
100769
|
+
console.log(source_default.gray(` Logs: stdout ${formatBytes(outSize)}, stderr ${formatBytes(errSize)}`));
|
|
100770
|
+
}
|
|
100771
|
+
console.log();
|
|
100772
|
+
});
|
|
100773
|
+
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) => {
|
|
100774
|
+
if (options.clear) {
|
|
100775
|
+
for (const f of [LOG_OUT, LOG_ERR]) {
|
|
100776
|
+
if (import_node_fs4.default.existsSync(f)) import_node_fs4.default.writeFileSync(f, "", "utf-8");
|
|
100777
|
+
}
|
|
100778
|
+
console.log(source_default.green("\n \u2713 Logs cleared.\n"));
|
|
100779
|
+
return;
|
|
100780
|
+
}
|
|
100781
|
+
const logFile = options.err ? LOG_ERR : LOG_OUT;
|
|
100782
|
+
if (!import_node_fs4.default.existsSync(logFile)) {
|
|
100783
|
+
console.log(source_default.gray(`
|
|
100784
|
+
No log file found: ${logFile}
|
|
100785
|
+
`));
|
|
100786
|
+
return;
|
|
100787
|
+
}
|
|
100788
|
+
const lines = parseInt(options.lines, 10) || 30;
|
|
100789
|
+
console.log(source_default.gray(`
|
|
100790
|
+
\u2500\u2500 ${options.err ? "stderr" : "stdout"}: ${logFile} (last ${lines} lines) \u2500\u2500
|
|
100791
|
+
`));
|
|
100792
|
+
const content = import_node_fs4.default.readFileSync(logFile, "utf-8");
|
|
100793
|
+
const allLines = content.split("\n");
|
|
100794
|
+
const lastLines = allLines.slice(-lines).join("\n");
|
|
100795
|
+
if (lastLines.trim()) console.log(lastLines);
|
|
100796
|
+
console.log(source_default.gray("\n (watching for new output, Ctrl+C to stop)\n"));
|
|
100797
|
+
let offset = Buffer.byteLength(content, "utf-8");
|
|
100798
|
+
const watcher = import_node_fs4.default.watchFile(logFile, { interval: 500 }, () => {
|
|
100799
|
+
try {
|
|
100800
|
+
const stat5 = import_node_fs4.default.statSync(logFile);
|
|
100801
|
+
if (stat5.size > offset) {
|
|
100802
|
+
const fd = import_node_fs4.default.openSync(logFile, "r");
|
|
100803
|
+
const buf = Buffer.alloc(stat5.size - offset);
|
|
100804
|
+
import_node_fs4.default.readSync(fd, buf, 0, buf.length, offset);
|
|
100805
|
+
import_node_fs4.default.closeSync(fd);
|
|
100806
|
+
process.stdout.write(buf.toString("utf-8"));
|
|
100807
|
+
offset = stat5.size;
|
|
100808
|
+
} else if (stat5.size < offset) {
|
|
100809
|
+
offset = 0;
|
|
100810
|
+
}
|
|
100811
|
+
} catch {
|
|
100812
|
+
}
|
|
100813
|
+
});
|
|
100814
|
+
const cleanup = () => {
|
|
100815
|
+
import_node_fs4.default.unwatchFile(logFile);
|
|
100816
|
+
process.exit(0);
|
|
100817
|
+
};
|
|
100818
|
+
process.on("SIGINT", cleanup);
|
|
100819
|
+
process.on("SIGTERM", cleanup);
|
|
100820
|
+
});
|
|
100821
|
+
svc.command("restart").description("Restart the daemon process (service will auto-relaunch)").action(async () => {
|
|
100822
|
+
const platform12 = import_node_os4.default.platform();
|
|
100823
|
+
const installed = isAutoStartServiceInstalled(platform12);
|
|
100824
|
+
if (!installed) {
|
|
100825
|
+
console.log(source_default.yellow("\n \u26A0 Service is not installed. Use `adhdev daemon:restart` for manual restart."));
|
|
100826
|
+
console.log(source_default.gray(" Or install the service first: adhdev service install\n"));
|
|
100827
|
+
return;
|
|
100828
|
+
}
|
|
100829
|
+
rotateLogs();
|
|
100830
|
+
if (platform12 === "darwin") {
|
|
100831
|
+
console.log(source_default.cyan("\n Refreshing LaunchAgent definition and reloading service..."));
|
|
100832
|
+
installAutoStartServiceForCurrentProcess(platform12);
|
|
100833
|
+
console.log();
|
|
100834
|
+
return;
|
|
100835
|
+
}
|
|
100836
|
+
const health = await fetchHealth();
|
|
100837
|
+
if (!health?.pid) {
|
|
100838
|
+
console.log(source_default.yellow("\n \u26A0 Daemon is not currently running."));
|
|
100839
|
+
console.log(source_default.gray(" Start with: adhdev daemon\n"));
|
|
100840
|
+
return;
|
|
100841
|
+
}
|
|
100842
|
+
console.log(source_default.cyan(`
|
|
100843
|
+
Stopping daemon (PID ${health.pid})...`));
|
|
100844
|
+
try {
|
|
100845
|
+
process.kill(health.pid, "SIGTERM");
|
|
100846
|
+
} catch {
|
|
100847
|
+
console.log(source_default.yellow(" Could not send SIGTERM. Process may have already exited."));
|
|
100848
|
+
}
|
|
100849
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
100850
|
+
if (platform12 === "win32") {
|
|
100851
|
+
const vbsPath = getWindowsVbsPath();
|
|
100852
|
+
if (import_node_fs4.default.existsSync(vbsPath)) {
|
|
100853
|
+
try {
|
|
100854
|
+
(0, import_node_child_process4.execSync)(`wscript.exe "${vbsPath}"`, { stdio: "ignore", windowsHide: true });
|
|
100855
|
+
} catch {
|
|
100856
|
+
}
|
|
100857
|
+
}
|
|
100858
|
+
}
|
|
100859
|
+
let restarted = false;
|
|
100860
|
+
for (let i = 0; i < 8; i++) {
|
|
100861
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
100862
|
+
const newHealth = await fetchHealth();
|
|
100863
|
+
if (newHealth?.ok && newHealth.pid !== health.pid) {
|
|
100864
|
+
restarted = true;
|
|
100865
|
+
const info = getProcessInfo(newHealth.pid);
|
|
100866
|
+
console.log(source_default.green(` \u2713 Daemon restarted \u2014 new PID ${newHealth.pid}${info ? `, ${info.memMB} MB` : ""}`));
|
|
100867
|
+
break;
|
|
100868
|
+
}
|
|
100869
|
+
}
|
|
100870
|
+
if (!restarted) {
|
|
100871
|
+
console.log(source_default.yellow(" \u26A0 Daemon did not restart within 10s."));
|
|
100872
|
+
console.log(source_default.gray(" Check: adhdev service logs --err"));
|
|
100873
|
+
}
|
|
100874
|
+
console.log();
|
|
100875
|
+
});
|
|
100876
|
+
}
|
|
100877
|
+
function formatBytes(bytes) {
|
|
100878
|
+
if (bytes === 0) return "0 B";
|
|
100879
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
100880
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
100881
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
100882
|
+
}
|
|
100883
|
+
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;
|
|
100884
|
+
var init_service_commands = __esm({
|
|
100885
|
+
"src/cli/service-commands.ts"() {
|
|
100886
|
+
"use strict";
|
|
100887
|
+
import_node_fs4 = __toESM(require("fs"));
|
|
100888
|
+
import_node_path5 = __toESM(require("path"));
|
|
100889
|
+
import_node_os4 = __toESM(require("os"));
|
|
100890
|
+
import_node_child_process4 = require("child_process");
|
|
100891
|
+
init_source();
|
|
100892
|
+
init_src();
|
|
100893
|
+
DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS2 = 1500;
|
|
100894
|
+
LAUNCHD_LABEL = "dev.adhf.daemon";
|
|
100895
|
+
ADHDEV_DIR = import_node_path5.default.join(import_node_os4.default.homedir(), ".adhdev");
|
|
100896
|
+
LOG_OUT = import_node_path5.default.join(ADHDEV_DIR, "daemon-launchd.out");
|
|
100897
|
+
LOG_ERR = import_node_path5.default.join(ADHDEV_DIR, "daemon-launchd.err");
|
|
100898
|
+
MAX_LOG_SIZE2 = 10 * 1024 * 1024;
|
|
100899
|
+
}
|
|
100900
|
+
});
|
|
100901
|
+
|
|
99642
100902
|
// ../../oss/packages/web-core/src/constants/supported.ts
|
|
99643
100903
|
var supported_exports = {};
|
|
99644
100904
|
__export(supported_exports, {
|
|
@@ -101612,7 +102872,7 @@ function formatDebugTraceEntryLine(entry) {
|
|
|
101612
102872
|
}
|
|
101613
102873
|
|
|
101614
102874
|
// src/cli/daemon-commands.ts
|
|
101615
|
-
var
|
|
102875
|
+
var DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS3 = 1500;
|
|
101616
102876
|
var DEFAULT_TRACE_FOLLOW_INTERVAL_MS = 1500;
|
|
101617
102877
|
var DEFAULT_DAEMON_PORT_TEXT = String(DEFAULT_DAEMON_PORT);
|
|
101618
102878
|
var DEV_SERVER_PORT2 = 19280;
|
|
@@ -101640,6 +102900,15 @@ async function resolveConfiguredUpdateChannel() {
|
|
|
101640
102900
|
function releaseChannelLabel(channel) {
|
|
101641
102901
|
return `${channel} (${CHANNEL_NPM_TAG3[channel]})`;
|
|
101642
102902
|
}
|
|
102903
|
+
function buildDaemonRestartCommandArgv(options = {}) {
|
|
102904
|
+
const cliPath = options.cliPath || process.argv[1];
|
|
102905
|
+
const daemonPort = options.daemonPort || DEFAULT_DAEMON_PORT_TEXT;
|
|
102906
|
+
const platform12 = options.platform || process.platform;
|
|
102907
|
+
if (platform12 === "darwin" && options.serviceInstalled) {
|
|
102908
|
+
return [cliPath, "service", "install"];
|
|
102909
|
+
}
|
|
102910
|
+
return [cliPath, "daemon", "-p", daemonPort];
|
|
102911
|
+
}
|
|
101643
102912
|
async function persistReleaseChannel(channel) {
|
|
101644
102913
|
const { updateConfig: updateConfig2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
101645
102914
|
updateConfig2({ updateChannel: channel, serverUrl: CHANNEL_SERVER_URL3[channel] });
|
|
@@ -101650,7 +102919,7 @@ function hideCommand(command) {
|
|
|
101650
102919
|
}
|
|
101651
102920
|
async function fetchLocalDaemonHealth(port) {
|
|
101652
102921
|
const controller = new AbortController();
|
|
101653
|
-
const timer = setTimeout(() => controller.abort(),
|
|
102922
|
+
const timer = setTimeout(() => controller.abort(), DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS3);
|
|
101654
102923
|
try {
|
|
101655
102924
|
const res = await fetch(`http://127.0.0.1:${port}/health`, { signal: controller.signal });
|
|
101656
102925
|
if (!res.ok) return null;
|
|
@@ -102016,6 +103285,9 @@ async function runDaemonUpgrade(options, pkgVersion3) {
|
|
|
102016
103285
|
} else {
|
|
102017
103286
|
console.log(source_default.cyan(`
|
|
102018
103287
|
Upgrading v${currentVersion} \u2192 v${latest}...`));
|
|
103288
|
+
const { isAutoStartServiceInstalled: isAutoStartServiceInstalled2 } = await Promise.resolve().then(() => (init_service_commands(), service_commands_exports));
|
|
103289
|
+
const serviceInstalled = isAutoStartServiceInstalled2();
|
|
103290
|
+
const shouldRefreshInstalledService = options.restart !== false && process.platform === "darwin" && serviceInstalled;
|
|
102019
103291
|
const daemonWasRunning = options.restart !== false && isDaemonRunning2();
|
|
102020
103292
|
if (daemonWasRunning) {
|
|
102021
103293
|
stopDaemon2();
|
|
@@ -102027,10 +103299,22 @@ async function runDaemonUpgrade(options, pkgVersion3) {
|
|
|
102027
103299
|
packageName: "adhdev",
|
|
102028
103300
|
targetVersion: latest,
|
|
102029
103301
|
parentPid: process.pid,
|
|
102030
|
-
restartArgv:
|
|
103302
|
+
restartArgv: shouldRefreshInstalledService ? buildDaemonRestartCommandArgv({
|
|
103303
|
+
cliPath: process.argv[1],
|
|
103304
|
+
daemonPort: DEFAULT_DAEMON_PORT_TEXT,
|
|
103305
|
+
platform: process.platform,
|
|
103306
|
+
serviceInstalled
|
|
103307
|
+
}) : daemonWasRunning ? buildDaemonRestartCommandArgv({
|
|
103308
|
+
cliPath: process.argv[1],
|
|
103309
|
+
daemonPort: DEFAULT_DAEMON_PORT_TEXT,
|
|
103310
|
+
platform: process.platform,
|
|
103311
|
+
serviceInstalled
|
|
103312
|
+
}) : [],
|
|
102031
103313
|
cwd: process.cwd()
|
|
102032
103314
|
});
|
|
102033
|
-
if (
|
|
103315
|
+
if (shouldRefreshInstalledService) {
|
|
103316
|
+
console.log(source_default.cyan(" Upgrading and refreshing background service in background..."));
|
|
103317
|
+
} else if (daemonWasRunning) {
|
|
102034
103318
|
console.log(source_default.cyan(" Upgrading and restarting daemon in background..."));
|
|
102035
103319
|
} else {
|
|
102036
103320
|
console.log(source_default.cyan(" Upgrading in background..."));
|
|
@@ -102042,29 +103326,44 @@ async function runDaemonUpgrade(options, pkgVersion3) {
|
|
|
102042
103326
|
return;
|
|
102043
103327
|
}
|
|
102044
103328
|
}
|
|
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));
|
|
103329
|
+
if (options.restart !== false) {
|
|
103330
|
+
const { installAutoStartServiceForCurrentProcess: installAutoStartServiceForCurrentProcess2, isAutoStartServiceInstalled: isAutoStartServiceInstalled2 } = await Promise.resolve().then(() => (init_service_commands(), service_commands_exports));
|
|
103331
|
+
const serviceInstalled = isAutoStartServiceInstalled2();
|
|
103332
|
+
if (process.platform === "darwin" && serviceInstalled) {
|
|
103333
|
+
console.log(source_default.yellow("\n Refreshing LaunchAgent definition..."));
|
|
103334
|
+
installAutoStartServiceForCurrentProcess2(process.platform);
|
|
103335
|
+
console.log();
|
|
103336
|
+
return;
|
|
103337
|
+
}
|
|
102059
103338
|
if (isDaemonRunning2()) {
|
|
102060
|
-
console.log(source_default.
|
|
103339
|
+
console.log(source_default.yellow("\n Restarting daemon..."));
|
|
103340
|
+
stopDaemon2();
|
|
103341
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
103342
|
+
stopManagedSessionHostProcess2();
|
|
103343
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
103344
|
+
const child = spawn7(process.execPath, buildDaemonRestartCommandArgv({
|
|
103345
|
+
cliPath: process.argv[1],
|
|
103346
|
+
daemonPort: DEFAULT_DAEMON_PORT_TEXT,
|
|
103347
|
+
platform: process.platform,
|
|
103348
|
+
serviceInstalled
|
|
103349
|
+
}), {
|
|
103350
|
+
detached: true,
|
|
103351
|
+
stdio: "ignore",
|
|
103352
|
+
windowsHide: true,
|
|
103353
|
+
env: { ...process.env }
|
|
103354
|
+
});
|
|
103355
|
+
child.unref();
|
|
103356
|
+
await new Promise((r) => setTimeout(r, 3e3));
|
|
103357
|
+
if (isDaemonRunning2()) {
|
|
103358
|
+
console.log(source_default.green(` \u2713 Daemon restarted with new version
|
|
102061
103359
|
`));
|
|
102062
|
-
|
|
102063
|
-
|
|
103360
|
+
} else {
|
|
103361
|
+
console.log(source_default.yellow(` \u26A0 Daemon not detected. Start manually: adhdev daemon
|
|
102064
103362
|
`));
|
|
103363
|
+
}
|
|
103364
|
+
} else {
|
|
103365
|
+
console.log(source_default.gray("\n Daemon was not running. Start with: adhdev daemon\n"));
|
|
102065
103366
|
}
|
|
102066
|
-
} else if (options.restart !== false) {
|
|
102067
|
-
console.log(source_default.gray("\n Daemon was not running. Start with: adhdev daemon\n"));
|
|
102068
103367
|
} else {
|
|
102069
103368
|
console.log(source_default.green("\n \u2713 Upgrade complete (daemon not restarted)\n"));
|
|
102070
103369
|
}
|
|
@@ -102235,7 +103534,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
|
|
|
102235
103534
|
}
|
|
102236
103535
|
try {
|
|
102237
103536
|
const controller = new AbortController();
|
|
102238
|
-
const timer = setTimeout(() => controller.abort(),
|
|
103537
|
+
const timer = setTimeout(() => controller.abort(), DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS3);
|
|
102239
103538
|
const res = await fetch(`${DEV_SERVER_BASE_URL}/api/status`, { signal: controller.signal });
|
|
102240
103539
|
clearTimeout(timer);
|
|
102241
103540
|
if (res.ok) {
|
|
@@ -102782,373 +104081,8 @@ function buildDoctorAdvice(input) {
|
|
|
102782
104081
|
return advice;
|
|
102783
104082
|
}
|
|
102784
104083
|
|
|
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
104084
|
// src/cli/doctor-commands.ts
|
|
104085
|
+
init_service_commands();
|
|
103152
104086
|
function resolvePackageRoot() {
|
|
103153
104087
|
return path39.resolve(__dirname, "..", "..");
|
|
103154
104088
|
}
|
|
@@ -104640,6 +105574,9 @@ function registerCdpCommands(program2) {
|
|
|
104640
105574
|
});
|
|
104641
105575
|
}
|
|
104642
105576
|
|
|
105577
|
+
// src/cli/index.ts
|
|
105578
|
+
init_service_commands();
|
|
105579
|
+
|
|
104643
105580
|
// src/cli/mcp-commands.ts
|
|
104644
105581
|
var import_node_child_process5 = require("child_process");
|
|
104645
105582
|
var fs23 = __toESM(require("fs"));
|