adhdev 0.9.82-rc.7 → 0.9.82-rc.8

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
@@ -45536,17 +45536,87 @@ function readCachedInlineMeshActiveSessions(node) {
45536
45536
  const sessionId = readStringValue(fallbackSession.id, fallbackSession.sessionId, fallbackSession.session_id, node?.activeSessionId, node?.active_session_id, node?.sessionId, node?.session_id);
45537
45537
  return sessionId ? [sessionId] : [];
45538
45538
  }
45539
+ function readCachedInlineMeshActiveSessionDetails(node) {
45540
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
45541
+ const activeSession = readObjectRecord(cachedStatus.activeSession);
45542
+ const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
45543
+ const sessionId = readStringValue(
45544
+ fallbackSession.id,
45545
+ fallbackSession.sessionId,
45546
+ fallbackSession.session_id,
45547
+ node?.activeSessionId,
45548
+ node?.active_session_id,
45549
+ node?.sessionId,
45550
+ node?.session_id
45551
+ );
45552
+ if (!sessionId) return [];
45553
+ return [{
45554
+ sessionId,
45555
+ providerType: readStringValue(
45556
+ fallbackSession.providerType,
45557
+ fallbackSession.provider_type,
45558
+ fallbackSession.cliType,
45559
+ fallbackSession.cli_type,
45560
+ fallbackSession.provider,
45561
+ node?.providerType,
45562
+ node?.provider_type
45563
+ ),
45564
+ state: readStringValue(fallbackSession.status, fallbackSession.state, fallbackSession.lifecycle),
45565
+ lifecycle: readStringValue(fallbackSession.lifecycle),
45566
+ title: readStringValue(fallbackSession.title, fallbackSession.displayName, fallbackSession.display_name) ?? null,
45567
+ workspace: readStringValue(fallbackSession.workspace, node?.workspace) ?? null,
45568
+ lastActivityAt: readStringValue(fallbackSession.lastActivityAt, fallbackSession.last_activity_at) ?? null,
45569
+ recoveryState: readStringValue(fallbackSession.recoveryState, fallbackSession.recovery_state) ?? null,
45570
+ isCached: true
45571
+ }];
45572
+ }
45573
+ function readLiveMeshSessionState(record2) {
45574
+ return readStringValue(
45575
+ record2?.meta?.sessionStatus,
45576
+ record2?.meta?.status,
45577
+ record2?.meta?.providerStatus,
45578
+ record2?.status,
45579
+ record2?.state,
45580
+ record2?.lifecycle
45581
+ );
45582
+ }
45583
+ function toIsoTimestamp(value) {
45584
+ if (typeof value === "number" && Number.isFinite(value)) return new Date(value).toISOString();
45585
+ const stringValue = readStringValue(value);
45586
+ return stringValue || null;
45587
+ }
45588
+ function summarizeMeshSessionRecord(record2) {
45589
+ return {
45590
+ sessionId: readStringValue(record2?.sessionId) || "unknown",
45591
+ providerType: readStringValue(record2?.providerType),
45592
+ state: readLiveMeshSessionState(record2),
45593
+ lifecycle: readStringValue(record2?.lifecycle),
45594
+ surfaceKind: getSessionHostSurfaceKind(record2),
45595
+ recoveryState: readStringValue(record2?.meta?.runtimeRecoveryState) ?? null,
45596
+ workspace: readStringValue(record2?.workspace) ?? null,
45597
+ title: readStringValue(record2?.displayName, record2?.workspaceLabel) ?? null,
45598
+ lastActivityAt: toIsoTimestamp(record2?.updatedAt ?? record2?.lastActivityAt ?? record2?.last_activity_at),
45599
+ isCached: false
45600
+ };
45601
+ }
45539
45602
  function applyCachedInlineMeshNodeStatus(status, node) {
45540
45603
  const cachedStatus = readObjectRecord(node?.cachedStatus);
45541
45604
  const git = buildCachedInlineMeshGitStatus(node);
45542
45605
  const error48 = readStringValue(cachedStatus.error, node?.error);
45543
45606
  const health = readStringValue(cachedStatus.health, node?.health);
45544
45607
  const machineStatus = readStringValue(cachedStatus.machineStatus, node?.machineStatus);
45608
+ const lastSeenAt = toIsoTimestamp(cachedStatus.lastSeenAt ?? cachedStatus.last_seen_at ?? node?.lastSeenAt ?? node?.last_seen_at);
45609
+ const updatedAt = toIsoTimestamp(cachedStatus.updatedAt ?? cachedStatus.updated_at ?? node?.updatedAt ?? node?.updated_at);
45545
45610
  const activeSessions = readCachedInlineMeshActiveSessions(node);
45546
- if (!git && !error48 && !health && !machineStatus && activeSessions.length === 0) return false;
45611
+ const activeSessionDetails = readCachedInlineMeshActiveSessionDetails(node);
45612
+ if (!git && !error48 && !health && !machineStatus && !lastSeenAt && !updatedAt && activeSessions.length === 0) return false;
45547
45613
  if (git) status.git = git;
45548
45614
  if (error48) status.error = error48;
45615
+ if (machineStatus) status.machineStatus = machineStatus;
45616
+ if (lastSeenAt) status.lastSeenAt = lastSeenAt;
45617
+ if (updatedAt) status.updatedAt = updatedAt;
45549
45618
  if (activeSessions.length > 0) status.activeSessions = activeSessions;
45619
+ if (activeSessionDetails.length > 0) status.activeSessionDetails = activeSessionDetails;
45550
45620
  if (health) {
45551
45621
  status.health = health;
45552
45622
  return true;
@@ -45555,7 +45625,7 @@ function applyCachedInlineMeshNodeStatus(status, node) {
45555
45625
  status.health = deriveMeshNodeHealthFromGit(git);
45556
45626
  return true;
45557
45627
  }
45558
- return activeSessions.length > 0 || !!machineStatus;
45628
+ return activeSessions.length > 0 || !!machineStatus || !!lastSeenAt || !!updatedAt;
45559
45629
  }
45560
45630
  async function resolveProviderTypeFromPriority(args) {
45561
45631
  if (!args.providerPriority.length) {
@@ -47834,28 +47904,79 @@ ${block}`);
47834
47904
  const ledgerSummary = getLedgerSummary2(meshId);
47835
47905
  const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
47836
47906
  const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
47907
+ const localMachineId = loadConfig().machineId || "";
47908
+ const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? readStringValue(mesh.nodes[0]?.id, mesh.nodes[0]?.nodeId) : void 0;
47909
+ const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
47837
47910
  const nodeStatuses = [];
47838
- for (const node of mesh.nodes || []) {
47911
+ for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
47912
+ const nodeId = String(node.id || node.nodeId || "");
47913
+ const daemonId = readStringValue(node.daemonId);
47914
+ const providerPriority = readProviderPriorityFromPolicy(node.policy);
47915
+ const isSelfNode = Boolean(
47916
+ nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId
47917
+ ) || Boolean(
47918
+ daemonId && (daemonId === localMachineId || daemonId === this.deps.statusInstanceId)
47919
+ ) || Boolean(meshRecord?.inline && nodeIndex === 0);
47839
47920
  const status = {
47840
- nodeId: node.id || node.nodeId,
47921
+ nodeId,
47841
47922
  machineLabel: node.machineLabel || node.id || node.nodeId,
47842
47923
  workspace: node.workspace,
47843
47924
  repoRoot: node.repoRoot,
47844
47925
  isLocalWorktree: node.isLocalWorktree,
47845
47926
  worktreeBranch: node.worktreeBranch,
47846
- daemonId: node.daemonId,
47927
+ daemonId,
47847
47928
  machineId: node.machineId,
47929
+ machineStatus: node.machineStatus,
47848
47930
  health: "unknown",
47849
47931
  providers: node.providers || [],
47850
- activeSessions: []
47932
+ providerPriority,
47933
+ activeSessions: [],
47934
+ activeSessionDetails: [],
47935
+ launchReady: false
47851
47936
  };
47852
- const nodeId = String(node.id || node.nodeId || "");
47853
- const matchedLiveSessions = liveMeshSessions.filter((record2) => this.sessionMatchesMeshNode(record2, node, nodeId)).map((record2) => typeof record2?.sessionId === "string" ? record2.sessionId : "").filter(Boolean);
47854
- if (matchedLiveSessions.length > 0) {
47855
- status.activeSessions = matchedLiveSessions;
47937
+ if (isSelfNode) {
47938
+ status.connection = {
47939
+ perspective: "selected_coordinator",
47940
+ source: "mesh_peer_status",
47941
+ state: "self",
47942
+ transport: "local",
47943
+ reported: true,
47944
+ reason: "Selected coordinator daemon",
47945
+ lastStateChangeAt: refreshedAt
47946
+ };
47947
+ } else if (daemonId) {
47948
+ const connection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
47949
+ status.connection = connection ?? {
47950
+ perspective: "selected_coordinator",
47951
+ source: "not_reported",
47952
+ state: "unknown",
47953
+ transport: "unknown",
47954
+ reported: false,
47955
+ reason: "No live mesh peer telemetry reported by the selected coordinator yet."
47956
+ };
47957
+ } else {
47958
+ status.connection = {
47959
+ perspective: "selected_coordinator",
47960
+ source: "not_reported",
47961
+ state: "unknown",
47962
+ transport: "unknown",
47963
+ reported: false,
47964
+ reason: "Node has no daemon id, so mesh transport cannot be reported from the selected coordinator."
47965
+ };
47966
+ }
47967
+ const matchedLiveSessionRecords = liveMeshSessions.filter((record2) => this.sessionMatchesMeshNode(record2, node, nodeId));
47968
+ if (matchedLiveSessionRecords.length > 0) {
47969
+ const sessionIds = matchedLiveSessionRecords.map((record2) => typeof record2?.sessionId === "string" ? record2.sessionId : "").filter(Boolean);
47970
+ const providerTypes = matchedLiveSessionRecords.map((record2) => readStringValue(record2?.providerType)).filter(Boolean);
47971
+ status.activeSessions = sessionIds;
47972
+ status.activeSessionDetails = matchedLiveSessionRecords.map(summarizeMeshSessionRecord);
47973
+ if (providerTypes.length > 0) {
47974
+ status.providers = Array.from(/* @__PURE__ */ new Set([...Array.isArray(status.providers) ? status.providers : [], ...providerTypes]));
47975
+ }
47856
47976
  }
47857
47977
  if (node.workspace && typeof node.workspace === "string") {
47858
47978
  if (!fs10.existsSync(node.workspace) && applyCachedInlineMeshNodeStatus(status, node)) {
47979
+ status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
47859
47980
  nodeStatuses.push(status);
47860
47981
  continue;
47861
47982
  }
@@ -47876,6 +47997,7 @@ ${block}`);
47876
47997
  } else {
47877
47998
  applyCachedInlineMeshNodeStatus(status, node);
47878
47999
  }
48000
+ status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
47879
48001
  nodeStatuses.push(status);
47880
48002
  }
