@adhdev/daemon-core 0.9.82-rc.117 → 0.9.82-rc.118

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-core",
3
- "version": "0.9.82-rc.117",
3
+ "version": "0.9.82-rc.118",
4
4
  "description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -402,11 +402,13 @@ function buildNativeHistoryFallbackReason(args: {
402
402
  provider?: ProviderModule;
403
403
  nativeSource?: string;
404
404
  nativeHistoryCoverage?: string;
405
+ unavailableReason?: string;
405
406
  nativeMessageCount: number;
406
407
  safeMapping: boolean;
407
408
  freshEnough: boolean;
408
409
  }): string {
409
410
  if (!supportsCliNativeTranscript(args.providerType, args.provider)) return 'provider_native_transcript_not_supported';
411
+ if (args.unavailableReason) return `native_history_unavailable:${args.unavailableReason}`;
410
412
  if (args.nativeSource === 'native-unavailable') return 'native_history_unavailable';
411
413
  if (args.nativeHistoryCoverage === 'partial') return 'native_history_partial';
412
414
  if (args.nativeHistoryCoverage === 'unavailable') return 'native_history_unavailable';
@@ -509,6 +511,15 @@ function readCliProviderNativeHistory(agentStr: string, args: {
509
511
  scripts?: ProviderScripts;
510
512
  exactSessionScoped?: boolean;
511
513
  }): ReturnType<typeof readProviderChatHistory> & { lookup: 'session' | 'workspace' } {
514
+ if (!args.historySessionId) {
515
+ return {
516
+ messages: [],
517
+ hasMore: false,
518
+ source: 'native-unavailable',
519
+ unavailableReason: 'native_history_workspace_only_lookup_unsafe',
520
+ lookup: 'session',
521
+ } as ReturnType<typeof readProviderChatHistory> & { lookup: 'session' | 'workspace' };
522
+ }
512
523
  const sessionHistory = readProviderChatHistory(agentStr, {
513
524
  canonicalHistory: args.canonicalHistory,
514
525
  historySessionId: args.historySessionId,
@@ -519,24 +530,10 @@ function readCliProviderNativeHistory(agentStr: string, args: {
519
530
  historyBehavior: args.historyBehavior,
520
531
  scripts: args.scripts as any,
521
532
  });
522
- // Exact runtime/provider transcript reads must not silently fall back to the
523
- // workspace's active or most recent native transcript: multiple Hermes/Gemini/
524
- // Codex sessions can run in the same workspace, and workspace fallback can make
525
- // read_chat/completion evidence point at a different runtime's prompt.
526
- if ((sessionHistory as any).source !== 'native-unavailable' || args.exactSessionScoped || !args.historySessionId || !args.workspace) {
527
- return { ...(sessionHistory as any), lookup: args.historySessionId ? 'session' : 'workspace' };
528
- }
529
- const workspaceHistory = readProviderChatHistory(agentStr, {
530
- canonicalHistory: args.canonicalHistory,
531
- historySessionId: undefined,
532
- workspace: args.workspace,
533
- offset: args.offset,
534
- limit: args.limit,
535
- excludeRecentCount: args.excludeRecentCount,
536
- historyBehavior: args.historyBehavior,
537
- scripts: args.scripts as any,
538
- });
539
- return { ...(workspaceHistory as any), lookup: 'workspace' };
533
+ // Native transcripts are keyed by provider/runtime session identity. Falling
534
+ // back to workspace makes concurrent local Codex/Hermes sessions alias each
535
+ // other when they share the same cwd.
536
+ return { ...(sessionHistory as any), lookup: 'session' };
540
537
  }
541
538
 
542
539
  function isNativeHistoryFreshEnough(args: {
@@ -1446,11 +1443,12 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
1446
1443
  const fallbackReason = buildNativeHistoryFallbackReason({
1447
1444
  providerType,
1448
1445
  provider,
1449
- nativeSource: (nativeHistory as any).source,
1450
- nativeHistoryCoverage,
1451
- nativeMessageCount: nativeMessages.length,
1452
- safeMapping,
1453
- freshEnough,
1446
+ nativeSource: (nativeHistory as any).source,
1447
+ nativeHistoryCoverage,
1448
+ unavailableReason,
1449
+ nativeMessageCount: nativeMessages.length,
1450
+ safeMapping,
1451
+ freshEnough,
1454
1452
  });
1455
1453
  messageSource = buildCliMessageSourceProvenance({
1456
1454
  selected: 'pty-parser',
@@ -1581,6 +1579,7 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
1581
1579
  provider,
1582
1580
  nativeSource: (history as any).source,
1583
1581
  nativeHistoryCoverage,
1582
+ unavailableReason,
1584
1583
  nativeMessageCount: historyMessages.length,
1585
1584
  safeMapping,
1586
1585
  freshEnough: true,
@@ -1079,9 +1079,12 @@ function summarizeMeshSessionRecord(record: any): Record<string, unknown> {
1079
1079
  };
1080
1080
  }
1081
1081
 
1082
- function liveSessionRecordMatchesMeshNode(record: any, meshId: string, nodeId: string): boolean {
1082
+ function liveSessionRecordMatchesMeshNode(record: any, meshId: string, nodeId: string, nodeWorkspace = '', nodeIsMissingLocalWorktree = false): boolean {
1083
1083
  const recordNodeId = readStringValue(record?.meta?.meshNodeId);
1084
1084
  if (!recordNodeId || recordNodeId !== nodeId) return false;
1085
+ if (nodeIsMissingLocalWorktree) return false;
1086
+ const recordWorkspace = readStringValue(record?.workspace);
1087
+ if (nodeWorkspace && recordWorkspace && recordWorkspace !== nodeWorkspace) return false;
1085
1088
  const recordMeshId = readStringValue(record?.meta?.meshNodeFor);
1086
1089
  return !recordMeshId || recordMeshId === meshId;
1087
1090
  }
@@ -1130,9 +1133,15 @@ function collectLiveMeshSessionRecords(args: {
1130
1133
  liveSessionRecords: any[];
1131
1134
  allowCoordinatorSession?: boolean;
1132
1135
  }): any[] {
1136
+ const nodeWorkspace = readStringValue(args.node?.workspace);
1137
+ const nodeIsMissingLocalWorktree = args.node?.isLocalWorktree === true
1138
+ && !!nodeWorkspace
1139
+ && !fs.existsSync(nodeWorkspace);
1133
1140
  const matches = args.liveSessionRecords.filter((record) => {
1134
- const nodeWorkspace = readStringValue(args.node?.workspace);
1135
- if (liveSessionRecordMatchesMeshNode(record, args.meshId, args.nodeId)) return true;
1141
+ const recordNodeId = readStringValue(record?.meta?.meshNodeId);
1142
+ if (recordNodeId && recordNodeId !== args.nodeId) return false;
1143
+ if (liveSessionRecordMatchesMeshNode(record, args.meshId, args.nodeId, nodeWorkspace || '', nodeIsMissingLocalWorktree)) return true;
1144
+ if (nodeIsMissingLocalWorktree) return false;
1136
1145
  return !!nodeWorkspace && liveSessionRecordMatchesMeshWorkspace(record, args.meshId, nodeWorkspace);
1137
1146
  });
1138
1147
 
@@ -1155,11 +1164,15 @@ function buildHistoricalMeshSessions(args: {
1155
1164
  }): { count: number; sessions: Record<string, unknown>[]; instruction: string } | undefined {
1156
1165
  const liveNodeIds = new Set<string>();
1157
1166
  const liveWorkspaces = new Set<string>();
1167
+ const missingLocalWorktreeNodeIds = new Set<string>();
1158
1168
  for (const node of args.nodes || []) {
1159
1169
  const nodeId = readStringValue(node?.id, node?.nodeId);
1160
1170
  const workspace = readStringValue(node?.workspace);
1161
1171
  if (nodeId) liveNodeIds.add(nodeId);
1162
1172
  if (workspace) liveWorkspaces.add(workspace);
1173
+ if (nodeId && node?.isLocalWorktree === true && workspace && !fs.existsSync(workspace)) {
1174
+ missingLocalWorktreeNodeIds.add(nodeId);
1175
+ }
1163
1176
  }
1164
1177
 
1165
1178
  const sessions: Record<string, unknown>[] = [];
@@ -1169,7 +1182,7 @@ function buildHistoricalMeshSessions(args: {
1169
1182
  if (recordMeshId !== args.meshId) continue;
1170
1183
  const recordNodeId = readStringValue(meta.meshNodeId);
1171
1184
  const workspace = readStringValue(record?.workspace);
1172
- const removedNode = !!recordNodeId && !liveNodeIds.has(recordNodeId);
1185
+ const removedNode = !!recordNodeId && (!liveNodeIds.has(recordNodeId) || missingLocalWorktreeNodeIds.has(recordNodeId));
1173
1186
  const orphanedWorkspace = !!workspace && !liveWorkspaces.has(workspace) && meta.meshCoordinatorFor !== args.meshId;
1174
1187
  if (!removedNode && !orphanedWorkspace) continue;
1175
1188
  sessions.push({
@@ -5636,12 +5649,22 @@ export class DaemonCommandRouter {
5636
5649
  for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
5637
5650
  const nodeId = String(node.id || node.nodeId || '');
5638
5651
  const daemonId = readStringValue(node.daemonId);
5652
+ const nodeMachineId = readMeshNodeMachineId(node as Record<string, unknown>);
5653
+ const nodeHostname = readMeshNodeHostname(node as Record<string, unknown>);
5639
5654
  const providerPriority = readProviderPriorityFromPolicy(node.policy);
5655
+ const configuredCoordinatorNode = Boolean(
5656
+ nodeId && selectedCoordinatorNodeId && nodeId === selectedCoordinatorNodeId,
5657
+ );
5658
+ const sparseConfiguredCoordinatorNode = configuredCoordinatorNode
5659
+ && !daemonId
5660
+ && !nodeMachineId
5661
+ && !nodeHostname;
5640
5662
  const isSelfNode = Boolean(
5641
5663
  nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId,
5642
5664
  ) || Boolean(
5643
5665
  daemonId && (daemonId === localMachineId || daemonId === this.deps.statusInstanceId),
5644
- ) || Boolean(meshRecord?.inline && nodeIndex === 0);
5666
+ ) || Boolean(meshRecord?.inline && nodeIndex === 0)
5667
+ || sparseConfiguredCoordinatorNode;
5645
5668
  const machineIdentity = buildMeshNodeMachineIdentity(node as Record<string, unknown>, {
5646
5669
  localMachineId,
5647
5670
  localDaemonId: this.deps.statusInstanceId,
@@ -5660,7 +5683,7 @@ export class DaemonCommandRouter {
5660
5683
  worktreeBranch: node.worktreeBranch,
5661
5684
  role: normalizeMeshDaemonRole(node.role) || (meshHost.hostNodeId && nodeId === meshHost.hostNodeId ? 'host' : undefined),
5662
5685
  daemonId,
5663
- machineId: readMeshNodeMachineId(node as Record<string, unknown>) || node.machineId,
5686
+ machineId: nodeMachineId || node.machineId,
5664
5687
  machine: machineIdentity,
5665
5688
  machineStatus: node.machineStatus,
5666
5689
  health: 'unknown',