@adhdev/daemon-core 0.9.81 → 0.9.82-rc.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/boot/daemon-lifecycle.d.ts +2 -0
- package/dist/commands/router.d.ts +2 -0
- package/dist/git/git-commands.d.ts +1 -0
- package/dist/git/git-status.d.ts +5 -0
- package/dist/git/git-types.d.ts +10 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +415 -78
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +414 -78
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-events.d.ts +3 -0
- package/dist/repo-mesh-types.d.ts +121 -0
- package/package.json +1 -1
- package/src/boot/daemon-lifecycle.ts +3 -0
- package/src/commands/router.ts +373 -67
- package/src/git/git-commands.ts +3 -3
- package/src/git/git-status.ts +97 -6
- package/src/git/git-summary.ts +3 -0
- package/src/git/git-types.ts +11 -0
- package/src/index.ts +9 -1
- package/src/mesh/mesh-events.ts +14 -3
- package/src/repo-mesh-types.ts +131 -0
package/dist/index.js
CHANGED
|
@@ -1896,10 +1896,18 @@ __export(mesh_events_exports, {
|
|
|
1896
1896
|
drainPendingMeshCoordinatorEvents: () => drainPendingMeshCoordinatorEvents,
|
|
1897
1897
|
getPendingMeshCoordinatorEvents: () => getPendingMeshCoordinatorEvents,
|
|
1898
1898
|
handleMeshForwardEvent: () => handleMeshForwardEvent,
|
|
1899
|
+
queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
|
|
1899
1900
|
setupMeshEventForwarding: () => setupMeshEventForwarding,
|
|
1900
1901
|
triggerMeshQueue: () => triggerMeshQueue,
|
|
1901
1902
|
tryAssignQueueTask: () => tryAssignQueueTask
|
|
1902
1903
|
});
|
|
1904
|
+
function queuePendingMeshCoordinatorEvent(event) {
|
|
1905
|
+
if (pendingMeshCoordinatorEvents.length >= MAX_PENDING_EVENTS) {
|
|
1906
|
+
return false;
|
|
1907
|
+
}
|
|
1908
|
+
pendingMeshCoordinatorEvents.push(event);
|
|
1909
|
+
return true;
|
|
1910
|
+
}
|
|
1903
1911
|
function drainPendingMeshCoordinatorEvents() {
|
|
1904
1912
|
return pendingMeshCoordinatorEvents.splice(0);
|
|
1905
1913
|
}
|
|
@@ -2471,17 +2479,18 @@ function injectMeshSystemMessage(components, args) {
|
|
|
2471
2479
|
return true;
|
|
2472
2480
|
});
|
|
2473
2481
|
if (coordinatorInstances.length === 0) {
|
|
2474
|
-
if (
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
}
|
|
2483
|
-
|
|
2484
|
-
|
|
2482
|
+
if (queuePendingMeshCoordinatorEvent({
|
|
2483
|
+
event: args.event,
|
|
2484
|
+
meshId: args.meshId,
|
|
2485
|
+
nodeLabel: args.nodeLabel,
|
|
2486
|
+
nodeId: args.nodeId || void 0,
|
|
2487
|
+
workspace: readNonEmptyString(args.metadataEvent.workspace),
|
|
2488
|
+
metadataEvent: {
|
|
2489
|
+
...args.metadataEvent,
|
|
2490
|
+
...recoveryContext ? { recoveryContext } : {}
|
|
2491
|
+
},
|
|
2492
|
+
queuedAt: Date.now()
|
|
2493
|
+
})) {
|
|
2485
2494
|
LOG.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId})`);
|
|
2486
2495
|
}
|
|
2487
2496
|
return { success: true, forwarded: 0 };
|
|
@@ -5860,6 +5869,7 @@ __export(index_exports, {
|
|
|
5860
5869
|
prepareSessionChatTailUpdate: () => prepareSessionChatTailUpdate,
|
|
5861
5870
|
prepareSessionModalUpdate: () => prepareSessionModalUpdate,
|
|
5862
5871
|
probeCdpPort: () => probeCdpPort,
|
|
5872
|
+
queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
|
|
5863
5873
|
readChatHistory: () => readChatHistory,
|
|
5864
5874
|
readLedgerEntries: () => readLedgerEntries,
|
|
5865
5875
|
readLedgerSlice: () => readLedgerSlice,
|
|
@@ -5913,8 +5923,14 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
5913
5923
|
const includeSubmodules = options.includeSubmodules !== false;
|
|
5914
5924
|
try {
|
|
5915
5925
|
const repo = await resolveGitRepository(workspace, options);
|
|
5916
|
-
|
|
5917
|
-
|
|
5926
|
+
let parsed = await readPorcelainStatus(repo, options);
|
|
5927
|
+
let upstreamProbe = getInitialUpstreamProbe(parsed);
|
|
5928
|
+
if (options.refreshUpstream) {
|
|
5929
|
+
upstreamProbe = await refreshTrackedUpstream(repo, parsed, options);
|
|
5930
|
+
if (upstreamProbe.upstreamStatus === "fresh") {
|
|
5931
|
+
parsed = await readPorcelainStatus(repo, options);
|
|
5932
|
+
}
|
|
5933
|
+
}
|
|
5918
5934
|
const head = await readHead(repo, options);
|
|
5919
5935
|
const stashCount = await readStashCount(repo, options);
|
|
5920
5936
|
let submodules;
|
|
@@ -5929,6 +5945,9 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
5929
5945
|
headCommit: head.commit,
|
|
5930
5946
|
headMessage: head.message,
|
|
5931
5947
|
upstream: parsed.upstream,
|
|
5948
|
+
upstreamStatus: parsed.upstream ? upstreamProbe.upstreamStatus : "no_upstream",
|
|
5949
|
+
upstreamFetchedAt: upstreamProbe.upstreamFetchedAt,
|
|
5950
|
+
upstreamFetchError: upstreamProbe.upstreamFetchError,
|
|
5932
5951
|
ahead: parsed.ahead,
|
|
5933
5952
|
behind: parsed.behind,
|
|
5934
5953
|
staged: parsed.staged,
|
|
@@ -5953,6 +5972,60 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
5953
5972
|
);
|
|
5954
5973
|
}
|
|
5955
5974
|
}
|
|
5975
|
+
async function readPorcelainStatus(repo, options) {
|
|
5976
|
+
const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
|
|
5977
|
+
return parsePorcelainV2Status(statusOutput.stdout);
|
|
5978
|
+
}
|
|
5979
|
+
function getInitialUpstreamProbe(parsed) {
|
|
5980
|
+
return {
|
|
5981
|
+
upstreamStatus: parsed.upstream ? "unchecked" : "no_upstream"
|
|
5982
|
+
};
|
|
5983
|
+
}
|
|
5984
|
+
async function refreshTrackedUpstream(repo, parsed, options) {
|
|
5985
|
+
if (!parsed.upstream || !parsed.branch) {
|
|
5986
|
+
return { upstreamStatus: "no_upstream" };
|
|
5987
|
+
}
|
|
5988
|
+
const remoteName = await readBranchRemote(repo, parsed.branch, options) ?? inferRemoteName(parsed.upstream);
|
|
5989
|
+
if (!remoteName) {
|
|
5990
|
+
return {
|
|
5991
|
+
upstreamStatus: "stale",
|
|
5992
|
+
upstreamFetchError: `Unable to resolve remote for upstream '${parsed.upstream}'`
|
|
5993
|
+
};
|
|
5994
|
+
}
|
|
5995
|
+
try {
|
|
5996
|
+
await runGit(repo, ["fetch", "--quiet", "--prune", "--no-tags", remoteName], options);
|
|
5997
|
+
return {
|
|
5998
|
+
upstreamStatus: "fresh",
|
|
5999
|
+
upstreamFetchedAt: Date.now()
|
|
6000
|
+
};
|
|
6001
|
+
} catch (error) {
|
|
6002
|
+
return {
|
|
6003
|
+
upstreamStatus: "stale",
|
|
6004
|
+
upstreamFetchError: formatGitError(error)
|
|
6005
|
+
};
|
|
6006
|
+
}
|
|
6007
|
+
}
|
|
6008
|
+
async function readBranchRemote(repo, branch, options) {
|
|
6009
|
+
try {
|
|
6010
|
+
const result = await runGit(repo, ["config", "--get", `branch.${branch}.remote`], options);
|
|
6011
|
+
return result.stdout.trim() || null;
|
|
6012
|
+
} catch {
|
|
6013
|
+
return null;
|
|
6014
|
+
}
|
|
6015
|
+
}
|
|
6016
|
+
function inferRemoteName(upstream) {
|
|
6017
|
+
const [remoteName] = upstream.split("/");
|
|
6018
|
+
return remoteName?.trim() || null;
|
|
6019
|
+
}
|
|
6020
|
+
function formatGitError(error) {
|
|
6021
|
+
if (error instanceof GitCommandError) {
|
|
6022
|
+
return error.stderr || error.message;
|
|
6023
|
+
}
|
|
6024
|
+
if (error instanceof Error) {
|
|
6025
|
+
return error.message;
|
|
6026
|
+
}
|
|
6027
|
+
return String(error);
|
|
6028
|
+
}
|
|
5956
6029
|
function parsePorcelainV2Status(output) {
|
|
5957
6030
|
const parsed = {
|
|
5958
6031
|
branch: null,
|
|
@@ -6047,6 +6120,7 @@ function emptyStatus(workspace, lastCheckedAt, error) {
|
|
|
6047
6120
|
headCommit: null,
|
|
6048
6121
|
headMessage: null,
|
|
6049
6122
|
upstream: null,
|
|
6123
|
+
upstreamStatus: "unavailable",
|
|
6050
6124
|
ahead: 0,
|
|
6051
6125
|
behind: 0,
|
|
6052
6126
|
staged: 0,
|
|
@@ -6327,6 +6401,9 @@ function createGitCompactSummary(status, diffSummary) {
|
|
|
6327
6401
|
isGitRepo: status.isGitRepo,
|
|
6328
6402
|
repoRoot: status.repoRoot,
|
|
6329
6403
|
branch: status.branch,
|
|
6404
|
+
upstreamStatus: status.upstreamStatus,
|
|
6405
|
+
upstreamFetchedAt: status.upstreamFetchedAt,
|
|
6406
|
+
upstreamFetchError: status.upstreamFetchError,
|
|
6330
6407
|
dirty: status.staged > 0 || status.modified > 0 || status.untracked > 0 || status.deleted > 0 || status.renamed > 0 || conflictCount > 0 || changedFiles > 0,
|
|
6331
6408
|
changedFiles,
|
|
6332
6409
|
ahead: status.ahead,
|
|
@@ -6671,7 +6748,7 @@ var defaultSnapshotStore = createGitSnapshotStore({
|
|
|
6671
6748
|
});
|
|
6672
6749
|
function createDefaultGitCommandServices() {
|
|
6673
6750
|
return {
|
|
6674
|
-
getStatus: ({ workspace }) => getGitRepoStatus(workspace),
|
|
6751
|
+
getStatus: ({ workspace, refreshUpstream }) => getGitRepoStatus(workspace, { refreshUpstream }),
|
|
6675
6752
|
getDiffSummary: ({ workspace }) => getGitDiffSummary(workspace),
|
|
6676
6753
|
getDiffFile: ({ workspace, path: filePath }) => getGitFileDiff(workspace, filePath),
|
|
6677
6754
|
createSnapshot: ({ workspace, reason, sessionId, turnId }) => defaultSnapshotStore.create({
|
|
@@ -6757,7 +6834,7 @@ async function handleGitCommand(command, args, services = defaultGitCommandServi
|
|
|
6757
6834
|
switch (command) {
|
|
6758
6835
|
case "git_status": {
|
|
6759
6836
|
if (!services.getStatus) return serviceNotImplemented(command);
|
|
6760
|
-
const status = await runService(() => services.getStatus({ workspace }));
|
|
6837
|
+
const status = await runService(() => services.getStatus({ workspace, refreshUpstream: optionalBoolean(args?.refreshUpstream) }));
|
|
6761
6838
|
return "success" in status ? status : { success: true, status };
|
|
6762
6839
|
}
|
|
6763
6840
|
case "git_diff_summary": {
|
|
@@ -23814,6 +23891,240 @@ function readProviderPriorityFromPolicy(policy) {
|
|
|
23814
23891
|
return true;
|
|
23815
23892
|
});
|
|
23816
23893
|
}
|
|
23894
|
+
function readObjectRecord(value) {
|
|
23895
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
23896
|
+
}
|
|
23897
|
+
function readStringValue(...values) {
|
|
23898
|
+
for (const value of values) {
|
|
23899
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
23900
|
+
}
|
|
23901
|
+
return void 0;
|
|
23902
|
+
}
|
|
23903
|
+
function readNumberValue(...values) {
|
|
23904
|
+
for (const value of values) {
|
|
23905
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
23906
|
+
}
|
|
23907
|
+
return void 0;
|
|
23908
|
+
}
|
|
23909
|
+
function readBooleanValue(...values) {
|
|
23910
|
+
for (const value of values) {
|
|
23911
|
+
if (typeof value === "boolean") return value;
|
|
23912
|
+
}
|
|
23913
|
+
return void 0;
|
|
23914
|
+
}
|
|
23915
|
+
function readGitSubmodules(value) {
|
|
23916
|
+
if (!Array.isArray(value)) return void 0;
|
|
23917
|
+
const submodules = value.map((entry) => {
|
|
23918
|
+
const submodule = readObjectRecord(entry);
|
|
23919
|
+
const path28 = readStringValue(submodule.path);
|
|
23920
|
+
const commit = readStringValue(submodule.commit);
|
|
23921
|
+
const repoPath = readStringValue(submodule.repoPath, submodule.repo_root);
|
|
23922
|
+
if (!path28 || !commit || !repoPath) return null;
|
|
23923
|
+
return {
|
|
23924
|
+
path: path28,
|
|
23925
|
+
commit,
|
|
23926
|
+
repoPath,
|
|
23927
|
+
dirty: readBooleanValue(submodule.dirty) ?? false,
|
|
23928
|
+
outOfSync: readBooleanValue(submodule.outOfSync, submodule.out_of_sync) ?? false,
|
|
23929
|
+
lastCheckedAt: readNumberValue(submodule.lastCheckedAt, submodule.last_checked_at) ?? Date.now(),
|
|
23930
|
+
...readStringValue(submodule.error) ? { error: readStringValue(submodule.error) } : {}
|
|
23931
|
+
};
|
|
23932
|
+
}).filter((entry) => entry !== null);
|
|
23933
|
+
return submodules.length > 0 ? submodules : void 0;
|
|
23934
|
+
}
|
|
23935
|
+
function buildCachedInlineMeshGitStatus(node) {
|
|
23936
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
23937
|
+
const cachedGit = readObjectRecord(cachedStatus.git);
|
|
23938
|
+
if (Object.keys(cachedGit).length) {
|
|
23939
|
+
const conflictFiles2 = Array.isArray(cachedGit.conflictFiles) ? cachedGit.conflictFiles.filter((value) => typeof value === "string") : [];
|
|
23940
|
+
const conflictCount2 = readNumberValue(cachedGit.conflicts) ?? conflictFiles2.length;
|
|
23941
|
+
const hasConflicts2 = readBooleanValue(cachedGit.hasConflicts) ?? conflictCount2 > 0;
|
|
23942
|
+
const isGitRepo2 = readBooleanValue(cachedGit.isGitRepo);
|
|
23943
|
+
if (isGitRepo2 !== void 0) {
|
|
23944
|
+
const submodules2 = readGitSubmodules(cachedGit.submodules);
|
|
23945
|
+
return {
|
|
23946
|
+
workspace: readStringValue(cachedGit.workspace, node?.workspace) || "",
|
|
23947
|
+
repoRoot: readStringValue(cachedGit.repoRoot, node?.repoRoot, node?.workspace) || null,
|
|
23948
|
+
isGitRepo: isGitRepo2,
|
|
23949
|
+
branch: readStringValue(cachedGit.branch) ?? null,
|
|
23950
|
+
headCommit: readStringValue(cachedGit.headCommit) ?? null,
|
|
23951
|
+
headMessage: readStringValue(cachedGit.headMessage) ?? null,
|
|
23952
|
+
upstream: readStringValue(cachedGit.upstream) ?? null,
|
|
23953
|
+
ahead: readNumberValue(cachedGit.ahead) ?? 0,
|
|
23954
|
+
behind: readNumberValue(cachedGit.behind) ?? 0,
|
|
23955
|
+
staged: readNumberValue(cachedGit.staged) ?? 0,
|
|
23956
|
+
modified: readNumberValue(cachedGit.modified) ?? 0,
|
|
23957
|
+
untracked: readNumberValue(cachedGit.untracked) ?? 0,
|
|
23958
|
+
deleted: readNumberValue(cachedGit.deleted) ?? 0,
|
|
23959
|
+
renamed: readNumberValue(cachedGit.renamed) ?? 0,
|
|
23960
|
+
hasConflicts: hasConflicts2,
|
|
23961
|
+
conflictFiles: conflictFiles2,
|
|
23962
|
+
stashCount: readNumberValue(cachedGit.stashCount) ?? 0,
|
|
23963
|
+
lastCheckedAt: readNumberValue(cachedGit.lastCheckedAt) ?? Date.now(),
|
|
23964
|
+
...submodules2 ? { submodules: submodules2 } : {}
|
|
23965
|
+
};
|
|
23966
|
+
}
|
|
23967
|
+
}
|
|
23968
|
+
const rawGit = readObjectRecord(node?.lastGit ?? node?.last_git);
|
|
23969
|
+
const gitResult = readObjectRecord(rawGit.result);
|
|
23970
|
+
const directStatus = readObjectRecord(rawGit.status);
|
|
23971
|
+
const nestedStatus = readObjectRecord(gitResult.status);
|
|
23972
|
+
const rawProbe = readObjectRecord(node?.lastProbe ?? node?.last_probe);
|
|
23973
|
+
const probeGit = readObjectRecord(rawProbe.git);
|
|
23974
|
+
const probeGitResult = readObjectRecord(probeGit.result);
|
|
23975
|
+
const probeDirectStatus = readObjectRecord(probeGit.status);
|
|
23976
|
+
const probeNestedStatus = readObjectRecord(probeGitResult.status);
|
|
23977
|
+
const status = Object.keys(directStatus).length ? directStatus : Object.keys(nestedStatus).length ? nestedStatus : Object.keys(probeDirectStatus).length ? probeDirectStatus : Object.keys(probeNestedStatus).length ? probeNestedStatus : {};
|
|
23978
|
+
const isGitRepo = readBooleanValue(status.isGitRepo);
|
|
23979
|
+
if (!Object.keys(status).length || isGitRepo === void 0) return void 0;
|
|
23980
|
+
const conflictFiles = Array.isArray(status.conflictFiles) ? status.conflictFiles.filter((value) => typeof value === "string") : [];
|
|
23981
|
+
const conflictCount = readNumberValue(status.conflicts) ?? conflictFiles.length;
|
|
23982
|
+
const hasConflicts = readBooleanValue(status.hasConflicts) ?? conflictCount > 0;
|
|
23983
|
+
const submodules = readGitSubmodules(status.submodules);
|
|
23984
|
+
return {
|
|
23985
|
+
workspace: readStringValue(status.workspace, node?.workspace) || "",
|
|
23986
|
+
repoRoot: readStringValue(status.repoRoot, node?.repoRoot, node?.workspace) || null,
|
|
23987
|
+
isGitRepo,
|
|
23988
|
+
branch: readStringValue(status.branch) ?? null,
|
|
23989
|
+
headCommit: readStringValue(status.headCommit) ?? null,
|
|
23990
|
+
headMessage: readStringValue(status.headMessage) ?? null,
|
|
23991
|
+
upstream: readStringValue(status.upstream) ?? null,
|
|
23992
|
+
ahead: readNumberValue(status.ahead) ?? 0,
|
|
23993
|
+
behind: readNumberValue(status.behind) ?? 0,
|
|
23994
|
+
staged: readNumberValue(status.staged) ?? 0,
|
|
23995
|
+
modified: readNumberValue(status.modified) ?? 0,
|
|
23996
|
+
untracked: readNumberValue(status.untracked) ?? 0,
|
|
23997
|
+
deleted: readNumberValue(status.deleted) ?? 0,
|
|
23998
|
+
renamed: readNumberValue(status.renamed) ?? 0,
|
|
23999
|
+
hasConflicts,
|
|
24000
|
+
conflictFiles,
|
|
24001
|
+
stashCount: readNumberValue(status.stashCount) ?? 0,
|
|
24002
|
+
lastCheckedAt: Date.now(),
|
|
24003
|
+
...submodules ? { submodules } : {}
|
|
24004
|
+
};
|
|
24005
|
+
}
|
|
24006
|
+
function hasGitWorktreeChanges(git) {
|
|
24007
|
+
if (!git) return false;
|
|
24008
|
+
return Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
|
|
24009
|
+
}
|
|
24010
|
+
function getGitSubmoduleDriftState(git) {
|
|
24011
|
+
const submodules = Array.isArray(git?.submodules) ? git.submodules : [];
|
|
24012
|
+
let dirty = false;
|
|
24013
|
+
let outOfSync = false;
|
|
24014
|
+
for (const entry of submodules) {
|
|
24015
|
+
const submodule = readObjectRecord(entry);
|
|
24016
|
+
if (readBooleanValue(submodule.dirty) === true) dirty = true;
|
|
24017
|
+
if (readBooleanValue(submodule.outOfSync) === true || !!readStringValue(submodule.error)) outOfSync = true;
|
|
24018
|
+
}
|
|
24019
|
+
return { dirty, outOfSync };
|
|
24020
|
+
}
|
|
24021
|
+
function deriveMeshNodeHealthFromGit(git) {
|
|
24022
|
+
if (!git || readBooleanValue(git.isGitRepo) === false) return "degraded";
|
|
24023
|
+
const branch = readStringValue(git.branch);
|
|
24024
|
+
if (!branch) return "degraded";
|
|
24025
|
+
const submoduleDrift = getGitSubmoduleDriftState(git);
|
|
24026
|
+
if (submoduleDrift.outOfSync) return "degraded";
|
|
24027
|
+
if (submoduleDrift.dirty || hasGitWorktreeChanges(git)) return "dirty";
|
|
24028
|
+
return "online";
|
|
24029
|
+
}
|
|
24030
|
+
function readCachedInlineMeshActiveSessions(node) {
|
|
24031
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
24032
|
+
const activeSession = readObjectRecord(cachedStatus.activeSession);
|
|
24033
|
+
const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
|
|
24034
|
+
const sessionId = readStringValue(fallbackSession.id, fallbackSession.sessionId, fallbackSession.session_id, node?.activeSessionId, node?.active_session_id, node?.sessionId, node?.session_id);
|
|
24035
|
+
return sessionId ? [sessionId] : [];
|
|
24036
|
+
}
|
|
24037
|
+
function readCachedInlineMeshActiveSessionDetails(node) {
|
|
24038
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
24039
|
+
const activeSession = readObjectRecord(cachedStatus.activeSession);
|
|
24040
|
+
const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
|
|
24041
|
+
const sessionId = readStringValue(
|
|
24042
|
+
fallbackSession.id,
|
|
24043
|
+
fallbackSession.sessionId,
|
|
24044
|
+
fallbackSession.session_id,
|
|
24045
|
+
node?.activeSessionId,
|
|
24046
|
+
node?.active_session_id,
|
|
24047
|
+
node?.sessionId,
|
|
24048
|
+
node?.session_id
|
|
24049
|
+
);
|
|
24050
|
+
if (!sessionId) return [];
|
|
24051
|
+
return [{
|
|
24052
|
+
sessionId,
|
|
24053
|
+
providerType: readStringValue(
|
|
24054
|
+
fallbackSession.providerType,
|
|
24055
|
+
fallbackSession.provider_type,
|
|
24056
|
+
fallbackSession.cliType,
|
|
24057
|
+
fallbackSession.cli_type,
|
|
24058
|
+
fallbackSession.provider,
|
|
24059
|
+
node?.providerType,
|
|
24060
|
+
node?.provider_type
|
|
24061
|
+
),
|
|
24062
|
+
state: readStringValue(fallbackSession.status, fallbackSession.state, fallbackSession.lifecycle),
|
|
24063
|
+
lifecycle: readStringValue(fallbackSession.lifecycle),
|
|
24064
|
+
title: readStringValue(fallbackSession.title, fallbackSession.displayName, fallbackSession.display_name) ?? null,
|
|
24065
|
+
workspace: readStringValue(fallbackSession.workspace, node?.workspace) ?? null,
|
|
24066
|
+
lastActivityAt: readStringValue(fallbackSession.lastActivityAt, fallbackSession.last_activity_at) ?? null,
|
|
24067
|
+
recoveryState: readStringValue(fallbackSession.recoveryState, fallbackSession.recovery_state) ?? null,
|
|
24068
|
+
isCached: true
|
|
24069
|
+
}];
|
|
24070
|
+
}
|
|
24071
|
+
function readLiveMeshSessionState(record) {
|
|
24072
|
+
return readStringValue(
|
|
24073
|
+
record?.meta?.sessionStatus,
|
|
24074
|
+
record?.meta?.status,
|
|
24075
|
+
record?.meta?.providerStatus,
|
|
24076
|
+
record?.status,
|
|
24077
|
+
record?.state,
|
|
24078
|
+
record?.lifecycle
|
|
24079
|
+
);
|
|
24080
|
+
}
|
|
24081
|
+
function toIsoTimestamp(value) {
|
|
24082
|
+
if (typeof value === "number" && Number.isFinite(value)) return new Date(value).toISOString();
|
|
24083
|
+
const stringValue = readStringValue(value);
|
|
24084
|
+
return stringValue || null;
|
|
24085
|
+
}
|
|
24086
|
+
function summarizeMeshSessionRecord(record) {
|
|
24087
|
+
return {
|
|
24088
|
+
sessionId: readStringValue(record?.sessionId) || "unknown",
|
|
24089
|
+
providerType: readStringValue(record?.providerType),
|
|
24090
|
+
state: readLiveMeshSessionState(record),
|
|
24091
|
+
lifecycle: readStringValue(record?.lifecycle),
|
|
24092
|
+
surfaceKind: getSessionHostSurfaceKind(record),
|
|
24093
|
+
recoveryState: readStringValue(record?.meta?.runtimeRecoveryState) ?? null,
|
|
24094
|
+
workspace: readStringValue(record?.workspace) ?? null,
|
|
24095
|
+
title: readStringValue(record?.displayName, record?.workspaceLabel) ?? null,
|
|
24096
|
+
lastActivityAt: toIsoTimestamp(record?.updatedAt ?? record?.lastActivityAt ?? record?.last_activity_at),
|
|
24097
|
+
isCached: false
|
|
24098
|
+
};
|
|
24099
|
+
}
|
|
24100
|
+
function applyCachedInlineMeshNodeStatus(status, node) {
|
|
24101
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
24102
|
+
const git = buildCachedInlineMeshGitStatus(node);
|
|
24103
|
+
const error = readStringValue(cachedStatus.error, node?.error);
|
|
24104
|
+
const health = readStringValue(cachedStatus.health, node?.health);
|
|
24105
|
+
const machineStatus = readStringValue(cachedStatus.machineStatus, node?.machineStatus);
|
|
24106
|
+
const lastSeenAt = toIsoTimestamp(cachedStatus.lastSeenAt ?? cachedStatus.last_seen_at ?? node?.lastSeenAt ?? node?.last_seen_at);
|
|
24107
|
+
const updatedAt = toIsoTimestamp(cachedStatus.updatedAt ?? cachedStatus.updated_at ?? node?.updatedAt ?? node?.updated_at);
|
|
24108
|
+
const activeSessions = readCachedInlineMeshActiveSessions(node);
|
|
24109
|
+
const activeSessionDetails = readCachedInlineMeshActiveSessionDetails(node);
|
|
24110
|
+
if (!git && !error && !health && !machineStatus && !lastSeenAt && !updatedAt && activeSessions.length === 0) return false;
|
|
24111
|
+
if (git) status.git = git;
|
|
24112
|
+
if (error) status.error = error;
|
|
24113
|
+
if (machineStatus) status.machineStatus = machineStatus;
|
|
24114
|
+
if (lastSeenAt) status.lastSeenAt = lastSeenAt;
|
|
24115
|
+
if (updatedAt) status.updatedAt = updatedAt;
|
|
24116
|
+
if (activeSessions.length > 0) status.activeSessions = activeSessions;
|
|
24117
|
+
if (activeSessionDetails.length > 0) status.activeSessionDetails = activeSessionDetails;
|
|
24118
|
+
if (health) {
|
|
24119
|
+
status.health = health;
|
|
24120
|
+
return true;
|
|
24121
|
+
}
|
|
24122
|
+
if (git) {
|
|
24123
|
+
status.health = deriveMeshNodeHealthFromGit(git);
|
|
24124
|
+
return true;
|
|
24125
|
+
}
|
|
24126
|
+
return activeSessions.length > 0 || !!machineStatus || !!lastSeenAt || !!updatedAt;
|
|
24127
|
+
}
|
|
23817
24128
|
async function resolveProviderTypeFromPriority(args) {
|
|
23818
24129
|
if (!args.providerPriority.length) {
|
|
23819
24130
|
return { error: `Node '${args.nodeId}' has no providerPriority policy; pass cliType explicitly or configure node.policy.providerPriority` };
|
|
@@ -24215,7 +24526,12 @@ var DaemonCommandRouter = class {
|
|
|
24215
24526
|
}
|
|
24216
24527
|
return this.inlineMeshCache.get(meshId);
|
|
24217
24528
|
}
|
|
24218
|
-
async getMeshForCommand(meshId, inlineMesh) {
|
|
24529
|
+
async getMeshForCommand(meshId, inlineMesh, options) {
|
|
24530
|
+
const preferInline = options?.preferInline === true;
|
|
24531
|
+
if (preferInline) {
|
|
24532
|
+
const cached2 = this.getCachedInlineMesh(meshId, inlineMesh);
|
|
24533
|
+
if (cached2) return { mesh: cached2, inline: true };
|
|
24534
|
+
}
|
|
24219
24535
|
try {
|
|
24220
24536
|
const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
24221
24537
|
const mesh = getMesh3(meshId);
|
|
@@ -26038,7 +26354,7 @@ ${block}`);
|
|
|
26038
26354
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
26039
26355
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
26040
26356
|
try {
|
|
26041
|
-
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
26357
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
26042
26358
|
const mesh = meshRecord?.mesh;
|
|
26043
26359
|
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
26044
26360
|
const { getMeshQueueStats: getMeshQueueStats2, getQueue: getQueue2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
@@ -26047,84 +26363,102 @@ ${block}`);
|
|
|
26047
26363
|
const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
26048
26364
|
const ledgerEntries = readLedgerEntries2(meshId, { tail: 20 });
|
|
26049
26365
|
const ledgerSummary = getLedgerSummary2(meshId);
|
|
26366
|
+
const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
|
|
26367
|
+
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
26368
|
+
const localMachineId = loadConfig().machineId || "";
|
|
26369
|
+
const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? readStringValue(mesh.nodes[0]?.id, mesh.nodes[0]?.nodeId) : void 0;
|
|
26370
|
+
const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
26050
26371
|
const nodeStatuses = [];
|
|
26051
|
-
for (const node of mesh.nodes || []) {
|
|
26372
|
+
for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
|
|
26373
|
+
const nodeId = String(node.id || node.nodeId || "");
|
|
26374
|
+
const daemonId = readStringValue(node.daemonId);
|
|
26375
|
+
const providerPriority = readProviderPriorityFromPolicy(node.policy);
|
|
26376
|
+
const isSelfNode = Boolean(
|
|
26377
|
+
nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId
|
|
26378
|
+
) || Boolean(
|
|
26379
|
+
daemonId && (daemonId === localMachineId || daemonId === this.deps.statusInstanceId)
|
|
26380
|
+
) || Boolean(meshRecord?.inline && nodeIndex === 0);
|
|
26052
26381
|
const status = {
|
|
26053
|
-
nodeId
|
|
26382
|
+
nodeId,
|
|
26054
26383
|
machineLabel: node.machineLabel || node.id || node.nodeId,
|
|
26055
26384
|
workspace: node.workspace,
|
|
26056
26385
|
repoRoot: node.repoRoot,
|
|
26057
26386
|
isLocalWorktree: node.isLocalWorktree,
|
|
26058
26387
|
worktreeBranch: node.worktreeBranch,
|
|
26059
|
-
daemonId
|
|
26388
|
+
daemonId,
|
|
26060
26389
|
machineId: node.machineId,
|
|
26390
|
+
machineStatus: node.machineStatus,
|
|
26061
26391
|
health: "unknown",
|
|
26062
26392
|
providers: node.providers || [],
|
|
26063
|
-
|
|
26393
|
+
providerPriority,
|
|
26394
|
+
activeSessions: [],
|
|
26395
|
+
activeSessionDetails: [],
|
|
26396
|
+
launchReady: false
|
|
26064
26397
|
};
|
|
26398
|
+
if (isSelfNode) {
|
|
26399
|
+
status.connection = {
|
|
26400
|
+
perspective: "selected_coordinator",
|
|
26401
|
+
source: "mesh_peer_status",
|
|
26402
|
+
state: "self",
|
|
26403
|
+
transport: "local",
|
|
26404
|
+
reported: true,
|
|
26405
|
+
reason: "Selected coordinator daemon",
|
|
26406
|
+
lastStateChangeAt: refreshedAt
|
|
26407
|
+
};
|
|
26408
|
+
} else if (daemonId) {
|
|
26409
|
+
const connection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
|
|
26410
|
+
status.connection = connection ?? {
|
|
26411
|
+
perspective: "selected_coordinator",
|
|
26412
|
+
source: "not_reported",
|
|
26413
|
+
state: "unknown",
|
|
26414
|
+
transport: "unknown",
|
|
26415
|
+
reported: false,
|
|
26416
|
+
reason: "No live mesh peer telemetry reported by the selected coordinator yet."
|
|
26417
|
+
};
|
|
26418
|
+
} else {
|
|
26419
|
+
status.connection = {
|
|
26420
|
+
perspective: "selected_coordinator",
|
|
26421
|
+
source: "not_reported",
|
|
26422
|
+
state: "unknown",
|
|
26423
|
+
transport: "unknown",
|
|
26424
|
+
reported: false,
|
|
26425
|
+
reason: "Node has no daemon id, so mesh transport cannot be reported from the selected coordinator."
|
|
26426
|
+
};
|
|
26427
|
+
}
|
|
26428
|
+
const matchedLiveSessionRecords = liveMeshSessions.filter((record) => this.sessionMatchesMeshNode(record, node, nodeId));
|
|
26429
|
+
if (matchedLiveSessionRecords.length > 0) {
|
|
26430
|
+
const sessionIds = matchedLiveSessionRecords.map((record) => typeof record?.sessionId === "string" ? record.sessionId : "").filter(Boolean);
|
|
26431
|
+
const providerTypes = matchedLiveSessionRecords.map((record) => readStringValue(record?.providerType)).filter(Boolean);
|
|
26432
|
+
status.activeSessions = sessionIds;
|
|
26433
|
+
status.activeSessionDetails = matchedLiveSessionRecords.map(summarizeMeshSessionRecord);
|
|
26434
|
+
if (providerTypes.length > 0) {
|
|
26435
|
+
status.providers = Array.from(/* @__PURE__ */ new Set([...Array.isArray(status.providers) ? status.providers : [], ...providerTypes]));
|
|
26436
|
+
}
|
|
26437
|
+
}
|
|
26065
26438
|
if (node.workspace && typeof node.workspace === "string") {
|
|
26439
|
+
if (!fs10.existsSync(node.workspace) && applyCachedInlineMeshNodeStatus(status, node)) {
|
|
26440
|
+
status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
|
|
26441
|
+
nodeStatuses.push(status);
|
|
26442
|
+
continue;
|
|
26443
|
+
}
|
|
26066
26444
|
try {
|
|
26067
|
-
const {
|
|
26068
|
-
|
|
26069
|
-
|
|
26070
|
-
|
|
26071
|
-
|
|
26072
|
-
|
|
26073
|
-
|
|
26074
|
-
});
|
|
26075
|
-
return result.stdout.trim();
|
|
26076
|
-
};
|
|
26077
|
-
const branch = await runGit2(["branch", "--show-current"]).catch(() => "");
|
|
26078
|
-
const porc = await runGit2(["status", "--porcelain"]).catch(() => "");
|
|
26079
|
-
const headCommit = await runGit2(["rev-parse", "--short", "HEAD"]).catch(() => null);
|
|
26080
|
-
const headMessage = await runGit2(["log", "-1", "--format=%s"]).catch(() => null);
|
|
26081
|
-
const upstream = await runGit2(["rev-parse", "--abbrev-ref", "@{upstream}"]).catch(() => null);
|
|
26082
|
-
const aheadBehind = await runGit2(["rev-list", "--left-right", "--count", "@{upstream}...HEAD"]).catch(() => "");
|
|
26083
|
-
const stashCount = await runGit2(["stash", "list"]).catch(() => "");
|
|
26084
|
-
let ahead = 0, behind = 0;
|
|
26085
|
-
if (aheadBehind) {
|
|
26086
|
-
const parts = aheadBehind.split(/\s+/);
|
|
26087
|
-
if (parts.length >= 2) {
|
|
26088
|
-
behind = parseInt(parts[0], 10) || 0;
|
|
26089
|
-
ahead = parseInt(parts[1], 10) || 0;
|
|
26090
|
-
}
|
|
26091
|
-
}
|
|
26092
|
-
const dirty = porc.length > 0;
|
|
26093
|
-
const lines = porc ? porc.split("\n").filter(Boolean) : [];
|
|
26094
|
-
let staged = 0, modified = 0, untracked = 0, deleted = 0, renamed = 0;
|
|
26095
|
-
for (const line of lines) {
|
|
26096
|
-
const xy = line.slice(0, 2);
|
|
26097
|
-
if (xy[0] !== " " && xy[0] !== "?") staged++;
|
|
26098
|
-
if (xy[1] === "M") modified++;
|
|
26099
|
-
if (xy[1] === "D") deleted++;
|
|
26100
|
-
if (xy[0] === "R" || xy[1] === "R") renamed++;
|
|
26101
|
-
if (xy === "??") untracked++;
|
|
26445
|
+
const gitStatus = await getGitRepoStatus(node.workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
26446
|
+
status.git = gitStatus;
|
|
26447
|
+
if (gitStatus.isGitRepo) {
|
|
26448
|
+
status.health = deriveMeshNodeHealthFromGit(gitStatus);
|
|
26449
|
+
} else {
|
|
26450
|
+
status.health = "degraded";
|
|
26451
|
+
if (gitStatus.error && !status.error) status.error = gitStatus.error;
|
|
26102
26452
|
}
|
|
26103
|
-
status.git = {
|
|
26104
|
-
workspace: node.workspace,
|
|
26105
|
-
repoRoot: node.workspace,
|
|
26106
|
-
isGitRepo: true,
|
|
26107
|
-
branch: branch || null,
|
|
26108
|
-
headCommit,
|
|
26109
|
-
headMessage,
|
|
26110
|
-
upstream,
|
|
26111
|
-
ahead,
|
|
26112
|
-
behind,
|
|
26113
|
-
staged,
|
|
26114
|
-
modified,
|
|
26115
|
-
untracked,
|
|
26116
|
-
deleted,
|
|
26117
|
-
renamed,
|
|
26118
|
-
hasConflicts: false,
|
|
26119
|
-
conflictFiles: [],
|
|
26120
|
-
stashCount: stashCount ? stashCount.split("\n").filter(Boolean).length : 0,
|
|
26121
|
-
lastCheckedAt: Date.now()
|
|
26122
|
-
};
|
|
26123
|
-
status.health = branch ? dirty ? "dirty" : "online" : "degraded";
|
|
26124
26453
|
} catch {
|
|
26125
|
-
status
|
|
26454
|
+
if (!applyCachedInlineMeshNodeStatus(status, node)) {
|
|
26455
|
+
status.health = "degraded";
|
|
26456
|
+
}
|
|
26126
26457
|
}
|
|
26458
|
+
} else {
|
|
26459
|
+
applyCachedInlineMeshNodeStatus(status, node);
|
|
26127
26460
|
}
|
|
26461
|
+
status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
|
|
26128
26462
|
nodeStatuses.push(status);
|
|
26129
26463
|
}
|
|
26130
26464
|
return {
|
|
@@ -26133,6 +26467,7 @@ ${block}`);
|
|
|
26133
26467
|
meshName: mesh.name,
|
|
26134
26468
|
repoIdentity: mesh.repoIdentity,
|
|
26135
26469
|
defaultBranch: mesh.defaultBranch,
|
|
26470
|
+
refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
26136
26471
|
nodes: nodeStatuses,
|
|
26137
26472
|
queue: { tasks: queue, summary: queueSummary },
|
|
26138
26473
|
ledger: { entries: ledgerEntries, summary: ledgerSummary }
|
|
@@ -34062,6 +34397,7 @@ async function initDaemonComponents(config) {
|
|
|
34062
34397
|
sessionHostControl: config.sessionHostControl,
|
|
34063
34398
|
statusInstanceId: config.statusInstanceId,
|
|
34064
34399
|
statusVersion: config.statusVersion,
|
|
34400
|
+
getMeshPeerConnectionStatus: config.getMeshPeerConnectionStatus,
|
|
34065
34401
|
getCdpLogFn: config.getCdpLogFn || ((ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn())
|
|
34066
34402
|
});
|
|
34067
34403
|
poller = new AgentStreamPoller({
|
|
@@ -34337,6 +34673,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
34337
34673
|
prepareSessionChatTailUpdate,
|
|
34338
34674
|
prepareSessionModalUpdate,
|
|
34339
34675
|
probeCdpPort,
|
|
34676
|
+
queuePendingMeshCoordinatorEvent,
|
|
34340
34677
|
readChatHistory,
|
|
34341
34678
|
readLedgerEntries,
|
|
34342
34679
|
readLedgerSlice,
|