adhdev 0.9.82-rc.2 → 0.9.82-rc.20

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
@@ -264,8 +264,14 @@ async function getGitRepoStatus(workspace, options = {}) {
264
264
  const includeSubmodules = options.includeSubmodules !== false;
265
265
  try {
266
266
  const repo = await resolveGitRepository(workspace, options);
267
- const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
268
- const parsed = parsePorcelainV2Status(statusOutput.stdout);
267
+ let parsed = await readPorcelainStatus(repo, options);
268
+ let upstreamProbe = getInitialUpstreamProbe(parsed);
269
+ if (options.refreshUpstream) {
270
+ upstreamProbe = await refreshTrackedUpstream(repo, parsed, options);
271
+ if (upstreamProbe.upstreamStatus === "fresh") {
272
+ parsed = await readPorcelainStatus(repo, options);
273
+ }
274
+ }
269
275
  const head = await readHead(repo, options);
270
276
  const stashCount = await readStashCount(repo, options);
271
277
  let submodules;
@@ -280,6 +286,9 @@ async function getGitRepoStatus(workspace, options = {}) {
280
286
  headCommit: head.commit,
281
287
  headMessage: head.message,
282
288
  upstream: parsed.upstream,
289
+ upstreamStatus: parsed.upstream ? upstreamProbe.upstreamStatus : "no_upstream",
290
+ upstreamFetchedAt: upstreamProbe.upstreamFetchedAt,
291
+ upstreamFetchError: upstreamProbe.upstreamFetchError,
283
292
  ahead: parsed.ahead,
284
293
  behind: parsed.behind,
285
294
  staged: parsed.staged,
@@ -304,6 +313,60 @@ async function getGitRepoStatus(workspace, options = {}) {
304
313
  );
305
314
  }
306
315
  }
316
+ async function readPorcelainStatus(repo, options) {
317
+ const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
318
+ return parsePorcelainV2Status(statusOutput.stdout);
319
+ }
320
+ function getInitialUpstreamProbe(parsed) {
321
+ return {
322
+ upstreamStatus: parsed.upstream ? "unchecked" : "no_upstream"
323
+ };
324
+ }
325
+ async function refreshTrackedUpstream(repo, parsed, options) {
326
+ if (!parsed.upstream || !parsed.branch) {
327
+ return { upstreamStatus: "no_upstream" };
328
+ }
329
+ const remoteName = await readBranchRemote(repo, parsed.branch, options) ?? inferRemoteName(parsed.upstream);
330
+ if (!remoteName) {
331
+ return {
332
+ upstreamStatus: "stale",
333
+ upstreamFetchError: `Unable to resolve remote for upstream '${parsed.upstream}'`
334
+ };
335
+ }
336
+ try {
337
+ await runGit(repo, ["fetch", "--quiet", "--prune", "--no-tags", remoteName], options);
338
+ return {
339
+ upstreamStatus: "fresh",
340
+ upstreamFetchedAt: Date.now()
341
+ };
342
+ } catch (error48) {
343
+ return {
344
+ upstreamStatus: "stale",
345
+ upstreamFetchError: formatGitError(error48)
346
+ };
347
+ }
348
+ }
349
+ async function readBranchRemote(repo, branch, options) {
350
+ try {
351
+ const result = await runGit(repo, ["config", "--get", `branch.${branch}.remote`], options);
352
+ return result.stdout.trim() || null;
353
+ } catch {
354
+ return null;
355
+ }
356
+ }
357
+ function inferRemoteName(upstream) {
358
+ const [remoteName] = upstream.split("/");
359
+ return remoteName?.trim() || null;
360
+ }
361
+ function formatGitError(error48) {
362
+ if (error48 instanceof GitCommandError) {
363
+ return error48.stderr || error48.message;
364
+ }
365
+ if (error48 instanceof Error) {
366
+ return error48.message;
367
+ }
368
+ return String(error48);
369
+ }
307
370
  function parsePorcelainV2Status(output) {
308
371
  const parsed = {
309
372
  branch: null,
@@ -398,6 +461,7 @@ function emptyStatus(workspace, lastCheckedAt, error48) {
398
461
  headCommit: null,
399
462
  headMessage: null,
400
463
  upstream: null,
464
+ upstreamStatus: "unavailable",
401
465
  ahead: 0,
402
466
  behind: 0,
403
467
  staged: 0,
@@ -690,6 +754,9 @@ function createGitCompactSummary(status, diffSummary) {
690
754
  isGitRepo: status.isGitRepo,
691
755
  repoRoot: status.repoRoot,
692
756
  branch: status.branch,
757
+ upstreamStatus: status.upstreamStatus,
758
+ upstreamFetchedAt: status.upstreamFetchedAt,
759
+ upstreamFetchError: status.upstreamFetchError,
693
760
  dirty: status.staged > 0 || status.modified > 0 || status.untracked > 0 || status.deleted > 0 || status.renamed > 0 || conflictCount > 0 || changedFiles > 0,
694
761
  changedFiles,
695
762
  ahead: status.ahead,
@@ -1017,7 +1084,7 @@ function serviceNotImplemented(command) {
1017
1084
  }
1018
1085
  function createDefaultGitCommandServices() {
1019
1086
  return {
1020
- getStatus: ({ workspace }) => getGitRepoStatus(workspace),
1087
+ getStatus: ({ workspace, refreshUpstream }) => getGitRepoStatus(workspace, { refreshUpstream }),
1021
1088
  getDiffSummary: ({ workspace }) => getGitDiffSummary(workspace),
1022
1089
  getDiffFile: ({ workspace, path: filePath }) => getGitFileDiff(workspace, filePath),
1023
1090
  createSnapshot: ({ workspace, reason, sessionId, turnId }) => defaultSnapshotStore.create({
@@ -1102,7 +1169,7 @@ async function handleGitCommand(command, args, services = defaultGitCommandServi
1102
1169
  switch (command) {
1103
1170
  case "git_status": {
1104
1171
  if (!services.getStatus) return serviceNotImplemented(command);
1105
- const status = await runService(() => services.getStatus({ workspace }));
1172
+ const status = await runService(() => services.getStatus({ workspace, refreshUpstream: optionalBoolean(args?.refreshUpstream) }));
1106
1173
  return "success" in status ? status : { success: true, status };
1107
1174
  }
1108
1175
  case "git_diff_summary": {
@@ -3759,10 +3826,18 @@ __export(mesh_events_exports, {
3759
3826
  drainPendingMeshCoordinatorEvents: () => drainPendingMeshCoordinatorEvents,
3760
3827
  getPendingMeshCoordinatorEvents: () => getPendingMeshCoordinatorEvents,
3761
3828
  handleMeshForwardEvent: () => handleMeshForwardEvent,
3829
+ queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
3762
3830
  setupMeshEventForwarding: () => setupMeshEventForwarding,
3763
3831
  triggerMeshQueue: () => triggerMeshQueue,
3764
3832
  tryAssignQueueTask: () => tryAssignQueueTask
3765
3833
  });
3834
+ function queuePendingMeshCoordinatorEvent(event) {
3835
+ if (pendingMeshCoordinatorEvents.length >= MAX_PENDING_EVENTS) {
3836
+ return false;
3837
+ }
3838
+ pendingMeshCoordinatorEvents.push(event);
3839
+ return true;
3840
+ }
3766
3841
  function drainPendingMeshCoordinatorEvents() {
3767
3842
  return pendingMeshCoordinatorEvents.splice(0);
3768
3843
  }
@@ -4334,17 +4409,18 @@ function injectMeshSystemMessage(components, args) {
4334
4409
  return true;
4335
4410
  });
4336
4411
  if (coordinatorInstances.length === 0) {
4337
- if (pendingMeshCoordinatorEvents.length < MAX_PENDING_EVENTS) {
4338
- pendingMeshCoordinatorEvents.push({
4339
- event: args.event,
4340
- meshId: args.meshId,
4341
- nodeLabel: args.nodeLabel,
4342
- metadataEvent: {
4343
- ...args.metadataEvent,
4344
- ...recoveryContext ? { recoveryContext } : {}
4345
- },
4346
- queuedAt: Date.now()
4347
- });
4412
+ if (queuePendingMeshCoordinatorEvent({
4413
+ event: args.event,
4414
+ meshId: args.meshId,
4415
+ nodeLabel: args.nodeLabel,
4416
+ nodeId: args.nodeId || void 0,
4417
+ workspace: readNonEmptyString(args.metadataEvent.workspace),
4418
+ metadataEvent: {
4419
+ ...args.metadataEvent,
4420
+ ...recoveryContext ? { recoveryContext } : {}
4421
+ },
4422
+ queuedAt: Date.now()
4423
+ })) {
4348
4424
  LOG.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId})`);
4349
4425
  }
4350
4426
  return { success: true, forwarded: 0 };
@@ -6679,7 +6755,7 @@ var init_status_monitor = __esm({
6679
6755
  });
6680
6756
 
6681
6757
  // ../../oss/packages/daemon-core/src/providers/chat-message-normalization.ts
6682
- function extractFinalSummaryFromMessages(messages, maxChars = 500) {
6758
+ function extractFinalSummaryFromMessages(messages, maxChars = DEFAULT_FINAL_SUMMARY_MAX_CHARS) {
6683
6759
  if (!Array.isArray(messages) || messages.length === 0) return "";
6684
6760
  for (let i = messages.length - 1; i >= 0; i--) {
6685
6761
  const msg = messages[i];
@@ -6981,11 +7057,12 @@ function filterInternalChatMessages(messages) {
6981
7057
  function filterChatMessagesByVisibility(messages, surface) {
6982
7058
  return (Array.isArray(messages) ? messages : []).filter((message) => classifyChatMessageVisibility(message).surface === surface);
6983
7059
  }
6984
- var BUILTIN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_VISIBILITIES, CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES, CHAT_MESSAGE_AUDIENCES, CHAT_MESSAGE_SOURCES, CHAT_MESSAGE_ACTIVITY_SOURCES, CHAT_MESSAGE_INTERNAL_SOURCES, KNOWN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_KIND_ALIASES, EXPLICIT_HIDDEN_VISIBILITIES, EXPLICIT_VISIBLE_VISIBILITIES, HIDDEN_AUDIENCES, ACTIVITY_SOURCE_SET, INTERNAL_SOURCE_SET;
7060
+ var DEFAULT_FINAL_SUMMARY_MAX_CHARS, BUILTIN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_VISIBILITIES, CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES, CHAT_MESSAGE_AUDIENCES, CHAT_MESSAGE_SOURCES, CHAT_MESSAGE_ACTIVITY_SOURCES, CHAT_MESSAGE_INTERNAL_SOURCES, KNOWN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_KIND_ALIASES, EXPLICIT_HIDDEN_VISIBILITIES, EXPLICIT_VISIBLE_VISIBILITIES, HIDDEN_AUDIENCES, ACTIVITY_SOURCE_SET, INTERNAL_SOURCE_SET;
6985
7061
  var init_chat_message_normalization = __esm({
6986
7062
  "../../oss/packages/daemon-core/src/providers/chat-message-normalization.ts"() {
6987
7063
  "use strict";
6988
7064
  init_contracts();
7065
+ DEFAULT_FINAL_SUMMARY_MAX_CHARS = 4e3;
6989
7066
  BUILTIN_CHAT_MESSAGE_KINDS = ["standard", "thought", "tool", "terminal", "system"];
6990
7067
  CHAT_MESSAGE_VISIBILITIES = ["user", "debug", "internal", "hidden"];
6991
7068
  CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES = ["visible", "chat", "user", "debug", "internal", "hidden"];
@@ -45414,6 +45491,26 @@ function readBooleanValue(...values) {
45414
45491
  }
45415
45492
  return void 0;
45416
45493
  }
45494
+ function readGitSubmodules(value) {
45495
+ if (!Array.isArray(value)) return void 0;
45496
+ const submodules = value.map((entry) => {
45497
+ const submodule = readObjectRecord(entry);
45498
+ const path35 = readStringValue(submodule.path);
45499
+ const commit = readStringValue(submodule.commit);
45500
+ const repoPath = readStringValue(submodule.repoPath, submodule.repo_root);
45501
+ if (!path35 || !commit || !repoPath) return null;
45502
+ return {
45503
+ path: path35,
45504
+ commit,
45505
+ repoPath,
45506
+ dirty: readBooleanValue(submodule.dirty) ?? false,
45507
+ outOfSync: readBooleanValue(submodule.outOfSync, submodule.out_of_sync) ?? false,
45508
+ lastCheckedAt: readNumberValue(submodule.lastCheckedAt, submodule.last_checked_at) ?? Date.now(),
45509
+ ...readStringValue(submodule.error) ? { error: readStringValue(submodule.error) } : {}
45510
+ };
45511
+ }).filter((entry) => entry !== null);
45512
+ return submodules.length > 0 ? submodules : void 0;
45513
+ }
45417
45514
  function buildCachedInlineMeshGitStatus(node) {
45418
45515
  const cachedStatus = readObjectRecord(node?.cachedStatus);
45419
45516
  const cachedGit = readObjectRecord(cachedStatus.git);
@@ -45423,6 +45520,7 @@ function buildCachedInlineMeshGitStatus(node) {
45423
45520
  const hasConflicts2 = readBooleanValue(cachedGit.hasConflicts) ?? conflictCount2 > 0;
45424
45521
  const isGitRepo2 = readBooleanValue(cachedGit.isGitRepo);
45425
45522
  if (isGitRepo2 !== void 0) {
45523
+ const submodules2 = readGitSubmodules(cachedGit.submodules);
45426
45524
  return {
45427
45525
  workspace: readStringValue(cachedGit.workspace, node?.workspace) || "",
45428
45526
  repoRoot: readStringValue(cachedGit.repoRoot, node?.repoRoot, node?.workspace) || null,
@@ -45441,7 +45539,8 @@ function buildCachedInlineMeshGitStatus(node) {
45441
45539
  hasConflicts: hasConflicts2,
45442
45540
  conflictFiles: conflictFiles2,
45443
45541
  stashCount: readNumberValue(cachedGit.stashCount) ?? 0,
45444
- lastCheckedAt: readNumberValue(cachedGit.lastCheckedAt) ?? Date.now()
45542
+ lastCheckedAt: readNumberValue(cachedGit.lastCheckedAt) ?? Date.now(),
45543
+ ...submodules2 ? { submodules: submodules2 } : {}
45445
45544
  };
45446
45545
  }
45447
45546
  }
@@ -45460,6 +45559,7 @@ function buildCachedInlineMeshGitStatus(node) {
45460
45559
  const conflictFiles = Array.isArray(status.conflictFiles) ? status.conflictFiles.filter((value) => typeof value === "string") : [];
45461
45560
  const conflictCount = readNumberValue(status.conflicts) ?? conflictFiles.length;
45462
45561
  const hasConflicts = readBooleanValue(status.hasConflicts) ?? conflictCount > 0;
45562
+ const submodules = readGitSubmodules(status.submodules);
45463
45563
  return {
45464
45564
  workspace: readStringValue(status.workspace, node?.workspace) || "",
45465
45565
  repoRoot: readStringValue(status.repoRoot, node?.repoRoot, node?.workspace) || null,
@@ -45478,29 +45578,161 @@ function buildCachedInlineMeshGitStatus(node) {
45478
45578
  hasConflicts,
45479
45579
  conflictFiles,
45480
45580
  stashCount: readNumberValue(status.stashCount) ?? 0,
45481
- lastCheckedAt: Date.now()
45581
+ lastCheckedAt: Date.now(),
45582
+ ...submodules ? { submodules } : {}
45482
45583
  };
45483
45584
  }
45585
+ function hasGitWorktreeChanges(git) {
45586
+ if (!git) return false;
45587
+ return Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
45588
+ }
45589
+ function getGitSubmoduleDriftState(git) {
45590
+ const submodules = Array.isArray(git?.submodules) ? git.submodules : [];
45591
+ let dirty = false;
45592
+ let outOfSync = false;
45593
+ for (const entry of submodules) {
45594
+ const submodule = readObjectRecord(entry);
45595
+ if (readBooleanValue(submodule.dirty) === true) dirty = true;
45596
+ if (readBooleanValue(submodule.outOfSync) === true || !!readStringValue(submodule.error)) outOfSync = true;
45597
+ }
45598
+ return { dirty, outOfSync };
45599
+ }
45600
+ function deriveMeshNodeHealthFromGit(git) {
45601
+ if (!git || readBooleanValue(git.isGitRepo) === false) return "degraded";
45602
+ const branch = readStringValue(git.branch);
45603
+ if (!branch) return "degraded";
45604
+ const submoduleDrift = getGitSubmoduleDriftState(git);
45605
+ if (submoduleDrift.outOfSync) return "degraded";
45606
+ if (submoduleDrift.dirty || hasGitWorktreeChanges(git)) return "dirty";
45607
+ return "online";
45608
+ }
45609
+ function readCachedInlineMeshActiveSessions(node) {
45610
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
45611
+ const activeSession = readObjectRecord(cachedStatus.activeSession);
45612
+ const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
45613
+ const sessionId = readStringValue(fallbackSession.id, fallbackSession.sessionId, fallbackSession.session_id, node?.activeSessionId, node?.active_session_id, node?.sessionId, node?.session_id);
45614
+ return sessionId ? [sessionId] : [];
45615
+ }
45616
+ function readCachedInlineMeshActiveSessionDetails(node) {
45617
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
45618
+ const activeSession = readObjectRecord(cachedStatus.activeSession);
45619
+ const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
45620
+ const sessionId = readStringValue(
45621
+ fallbackSession.id,
45622
+ fallbackSession.sessionId,
45623
+ fallbackSession.session_id,
45624
+ node?.activeSessionId,
45625
+ node?.active_session_id,
45626
+ node?.sessionId,
45627
+ node?.session_id
45628
+ );
45629
+ if (!sessionId) return [];
45630
+ return [{
45631
+ sessionId,
45632
+ providerType: readStringValue(
45633
+ fallbackSession.providerType,
45634
+ fallbackSession.provider_type,
45635
+ fallbackSession.cliType,
45636
+ fallbackSession.cli_type,
45637
+ fallbackSession.provider,
45638
+ node?.providerType,
45639
+ node?.provider_type
45640
+ ),
45641
+ state: readStringValue(fallbackSession.status, fallbackSession.state, fallbackSession.lifecycle),
45642
+ lifecycle: readStringValue(fallbackSession.lifecycle),
45643
+ title: readStringValue(fallbackSession.title, fallbackSession.displayName, fallbackSession.display_name) ?? null,
45644
+ workspace: readStringValue(fallbackSession.workspace, node?.workspace) ?? null,
45645
+ lastActivityAt: readStringValue(fallbackSession.lastActivityAt, fallbackSession.last_activity_at) ?? null,
45646
+ recoveryState: readStringValue(fallbackSession.recoveryState, fallbackSession.recovery_state) ?? null,
45647
+ isCached: true
45648
+ }];
45649
+ }
45650
+ function readLiveMeshSessionState(record2) {
45651
+ return readStringValue(
45652
+ record2?.meta?.sessionStatus,
45653
+ record2?.meta?.status,
45654
+ record2?.meta?.providerStatus,
45655
+ record2?.status,
45656
+ record2?.state,
45657
+ record2?.lifecycle
45658
+ );
45659
+ }
45660
+ function toIsoTimestamp(value) {
45661
+ if (typeof value === "number" && Number.isFinite(value)) return new Date(value).toISOString();
45662
+ const stringValue = readStringValue(value);
45663
+ return stringValue || null;
45664
+ }
45665
+ function summarizeMeshSessionRecord(record2) {
45666
+ return {
45667
+ sessionId: readStringValue(record2?.sessionId) || "unknown",
45668
+ providerType: readStringValue(record2?.providerType),
45669
+ state: readLiveMeshSessionState(record2),
45670
+ lifecycle: readStringValue(record2?.lifecycle),
45671
+ surfaceKind: getSessionHostSurfaceKind(record2),
45672
+ recoveryState: readStringValue(record2?.meta?.runtimeRecoveryState) ?? null,
45673
+ workspace: readStringValue(record2?.workspace) ?? null,
45674
+ title: readStringValue(record2?.displayName, record2?.workspaceLabel) ?? null,
45675
+ lastActivityAt: toIsoTimestamp(record2?.updatedAt ?? record2?.lastActivityAt ?? record2?.last_activity_at),
45676
+ isCached: false
45677
+ };
45678
+ }
45679
+ function readLiveMeshNodeWorkspace(args) {
45680
+ const directNodeWorkspace = args.liveSessionRecords.find((record2) => readStringValue(record2?.meta?.meshNodeId) === args.nodeId && readStringValue(record2?.workspace));
45681
+ if (directNodeWorkspace) {
45682
+ return readStringValue(directNodeWorkspace.workspace) || "";
45683
+ }
45684
+ if (args.allowCoordinatorSession) {
45685
+ const coordinatorWorkspace = args.liveSessionRecords.find((record2) => readStringValue(record2?.meta?.meshCoordinatorFor) === args.meshId && readStringValue(record2?.workspace));
45686
+ if (coordinatorWorkspace) {
45687
+ return readStringValue(coordinatorWorkspace.workspace) || "";
45688
+ }
45689
+ }
45690
+ return "";
45691
+ }
45692
+ function collectLiveMeshSessionRecords(args) {
45693
+ const matches = args.liveSessionRecords.filter((record2) => {
45694
+ if (readStringValue(record2?.meta?.meshNodeId) === args.nodeId) return true;
45695
+ const recordWorkspace = readStringValue(record2?.workspace);
45696
+ const nodeWorkspace = readStringValue(args.node?.workspace);
45697
+ return !!recordWorkspace && !!nodeWorkspace && recordWorkspace === nodeWorkspace;
45698
+ });
45699
+ if (args.allowCoordinatorSession) {
45700
+ for (const record2 of args.liveSessionRecords) {
45701
+ if (readStringValue(record2?.meta?.meshCoordinatorFor) !== args.meshId) continue;
45702
+ const sessionId = readStringValue(record2?.sessionId);
45703
+ if (sessionId && matches.some((entry) => readStringValue(entry?.sessionId) === sessionId)) continue;
45704
+ matches.push(record2);
45705
+ }
45706
+ }
45707
+ return matches;
45708
+ }
45484
45709
  function applyCachedInlineMeshNodeStatus(status, node) {
45485
45710
  const cachedStatus = readObjectRecord(node?.cachedStatus);
45486
45711
  const git = buildCachedInlineMeshGitStatus(node);
45487
45712
  const error48 = readStringValue(cachedStatus.error, node?.error);
45488
45713
  const health = readStringValue(cachedStatus.health, node?.health);
45489
45714
  const machineStatus = readStringValue(cachedStatus.machineStatus, node?.machineStatus);
45490
- if (!git && !error48 && !health) return false;
45491
- if (!machineStatus && !git && !error48) return false;
45715
+ const lastSeenAt = toIsoTimestamp(cachedStatus.lastSeenAt ?? cachedStatus.last_seen_at ?? node?.lastSeenAt ?? node?.last_seen_at);
45716
+ const updatedAt = toIsoTimestamp(cachedStatus.updatedAt ?? cachedStatus.updated_at ?? node?.updatedAt ?? node?.updated_at);
45717
+ const activeSessions = readCachedInlineMeshActiveSessions(node);
45718
+ const activeSessionDetails = readCachedInlineMeshActiveSessionDetails(node);
45719
+ if (!git && !error48 && !health && !machineStatus && !lastSeenAt && !updatedAt && activeSessions.length === 0) return false;
45492
45720
  if (git) status.git = git;
45493
45721
  if (error48) status.error = error48;
45722
+ if (machineStatus) status.machineStatus = machineStatus;
45723
+ if (lastSeenAt) status.lastSeenAt = lastSeenAt;
45724
+ if (updatedAt) status.updatedAt = updatedAt;
45725
+ if (activeSessions.length > 0) status.activeSessions = activeSessions;
45726
+ if (activeSessionDetails.length > 0) status.activeSessionDetails = activeSessionDetails;
45494
45727
  if (health) {
45495
45728
  status.health = health;
45496
45729
  return true;
45497
45730
  }
45498
45731
  if (git) {
45499
- const dirty = Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
45500
- status.health = git.isGitRepo === false ? "degraded" : dirty ? "dirty" : "online";
45732
+ status.health = deriveMeshNodeHealthFromGit(git);
45501
45733
  return true;
45502
45734
  }
45503
- return false;
45735
+ return activeSessions.length > 0 || !!machineStatus || !!lastSeenAt || !!updatedAt;
45504
45736
  }
45505
45737
  async function resolveProviderTypeFromPriority(args) {
45506
45738
  if (!args.providerPriority.length) {
@@ -45890,6 +46122,7 @@ var init_router = __esm({
45890
46122
  init_chat_history();
45891
46123
  init_ide_detector();
45892
46124
  init_cli_detector();
46125
+ init_git_status();
45893
46126
  init_logger();
45894
46127
  init_command_log();
45895
46128
  init_js_yaml();
@@ -45934,25 +46167,35 @@ var init_router = __esm({
45934
46167
  }
45935
46168
  getCachedInlineMesh(meshId, inlineMesh) {
45936
46169
  if (inlineMesh && typeof inlineMesh === "object") {
45937
- this.inlineMeshCache.set(meshId, inlineMesh);
45938
- return inlineMesh;
46170
+ return this.warmInlineMeshCache(meshId, inlineMesh);
45939
46171
  }
45940
46172
  return this.inlineMeshCache.get(meshId);
45941
46173
  }
46174
+ warmInlineMeshCache(meshId, inlineMesh) {
46175
+ if (!inlineMesh || typeof inlineMesh !== "object") return void 0;
46176
+ const cached2 = this.inlineMeshCache.get(meshId);
46177
+ if (cached2) return cached2;
46178
+ this.inlineMeshCache.set(meshId, inlineMesh);
46179
+ return inlineMesh;
46180
+ }
45942
46181
  async getMeshForCommand(meshId, inlineMesh, options) {
45943
46182
  const preferInline = options?.preferInline === true;
45944
46183
  if (preferInline) {
45945
- const cached3 = this.getCachedInlineMesh(meshId, inlineMesh);
45946
- if (cached3) return { mesh: cached3, inline: true };
46184
+ const cached3 = this.getCachedInlineMesh(meshId);
46185
+ if (cached3) return { mesh: cached3, inline: true, source: "inline_cache" };
46186
+ const warmedInline2 = this.warmInlineMeshCache(meshId, inlineMesh);
46187
+ if (warmedInline2) return { mesh: warmedInline2, inline: true, source: "inline_bootstrap" };
45947
46188
  }
45948
46189
  try {
45949
46190
  const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
45950
46191
  const mesh = getMesh3(meshId);
45951
- if (mesh) return { mesh, inline: false };
46192
+ if (mesh) return { mesh, inline: false, source: "local_config" };
45952
46193
  } catch {
45953
46194
  }
45954
- const cached2 = this.getCachedInlineMesh(meshId, inlineMesh);
45955
- return cached2 ? { mesh: cached2, inline: true } : null;
46195
+ const cached2 = this.getCachedInlineMesh(meshId);
46196
+ if (cached2) return { mesh: cached2, inline: true, source: "inline_cache" };
46197
+ const warmedInline = this.warmInlineMeshCache(meshId, inlineMesh);
46198
+ return warmedInline ? { mesh: warmedInline, inline: true, source: "inline_bootstrap" } : null;
45956
46199
  }
45957
46200
  updateInlineMeshNode(meshId, mesh, node) {
45958
46201
  if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
@@ -46181,6 +46424,7 @@ var init_router = __esm({
46181
46424
  const deletedSessionIds = [];
46182
46425
  const skippedSessionIds = [];
46183
46426
  const skippedLiveSessionIds = [];
46427
+ const skippedCoordinatorSessionIds = [];
46184
46428
  const deleteUnsupportedSessionIds = [];
46185
46429
  const recordsRemainSessionIds = [];
46186
46430
  const errors = [];
@@ -46213,6 +46457,12 @@ var init_router = __esm({
46213
46457
  const completed = this.isCompletedHostedSession(record2);
46214
46458
  const surfaceKind = getSessionHostSurfaceKind(record2);
46215
46459
  const liveRuntime = surfaceKind === "live_runtime";
46460
+ const coordinatorSession = readStringValue(record2?.meta?.meshCoordinatorFor) === args.meshId;
46461
+ if (!hasExplicitSessionIds && coordinatorSession) {
46462
+ skippedSessionIds.push(sessionId);
46463
+ skippedCoordinatorSessionIds.push(sessionId);
46464
+ continue;
46465
+ }
46216
46466
  if (!hasExplicitSessionIds && liveRuntime) {
46217
46467
  skippedSessionIds.push(sessionId);
46218
46468
  skippedLiveSessionIds.push(sessionId);
@@ -46278,6 +46528,7 @@ var init_router = __esm({
46278
46528
  deletedSessionIds,
46279
46529
  skippedSessionIds,
46280
46530
  skippedLiveSessionIds,
46531
+ skippedCoordinatorSessionIds,
46281
46532
  ...deleteUnsupported ? {
46282
46533
  deleteUnsupported: true,
46283
46534
  effectiveCleanup: args.mode === "stop_and_delete" ? "stopped_only_records_remain" : "delete_unsupported_records_remain",
@@ -46939,14 +47190,8 @@ var init_router = __esm({
46939
47190
  case "get_mesh": {
46940
47191
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
46941
47192
  if (!meshId) return { success: false, error: "meshId required" };
46942
- try {
46943
- const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
46944
- const mesh = getMesh3(meshId);
46945
- if (mesh) return { success: true, mesh };
46946
- } catch {
46947
- }
46948
- const cached2 = this.inlineMeshCache.get(meshId);
46949
- if (cached2) return { success: true, mesh: cached2 };
47193
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
47194
+ if (meshRecord?.mesh) return { success: true, mesh: meshRecord.mesh };
46950
47195
  return { success: false, error: "Mesh not found" };
46951
47196
  }
46952
47197
  case "create_mesh": {
@@ -47468,7 +47713,14 @@ var init_router = __esm({
47468
47713
  cliType
47469
47714
  };
47470
47715
  }
47471
- const workspace = typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "";
47716
+ const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
47717
+ const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
47718
+ const workspace = readLiveMeshNodeWorkspace({
47719
+ meshId,
47720
+ nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || ""),
47721
+ liveSessionRecords: liveMeshSessions,
47722
+ allowCoordinatorSession: true
47723
+ }) || (typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "");
47472
47724
  if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
47473
47725
  if (!cliType) {
47474
47726
  const resolved = await resolveProviderTypeFromPriority({
@@ -47776,84 +48028,111 @@ ${block}`);
47776
48028
  const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
47777
48029
  const ledgerEntries = readLedgerEntries2(meshId, { tail: 20 });
47778
48030
  const ledgerSummary = getLedgerSummary2(meshId);
48031
+ const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
48032
+ const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
48033
+ const localMachineId = loadConfig().machineId || "";
48034
+ const selectedCoordinatorNodeId = readStringValue(
48035
+ mesh.coordinator?.preferredNodeId,
48036
+ mesh.nodes?.[0]?.id,
48037
+ mesh.nodes?.[0]?.nodeId
48038
+ );
48039
+ const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? selectedCoordinatorNodeId : void 0;
48040
+ const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
47779
48041
  const nodeStatuses = [];
47780
- for (const node of mesh.nodes || []) {
48042
+ for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
48043
+ const nodeId = String(node.id || node.nodeId || "");
48044
+ const daemonId = readStringValue(node.daemonId);
48045
+ const providerPriority = readProviderPriorityFromPolicy(node.policy);
48046
+ const isSelfNode = Boolean(
48047
+ nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId
48048
+ ) || Boolean(
48049
+ daemonId && (daemonId === localMachineId || daemonId === this.deps.statusInstanceId)
48050
+ ) || Boolean(meshRecord?.inline && nodeIndex === 0);
47781
48051
  const status = {
47782
- nodeId: node.id || node.nodeId,
48052
+ nodeId,
47783
48053
  machineLabel: node.machineLabel || node.id || node.nodeId,
47784
48054
  workspace: node.workspace,
47785
48055
  repoRoot: node.repoRoot,
47786
48056
  isLocalWorktree: node.isLocalWorktree,
47787
48057
  worktreeBranch: node.worktreeBranch,
47788
- daemonId: node.daemonId,
48058
+ daemonId,
47789
48059
  machineId: node.machineId,
48060
+ machineStatus: node.machineStatus,
47790
48061
  health: "unknown",
47791
48062
  providers: node.providers || [],
47792
- activeSessions: []
48063
+ providerPriority,
48064
+ activeSessions: [],
48065
+ activeSessionDetails: [],
48066
+ launchReady: false
47793
48067
  };
47794
- if (node.workspace && typeof node.workspace === "string") {
47795
- if (!fs10.existsSync(node.workspace) && applyCachedInlineMeshNodeStatus(status, node)) {
48068
+ if (isSelfNode) {
48069
+ status.connection = {
48070
+ perspective: "selected_coordinator",
48071
+ source: "mesh_peer_status",
48072
+ state: "self",
48073
+ transport: "local",
48074
+ reported: true,
48075
+ reason: "Selected coordinator daemon",
48076
+ lastStateChangeAt: refreshedAt
48077
+ };
48078
+ } else if (daemonId) {
48079
+ const connection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
48080
+ status.connection = connection ?? {
48081
+ perspective: "selected_coordinator",
48082
+ source: "not_reported",
48083
+ state: "unknown",
48084
+ transport: "unknown",
48085
+ reported: false,
48086
+ reason: "No live mesh peer telemetry reported by the selected coordinator yet."
48087
+ };
48088
+ } else {
48089
+ status.connection = {
48090
+ perspective: "selected_coordinator",
48091
+ source: "not_reported",
48092
+ state: "unknown",
48093
+ transport: "unknown",
48094
+ reported: false,
48095
+ reason: "Node has no daemon id, so mesh transport cannot be reported from the selected coordinator."
48096
+ };
48097
+ }
48098
+ const matchedLiveSessionRecords = collectLiveMeshSessionRecords({
48099
+ meshId,
48100
+ node,
48101
+ nodeId,
48102
+ liveSessionRecords: liveMeshSessions,
48103
+ allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
48104
+ });
48105
+ const workspace = readLiveMeshNodeWorkspace({
48106
+ meshId,
48107
+ nodeId,
48108
+ liveSessionRecords: matchedLiveSessionRecords,
48109
+ allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
48110
+ }) || (typeof node.workspace === "string" ? node.workspace : "");
48111
+ status.workspace = workspace || node.workspace;
48112
+ if (matchedLiveSessionRecords.length > 0) {
48113
+ const sessionIds = matchedLiveSessionRecords.map((record2) => typeof record2?.sessionId === "string" ? record2.sessionId : "").filter(Boolean);
48114
+ const providerTypes = matchedLiveSessionRecords.map((record2) => readStringValue(record2?.providerType)).filter(Boolean);
48115
+ status.activeSessions = sessionIds;
48116
+ status.activeSessionDetails = matchedLiveSessionRecords.map(summarizeMeshSessionRecord);
48117
+ if (providerTypes.length > 0) {
48118
+ status.providers = Array.from(/* @__PURE__ */ new Set([...Array.isArray(status.providers) ? status.providers : [], ...providerTypes]));
48119
+ }
48120
+ }
48121
+ if (workspace) {
48122
+ if (!fs10.existsSync(workspace) && applyCachedInlineMeshNodeStatus(status, node)) {
48123
+ status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
47796
48124
  nodeStatuses.push(status);
47797
48125
  continue;
47798
48126
  }
47799
48127
  try {
47800
- const { execFile: execFile3 } = await import("child_process");
47801
- const { promisify: promisify3 } = await import("util");
47802
- const execFileAsync3 = promisify3(execFile3);
47803
- const runGit2 = async (args2) => {
47804
- const result = await execFileAsync3("git", ["-C", node.workspace, ...args2], {
47805
- encoding: "utf8",
47806
- timeout: 1e4
47807
- });
47808
- return result.stdout.trim();
47809
- };
47810
- const branch = await runGit2(["branch", "--show-current"]).catch(() => "");
47811
- const porc = await runGit2(["status", "--porcelain"]).catch(() => "");
47812
- const headCommit = await runGit2(["rev-parse", "--short", "HEAD"]).catch(() => null);
47813
- const headMessage = await runGit2(["log", "-1", "--format=%s"]).catch(() => null);
47814
- const upstream = await runGit2(["rev-parse", "--abbrev-ref", "@{upstream}"]).catch(() => null);
47815
- const aheadBehind = await runGit2(["rev-list", "--left-right", "--count", "@{upstream}...HEAD"]).catch(() => "");
47816
- const stashCount = await runGit2(["stash", "list"]).catch(() => "");
47817
- let ahead = 0, behind = 0;
47818
- if (aheadBehind) {
47819
- const parts = aheadBehind.split(/\s+/);
47820
- if (parts.length >= 2) {
47821
- behind = parseInt(parts[0], 10) || 0;
47822
- ahead = parseInt(parts[1], 10) || 0;
47823
- }
47824
- }
47825
- const dirty = porc.length > 0;
47826
- const lines = porc ? porc.split("\n").filter(Boolean) : [];
47827
- let staged = 0, modified = 0, untracked = 0, deleted = 0, renamed2 = 0;
47828
- for (const line of lines) {
47829
- const xy = line.slice(0, 2);
47830
- if (xy[0] !== " " && xy[0] !== "?") staged++;
47831
- if (xy[1] === "M") modified++;
47832
- if (xy[1] === "D") deleted++;
47833
- if (xy[0] === "R" || xy[1] === "R") renamed2++;
47834
- if (xy === "??") untracked++;
48128
+ const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
48129
+ status.git = gitStatus;
48130
+ if (gitStatus.isGitRepo) {
48131
+ status.health = deriveMeshNodeHealthFromGit(gitStatus);
48132
+ } else {
48133
+ status.health = "degraded";
48134
+ if (gitStatus.error && !status.error) status.error = gitStatus.error;
47835
48135
  }
47836
- status.git = {
47837
- workspace: node.workspace,
47838
- repoRoot: node.workspace,
47839
- isGitRepo: true,
47840
- branch: branch || null,
47841
- headCommit,
47842
- headMessage,
47843
- upstream,
47844
- ahead,
47845
- behind,
47846
- staged,
47847
- modified,
47848
- untracked,
47849
- deleted,
47850
- renamed: renamed2,
47851
- hasConflicts: false,
47852
- conflictFiles: [],
47853
- stashCount: stashCount ? stashCount.split("\n").filter(Boolean).length : 0,
47854
- lastCheckedAt: Date.now()
47855
- };
47856
- status.health = branch ? dirty ? "dirty" : "online" : "degraded";
47857
48136
  } catch {
47858
48137
  if (!applyCachedInlineMeshNodeStatus(status, node)) {
47859
48138
  status.health = "degraded";
@@ -47862,6 +48141,7 @@ ${block}`);
47862
48141
  } else {
47863
48142
  applyCachedInlineMeshNodeStatus(status, node);
47864
48143
  }
48144
+ status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
47865
48145
  nodeStatuses.push(status);
47866
48146
  }
47867
48147
  return {
@@ -47870,6 +48150,12 @@ ${block}`);
47870
48150
  meshName: mesh.name,
47871
48151
  repoIdentity: mesh.repoIdentity,
47872
48152
  defaultBranch: mesh.defaultBranch,
48153
+ refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
48154
+ sourceOfTruth: {
48155
+ membership: meshRecord?.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord?.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
48156
+ coordinatorOwnsLiveTruth: meshRecord?.source !== "inline_bootstrap",
48157
+ historicalEvidenceOnly: ["recoveryHints", "ledger.summary", "queue.summary"]
48158
+ },
47873
48159
  nodes: nodeStatuses,
47874
48160
  queue: { tasks: queue, summary: queueSummary },
47875
48161
  ledger: { entries: ledgerEntries, summary: ledgerSummary }
@@ -55948,6 +56234,7 @@ async function initDaemonComponents(config2) {
55948
56234
  sessionHostControl: config2.sessionHostControl,
55949
56235
  statusInstanceId: config2.statusInstanceId,
55950
56236
  statusVersion: config2.statusVersion,
56237
+ getMeshPeerConnectionStatus: config2.getMeshPeerConnectionStatus,
55951
56238
  getCdpLogFn: config2.getCdpLogFn || ((ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn())
55952
56239
  });
55953
56240
  poller = new AgentStreamPoller({
@@ -56249,6 +56536,7 @@ __export(src_exports, {
56249
56536
  prepareSessionChatTailUpdate: () => prepareSessionChatTailUpdate,
56250
56537
  prepareSessionModalUpdate: () => prepareSessionModalUpdate,
56251
56538
  probeCdpPort: () => probeCdpPort,
56539
+ queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
56252
56540
  readChatHistory: () => readChatHistory,
56253
56541
  readLedgerEntries: () => readLedgerEntries,
56254
56542
  readLedgerSlice: () => readLedgerSlice,
@@ -66040,11 +66328,30 @@ var init_daemon_mesh_manager = __esm({
66040
66328
  nodeDatachannel = null;
66041
66329
  peers = /* @__PURE__ */ new Map();
66042
66330
  // Map<targetDaemonId, PeerEntry>
66331
+ peerSnapshots = /* @__PURE__ */ new Map();
66043
66332
  pendingRequests = /* @__PURE__ */ new Map();
66044
66333
  commandCallback;
66045
66334
  p2pFailure(message, command, targetDaemonId) {
66046
66335
  return new P2pRelayFailureError(message, { command, targetDaemonId });
66047
66336
  }
66337
+ updatePeerSnapshot(targetDaemonId, state, patch = {}) {
66338
+ const previous = this.peerSnapshots.get(targetDaemonId);
66339
+ const now = (/* @__PURE__ */ new Date()).toISOString();
66340
+ this.peerSnapshots.set(targetDaemonId, {
66341
+ perspective: "selected_coordinator",
66342
+ source: "mesh_peer_status",
66343
+ reported: true,
66344
+ state,
66345
+ transport: patch.transport ?? previous?.transport ?? "unknown",
66346
+ reason: patch.reason ?? previous?.reason,
66347
+ lastStateChangeAt: now,
66348
+ lastConnectedAt: patch.lastConnectedAt ?? previous?.lastConnectedAt,
66349
+ lastCommandAt: patch.lastCommandAt ?? previous?.lastCommandAt
66350
+ });
66351
+ }
66352
+ getPeerConnectionStatus(targetDaemonId) {
66353
+ return this.peerSnapshots.get(targetDaemonId) ?? null;
66354
+ }
66048
66355
  invalidatePeer(targetDaemonId, reason, options = {}) {
66049
66356
  const peer = this.peers.get(targetDaemonId);
66050
66357
  if (peer?.commandQueue) {
@@ -66059,6 +66366,11 @@ var init_daemon_mesh_manager = __esm({
66059
66366
  pending.reject(this.p2pFailure(reason, pending.command, targetDaemonId));
66060
66367
  }
66061
66368
  }
66369
+ const snapshotState = peer?.state === "closed" ? "closed" : peer?.state === "disconnected" ? "disconnected" : "failed";
66370
+ this.updatePeerSnapshot(targetDaemonId, snapshotState, {
66371
+ reason,
66372
+ transport: peer?.isRelay === true ? "relay" : peer?.isRelay === false ? "direct" : "unknown"
66373
+ });
66062
66374
  if (options.closeResources !== false && peer) {
66063
66375
  try {
66064
66376
  peer.dataChannel?.close?.();
@@ -66091,6 +66403,7 @@ var init_daemon_mesh_manager = __esm({
66091
66403
  "send_chat",
66092
66404
  "read_chat",
66093
66405
  "get_chat_debug_bundle",
66406
+ "get_pending_mesh_events",
66094
66407
  "git_status",
66095
66408
  "git_diff_summary",
66096
66409
  "launch_cli",
@@ -66178,6 +66491,20 @@ var init_daemon_mesh_manager = __esm({
66178
66491
  if (!peer) {
66179
66492
  throw this.p2pFailure("Failed to initiate P2P connection entry", command, targetDaemonId);
66180
66493
  }
66494
+ const lastCommandAt = (/* @__PURE__ */ new Date()).toISOString();
66495
+ if (peer.state === "connected") {
66496
+ this.updatePeerSnapshot(targetDaemonId, "connected", {
66497
+ transport: peer.isRelay === true ? "relay" : peer.isRelay === false ? "direct" : "unknown",
66498
+ lastConnectedAt: this.peerSnapshots.get(targetDaemonId)?.lastConnectedAt,
66499
+ lastCommandAt
66500
+ });
66501
+ } else {
66502
+ this.updatePeerSnapshot(targetDaemonId, "connecting", {
66503
+ transport: peer.isRelay === true ? "relay" : peer.isRelay === false ? "direct" : "unknown",
66504
+ reason: "Waiting for mesh DataChannel to open.",
66505
+ lastCommandAt
66506
+ });
66507
+ }
66181
66508
  return new Promise((resolve20, reject) => {
66182
66509
  const requestId = `req_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
66183
66510
  const timer = setTimeout(() => {
@@ -66321,6 +66648,9 @@ var init_daemon_mesh_manager = __esm({
66321
66648
  remoteDescriptionSet: false
66322
66649
  };
66323
66650
  this.peers.set(targetDaemonId, entry);
66651
+ this.updatePeerSnapshot(targetDaemonId, "connecting", {
66652
+ reason: isInitiator ? "P2P mesh connection initiated by the selected coordinator." : "Waiting for the remote daemon to finish the mesh DataChannel handshake."
66653
+ });
66324
66654
  pc.onLocalDescription((sdp, type2) => {
66325
66655
  this.serverConn.sendMeshCommand(targetDaemonId, type2 === "offer" ? "mesh_p2p_offer" : "mesh_p2p_answer", { sdp, type: type2 });
66326
66656
  });
@@ -66331,7 +66661,26 @@ var init_daemon_mesh_manager = __esm({
66331
66661
  LOG.info("Mesh", `[Mesh] P2P state with ${targetDaemonId.slice(0, 12)}: ${state}`);
66332
66662
  if (state === "connected") {
66333
66663
  entry.state = "connected";
66664
+ let transport = "unknown";
66665
+ try {
66666
+ const pair = pc.getSelectedCandidatePair?.();
66667
+ if (pair) {
66668
+ const localType = pair.local?.type || "unknown";
66669
+ const remoteType = pair.remote?.type || "unknown";
66670
+ entry.isRelay = localType === "relay" || remoteType === "relay";
66671
+ transport = entry.isRelay ? "relay" : "direct";
66672
+ LOG.info("Mesh", `[Mesh] Candidate pair with ${targetDaemonId.slice(0, 12)}: local=${localType} remote=${remoteType} \u2192 ${transport}`);
66673
+ }
66674
+ } catch {
66675
+ transport = entry.isRelay === true ? "relay" : entry.isRelay === false ? "direct" : "unknown";
66676
+ }
66677
+ this.updatePeerSnapshot(targetDaemonId, "connected", {
66678
+ transport,
66679
+ reason: transport === "relay" ? "Connected over TURN relay." : transport === "direct" ? "Connected directly peer-to-peer." : "Connected, but selected candidate pair details are unavailable.",
66680
+ lastConnectedAt: (/* @__PURE__ */ new Date()).toISOString()
66681
+ });
66334
66682
  } else if (state === "failed" || state === "closed" || state === "disconnected") {
66683
+ entry.state = state;
66335
66684
  this.invalidatePeer(targetDaemonId, `P2P state changed to ${state}`, { rejectPending: true, closeResources: false });
66336
66685
  }
66337
66686
  });
@@ -66349,6 +66698,11 @@ var init_daemon_mesh_manager = __esm({
66349
66698
  dc.onOpen(() => {
66350
66699
  LOG.info("Mesh", `[Mesh] DataChannel OPEN with ${targetDaemonId.slice(0, 12)}`);
66351
66700
  entry.state = "connected";
66701
+ this.updatePeerSnapshot(targetDaemonId, "connected", {
66702
+ transport: entry.isRelay === true ? "relay" : entry.isRelay === false ? "direct" : "unknown",
66703
+ reason: entry.isRelay === true ? "Connected over TURN relay." : entry.isRelay === false ? "Connected directly peer-to-peer." : "DataChannel open; transport details not reported yet.",
66704
+ lastConnectedAt: (/* @__PURE__ */ new Date()).toISOString()
66705
+ });
66352
66706
  if (entry.commandQueue) {
66353
66707
  const queue = entry.commandQueue;
66354
66708
  entry.commandQueue = [];
@@ -66628,6 +66982,7 @@ var init_adhdev_daemon = __esm({
66628
66982
  "use strict";
66629
66983
  init_server_connection();
66630
66984
  init_src();
66985
+ init_mesh_events();
66631
66986
  init_daemon_p2p2();
66632
66987
  init_screenshot_controller();
66633
66988
  init_session_host();
@@ -66644,7 +66999,7 @@ var init_adhdev_daemon = __esm({
66644
66999
  init_version();
66645
67000
  init_src();
66646
67001
  init_runtime_defaults();
66647
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.82-rc.2" });
67002
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.82-rc.20" });
66648
67003
  AdhdevDaemon = class _AdhdevDaemon {
66649
67004
  localHttpServer = null;
66650
67005
  localWss = null;
@@ -67168,6 +67523,7 @@ ${err?.stack || ""}`);
67168
67523
  if (!this.meshManager) throw new Error("Mesh manager not initialized");
67169
67524
  return this.meshManager.sendCommand(daemonId, command, args);
67170
67525
  },
67526
+ getMeshPeerConnectionStatus: (daemonId) => this.meshManager?.getPeerConnectionStatus(daemonId) ?? null,
67171
67527
  onStatusChange: () => {
67172
67528
  this.invalidateHotChatSnapshotCache();
67173
67529
  this.statusReporter?.onStatusChange();
@@ -67560,6 +67916,21 @@ ${err?.stack || ""}`);
67560
67916
  await this.meshManager.sendCommand(coordinatorDaemonId, "mesh_forward_event", payload);
67561
67917
  LOG.info("MeshEvents", `Relayed ${payload.event} for mesh ${meshId} to coordinator daemon ${coordinatorDaemonId.slice(0, 12)}\u2026`);
67562
67918
  } catch (error48) {
67919
+ queuePendingMeshCoordinatorEvent({
67920
+ event: payload.event,
67921
+ meshId,
67922
+ nodeLabel: payload.nodeId ? `Node '${payload.nodeId}'` : payload.workspace ? `Agent at ${payload.workspace}` : "Remote agent",
67923
+ nodeId: payload.nodeId || void 0,
67924
+ workspace: payload.workspace || void 0,
67925
+ metadataEvent: {
67926
+ targetSessionId: payload.targetSessionId,
67927
+ providerType: payload.providerType,
67928
+ providerSessionId: payload.providerSessionId,
67929
+ finalSummary: payload.finalSummary,
67930
+ workspace: payload.workspace
67931
+ },
67932
+ queuedAt: Date.now()
67933
+ });
67563
67934
  LOG.warn("MeshEvents", `Failed to relay ${payload.event} for mesh ${meshId}: ${error48?.message || error48}`);
67564
67935
  }
67565
67936
  }
@@ -68162,7 +68533,7 @@ var require_yoctocolors_cjs = __commonJS({
68162
68533
  }
68163
68534
  });
68164
68535
 
68165
- // ../../node_modules/@inquirer/figures/dist/esm/index.js
68536
+ // ../../node_modules/@inquirer/figures/dist/esm/index.mjs
68166
68537
  function isUnicodeSupported() {
68167
68538
  if (import_node_process3.default.platform !== "win32") {
68168
68539
  return import_node_process3.default.env["TERM"] !== "linux";
@@ -68174,7 +68545,7 @@ function isUnicodeSupported() {
68174
68545
  }
68175
68546
  var import_node_process3, common2, specialMainSymbols, specialFallbackSymbols, mainSymbols, fallbackSymbols, shouldUseMain, figures, esm_default, replacements;
68176
68547
  var init_esm3 = __esm({
68177
- "../../node_modules/@inquirer/figures/dist/esm/index.js"() {
68548
+ "../../node_modules/@inquirer/figures/dist/esm/index.mjs"() {
68178
68549
  "use strict";
68179
68550
  import_node_process3 = __toESM(require("process"), 1);
68180
68551
  common2 = {
@@ -68445,10 +68816,7 @@ var init_esm3 = __esm({
68445
68816
  oneNinth: "1/9",
68446
68817
  oneTenth: "1/10"
68447
68818
  };
68448
- mainSymbols = {
68449
- ...common2,
68450
- ...specialMainSymbols
68451
- };
68819
+ mainSymbols = { ...common2, ...specialMainSymbols };
68452
68820
  fallbackSymbols = {
68453
68821
  ...common2,
68454
68822
  ...specialFallbackSymbols