@adhdev/daemon-core 0.9.82-rc.7 → 0.9.82-rc.9

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.
@@ -59,6 +59,8 @@ export interface DaemonInitConfig {
59
59
  }) => void;
60
60
  /** Relays a command to a remote mesh node daemon */
61
61
  dispatchMeshCommand?: (daemonId: string, command: string, args: Record<string, unknown>) => Promise<any>;
62
+ /** Returns selected-coordinator mesh peer telemetry for a target daemon when available. */
63
+ getMeshPeerConnectionStatus?: (daemonId: string) => Record<string, unknown> | null;
62
64
  }
63
65
  export interface DaemonComponents {
64
66
  providerLoader: ProviderLoader;
@@ -72,6 +72,8 @@ export interface CommandRouterDeps {
72
72
  statusVersion?: string;
73
73
  /** Session host control plane */
74
74
  sessionHostControl?: SessionHostControlPlane | null;
75
+ /** Selected-coordinator mesh peer telemetry surface for target daemons, when supported by the runtime. */
76
+ getMeshPeerConnectionStatus?: (daemonId: string) => Record<string, unknown> | null;
75
77
  }
76
78
  export interface CommandRouterResult {
77
79
  success: boolean;
@@ -42,6 +42,7 @@ export interface GitPushResult extends GitRepoIdentity {
42
42
  export interface GitCommandServices {
43
43
  getStatus?: (params: {
44
44
  workspace: string;
45
+ refreshUpstream?: boolean;
45
46
  }) => Promise<GitRepoStatus> | GitRepoStatus;
46
47
  getDiffSummary?: (params: {
47
48
  workspace: string;
@@ -5,6 +5,11 @@ export interface GitStatusOptions {
5
5
  includeSubmodules?: boolean;
6
6
  /** Optional filter to exclude specific submodule paths from status */
7
7
  submoduleIgnorePaths?: string[];
8
+ /**
9
+ * When true, refresh the tracked remote before trusting ahead/behind.
10
+ * Callers should opt into this only for convergence-critical surfaces.
11
+ */
12
+ refreshUpstream?: boolean;
8
13
  }
9
14
  export declare function getGitRepoStatus(workspace: string, options?: GitStatusOptions): Promise<GitRepoStatus>;
10
15
  interface ParsedPorcelainStatus {
@@ -27,11 +27,18 @@ export interface GitSubmoduleStatus {
27
27
  /** Error message if submodule status could not be read */
28
28
  error?: string;
29
29
  }
30
+ export type GitUpstreamFreshness = 'fresh' | 'unchecked' | 'stale' | 'no_upstream' | 'unavailable';
30
31
  export interface GitRepoStatus extends GitRepoIdentity {
31
32
  branch: string | null;
32
33
  headCommit: string | null;
33
34
  headMessage: string | null;
34
35
  upstream: string | null;
36
+ /** Whether ahead/behind was verified against a freshly fetched upstream ref. */
37
+ upstreamStatus: GitUpstreamFreshness;
38
+ /** Timestamp for the fetch that refreshed upstream refs when upstreamStatus === 'fresh'. */
39
+ upstreamFetchedAt?: number;
40
+ /** Error from the last refresh attempt when upstreamStatus === 'stale'. */
41
+ upstreamFetchError?: string;
35
42
  ahead: number;
36
43
  behind: number;
37
44
  staged: number;
@@ -105,6 +112,9 @@ export interface GitCompactSummary {
105
112
  isGitRepo: boolean;
106
113
  repoRoot: string | null;
107
114
  branch: string | null;
115
+ upstreamStatus: GitUpstreamFreshness;
116
+ upstreamFetchedAt?: number;
117
+ upstreamFetchError?: string;
108
118
  dirty: boolean;
109
119
  changedFiles: number;
110
120
  ahead: number;
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  */
6
6
  export type { ChatBubbleState, ChatMessage, ExtensionInfo, CommandResult as CoreCommandResult, ProviderConfig, DaemonEvent, StatusResponse, SystemInfo, DetectedIde, ProviderInfo, AgentEntry, } from './types.js';
7
7
  export type { SessionEntry, CompactSessionEntry, CompactDaemonEntry, CloudDaemonSummaryEntry, DashboardBootstrapDaemonEntry, VersionUpdateReason, CloudStatusReportPayload, DaemonStatusEventPayload, DashboardStatusEventPayload, SessionTransport, SessionKind, SessionCapability, AgentSessionStream, ReadChatCursor, ReadChatSyncResult, TransportTopic, SessionChatTailSubscriptionParams, SessionRuntimeOutputSubscriptionParams, MachineRuntimeSubscriptionParams, SessionHostDiagnosticsSubscriptionParams, SessionModalSubscriptionParams, DaemonMetadataSubscriptionParams, WorkspaceGitSubscriptionParams, SessionChatTailUpdate, MachineRuntimeUpdate, SessionHostDiagnosticsUpdate, SessionModalUpdate, DaemonMetadataUpdate, TopicUpdateEnvelope, SubscribeRequest, UnsubscribeRequest, StandaloneWsStatusPayload, AvailableProviderInfo, AcpConfigOption, AcpMode, ProviderControlSchema, StatusReportPayload, MachineInfo, SessionHostDiagnosticsSnapshot, SessionHostRecord, SessionHostWriteOwner, SessionHostAttachedClient, SessionHostLogEntry, SessionHostRequestTrace, SessionHostRuntimeTransition, DetectedIdeInfo, WorkspaceEntry, ProviderSummaryItem, ProviderSummaryMetadata, ProviderState, ProviderStatus, ProviderErrorReason, SessionActiveChatData, ActiveChatData, IdeProviderState, CliProviderState, AcpProviderState, ExtensionProviderState, MessageInputSupport, InputMediaStrategyDescriptor, InputAttachmentStrategy, InputMediaType, } from './shared-types.js';
8
- export type { RepoMesh, RepoMeshNode, RepoMeshNodeHealth, RepoMeshPolicy, RepoMeshNodePolicy, RepoMeshRelatedRepo, RepoMeshNodeCapabilities, DetectedCommand, ProjectContextSnapshot, ProjectContextSource, RepoMeshCoordinatorConfig, LocalMeshConfig, LocalMeshEntry, LocalMeshNodeEntry, RepoMeshStatus, RepoMeshNodeStatus, } from './repo-mesh-types.js';
8
+ export type { RepoMesh, RepoMeshNode, RepoMeshNodeHealth, RepoMeshPolicy, RepoMeshNodePolicy, RepoMeshRelatedRepo, RepoMeshNodeCapabilities, DetectedCommand, ProjectContextSnapshot, ProjectContextSource, RepoMeshCoordinatorConfig, LocalMeshConfig, LocalMeshEntry, LocalMeshNodeEntry, RepoMeshStatus, RepoMeshNodeStatus, RepoMeshSessionStatus, RepoMeshQueueTask, RepoMeshQueueTaskStatus, RepoMeshQueueSummary, RepoMeshQueueStatus, RepoMeshLedgerEntryStatus, RepoMeshLedgerSummaryStatus, RepoMeshLedgerStatus, } from './repo-mesh-types.js';
9
9
  export { DEFAULT_MESH_POLICY } from './repo-mesh-types.js';
10
10
  export * from './git/index.js';
11
11
  import type { RuntimeWriteOwner as _RuntimeWriteOwner } from './shared-types-extra.js';
package/dist/index.js CHANGED
@@ -5913,8 +5913,14 @@ async function getGitRepoStatus(workspace, options = {}) {
5913
5913
  const includeSubmodules = options.includeSubmodules !== false;
5914
5914
  try {
5915
5915
  const repo = await resolveGitRepository(workspace, options);
5916
- const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
5917
- const parsed = parsePorcelainV2Status(statusOutput.stdout);
5916
+ let parsed = await readPorcelainStatus(repo, options);
5917
+ let upstreamProbe = getInitialUpstreamProbe(parsed);
5918
+ if (options.refreshUpstream) {
5919
+ upstreamProbe = await refreshTrackedUpstream(repo, parsed, options);
5920
+ if (upstreamProbe.upstreamStatus === "fresh") {
5921
+ parsed = await readPorcelainStatus(repo, options);
5922
+ }
5923
+ }
5918
5924
  const head = await readHead(repo, options);
5919
5925
  const stashCount = await readStashCount(repo, options);
5920
5926
  let submodules;
@@ -5929,6 +5935,9 @@ async function getGitRepoStatus(workspace, options = {}) {
5929
5935
  headCommit: head.commit,
5930
5936
  headMessage: head.message,
5931
5937
  upstream: parsed.upstream,
5938
+ upstreamStatus: parsed.upstream ? upstreamProbe.upstreamStatus : "no_upstream",
5939
+ upstreamFetchedAt: upstreamProbe.upstreamFetchedAt,
5940
+ upstreamFetchError: upstreamProbe.upstreamFetchError,
5932
5941
  ahead: parsed.ahead,
5933
5942
  behind: parsed.behind,
5934
5943
  staged: parsed.staged,
@@ -5953,6 +5962,60 @@ async function getGitRepoStatus(workspace, options = {}) {
5953
5962
  );
5954
5963
  }
5955
5964
  }
5965
+ async function readPorcelainStatus(repo, options) {
5966
+ const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
5967
+ return parsePorcelainV2Status(statusOutput.stdout);
5968
+ }
5969
+ function getInitialUpstreamProbe(parsed) {
5970
+ return {
5971
+ upstreamStatus: parsed.upstream ? "unchecked" : "no_upstream"
5972
+ };
5973
+ }
5974
+ async function refreshTrackedUpstream(repo, parsed, options) {
5975
+ if (!parsed.upstream || !parsed.branch) {
5976
+ return { upstreamStatus: "no_upstream" };
5977
+ }
5978
+ const remoteName = await readBranchRemote(repo, parsed.branch, options) ?? inferRemoteName(parsed.upstream);
5979
+ if (!remoteName) {
5980
+ return {
5981
+ upstreamStatus: "stale",
5982
+ upstreamFetchError: `Unable to resolve remote for upstream '${parsed.upstream}'`
5983
+ };
5984
+ }
5985
+ try {
5986
+ await runGit(repo, ["fetch", "--quiet", "--prune", "--no-tags", remoteName], options);
5987
+ return {
5988
+ upstreamStatus: "fresh",
5989
+ upstreamFetchedAt: Date.now()
5990
+ };
5991
+ } catch (error) {
5992
+ return {
5993
+ upstreamStatus: "stale",
5994
+ upstreamFetchError: formatGitError(error)
5995
+ };
5996
+ }
5997
+ }
5998
+ async function readBranchRemote(repo, branch, options) {
5999
+ try {
6000
+ const result = await runGit(repo, ["config", "--get", `branch.${branch}.remote`], options);
6001
+ return result.stdout.trim() || null;
6002
+ } catch {
6003
+ return null;
6004
+ }
6005
+ }
6006
+ function inferRemoteName(upstream) {
6007
+ const [remoteName] = upstream.split("/");
6008
+ return remoteName?.trim() || null;
6009
+ }
6010
+ function formatGitError(error) {
6011
+ if (error instanceof GitCommandError) {
6012
+ return error.stderr || error.message;
6013
+ }
6014
+ if (error instanceof Error) {
6015
+ return error.message;
6016
+ }
6017
+ return String(error);
6018
+ }
5956
6019
  function parsePorcelainV2Status(output) {
5957
6020
  const parsed = {
5958
6021
  branch: null,
@@ -6047,6 +6110,7 @@ function emptyStatus(workspace, lastCheckedAt, error) {
6047
6110
  headCommit: null,
6048
6111
  headMessage: null,
6049
6112
  upstream: null,
6113
+ upstreamStatus: "unavailable",
6050
6114
  ahead: 0,
6051
6115
  behind: 0,
6052
6116
  staged: 0,
@@ -6327,6 +6391,9 @@ function createGitCompactSummary(status, diffSummary) {
6327
6391
  isGitRepo: status.isGitRepo,
6328
6392
  repoRoot: status.repoRoot,
6329
6393
  branch: status.branch,
6394
+ upstreamStatus: status.upstreamStatus,
6395
+ upstreamFetchedAt: status.upstreamFetchedAt,
6396
+ upstreamFetchError: status.upstreamFetchError,
6330
6397
  dirty: status.staged > 0 || status.modified > 0 || status.untracked > 0 || status.deleted > 0 || status.renamed > 0 || conflictCount > 0 || changedFiles > 0,
6331
6398
  changedFiles,
6332
6399
  ahead: status.ahead,
@@ -6671,7 +6738,7 @@ var defaultSnapshotStore = createGitSnapshotStore({
6671
6738
  });
6672
6739
  function createDefaultGitCommandServices() {
6673
6740
  return {
6674
- getStatus: ({ workspace }) => getGitRepoStatus(workspace),
6741
+ getStatus: ({ workspace, refreshUpstream }) => getGitRepoStatus(workspace, { refreshUpstream }),
6675
6742
  getDiffSummary: ({ workspace }) => getGitDiffSummary(workspace),
6676
6743
  getDiffFile: ({ workspace, path: filePath }) => getGitFileDiff(workspace, filePath),
6677
6744
  createSnapshot: ({ workspace, reason, sessionId, turnId }) => defaultSnapshotStore.create({
@@ -6757,7 +6824,7 @@ async function handleGitCommand(command, args, services = defaultGitCommandServi
6757
6824
  switch (command) {
6758
6825
  case "git_status": {
6759
6826
  if (!services.getStatus) return serviceNotImplemented(command);
6760
- const status = await runService(() => services.getStatus({ workspace }));
6827
+ const status = await runService(() => services.getStatus({ workspace, refreshUpstream: optionalBoolean(args?.refreshUpstream) }));
6761
6828
  return "success" in status ? status : { success: true, status };
6762
6829
  }
6763
6830
  case "git_diff_summary": {
@@ -23957,17 +24024,87 @@ function readCachedInlineMeshActiveSessions(node) {
23957
24024
  const sessionId = readStringValue(fallbackSession.id, fallbackSession.sessionId, fallbackSession.session_id, node?.activeSessionId, node?.active_session_id, node?.sessionId, node?.session_id);
23958
24025
  return sessionId ? [sessionId] : [];
23959
24026
  }
24027
+ function readCachedInlineMeshActiveSessionDetails(node) {
24028
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
24029
+ const activeSession = readObjectRecord(cachedStatus.activeSession);
24030
+ const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
24031
+ const sessionId = readStringValue(
24032
+ fallbackSession.id,
24033
+ fallbackSession.sessionId,
24034
+ fallbackSession.session_id,
24035
+ node?.activeSessionId,
24036
+ node?.active_session_id,
24037
+ node?.sessionId,
24038
+ node?.session_id
24039
+ );
24040
+ if (!sessionId) return [];
24041
+ return [{
24042
+ sessionId,
24043
+ providerType: readStringValue(
24044
+ fallbackSession.providerType,
24045
+ fallbackSession.provider_type,
24046
+ fallbackSession.cliType,
24047
+ fallbackSession.cli_type,
24048
+ fallbackSession.provider,
24049
+ node?.providerType,
24050
+ node?.provider_type
24051
+ ),
24052
+ state: readStringValue(fallbackSession.status, fallbackSession.state, fallbackSession.lifecycle),
24053
+ lifecycle: readStringValue(fallbackSession.lifecycle),
24054
+ title: readStringValue(fallbackSession.title, fallbackSession.displayName, fallbackSession.display_name) ?? null,
24055
+ workspace: readStringValue(fallbackSession.workspace, node?.workspace) ?? null,
24056
+ lastActivityAt: readStringValue(fallbackSession.lastActivityAt, fallbackSession.last_activity_at) ?? null,
24057
+ recoveryState: readStringValue(fallbackSession.recoveryState, fallbackSession.recovery_state) ?? null,
24058
+ isCached: true
24059
+ }];
24060
+ }
24061
+ function readLiveMeshSessionState(record) {
24062
+ return readStringValue(
24063
+ record?.meta?.sessionStatus,
24064
+ record?.meta?.status,
24065
+ record?.meta?.providerStatus,
24066
+ record?.status,
24067
+ record?.state,
24068
+ record?.lifecycle
24069
+ );
24070
+ }
24071
+ function toIsoTimestamp(value) {
24072
+ if (typeof value === "number" && Number.isFinite(value)) return new Date(value).toISOString();
24073
+ const stringValue = readStringValue(value);
24074
+ return stringValue || null;
24075
+ }
24076
+ function summarizeMeshSessionRecord(record) {
24077
+ return {
24078
+ sessionId: readStringValue(record?.sessionId) || "unknown",
24079
+ providerType: readStringValue(record?.providerType),
24080
+ state: readLiveMeshSessionState(record),
24081
+ lifecycle: readStringValue(record?.lifecycle),
24082
+ surfaceKind: getSessionHostSurfaceKind(record),
24083
+ recoveryState: readStringValue(record?.meta?.runtimeRecoveryState) ?? null,
24084
+ workspace: readStringValue(record?.workspace) ?? null,
24085
+ title: readStringValue(record?.displayName, record?.workspaceLabel) ?? null,
24086
+ lastActivityAt: toIsoTimestamp(record?.updatedAt ?? record?.lastActivityAt ?? record?.last_activity_at),
24087
+ isCached: false
24088
+ };
24089
+ }
23960
24090
  function applyCachedInlineMeshNodeStatus(status, node) {
23961
24091
  const cachedStatus = readObjectRecord(node?.cachedStatus);
23962
24092
  const git = buildCachedInlineMeshGitStatus(node);
23963
24093
  const error = readStringValue(cachedStatus.error, node?.error);
23964
24094
  const health = readStringValue(cachedStatus.health, node?.health);
23965
24095
  const machineStatus = readStringValue(cachedStatus.machineStatus, node?.machineStatus);
24096
+ const lastSeenAt = toIsoTimestamp(cachedStatus.lastSeenAt ?? cachedStatus.last_seen_at ?? node?.lastSeenAt ?? node?.last_seen_at);
24097
+ const updatedAt = toIsoTimestamp(cachedStatus.updatedAt ?? cachedStatus.updated_at ?? node?.updatedAt ?? node?.updated_at);
23966
24098
  const activeSessions = readCachedInlineMeshActiveSessions(node);
23967
- if (!git && !error && !health && !machineStatus && activeSessions.length === 0) return false;
24099
+ const activeSessionDetails = readCachedInlineMeshActiveSessionDetails(node);
24100
+ if (!git && !error && !health && !machineStatus && !lastSeenAt && !updatedAt && activeSessions.length === 0) return false;
23968
24101
  if (git) status.git = git;
23969
24102
  if (error) status.error = error;
24103
+ if (machineStatus) status.machineStatus = machineStatus;
24104
+ if (lastSeenAt) status.lastSeenAt = lastSeenAt;
24105
+ if (updatedAt) status.updatedAt = updatedAt;
23970
24106
  if (activeSessions.length > 0) status.activeSessions = activeSessions;
24107
+ if (activeSessionDetails.length > 0) status.activeSessionDetails = activeSessionDetails;
23971
24108
  if (health) {
23972
24109
  status.health = health;
23973
24110
  return true;
@@ -23976,7 +24113,7 @@ function applyCachedInlineMeshNodeStatus(status, node) {
23976
24113
  status.health = deriveMeshNodeHealthFromGit(git);
23977
24114
  return true;
23978
24115
  }
23979
- return activeSessions.length > 0 || !!machineStatus;
24116
+ return activeSessions.length > 0 || !!machineStatus || !!lastSeenAt || !!updatedAt;
23980
24117
  }
23981
24118
  async function resolveProviderTypeFromPriority(args) {
23982
24119
  if (!args.providerPriority.length) {
@@ -26218,33 +26355,84 @@ ${block}`);
26218
26355
  const ledgerSummary = getLedgerSummary2(meshId);
26219
26356
  const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
26220
26357
  const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
26358
+ const localMachineId = loadConfig().machineId || "";
26359
+ const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? readStringValue(mesh.nodes[0]?.id, mesh.nodes[0]?.nodeId) : void 0;
26360
+ const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
26221
26361
  const nodeStatuses = [];
26222
- for (const node of mesh.nodes || []) {
26362
+ for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
26363
+ const nodeId = String(node.id || node.nodeId || "");
26364
+ const daemonId = readStringValue(node.daemonId);
26365
+ const providerPriority = readProviderPriorityFromPolicy(node.policy);
26366
+ const isSelfNode = Boolean(
26367
+ nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId
26368
+ ) || Boolean(
26369
+ daemonId && (daemonId === localMachineId || daemonId === this.deps.statusInstanceId)
26370
+ ) || Boolean(meshRecord?.inline && nodeIndex === 0);
26223
26371
  const status = {
26224
- nodeId: node.id || node.nodeId,
26372
+ nodeId,
26225
26373
  machineLabel: node.machineLabel || node.id || node.nodeId,
26226
26374
  workspace: node.workspace,
26227
26375
  repoRoot: node.repoRoot,
26228
26376
  isLocalWorktree: node.isLocalWorktree,
26229
26377
  worktreeBranch: node.worktreeBranch,
26230
- daemonId: node.daemonId,
26378
+ daemonId,
26231
26379
  machineId: node.machineId,
26380
+ machineStatus: node.machineStatus,
26232
26381
  health: "unknown",
26233
26382
  providers: node.providers || [],
26234
- activeSessions: []
26383
+ providerPriority,
26384
+ activeSessions: [],
26385
+ activeSessionDetails: [],
26386
+ launchReady: false
26235
26387
  };
26236
- const nodeId = String(node.id || node.nodeId || "");
26237
- const matchedLiveSessions = liveMeshSessions.filter((record) => this.sessionMatchesMeshNode(record, node, nodeId)).map((record) => typeof record?.sessionId === "string" ? record.sessionId : "").filter(Boolean);
26238
- if (matchedLiveSessions.length > 0) {
26239
- status.activeSessions = matchedLiveSessions;
26388
+ if (isSelfNode) {
26389
+ status.connection = {
26390
+ perspective: "selected_coordinator",
26391
+ source: "mesh_peer_status",
26392
+ state: "self",
26393
+ transport: "local",
26394
+ reported: true,
26395
+ reason: "Selected coordinator daemon",
26396
+ lastStateChangeAt: refreshedAt
26397
+ };
26398
+ } else if (daemonId) {
26399
+ const connection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
26400
+ status.connection = connection ?? {
26401
+ perspective: "selected_coordinator",
26402
+ source: "not_reported",
26403
+ state: "unknown",
26404
+ transport: "unknown",
26405
+ reported: false,
26406
+ reason: "No live mesh peer telemetry reported by the selected coordinator yet."
26407
+ };
26408
+ } else {
26409
+ status.connection = {
26410
+ perspective: "selected_coordinator",
26411
+ source: "not_reported",
26412
+ state: "unknown",
26413
+ transport: "unknown",
26414
+ reported: false,
26415
+ reason: "Node has no daemon id, so mesh transport cannot be reported from the selected coordinator."
26416
+ };
26417
+ }
26418
+ const matchedLiveSessionRecords = liveMeshSessions.filter((record) => this.sessionMatchesMeshNode(record, node, nodeId));
26419
+ if (matchedLiveSessionRecords.length > 0) {
26420
+ const sessionIds = matchedLiveSessionRecords.map((record) => typeof record?.sessionId === "string" ? record.sessionId : "").filter(Boolean);
26421
+ const providerTypes = matchedLiveSessionRecords.map((record) => readStringValue(record?.providerType)).filter(Boolean);
26422
+ status.activeSessions = sessionIds;
26423
+ status.activeSessionDetails = matchedLiveSessionRecords.map(summarizeMeshSessionRecord);
26424
+ if (providerTypes.length > 0) {
26425
+ status.providers = Array.from(/* @__PURE__ */ new Set([...Array.isArray(status.providers) ? status.providers : [], ...providerTypes]));
26426
+ }
26240
26427
  }
26241
26428
  if (node.workspace && typeof node.workspace === "string") {
26242
26429
  if (!fs10.existsSync(node.workspace) && applyCachedInlineMeshNodeStatus(status, node)) {
26430
+ status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
26243
26431
  nodeStatuses.push(status);
26244
26432
  continue;
26245
26433
  }
26246
26434
  try {
26247
- const gitStatus = await getGitRepoStatus(node.workspace, { timeoutMs: 1e4 });
26435
+ const gitStatus = await getGitRepoStatus(node.workspace, { timeoutMs: 1e4, refreshUpstream: true });
26248
26436
  status.git = gitStatus;
26249
26437
  if (gitStatus.isGitRepo) {
26250
26438
  status.health = deriveMeshNodeHealthFromGit(gitStatus);
@@ -26260,6 +26448,7 @@ ${block}`);
26260
26448
  } else {
26261
26449
  applyCachedInlineMeshNodeStatus(status, node);
26262
26450
  }
26451
+ status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
26263
26452
  nodeStatuses.push(status);
26264
26453
  }
26265
26454
  return {
@@ -26268,6 +26457,7 @@ ${block}`);
26268
26457
  meshName: mesh.name,
26269
26458
  repoIdentity: mesh.repoIdentity,
26270
26459
  defaultBranch: mesh.defaultBranch,
26460
+ refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
26271
26461
  nodes: nodeStatuses,
26272
26462
  queue: { tasks: queue, summary: queueSummary },
26273
26463
  ledger: { entries: ledgerEntries, summary: ledgerSummary }
@@ -34197,6 +34387,7 @@ async function initDaemonComponents(config) {
34197
34387
  sessionHostControl: config.sessionHostControl,
34198
34388
  statusInstanceId: config.statusInstanceId,
34199
34389
  statusVersion: config.statusVersion,
34390
+ getMeshPeerConnectionStatus: config.getMeshPeerConnectionStatus,
34200
34391
  getCdpLogFn: config.getCdpLogFn || ((ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn())
34201
34392
  });
34202
34393
  poller = new AgentStreamPoller({