@adhdev/daemon-core 0.9.82-rc.2 → 0.9.82-rc.21

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": {
@@ -9843,7 +9920,8 @@ var StatusMonitor = class {
9843
9920
  };
9844
9921
 
9845
9922
  // src/providers/chat-message-normalization.ts
9846
- function extractFinalSummaryFromMessages(messages, maxChars = 500) {
9923
+ var DEFAULT_FINAL_SUMMARY_MAX_CHARS = 4e3;
9924
+ function extractFinalSummaryFromMessages(messages, maxChars = DEFAULT_FINAL_SUMMARY_MAX_CHARS) {
9847
9925
  if (!Array.isArray(messages) || messages.length === 0) return "";
9848
9926
  for (let i = messages.length - 1; i >= 0; i--) {
9849
9927
  const msg = messages[i];
@@ -23835,6 +23913,26 @@ function readBooleanValue(...values) {
23835
23913
  }
23836
23914
  return void 0;
23837
23915
  }
23916
+ function readGitSubmodules(value) {
23917
+ if (!Array.isArray(value)) return void 0;
23918
+ const submodules = value.map((entry) => {
23919
+ const submodule = readObjectRecord(entry);
23920
+ const path28 = readStringValue(submodule.path);
23921
+ const commit = readStringValue(submodule.commit);
23922
+ const repoPath = readStringValue(submodule.repoPath, submodule.repo_root);
23923
+ if (!path28 || !commit || !repoPath) return null;
23924
+ return {
23925
+ path: path28,
23926
+ commit,
23927
+ repoPath,
23928
+ dirty: readBooleanValue(submodule.dirty) ?? false,
23929
+ outOfSync: readBooleanValue(submodule.outOfSync, submodule.out_of_sync) ?? false,
23930
+ lastCheckedAt: readNumberValue(submodule.lastCheckedAt, submodule.last_checked_at) ?? Date.now(),
23931
+ ...readStringValue(submodule.error) ? { error: readStringValue(submodule.error) } : {}
23932
+ };
23933
+ }).filter((entry) => entry !== null);
23934
+ return submodules.length > 0 ? submodules : void 0;
23935
+ }
23838
23936
  function buildCachedInlineMeshGitStatus(node) {
23839
23937
  const cachedStatus = readObjectRecord(node?.cachedStatus);
23840
23938
  const cachedGit = readObjectRecord(cachedStatus.git);
@@ -23844,6 +23942,7 @@ function buildCachedInlineMeshGitStatus(node) {
23844
23942
  const hasConflicts2 = readBooleanValue(cachedGit.hasConflicts) ?? conflictCount2 > 0;
23845
23943
  const isGitRepo2 = readBooleanValue(cachedGit.isGitRepo);
23846
23944
  if (isGitRepo2 !== void 0) {
23945
+ const submodules2 = readGitSubmodules(cachedGit.submodules);
23847
23946
  return {
23848
23947
  workspace: readStringValue(cachedGit.workspace, node?.workspace) || "",
23849
23948
  repoRoot: readStringValue(cachedGit.repoRoot, node?.repoRoot, node?.workspace) || null,
@@ -23862,7 +23961,8 @@ function buildCachedInlineMeshGitStatus(node) {
23862
23961
  hasConflicts: hasConflicts2,
23863
23962
  conflictFiles: conflictFiles2,
23864
23963
  stashCount: readNumberValue(cachedGit.stashCount) ?? 0,
23865
- lastCheckedAt: readNumberValue(cachedGit.lastCheckedAt) ?? Date.now()
23964
+ lastCheckedAt: readNumberValue(cachedGit.lastCheckedAt) ?? Date.now(),
23965
+ ...submodules2 ? { submodules: submodules2 } : {}
23866
23966
  };
23867
23967
  }
23868
23968
  }
@@ -23881,6 +23981,7 @@ function buildCachedInlineMeshGitStatus(node) {
23881
23981
  const conflictFiles = Array.isArray(status.conflictFiles) ? status.conflictFiles.filter((value) => typeof value === "string") : [];
23882
23982
  const conflictCount = readNumberValue(status.conflicts) ?? conflictFiles.length;
23883
23983
  const hasConflicts = readBooleanValue(status.hasConflicts) ?? conflictCount > 0;
23984
+ const submodules = readGitSubmodules(status.submodules);
23884
23985
  return {
23885
23986
  workspace: readStringValue(status.workspace, node?.workspace) || "",
23886
23987
  repoRoot: readStringValue(status.repoRoot, node?.repoRoot, node?.workspace) || null,
@@ -23899,29 +24000,161 @@ function buildCachedInlineMeshGitStatus(node) {
23899
24000
  hasConflicts,
23900
24001
  conflictFiles,
23901
24002
  stashCount: readNumberValue(status.stashCount) ?? 0,
23902
- lastCheckedAt: Date.now()
24003
+ lastCheckedAt: Date.now(),
24004
+ ...submodules ? { submodules } : {}
24005
+ };
24006
+ }
24007
+ function hasGitWorktreeChanges(git) {
24008
+ if (!git) return false;
24009
+ return Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
24010
+ }
24011
+ function getGitSubmoduleDriftState(git) {
24012
+ const submodules = Array.isArray(git?.submodules) ? git.submodules : [];
24013
+ let dirty = false;
24014
+ let outOfSync = false;
24015
+ for (const entry of submodules) {
24016
+ const submodule = readObjectRecord(entry);
24017
+ if (readBooleanValue(submodule.dirty) === true) dirty = true;
24018
+ if (readBooleanValue(submodule.outOfSync) === true || !!readStringValue(submodule.error)) outOfSync = true;
24019
+ }
24020
+ return { dirty, outOfSync };
24021
+ }
24022
+ function deriveMeshNodeHealthFromGit(git) {
24023
+ if (!git || readBooleanValue(git.isGitRepo) === false) return "degraded";
24024
+ const branch = readStringValue(git.branch);
24025
+ if (!branch) return "degraded";
24026
+ const submoduleDrift = getGitSubmoduleDriftState(git);
24027
+ if (submoduleDrift.outOfSync) return "degraded";
24028
+ if (submoduleDrift.dirty || hasGitWorktreeChanges(git)) return "dirty";
24029
+ return "online";
24030
+ }
24031
+ function readCachedInlineMeshActiveSessions(node) {
24032
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
24033
+ const activeSession = readObjectRecord(cachedStatus.activeSession);
24034
+ const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
24035
+ const sessionId = readStringValue(fallbackSession.id, fallbackSession.sessionId, fallbackSession.session_id, node?.activeSessionId, node?.active_session_id, node?.sessionId, node?.session_id);
24036
+ return sessionId ? [sessionId] : [];
24037
+ }
24038
+ function readCachedInlineMeshActiveSessionDetails(node) {
24039
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
24040
+ const activeSession = readObjectRecord(cachedStatus.activeSession);
24041
+ const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
24042
+ const sessionId = readStringValue(
24043
+ fallbackSession.id,
24044
+ fallbackSession.sessionId,
24045
+ fallbackSession.session_id,
24046
+ node?.activeSessionId,
24047
+ node?.active_session_id,
24048
+ node?.sessionId,
24049
+ node?.session_id
24050
+ );
24051
+ if (!sessionId) return [];
24052
+ return [{
24053
+ sessionId,
24054
+ providerType: readStringValue(
24055
+ fallbackSession.providerType,
24056
+ fallbackSession.provider_type,
24057
+ fallbackSession.cliType,
24058
+ fallbackSession.cli_type,
24059
+ fallbackSession.provider,
24060
+ node?.providerType,
24061
+ node?.provider_type
24062
+ ),
24063
+ state: readStringValue(fallbackSession.status, fallbackSession.state, fallbackSession.lifecycle),
24064
+ lifecycle: readStringValue(fallbackSession.lifecycle),
24065
+ title: readStringValue(fallbackSession.title, fallbackSession.displayName, fallbackSession.display_name) ?? null,
24066
+ workspace: readStringValue(fallbackSession.workspace, node?.workspace) ?? null,
24067
+ lastActivityAt: readStringValue(fallbackSession.lastActivityAt, fallbackSession.last_activity_at) ?? null,
24068
+ recoveryState: readStringValue(fallbackSession.recoveryState, fallbackSession.recovery_state) ?? null,
24069
+ isCached: true
24070
+ }];
24071
+ }
24072
+ function readLiveMeshSessionState(record) {
24073
+ return readStringValue(
24074
+ record?.meta?.sessionStatus,
24075
+ record?.meta?.status,
24076
+ record?.meta?.providerStatus,
24077
+ record?.status,
24078
+ record?.state,
24079
+ record?.lifecycle
24080
+ );
24081
+ }
24082
+ function toIsoTimestamp(value) {
24083
+ if (typeof value === "number" && Number.isFinite(value)) return new Date(value).toISOString();
24084
+ const stringValue = readStringValue(value);
24085
+ return stringValue || null;
24086
+ }
24087
+ function summarizeMeshSessionRecord(record) {
24088
+ return {
24089
+ sessionId: readStringValue(record?.sessionId) || "unknown",
24090
+ providerType: readStringValue(record?.providerType),
24091
+ state: readLiveMeshSessionState(record),
24092
+ lifecycle: readStringValue(record?.lifecycle),
24093
+ surfaceKind: getSessionHostSurfaceKind(record),
24094
+ recoveryState: readStringValue(record?.meta?.runtimeRecoveryState) ?? null,
24095
+ workspace: readStringValue(record?.workspace) ?? null,
24096
+ title: readStringValue(record?.displayName, record?.workspaceLabel) ?? null,
24097
+ lastActivityAt: toIsoTimestamp(record?.updatedAt ?? record?.lastActivityAt ?? record?.last_activity_at),
24098
+ isCached: false
23903
24099
  };
23904
24100
  }
24101
+ function readLiveMeshNodeWorkspace(args) {
24102
+ const directNodeWorkspace = args.liveSessionRecords.find((record) => readStringValue(record?.meta?.meshNodeId) === args.nodeId && readStringValue(record?.workspace));
24103
+ if (directNodeWorkspace) {
24104
+ return readStringValue(directNodeWorkspace.workspace) || "";
24105
+ }
24106
+ if (args.allowCoordinatorSession) {
24107
+ const coordinatorWorkspace = args.liveSessionRecords.find((record) => readStringValue(record?.meta?.meshCoordinatorFor) === args.meshId && readStringValue(record?.workspace));
24108
+ if (coordinatorWorkspace) {
24109
+ return readStringValue(coordinatorWorkspace.workspace) || "";
24110
+ }
24111
+ }
24112
+ return "";
24113
+ }
24114
+ function collectLiveMeshSessionRecords(args) {
24115
+ const matches = args.liveSessionRecords.filter((record) => {
24116
+ if (readStringValue(record?.meta?.meshNodeId) === args.nodeId) return true;
24117
+ const recordWorkspace = readStringValue(record?.workspace);
24118
+ const nodeWorkspace = readStringValue(args.node?.workspace);
24119
+ return !!recordWorkspace && !!nodeWorkspace && recordWorkspace === nodeWorkspace;
24120
+ });
24121
+ if (args.allowCoordinatorSession) {
24122
+ for (const record of args.liveSessionRecords) {
24123
+ if (readStringValue(record?.meta?.meshCoordinatorFor) !== args.meshId) continue;
24124
+ const sessionId = readStringValue(record?.sessionId);
24125
+ if (sessionId && matches.some((entry) => readStringValue(entry?.sessionId) === sessionId)) continue;
24126
+ matches.push(record);
24127
+ }
24128
+ }
24129
+ return matches;
24130
+ }
23905
24131
  function applyCachedInlineMeshNodeStatus(status, node) {
23906
24132
  const cachedStatus = readObjectRecord(node?.cachedStatus);
23907
24133
  const git = buildCachedInlineMeshGitStatus(node);
23908
24134
  const error = readStringValue(cachedStatus.error, node?.error);
23909
24135
  const health = readStringValue(cachedStatus.health, node?.health);
23910
24136
  const machineStatus = readStringValue(cachedStatus.machineStatus, node?.machineStatus);
23911
- if (!git && !error && !health) return false;
23912
- if (!machineStatus && !git && !error) return false;
24137
+ const lastSeenAt = toIsoTimestamp(cachedStatus.lastSeenAt ?? cachedStatus.last_seen_at ?? node?.lastSeenAt ?? node?.last_seen_at);
24138
+ const updatedAt = toIsoTimestamp(cachedStatus.updatedAt ?? cachedStatus.updated_at ?? node?.updatedAt ?? node?.updated_at);
24139
+ const activeSessions = readCachedInlineMeshActiveSessions(node);
24140
+ const activeSessionDetails = readCachedInlineMeshActiveSessionDetails(node);
24141
+ if (!git && !error && !health && !machineStatus && !lastSeenAt && !updatedAt && activeSessions.length === 0) return false;
23913
24142
  if (git) status.git = git;
23914
24143
  if (error) status.error = error;
24144
+ if (machineStatus) status.machineStatus = machineStatus;
24145
+ if (lastSeenAt) status.lastSeenAt = lastSeenAt;
24146
+ if (updatedAt) status.updatedAt = updatedAt;
24147
+ if (activeSessions.length > 0) status.activeSessions = activeSessions;
24148
+ if (activeSessionDetails.length > 0) status.activeSessionDetails = activeSessionDetails;
23915
24149
  if (health) {
23916
24150
  status.health = health;
23917
24151
  return true;
23918
24152
  }
23919
24153
  if (git) {
23920
- const dirty = Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
23921
- status.health = git.isGitRepo === false ? "degraded" : dirty ? "dirty" : "online";
24154
+ status.health = deriveMeshNodeHealthFromGit(git);
23922
24155
  return true;
23923
24156
  }
23924
- return false;
24157
+ return activeSessions.length > 0 || !!machineStatus || !!lastSeenAt || !!updatedAt;
23925
24158
  }
23926
24159
  async function resolveProviderTypeFromPriority(args) {
23927
24160
  if (!args.providerPriority.length) {
@@ -24319,25 +24552,35 @@ var DaemonCommandRouter = class {
24319
24552
  }
24320
24553
  getCachedInlineMesh(meshId, inlineMesh) {
24321
24554
  if (inlineMesh && typeof inlineMesh === "object") {
24322
- this.inlineMeshCache.set(meshId, inlineMesh);
24323
- return inlineMesh;
24555
+ return this.warmInlineMeshCache(meshId, inlineMesh);
24324
24556
  }
24325
24557
  return this.inlineMeshCache.get(meshId);
24326
24558
  }
24559
+ warmInlineMeshCache(meshId, inlineMesh) {
24560
+ if (!inlineMesh || typeof inlineMesh !== "object") return void 0;
24561
+ const cached = this.inlineMeshCache.get(meshId);
24562
+ if (cached) return cached;
24563
+ this.inlineMeshCache.set(meshId, inlineMesh);
24564
+ return inlineMesh;
24565
+ }
24327
24566
  async getMeshForCommand(meshId, inlineMesh, options) {
24328
24567
  const preferInline = options?.preferInline === true;
24329
24568
  if (preferInline) {
24330
- const cached2 = this.getCachedInlineMesh(meshId, inlineMesh);
24331
- if (cached2) return { mesh: cached2, inline: true };
24569
+ const cached2 = this.getCachedInlineMesh(meshId);
24570
+ if (cached2) return { mesh: cached2, inline: true, source: "inline_cache" };
24571
+ const warmedInline2 = this.warmInlineMeshCache(meshId, inlineMesh);
24572
+ if (warmedInline2) return { mesh: warmedInline2, inline: true, source: "inline_bootstrap" };
24332
24573
  }
24333
24574
  try {
24334
24575
  const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
24335
24576
  const mesh = getMesh3(meshId);
24336
- if (mesh) return { mesh, inline: false };
24577
+ if (mesh) return { mesh, inline: false, source: "local_config" };
24337
24578
  } catch {
24338
24579
  }
24339
- const cached = this.getCachedInlineMesh(meshId, inlineMesh);
24340
- return cached ? { mesh: cached, inline: true } : null;
24580
+ const cached = this.getCachedInlineMesh(meshId);
24581
+ if (cached) return { mesh: cached, inline: true, source: "inline_cache" };
24582
+ const warmedInline = this.warmInlineMeshCache(meshId, inlineMesh);
24583
+ return warmedInline ? { mesh: warmedInline, inline: true, source: "inline_bootstrap" } : null;
24341
24584
  }
24342
24585
  updateInlineMeshNode(meshId, mesh, node) {
24343
24586
  if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
@@ -24566,6 +24809,7 @@ var DaemonCommandRouter = class {
24566
24809
  const deletedSessionIds = [];
24567
24810
  const skippedSessionIds = [];
24568
24811
  const skippedLiveSessionIds = [];
24812
+ const skippedCoordinatorSessionIds = [];
24569
24813
  const deleteUnsupportedSessionIds = [];
24570
24814
  const recordsRemainSessionIds = [];
24571
24815
  const errors = [];
@@ -24598,6 +24842,12 @@ var DaemonCommandRouter = class {
24598
24842
  const completed = this.isCompletedHostedSession(record);
24599
24843
  const surfaceKind = getSessionHostSurfaceKind(record);
24600
24844
  const liveRuntime = surfaceKind === "live_runtime";
24845
+ const coordinatorSession = readStringValue(record?.meta?.meshCoordinatorFor) === args.meshId;
24846
+ if (!hasExplicitSessionIds && coordinatorSession) {
24847
+ skippedSessionIds.push(sessionId);
24848
+ skippedCoordinatorSessionIds.push(sessionId);
24849
+ continue;
24850
+ }
24601
24851
  if (!hasExplicitSessionIds && liveRuntime) {
24602
24852
  skippedSessionIds.push(sessionId);
24603
24853
  skippedLiveSessionIds.push(sessionId);
@@ -24663,6 +24913,7 @@ var DaemonCommandRouter = class {
24663
24913
  deletedSessionIds,
24664
24914
  skippedSessionIds,
24665
24915
  skippedLiveSessionIds,
24916
+ skippedCoordinatorSessionIds,
24666
24917
  ...deleteUnsupported ? {
24667
24918
  deleteUnsupported: true,
24668
24919
  effectiveCleanup: args.mode === "stop_and_delete" ? "stopped_only_records_remain" : "delete_unsupported_records_remain",
@@ -25324,14 +25575,8 @@ var DaemonCommandRouter = class {
25324
25575
  case "get_mesh": {
25325
25576
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
25326
25577
  if (!meshId) return { success: false, error: "meshId required" };
25327
- try {
25328
- const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
25329
- const mesh = getMesh3(meshId);
25330
- if (mesh) return { success: true, mesh };
25331
- } catch {
25332
- }
25333
- const cached = this.inlineMeshCache.get(meshId);
25334
- if (cached) return { success: true, mesh: cached };
25578
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
25579
+ if (meshRecord?.mesh) return { success: true, mesh: meshRecord.mesh };
25335
25580
  return { success: false, error: "Mesh not found" };
25336
25581
  }
25337
25582
  case "create_mesh": {
@@ -25853,7 +26098,14 @@ var DaemonCommandRouter = class {
25853
26098
  cliType
25854
26099
  };
25855
26100
  }
25856
- const workspace = typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "";
26101
+ const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
26102
+ const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
26103
+ const workspace = readLiveMeshNodeWorkspace({
26104
+ meshId,
26105
+ nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || ""),
26106
+ liveSessionRecords: liveMeshSessions,
26107
+ allowCoordinatorSession: true
26108
+ }) || (typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "");
25857
26109
  if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
25858
26110
  if (!cliType) {
25859
26111
  const resolved = await resolveProviderTypeFromPriority({
@@ -26161,84 +26413,111 @@ ${block}`);
26161
26413
  const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
26162
26414
  const ledgerEntries = readLedgerEntries2(meshId, { tail: 20 });
26163
26415
  const ledgerSummary = getLedgerSummary2(meshId);
26416
+ const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
26417
+ const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
26418
+ const localMachineId = loadConfig().machineId || "";
26419
+ const selectedCoordinatorNodeId = readStringValue(
26420
+ mesh.coordinator?.preferredNodeId,
26421
+ mesh.nodes?.[0]?.id,
26422
+ mesh.nodes?.[0]?.nodeId
26423
+ );
26424
+ const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? selectedCoordinatorNodeId : void 0;
26425
+ const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
26164
26426
  const nodeStatuses = [];
26165
- for (const node of mesh.nodes || []) {
26427
+ for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
26428
+ const nodeId = String(node.id || node.nodeId || "");
26429
+ const daemonId = readStringValue(node.daemonId);
26430
+ const providerPriority = readProviderPriorityFromPolicy(node.policy);
26431
+ const isSelfNode = Boolean(
26432
+ nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId
26433
+ ) || Boolean(
26434
+ daemonId && (daemonId === localMachineId || daemonId === this.deps.statusInstanceId)
26435
+ ) || Boolean(meshRecord?.inline && nodeIndex === 0);
26166
26436
  const status = {
26167
- nodeId: node.id || node.nodeId,
26437
+ nodeId,
26168
26438
  machineLabel: node.machineLabel || node.id || node.nodeId,
26169
26439
  workspace: node.workspace,
26170
26440
  repoRoot: node.repoRoot,
26171
26441
  isLocalWorktree: node.isLocalWorktree,
26172
26442
  worktreeBranch: node.worktreeBranch,
26173
- daemonId: node.daemonId,
26443
+ daemonId,
26174
26444
  machineId: node.machineId,
26445
+ machineStatus: node.machineStatus,
26175
26446
  health: "unknown",
26176
26447
  providers: node.providers || [],
26177
- activeSessions: []
26448
+ providerPriority,
26449
+ activeSessions: [],
26450
+ activeSessionDetails: [],
26451
+ launchReady: false
26178
26452
  };
26179
- if (node.workspace && typeof node.workspace === "string") {
26180
- if (!fs10.existsSync(node.workspace) && applyCachedInlineMeshNodeStatus(status, node)) {
26453
+ if (isSelfNode) {
26454
+ status.connection = {
26455
+ perspective: "selected_coordinator",
26456
+ source: "mesh_peer_status",
26457
+ state: "self",
26458
+ transport: "local",
26459
+ reported: true,
26460
+ reason: "Selected coordinator daemon",
26461
+ lastStateChangeAt: refreshedAt
26462
+ };
26463
+ } else if (daemonId) {
26464
+ const connection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
26465
+ status.connection = connection ?? {
26466
+ perspective: "selected_coordinator",
26467
+ source: "not_reported",
26468
+ state: "unknown",
26469
+ transport: "unknown",
26470
+ reported: false,
26471
+ reason: "No live mesh peer telemetry reported by the selected coordinator yet."
26472
+ };
26473
+ } else {
26474
+ status.connection = {
26475
+ perspective: "selected_coordinator",
26476
+ source: "not_reported",
26477
+ state: "unknown",
26478
+ transport: "unknown",
26479
+ reported: false,
26480
+ reason: "Node has no daemon id, so mesh transport cannot be reported from the selected coordinator."
26481
+ };
26482
+ }
26483
+ const matchedLiveSessionRecords = collectLiveMeshSessionRecords({
26484
+ meshId,
26485
+ node,
26486
+ nodeId,
26487
+ liveSessionRecords: liveMeshSessions,
26488
+ allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
26489
+ });
26490
+ const workspace = readLiveMeshNodeWorkspace({
26491
+ meshId,
26492
+ nodeId,
26493
+ liveSessionRecords: matchedLiveSessionRecords,
26494
+ allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
26495
+ }) || (typeof node.workspace === "string" ? node.workspace : "");
26496
+ status.workspace = workspace || node.workspace;
26497
+ if (matchedLiveSessionRecords.length > 0) {
26498
+ const sessionIds = matchedLiveSessionRecords.map((record) => typeof record?.sessionId === "string" ? record.sessionId : "").filter(Boolean);
26499
+ const providerTypes = matchedLiveSessionRecords.map((record) => readStringValue(record?.providerType)).filter(Boolean);
26500
+ status.activeSessions = sessionIds;
26501
+ status.activeSessionDetails = matchedLiveSessionRecords.map(summarizeMeshSessionRecord);
26502
+ if (providerTypes.length > 0) {
26503
+ status.providers = Array.from(/* @__PURE__ */ new Set([...Array.isArray(status.providers) ? status.providers : [], ...providerTypes]));
26504
+ }
26505
+ }
26506
+ if (workspace) {
26507
+ if (!fs10.existsSync(workspace) && applyCachedInlineMeshNodeStatus(status, node)) {
26508
+ status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
26181
26509
  nodeStatuses.push(status);
26182
26510
  continue;
26183
26511
  }
26184
26512
  try {
26185
- const { execFile: execFile3 } = await import("child_process");
26186
- const { promisify: promisify3 } = await import("util");
26187
- const execFileAsync3 = promisify3(execFile3);
26188
- const runGit2 = async (args2) => {
26189
- const result = await execFileAsync3("git", ["-C", node.workspace, ...args2], {
26190
- encoding: "utf8",
26191
- timeout: 1e4
26192
- });
26193
- return result.stdout.trim();
26194
- };
26195
- const branch = await runGit2(["branch", "--show-current"]).catch(() => "");
26196
- const porc = await runGit2(["status", "--porcelain"]).catch(() => "");
26197
- const headCommit = await runGit2(["rev-parse", "--short", "HEAD"]).catch(() => null);
26198
- const headMessage = await runGit2(["log", "-1", "--format=%s"]).catch(() => null);
26199
- const upstream = await runGit2(["rev-parse", "--abbrev-ref", "@{upstream}"]).catch(() => null);
26200
- const aheadBehind = await runGit2(["rev-list", "--left-right", "--count", "@{upstream}...HEAD"]).catch(() => "");
26201
- const stashCount = await runGit2(["stash", "list"]).catch(() => "");
26202
- let ahead = 0, behind = 0;
26203
- if (aheadBehind) {
26204
- const parts = aheadBehind.split(/\s+/);
26205
- if (parts.length >= 2) {
26206
- behind = parseInt(parts[0], 10) || 0;
26207
- ahead = parseInt(parts[1], 10) || 0;
26208
- }
26209
- }
26210
- const dirty = porc.length > 0;
26211
- const lines = porc ? porc.split("\n").filter(Boolean) : [];
26212
- let staged = 0, modified = 0, untracked = 0, deleted = 0, renamed = 0;
26213
- for (const line of lines) {
26214
- const xy = line.slice(0, 2);
26215
- if (xy[0] !== " " && xy[0] !== "?") staged++;
26216
- if (xy[1] === "M") modified++;
26217
- if (xy[1] === "D") deleted++;
26218
- if (xy[0] === "R" || xy[1] === "R") renamed++;
26219
- if (xy === "??") untracked++;
26513
+ const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
26514
+ status.git = gitStatus;
26515
+ if (gitStatus.isGitRepo) {
26516
+ status.health = deriveMeshNodeHealthFromGit(gitStatus);
26517
+ } else {
26518
+ status.health = "degraded";
26519
+ if (gitStatus.error && !status.error) status.error = gitStatus.error;
26220
26520
  }
26221
- status.git = {
26222
- workspace: node.workspace,
26223
- repoRoot: node.workspace,
26224
- isGitRepo: true,
26225
- branch: branch || null,
26226
- headCommit,
26227
- headMessage,
26228
- upstream,
26229
- ahead,
26230
- behind,
26231
- staged,
26232
- modified,
26233
- untracked,
26234
- deleted,
26235
- renamed,
26236
- hasConflicts: false,
26237
- conflictFiles: [],
26238
- stashCount: stashCount ? stashCount.split("\n").filter(Boolean).length : 0,
26239
- lastCheckedAt: Date.now()
26240
- };
26241
- status.health = branch ? dirty ? "dirty" : "online" : "degraded";
26242
26521
  } catch {
26243
26522
  if (!applyCachedInlineMeshNodeStatus(status, node)) {
26244
26523
  status.health = "degraded";
@@ -26247,6 +26526,7 @@ ${block}`);
26247
26526
  } else {
26248
26527
  applyCachedInlineMeshNodeStatus(status, node);
26249
26528
  }
26529
+ status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
26250
26530
  nodeStatuses.push(status);
26251
26531
  }
26252
26532
  return {
@@ -26255,6 +26535,12 @@ ${block}`);
26255
26535
  meshName: mesh.name,
26256
26536
  repoIdentity: mesh.repoIdentity,
26257
26537
  defaultBranch: mesh.defaultBranch,
26538
+ refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
26539
+ sourceOfTruth: {
26540
+ membership: meshRecord?.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord?.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
26541
+ coordinatorOwnsLiveTruth: meshRecord?.source !== "inline_bootstrap",
26542
+ historicalEvidenceOnly: ["recoveryHints", "ledger.summary", "queue.summary"]
26543
+ },
26258
26544
  nodes: nodeStatuses,
26259
26545
  queue: { tasks: queue, summary: queueSummary },
26260
26546
  ledger: { entries: ledgerEntries, summary: ledgerSummary }
@@ -34184,6 +34470,7 @@ async function initDaemonComponents(config) {
34184
34470
  sessionHostControl: config.sessionHostControl,
34185
34471
  statusInstanceId: config.statusInstanceId,
34186
34472
  statusVersion: config.statusVersion,
34473
+ getMeshPeerConnectionStatus: config.getMeshPeerConnectionStatus,
34187
34474
  getCdpLogFn: config.getCdpLogFn || ((ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn())
34188
34475
  });
34189
34476
  poller = new AgentStreamPoller({
@@ -34459,6 +34746,7 @@ async function shutdownDaemonComponents(components) {
34459
34746
  prepareSessionChatTailUpdate,
34460
34747
  prepareSessionModalUpdate,
34461
34748
  probeCdpPort,
34749
+ queuePendingMeshCoordinatorEvent,
34462
34750
  readChatHistory,
34463
34751
  readLedgerEntries,
34464
34752
  readLedgerSlice,