47881
48003
  return {
@@ -47884,6 +48006,7 @@ ${block}`);
47884
48006
  meshName: mesh.name,
47885
48007
  repoIdentity: mesh.repoIdentity,
47886
48008
  defaultBranch: mesh.defaultBranch,
48009
+ refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
47887
48010
  nodes: nodeStatuses,
47888
48011
  queue: { tasks: queue, summary: queueSummary },
47889
48012
  ledger: { entries: ledgerEntries, summary: ledgerSummary }
@@ -55962,6 +56085,7 @@ async function initDaemonComponents(config2) {
55962
56085
  sessionHostControl: config2.sessionHostControl,
55963
56086
  statusInstanceId: config2.statusInstanceId,
55964
56087
  statusVersion: config2.statusVersion,
56088
+ getMeshPeerConnectionStatus: config2.getMeshPeerConnectionStatus,
55965
56089
  getCdpLogFn: config2.getCdpLogFn || ((ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn())
55966
56090
  });
55967
56091
  poller = new AgentStreamPoller({
@@ -66054,11 +66178,30 @@ var init_daemon_mesh_manager = __esm({
66054
66178
  nodeDatachannel = null;
66055
66179
  peers = /* @__PURE__ */ new Map();
66056
66180
  // Map<targetDaemonId, PeerEntry>
66181
+ peerSnapshots = /* @__PURE__ */ new Map();
66057
66182
  pendingRequests = /* @__PURE__ */ new Map();
66058
66183
  commandCallback;
66059
66184
  p2pFailure(message, command, targetDaemonId) {
66060
66185
  return new P2pRelayFailureError(message, { command, targetDaemonId });
66061
66186
  }
66187
+ updatePeerSnapshot(targetDaemonId, state, patch = {}) {
66188
+ const previous = this.peerSnapshots.get(targetDaemonId);
66189
+ const now = (/* @__PURE__ */ new Date()).toISOString();
66190
+ this.peerSnapshots.set(targetDaemonId, {
66191
+ perspective: "selected_coordinator",
66192
+ source: "mesh_peer_status",
66193
+ reported: true,
66194
+ state,
66195
+ transport: patch.transport ?? previous?.transport ?? "unknown",
66196
+ reason: patch.reason ?? previous?.reason,
66197
+ lastStateChangeAt: now,
66198
+ lastConnectedAt: patch.lastConnectedAt ?? previous?.lastConnectedAt,
66199
+ lastCommandAt: patch.lastCommandAt ?? previous?.lastCommandAt
66200
+ });
66201
+ }
66202
+ getPeerConnectionStatus(targetDaemonId) {
66203
+ return this.peerSnapshots.get(targetDaemonId) ?? null;
66204
+ }
66062
66205
  invalidatePeer(targetDaemonId, reason, options = {}) {
66063
66206
  const peer = this.peers.get(targetDaemonId);
66064
66207
  if (peer?.commandQueue) {
@@ -66073,6 +66216,11 @@ var init_daemon_mesh_manager = __esm({
66073
66216
  pending.reject(this.p2pFailure(reason, pending.command, targetDaemonId));
66074
66217
  }
66075
66218
  }
66219
+ const snapshotState = peer?.state === "closed" ? "closed" : peer?.state === "disconnected" ? "disconnected" : "failed";
66220
+ this.updatePeerSnapshot(targetDaemonId, snapshotState, {
66221
+ reason,
66222
+ transport: peer?.isRelay === true ? "relay" : peer?.isRelay === false ? "direct" : "unknown"
66223
+ });
66076
66224
  if (options.closeResources !== false && peer) {
66077
66225
  try {
66078
66226
  peer.dataChannel?.close?.();
@@ -66192,6 +66340,20 @@ var init_daemon_mesh_manager = __esm({
66192
66340
  if (!peer) {
66193
66341
  throw this.p2pFailure("Failed to initiate P2P connection entry", command, targetDaemonId);
66194
66342
  }
66343
+ const lastCommandAt = (/* @__PURE__ */ new Date()).toISOString();
66344
+ if (peer.state === "connected") {
66345
+ this.updatePeerSnapshot(targetDaemonId, "connected", {
66346
+ transport: peer.isRelay === true ? "relay" : peer.isRelay === false ? "direct" : "unknown",
66347
+ lastConnectedAt: this.peerSnapshots.get(targetDaemonId)?.lastConnectedAt,
66348
+ lastCommandAt
66349
+ });
66350
+ } else {
66351
+ this.updatePeerSnapshot(targetDaemonId, "connecting", {
66352
+ transport: peer.isRelay === true ? "relay" : peer.isRelay === false ? "direct" : "unknown",
66353
+ reason: "Waiting for mesh DataChannel to open.",
66354
+ lastCommandAt
66355
+ });
66356
+ }
66195
66357
  return new Promise((resolve20, reject) => {
66196
66358
  const requestId = `req_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
66197
66359
  const timer = setTimeout(() => {
@@ -66335,6 +66497,9 @@ var init_daemon_mesh_manager = __esm({
66335
66497
  remoteDescriptionSet: false
66336
66498
  };
66337
66499
  this.peers.set(targetDaemonId, entry);
66500
+ this.updatePeerSnapshot(targetDaemonId, "connecting", {
66501
+ reason: isInitiator ? "P2P mesh connection initiated by the selected coordinator." : "Waiting for the remote daemon to finish the mesh DataChannel handshake."
66502
+ });
66338
66503
  pc.onLocalDescription((sdp, type2) => {
66339
66504
  this.serverConn.sendMeshCommand(targetDaemonId, type2 === "offer" ? "mesh_p2p_offer" : "mesh_p2p_answer", { sdp, type: type2 });
66340
66505
  });
@@ -66345,7 +66510,26 @@ var init_daemon_mesh_manager = __esm({
66345
66510
  LOG.info("Mesh", `[Mesh] P2P state with ${targetDaemonId.slice(0, 12)}: ${state}`);
66346
66511
  if (state === "connected") {
66347
66512
  entry.state = "connected";
66513
+ let transport = "unknown";
66514
+ try {
66515
+ const pair = pc.getSelectedCandidatePair?.();
66516
+ if (pair) {
66517
+ const localType = pair.local?.type || "unknown";
66518
+ const remoteType = pair.remote?.type || "unknown";
66519
+ entry.isRelay = localType === "relay" || remoteType === "relay";
66520
+ transport = entry.isRelay ? "relay" : "direct";
66521
+ LOG.info("Mesh", `[Mesh] Candidate pair with ${targetDaemonId.slice(0, 12)}: local=${localType} remote=${remoteType} \u2192 ${transport}`);
66522
+ }
66523
+ } catch {
66524
+ transport = entry.isRelay === true ? "relay" : entry.isRelay === false ? "direct" : "unknown";
66525
+ }
66526
+ this.updatePeerSnapshot(targetDaemonId, "connected", {
66527
+ transport,
66528
+ reason: transport === "relay" ? "Connected over TURN relay." : transport === "direct" ? "Connected directly peer-to-peer." : "Connected, but selected candidate pair details are unavailable.",
66529
+ lastConnectedAt: (/* @__PURE__ */ new Date()).toISOString()
66530
+ });
66348
66531
  } else if (state === "failed" || state === "closed" || state === "disconnected") {
66532
+ entry.state = state;
66349
66533
  this.invalidatePeer(targetDaemonId, `P2P state changed to ${state}`, { rejectPending: true, closeResources: false });
66350
66534
  }
66351
66535
  });
@@ -66363,6 +66547,11 @@ var init_daemon_mesh_manager = __esm({
66363
66547
  dc.onOpen(() => {
66364
66548
  LOG.info("Mesh", `[Mesh] DataChannel OPEN with ${targetDaemonId.slice(0, 12)}`);
66365
66549
  entry.state = "connected";
66550
+ this.updatePeerSnapshot(targetDaemonId, "connected", {
66551
+ transport: entry.isRelay === true ? "relay" : entry.isRelay === false ? "direct" : "unknown",
66552
+ reason: entry.isRelay === true ? "Connected over TURN relay." : entry.isRelay === false ? "Connected directly peer-to-peer." : "DataChannel open; transport details not reported yet.",
66553
+ lastConnectedAt: (/* @__PURE__ */ new Date()).toISOString()
66554
+ });
66366
66555
  if (entry.commandQueue) {
66367
66556
  const queue = entry.commandQueue;
66368
66557
  entry.commandQueue = [];
@@ -66658,7 +66847,7 @@ var init_adhdev_daemon = __esm({
66658
66847
  init_version();
66659
66848
  init_src();
66660
66849
  init_runtime_defaults();
66661
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.82-rc.7" });
66850
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.82-rc.8" });
66662
66851
  AdhdevDaemon = class _AdhdevDaemon {
66663
66852
  localHttpServer = null;
66664
66853
  localWss = null;
@@ -67182,6 +67371,7 @@ ${err?.stack || ""}`);
67182
67371
  if (!this.meshManager) throw new Error("Mesh manager not initialized");
67183
67372
  return this.meshManager.sendCommand(daemonId, command, args);
67184
67373
  },
67374
+ getMeshPeerConnectionStatus: (daemonId) => this.meshManager?.getPeerConnectionStatus(daemonId) ?? null,
67185
67375
  onStatusChange: () => {
67186
67376
  this.invalidateHotChatSnapshotCache();
67187
67377
  this.statusReporter?.onStatusChange();