@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/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 (pendingMeshCoordinatorEvents.length < MAX_PENDING_EVENTS) {
2475
- pendingMeshCoordinatorEvents.push({
2476
- event: args.event,
2477
- meshId: args.meshId,
2478
- nodeLabel: args.nodeLabel,
2479
- metadataEvent: {
2480
- ...args.metadataEvent,
2481
- ...recoveryContext ? { recoveryContext } : {}
2482
- },
2483
- queuedAt: Date.now()
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
- const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
5917
- const parsed = parsePorcelainV2Status(statusOutput.stdout);
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: node.id || node.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: node.daemonId,
26388
+ daemonId,
26060
26389
  machineId: node.machineId,
26390
+ machineStatus: node.machineStatus,
26061
26391
  health: "unknown",
26062
26392
  providers: node.providers || [],
26063
- activeSessions: []
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 { execFile: execFile3 } = await import("child_process");
26068
- const { promisify: promisify3 } = await import("util");
26069
- const execFileAsync3 = promisify3(execFile3);
26070
- const runGit2 = async (args2) => {
26071
- const result = await execFileAsync3("git", ["-C", node.workspace, ...args2], {
26072
- encoding: "utf8",
26073
- timeout: 1e4
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.health = "degraded";
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,