@adhdev/daemon-core 0.9.82-rc.91 → 0.9.82-rc.93

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.91",
3
+ "version": "0.9.82-rc.93",
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",
@@ -1671,7 +1671,8 @@ export class ProviderCliAdapter implements CliAdapter {
1671
1671
  const cached = this.parsedStatusCache;
1672
1672
  const accumulatedRawBufferKey = this.getAccumulatedRawBufferCacheKey();
1673
1673
  if (
1674
- cached
1674
+ !this.providerOwnsTranscript()
1675
+ && cached
1675
1676
  && cached.responseBuffer === this.responseBuffer
1676
1677
  && cached.currentTurnScope === this.currentTurnScope
1677
1678
  && cached.recentOutputBuffer === this.recentOutputBuffer
@@ -50,6 +50,16 @@ function getTargetedCliAdapter(h: CommandHelpers, args: any, providerType?: stri
50
50
  return h.getCliAdapter(args?.targetSessionId || providerType || h.currentSession?.providerType || h.currentManagerKey);
51
51
  }
52
52
 
53
+ function getExplicitHistorySessionId(args: any): string | undefined {
54
+ const explicit = typeof args?.historySessionId === 'string' ? args.historySessionId.trim() : '';
55
+ if (explicit) return explicit;
56
+
57
+ const explicitProviderSessionId = typeof args?.providerSessionId === 'string' ? args.providerSessionId.trim() : '';
58
+ if (explicitProviderSessionId) return explicitProviderSessionId;
59
+
60
+ return undefined;
61
+ }
62
+
53
63
  function getTargetInstance(h: CommandHelpers, args: any): ApprovalSelectableInstance | null {
54
64
  const targetSessionId = typeof args?.targetSessionId === 'string' ? args.targetSessionId.trim() : '';
55
65
  const sessionId = targetSessionId || h.currentSession?.sessionId || '';
@@ -141,16 +151,17 @@ async function waitOnceForFreshHermesCliStart(adapter: CliAdapter, log: (msg: st
141
151
  }
142
152
 
143
153
  function getHistorySessionId(h: CommandHelpers, args: any): string | undefined {
144
- const explicit = typeof args?.historySessionId === 'string' ? args.historySessionId.trim() : '';
154
+ const explicit = getExplicitHistorySessionId(args);
145
155
  if (explicit) return explicit;
146
156
 
147
- const explicitProviderSessionId = typeof args?.providerSessionId === 'string' ? args.providerSessionId.trim() : '';
148
- if (explicitProviderSessionId) return explicitProviderSessionId;
149
-
150
157
  const targetSessionId = typeof args?.targetSessionId === 'string' ? args.targetSessionId.trim() : '';
151
158
  if (!targetSessionId) return undefined;
152
159
 
153
- const instance = h.ctx.instanceManager?.getInstance(targetSessionId);
160
+ const session = h.ctx.sessionRegistry?.get(targetSessionId) as any;
161
+ const registeredProviderSessionId = typeof session?.providerSessionId === 'string' ? session.providerSessionId.trim() : '';
162
+ if (registeredProviderSessionId) return registeredProviderSessionId;
163
+
164
+ const instance = getTargetInstance(h, args);
154
165
  const state = instance?.getState?.();
155
166
  const providerSessionId = typeof state?.providerSessionId === 'string' ? state.providerSessionId.trim() : '';
156
167
  if (providerSessionId) return providerSessionId;
@@ -166,6 +177,23 @@ function getHistorySessionId(h: CommandHelpers, args: any): string | undefined {
166
177
  return targetSessionId;
167
178
  }
168
179
 
180
+ function resolveCliNativeHistorySessionId(args: any, currentHistorySessionId: string | undefined, parsedProviderSessionId: string | undefined): string | undefined {
181
+ const explicit = getExplicitHistorySessionId(args);
182
+ if (explicit) return explicit;
183
+
184
+ const parsed = typeof parsedProviderSessionId === 'string' ? parsedProviderSessionId.trim() : '';
185
+ const current = typeof currentHistorySessionId === 'string' ? currentHistorySessionId.trim() : '';
186
+ const targetSessionId = typeof args?.targetSessionId === 'string' ? args.targetSessionId.trim() : '';
187
+
188
+ // getHistorySessionId falls back to the runtime session id when no native
189
+ // handle has been registered yet. For live CLI adapters the parser may
190
+ // already know the provider-native handle; prefer it over the runtime id so
191
+ // exact native reads do not miss the worker transcript and fall back to PTY
192
+ // or same-workspace history.
193
+ if (parsed && (!current || current === targetSessionId)) return parsed;
194
+ return current || parsed || undefined;
195
+ }
196
+
169
197
  function getInteractionId(args: any): string | undefined {
170
198
  return typeof args?._interactionId === 'string' && args._interactionId.trim()
171
199
  ? args._interactionId.trim()
@@ -368,11 +396,38 @@ function supportsCliNativeTranscript(providerType: string, provider?: ProviderMo
368
396
  return provider?.category === 'cli' && isNativeSourceCanonicalHistory(provider?.canonicalHistory);
369
397
  }
370
398
 
399
+ function getComparableVisibleText(message: ChatMessage | undefined): string {
400
+ if (!message) return '';
401
+ const role = String((message as any).role || '').trim().toLowerCase();
402
+ if (role !== 'user' && role !== 'assistant') return '';
403
+ const kind = String((message as any).kind || 'standard').trim().toLowerCase();
404
+ if (kind && kind !== 'standard') return '';
405
+ const content = flattenContent((message as any).content).replace(/\s+/g, ' ').trim();
406
+ return content;
407
+ }
408
+
409
+ function hasOverlappingVisibleConversationText(nativeMessages: ChatMessage[], ptyMessages: ChatMessage[]): boolean {
410
+ const nativeTexts = nativeMessages.map(getComparableVisibleText).filter(Boolean);
411
+ const ptyTexts = ptyMessages.map(getComparableVisibleText).filter(Boolean);
412
+ if (nativeTexts.length === 0 || ptyTexts.length === 0) return false;
413
+ for (const nativeText of nativeTexts) {
414
+ for (const ptyText of ptyTexts) {
415
+ if (nativeText === ptyText) return true;
416
+ const shorter = nativeText.length <= ptyText.length ? nativeText : ptyText;
417
+ const longer = nativeText.length <= ptyText.length ? ptyText : nativeText;
418
+ if (shorter.length >= 32 && longer.includes(shorter)) return true;
419
+ }
420
+ }
421
+ return false;
422
+ }
423
+
371
424
  function hasSafeNativeHistoryMapping(args: {
372
425
  historySessionId?: string;
373
426
  providerSessionId?: string;
374
427
  workspace?: string;
375
428
  nativeMessages: ChatMessage[];
429
+ ptyMessages?: ChatMessage[];
430
+ requireWorkspaceContentOverlap?: boolean;
376
431
  }): boolean {
377
432
  const explicitSessionId = String(args.historySessionId || args.providerSessionId || '').trim();
378
433
  if (explicitSessionId) {
@@ -384,7 +439,10 @@ function hasSafeNativeHistoryMapping(args: {
384
439
  }
385
440
  const workspace = String(args.workspace || '').trim();
386
441
  if (!workspace) return false;
387
- return args.nativeMessages.some((message: any) => String(message?.workspace || '').trim() === workspace);
442
+ const workspaceMatches = args.nativeMessages.some((message: any) => String(message?.workspace || '').trim() === workspace);
443
+ if (!workspaceMatches) return false;
444
+ if (!args.requireWorkspaceContentOverlap) return true;
445
+ return hasOverlappingVisibleConversationText(args.nativeMessages, args.ptyMessages || []);
388
446
  }
389
447
 
390
448
  function readCliProviderNativeHistory(agentStr: string, args: {
@@ -445,6 +503,22 @@ function shouldPreserveReadChatPayloadField(key: string): boolean {
445
503
  return key === 'messageSource' || key === 'transcriptProvenance';
446
504
  }
447
505
 
506
+ function updateMessageSourceReturnedCount(value: unknown, returnedMessageCount: number): unknown {
507
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return value;
508
+ const record = value as Record<string, unknown>;
509
+ const coverage = record.coverage && typeof record.coverage === 'object' && !Array.isArray(record.coverage)
510
+ ? record.coverage as Record<string, unknown>
511
+ : undefined;
512
+ if (!coverage) return value;
513
+ return {
514
+ ...record,
515
+ coverage: {
516
+ ...coverage,
517
+ returnedMessageCount,
518
+ },
519
+ };
520
+ }
521
+
448
522
  function deriveHistoryDedupKey(message: ChatMessage & { _unitKey?: string; _turnKey?: string }): string | undefined {
449
523
  const unitKey = typeof message._unitKey === 'string' ? message._unitKey.trim() : '';
450
524
  if (unitKey) return `read_chat:${unitKey}`;
@@ -594,6 +668,13 @@ function buildReadChatCommandResult(payload: Record<string, any>, args: any): Co
594
668
  const visibleMessages = filterUserFacingChatMessages(messages);
595
669
  const sync = buildFullTail(visibleMessages, normalizeReadChatTailLimit(args));
596
670
  const hiddenMsgCount = Math.max(0, messages.length - visibleMessages.length);
671
+ const preservedPayloadFields = Object.fromEntries(Object.entries(payload).filter(([key]) => shouldPreserveReadChatPayloadField(key)));
672
+ if (preservedPayloadFields.messageSource) {
673
+ preservedPayloadFields.messageSource = updateMessageSourceReturnedCount(preservedPayloadFields.messageSource, sync.messages.length);
674
+ }
675
+ if (preservedPayloadFields.transcriptProvenance) {
676
+ preservedPayloadFields.transcriptProvenance = updateMessageSourceReturnedCount(preservedPayloadFields.transcriptProvenance, sync.messages.length);
677
+ }
597
678
  const returnedDebugReadChat = debugReadChat
598
679
  ? {
599
680
  ...debugReadChat,
@@ -608,7 +689,7 @@ function buildReadChatCommandResult(payload: Record<string, any>, args: any): Co
608
689
  return {
609
690
  success: true,
610
691
  ...validatedPayload,
611
- ...Object.fromEntries(Object.entries(payload).filter(([key]) => shouldPreserveReadChatPayloadField(key))),
692
+ ...preservedPayloadFields,
612
693
  messages: sync.messages,
613
694
  totalMessages: sync.totalMessages,
614
695
  ...(returnedDebugReadChat ? { debugReadChat: returnedDebugReadChat } : {}),
@@ -1168,17 +1249,20 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
1168
1249
  returnedMessages.length,
1169
1250
  200,
1170
1251
  );
1252
+ const nativeHistorySessionId = resolveCliNativeHistorySessionId(args, historySessionId, providerSessionId);
1253
+ const targetSessionId = typeof args?.targetSessionId === 'string' ? args.targetSessionId.trim() : '';
1171
1254
  const exactNativeHistoryScope = Boolean(
1172
1255
  (typeof args?.historySessionId === 'string' && args.historySessionId.trim())
1173
1256
  || (typeof args?.providerSessionId === 'string' && args.providerSessionId.trim())
1174
1257
  || providerSessionId
1258
+ || (nativeHistorySessionId && nativeHistorySessionId !== targetSessionId)
1175
1259
  || ((h.currentSession as any)?.sessionId === args?.targetSessionId && typeof (h.currentSession as any)?.providerSessionId === 'string' && (h.currentSession as any).providerSessionId.trim())
1176
1260
  );
1177
1261
  let nativeHistory: (ReturnType<typeof readProviderChatHistory> & { lookup?: 'session' | 'workspace' }) | null = null;
1178
1262
  try {
1179
1263
  nativeHistory = readCliProviderNativeHistory(agentStr, {
1180
1264
  canonicalHistory: provider?.canonicalHistory,
1181
- historySessionId,
1265
+ historySessionId: nativeHistorySessionId,
1182
1266
  workspace,
1183
1267
  offset: 0,
1184
1268
  limit: nativeHistoryLimit,
@@ -1206,13 +1290,15 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
1206
1290
  : [];
1207
1291
  const historyProviderSessionId = typeof (nativeHistory as any)?.providerSessionId === 'string'
1208
1292
  ? (nativeHistory as any).providerSessionId
1209
- : readHistorySessionIdFromMessages(nativeMessages) || historySessionId;
1293
+ : readHistorySessionIdFromMessages(nativeMessages) || nativeHistorySessionId || historySessionId;
1210
1294
  const lookup = (nativeHistory as any).lookup === 'workspace' ? 'workspace' : 'session';
1211
1295
  const safeMapping = hasSafeNativeHistoryMapping({
1212
- historySessionId: lookup === 'workspace' ? undefined : historySessionId,
1213
- providerSessionId: lookup === 'workspace' ? undefined : providerSessionId,
1296
+ historySessionId: lookup === 'workspace' ? undefined : nativeHistorySessionId,
1297
+ providerSessionId: lookup === 'workspace' ? undefined : historyProviderSessionId || providerSessionId,
1214
1298
  workspace,
1215
1299
  nativeMessages,
1300
+ ptyMessages: returnedMessages,
1301
+ requireWorkspaceContentOverlap: lookup === 'workspace' && !exactNativeHistoryScope,
1216
1302
  });
1217
1303
  const freshEnough = isNativeHistoryFreshEnough({
1218
1304
  sourceMtimeMs: (nativeHistory as any).sourceMtimeMs,
@@ -1227,7 +1313,7 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
1227
1313
  messageSource = buildCliMessageSourceProvenance({
1228
1314
  selected: 'native-history',
1229
1315
  provider: adapter.cliType,
1230
- nativeHandle: selectedProviderSessionId || historySessionId,
1316
+ nativeHandle: selectedProviderSessionId || nativeHistorySessionId || historySessionId,
1231
1317
  nativeSource: (nativeHistory as any).source,
1232
1318
  sourcePath: (nativeHistory as any).sourcePath,
1233
1319
  sourceMtimeMs: (nativeHistory as any).sourceMtimeMs,
@@ -1250,7 +1336,7 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
1250
1336
  messageSource = buildCliMessageSourceProvenance({
1251
1337
  selected: 'pty-parser',
1252
1338
  provider: adapter.cliType,
1253
- nativeHandle: historyProviderSessionId || historySessionId,
1339
+ nativeHandle: historyProviderSessionId || nativeHistorySessionId || historySessionId,
1254
1340
  fallbackReason,
1255
1341
  nativeSource: (nativeHistory as any).source,
1256
1342
  sourcePath: (nativeHistory as any).sourcePath,