adhdev 0.9.82-rc.6 → 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
@@ -45505,26 +45505,127 @@ function buildCachedInlineMeshGitStatus(node) {
45505
45505
  ...submodules ? { submodules } : {}
45506
45506
  };
45507
45507
  }
45508
+ function hasGitWorktreeChanges(git) {
45509
+ if (!git) return false;
45510
+ return Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
45511
+ }
45512
+ function getGitSubmoduleDriftState(git) {
45513
+ const submodules = Array.isArray(git?.submodules) ? git.submodules : [];
45514
+ let dirty = false;
45515
+ let outOfSync = false;
45516
+ for (const entry of submodules) {
45517
+ const submodule = readObjectRecord(entry);
45518
+ if (readBooleanValue(submodule.dirty) === true) dirty = true;
45519
+ if (readBooleanValue(submodule.outOfSync) === true || !!readStringValue(submodule.error)) outOfSync = true;
45520
+ }
45521
+ return { dirty, outOfSync };
45522
+ }
45523
+ function deriveMeshNodeHealthFromGit(git) {
45524
+ if (!git || readBooleanValue(git.isGitRepo) === false) return "degraded";
45525
+ const branch = readStringValue(git.branch);
45526
+ if (!branch) return "degraded";
45527
+ const submoduleDrift = getGitSubmoduleDriftState(git);
45528
+ if (submoduleDrift.outOfSync) return "degraded";
45529
+ if (submoduleDrift.dirty || hasGitWorktreeChanges(git)) return "dirty";
45530
+ return "online";
45531
+ }
45532
+ function readCachedInlineMeshActiveSessions(node) {
45533
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
45534
+ const activeSession = readObjectRecord(cachedStatus.activeSession);
45535
+ const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
45536
+ const sessionId = readStringValue(fallbackSession.id, fallbackSession.sessionId, fallbackSession.session_id, node?.activeSessionId, node?.active_session_id, node?.sessionId, node?.session_id);
45537
+ return sessionId ? [sessionId] : [];
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
+ }
45508
45602
  function applyCachedInlineMeshNodeStatus(status, node) {
45509
45603
  const cachedStatus = readObjectRecord(node?.cachedStatus);
45510
45604
  const git = buildCachedInlineMeshGitStatus(node);
45511
45605
  const error48 = readStringValue(cachedStatus.error, node?.error);
45512
45606
  const health = readStringValue(cachedStatus.health, node?.health);
45513
45607
  const machineStatus = readStringValue(cachedStatus.machineStatus, node?.machineStatus);
45514
- if (!git && !error48 && !health) return false;
45515
- if (!machineStatus && !git && !error48) return false;
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);
45610
+ const activeSessions = readCachedInlineMeshActiveSessions(node);
45611
+ const activeSessionDetails = readCachedInlineMeshActiveSessionDetails(node);
45612
+ if (!git && !error48 && !health && !machineStatus && !lastSeenAt && !updatedAt && activeSessions.length === 0) return false;
45516
45613
  if (git) status.git = git;
45517
45614
  if (error48) status.error = error48;
45615
+ if (machineStatus) status.machineStatus = machineStatus;
45616
+ if (lastSeenAt) status.lastSeenAt = lastSeenAt;
45617
+ if (updatedAt) status.updatedAt = updatedAt;
45618
+ if (activeSessions.length > 0) status.activeSessions = activeSessions;
45619
+ if (activeSessionDetails.length > 0) status.activeSessionDetails = activeSessionDetails;
45518
45620
  if (health) {
45519
45621
  status.health = health;
45520
45622
  return true;
45521
45623
  }
45522
45624
  if (git) {
45523
- const dirty = Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
45524
- status.health = git.isGitRepo === false ? "degraded" : dirty ? "dirty" : "online";
45625
+ status.health = deriveMeshNodeHealthFromGit(git);
45525
45626
  return true;
45526
45627
  }
45527
- return false;
45628
+ return activeSessions.length > 0 || !!machineStatus || !!lastSeenAt || !!updatedAt;
45528
45629
  }
45529
45630
  async function resolveProviderTypeFromPriority(args) {
45530
45631
  if (!args.providerPriority.length) {
@@ -47801,23 +47902,81 @@ ${block}`);
47801
47902
  const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
47802
47903
  const ledgerEntries = readLedgerEntries2(meshId, { tail: 20 });
47803
47904
  const ledgerSummary = getLedgerSummary2(meshId);
47905
+ const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
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();
47804
47910
  const nodeStatuses = [];
47805
- 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);
47806
47920
  const status = {
47807
- nodeId: node.id || node.nodeId,
47921
+ nodeId,
47808
47922
  machineLabel: node.machineLabel || node.id || node.nodeId,
47809
47923
  workspace: node.workspace,
47810
47924
  repoRoot: node.repoRoot,
47811
47925
  isLocalWorktree: node.isLocalWorktree,
47812
47926
  worktreeBranch: node.worktreeBranch,
47813
- daemonId: node.daemonId,
47927
+ daemonId,
47814
47928
  machineId: node.machineId,
47929
+ machineStatus: node.machineStatus,
47815
47930
  health: "unknown",
47816
47931
  providers: node.providers || [],
47817
- activeSessions: []
47932
+ providerPriority,
47933
+ activeSessions: [],
47934
+ activeSessionDetails: [],
47935
+ launchReady: false
47818
47936
  };
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
+ }
47976
+ }
47819
47977
  if (node.workspace && typeof node.workspace === "string") {
47820
47978
  if (!fs10.existsSync(node.workspace) && applyCachedInlineMeshNodeStatus(status, node)) {
47979
+ status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
47821
47980
  nodeStatuses.push(status);
47822
47981
  continue;
47823
47982
  }
@@ -47825,8 +47984,7 @@ ${block}`);
47825
47984
  const gitStatus = await getGitRepoStatus(node.workspace, { timeoutMs: 1e4 });
47826
47985
  status.git = gitStatus;
47827
47986
  if (gitStatus.isGitRepo) {
47828
- const dirty = gitStatus.staged + gitStatus.modified + gitStatus.untracked + gitStatus.deleted + gitStatus.renamed > 0;
47829
- status.health = gitStatus.branch ? dirty ? "dirty" : "online" : "degraded";
47987
+ status.health = deriveMeshNodeHealthFromGit(gitStatus);
47830
47988
  } else {
47831
47989
  status.health = "degraded";
47832
47990
  if (gitStatus.error && !status.error) status.error = gitStatus.error;
@@ -47839,6 +47997,7 @@ ${block}`);
47839
47997
  } else {
47840
47998
  applyCachedInlineMeshNodeStatus(status, node);
47841
47999
  }
48000
+ status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
47842
48001
  nodeStatuses.push(status);
47843
48002
  }
47844
48003
  return {
@@ -47847,6 +48006,7 @@ ${block}`);
47847
48006
  meshName: mesh.name,
47848
48007
  repoIdentity: mesh.repoIdentity,
47849
48008
  defaultBranch: mesh.defaultBranch,
48009
+ refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
47850
48010
  nodes: nodeStatuses,
47851
48011
  queue: { tasks: queue, summary: queueSummary },
47852
48012
  ledger: { entries: ledgerEntries, summary: ledgerSummary }
@@ -55925,6 +56085,7 @@ async function initDaemonComponents(config2) {
55925
56085
  sessionHostControl: config2.sessionHostControl,
55926
56086
  statusInstanceId: config2.statusInstanceId,
55927
56087
  statusVersion: config2.statusVersion,
56088
+ getMeshPeerConnectionStatus: config2.getMeshPeerConnectionStatus,
55928
56089
  getCdpLogFn: config2.getCdpLogFn || ((ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn())
55929
56090
  });
55930
56091
  poller = new AgentStreamPoller({
@@ -66017,11 +66178,30 @@ var init_daemon_mesh_manager = __esm({
66017
66178
  nodeDatachannel = null;
66018
66179
  peers = /* @__PURE__ */ new Map();
66019
66180
  // Map<targetDaemonId, PeerEntry>
66181
+ peerSnapshots = /* @__PURE__ */ new Map();
66020
66182
  pendingRequests = /* @__PURE__ */ new Map();
66021
66183
  commandCallback;
66022
66184
  p2pFailure(message, command, targetDaemonId) {
66023
66185
  return new P2pRelayFailureError(message, { command, targetDaemonId });
66024
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
+ }
66025
66205
  invalidatePeer(targetDaemonId, reason, options = {}) {
66026
66206
  const peer = this.peers.get(targetDaemonId);
66027
66207
  if (peer?.commandQueue) {
@@ -66036,6 +66216,11 @@ var init_daemon_mesh_manager = __esm({
66036
66216
  pending.reject(this.p2pFailure(reason, pending.command, targetDaemonId));
66037
66217
  }
66038
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
+ });
66039
66224
  if (options.closeResources !== false && peer) {
66040
66225
  try {
66041
66226
  peer.dataChannel?.close?.();
@@ -66155,6 +66340,20 @@ var init_daemon_mesh_manager = __esm({
66155
66340
  if (!peer) {
66156
66341
  throw this.p2pFailure("Failed to initiate P2P connection entry", command, targetDaemonId);
66157
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
+ }
66158
66357
  return new Promise((resolve20, reject) => {
66159
66358
  const requestId = `req_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
66160
66359
  const timer = setTimeout(() => {
@@ -66298,6 +66497,9 @@ var init_daemon_mesh_manager = __esm({
66298
66497
  remoteDescriptionSet: false
66299
66498
  };
66300
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
+ });
66301
66503
  pc.onLocalDescription((sdp, type2) => {
66302
66504
  this.serverConn.sendMeshCommand(targetDaemonId, type2 === "offer" ? "mesh_p2p_offer" : "mesh_p2p_answer", { sdp, type: type2 });
66303
66505
  });
@@ -66308,7 +66510,26 @@ var init_daemon_mesh_manager = __esm({
66308
66510
  LOG.info("Mesh", `[Mesh] P2P state with ${targetDaemonId.slice(0, 12)}: ${state}`);
66309
66511
  if (state === "connected") {
66310
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
+ });
66311
66531
  } else if (state === "failed" || state === "closed" || state === "disconnected") {
66532
+ entry.state = state;
66312
66533
  this.invalidatePeer(targetDaemonId, `P2P state changed to ${state}`, { rejectPending: true, closeResources: false });
66313
66534
  }
66314
66535
  });
@@ -66326,6 +66547,11 @@ var init_daemon_mesh_manager = __esm({
66326
66547
  dc.onOpen(() => {
66327
66548
  LOG.info("Mesh", `[Mesh] DataChannel OPEN with ${targetDaemonId.slice(0, 12)}`);
66328
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
+ });
66329
66555
  if (entry.commandQueue) {
66330
66556
  const queue = entry.commandQueue;
66331
66557
  entry.commandQueue = [];
@@ -66621,7 +66847,7 @@ var init_adhdev_daemon = __esm({
66621
66847
  init_version();
66622
66848
  init_src();
66623
66849
  init_runtime_defaults();
66624
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.82-rc.6" });
66850
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.82-rc.8" });
66625
66851
  AdhdevDaemon = class _AdhdevDaemon {
66626
66852
  localHttpServer = null;
66627
66853
  localWss = null;
@@ -67145,6 +67371,7 @@ ${err?.stack || ""}`);
67145
67371
  if (!this.meshManager) throw new Error("Mesh manager not initialized");
67146
67372
  return this.meshManager.sendCommand(daemonId, command, args);
67147
67373
  },
67374
+ getMeshPeerConnectionStatus: (daemonId) => this.meshManager?.getPeerConnectionStatus(daemonId) ?? null,
67148
67375
  onStatusChange: () => {
67149
67376
  this.invalidateHotChatSnapshotCache();
67150
67377
  this.statusReporter?.onStatusChange();