@adhdev/daemon-core 0.9.76-rc.53 → 0.9.76-rc.55

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.76-rc.53",
3
+ "version": "0.9.76-rc.55",
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",
@@ -19,6 +19,7 @@ import { getRecentDebugTrace, recordDebugTrace } from '../logging/debug-trace.js
19
19
  import { buildChatMessageSignature } from '../chat/chat-signatures.js';
20
20
  import type { ChatMessage } from '../types.js';
21
21
  import type { SessionTransport } from '../shared-types.js';
22
+ import { filterUserFacingChatMessages, normalizeChatMessages } from '../providers/chat-message-normalization.js';
22
23
 
23
24
  const RECENT_SEND_WINDOW_MS = 1200;
24
25
  export const READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS = 25_000;
@@ -195,7 +196,7 @@ function normalizeReadChatTailLimit(args: any): number {
195
196
 
196
197
  function normalizeReadChatMessages(payload: Record<string, any>): ChatMessage[] {
197
198
  const messages = Array.isArray(payload.messages) ? payload.messages as ChatMessage[] : [];
198
- return messages;
199
+ return normalizeChatMessages(messages);
199
200
  }
200
201
 
201
202
 
@@ -316,13 +317,22 @@ function buildReadChatCommandResult(payload: Record<string, any>, args: any): Co
316
317
  return { success: false, error: error?.message || String(error) };
317
318
  }
318
319
  const messages = normalizeReadChatMessages(validatedPayload);
319
- const sync = buildFullTail(messages, normalizeReadChatTailLimit(args));
320
+ const visibleMessages = filterUserFacingChatMessages(messages);
321
+ const sync = buildFullTail(visibleMessages, normalizeReadChatTailLimit(args));
322
+ const hiddenMsgCount = Math.max(0, messages.length - visibleMessages.length);
323
+ const nextDebugReadChat = {
324
+ ...(debugReadChat || {}),
325
+ fullMsgCount: messages.length,
326
+ visibleMsgCount: visibleMessages.length,
327
+ hiddenMsgCount,
328
+ returnedMsgCount: sync.messages.length,
329
+ };
320
330
  return {
321
331
  success: true,
322
332
  ...validatedPayload,
323
333
  messages: sync.messages,
324
334
  totalMessages: sync.totalMessages,
325
- ...(debugReadChat ? { debugReadChat } : {}),
335
+ debugReadChat: nextDebugReadChat,
326
336
  };
327
337
  }
328
338
 
package/src/index.ts CHANGED
@@ -311,6 +311,8 @@ export {
311
311
  buildUserChatMessage,
312
312
  normalizeChatMessage,
313
313
  normalizeChatMessages,
314
+ isUserFacingChatMessage,
315
+ filterUserFacingChatMessages,
314
316
  } from './providers/chat-message-normalization.js';
315
317
  export type { BuiltinChatMessageKind, ChatMessageKind } from './providers/chat-message-normalization.js';
316
318
  export { VersionArchive, detectAllVersions } from './providers/version-archive.js';
@@ -25,7 +25,7 @@ import { formatAutoApprovalMessage, pickApprovalButton } from './approval-utils.
25
25
  import { getCliScriptCommand, parseCliScriptResult } from './cli-script-results.js';
26
26
  import { mergeProviderPatchState, resolveProviderStateSurface } from './provider-patch-state.js';
27
27
  import { normalizeProviderSessionId } from './provider-session-id.js';
28
- import { buildChatMessage, buildRuntimeSystemChatMessage, normalizeChatMessages } from './chat-message-normalization.js';
28
+ import { buildChatMessage, buildRuntimeSystemChatMessage, normalizeChatMessages, resolveChatMessageKind } from './chat-message-normalization.js';
29
29
 
30
30
  type PersistableCliHistoryMessage = {
31
31
  role: string;
@@ -1007,7 +1007,7 @@ export class CliProviderInstance implements ProviderInstance {
1007
1007
  private mergeConversationMessages(parsedMessages: any[]): ChatMessage[] {
1008
1008
  if (this.runtimeMessages.length === 0) return normalizeChatMessages(parsedMessages);
1009
1009
 
1010
- type MergeEntry = { message: ChatMessage; index: number; source: 'parsed' | 'runtime' };
1010
+ type MergeEntry = { message: ChatMessage; index: number; source: 'parsed' | 'runtime'; runtimeKey?: string };
1011
1011
  const parsedEntries: MergeEntry[] = parsedMessages.map((message, index) => ({
1012
1012
  message,
1013
1013
  index,
@@ -1017,6 +1017,7 @@ export class CliProviderInstance implements ProviderInstance {
1017
1017
  message: entry.message,
1018
1018
  index: parsedMessages.length + index,
1019
1019
  source: 'runtime',
1020
+ runtimeKey: entry.key,
1020
1021
  }));
1021
1022
  const getTime = (message: ChatMessage): number => {
1022
1023
  const value = typeof message.receivedAt === 'number'
@@ -1027,16 +1028,52 @@ export class CliProviderInstance implements ProviderInstance {
1027
1028
  return Number.isFinite(value) && value > 0 ? value : 0;
1028
1029
  };
1029
1030
 
1031
+ const getRole = (message: ChatMessage): string => typeof message.role === 'string'
1032
+ ? message.role.trim().toLowerCase()
1033
+ : '';
1034
+ const isAutoApprovalRuntimeOverlay = (entry: MergeEntry): boolean => {
1035
+ if (entry.source !== 'runtime') return false;
1036
+ const key = typeof entry.runtimeKey === 'string' ? entry.runtimeKey.trim().toLowerCase() : '';
1037
+ if (key.startsWith('auto_approval:')) return true;
1038
+ const content = typeof entry.message.content === 'string'
1039
+ ? entry.message.content.trim().toLowerCase()
1040
+ : flattenContent(entry.message.content).trim().toLowerCase();
1041
+ return content.startsWith('auto-approved:');
1042
+ };
1043
+ const shouldKeepParsedBeforeUntimedRuntime = (message: ChatMessage): boolean => {
1044
+ const role = getRole(message);
1045
+ return role === 'user' || role === 'human';
1046
+ };
1047
+ const shouldKeepParsedAfterUntimedRuntime = (message: ChatMessage): boolean => {
1048
+ const role = getRole(message);
1049
+ if (role !== 'assistant') return false;
1050
+ const kind = resolveChatMessageKind(message);
1051
+ return kind === 'standard' || kind === 'terminal';
1052
+ };
1053
+
1030
1054
  return normalizeChatMessages([...parsedEntries, ...runtimeEntries]
1031
1055
  .sort((a, b) => {
1032
1056
  const aTime = getTime(a.message);
1033
1057
  const bTime = getTime(b.message);
1034
1058
  if (aTime && bTime && aTime !== bTime) return aTime - bTime;
1059
+ if (a.source !== b.source && aTime !== bTime) {
1060
+ const parsedEntry = a.source === 'parsed' ? a : b.source === 'parsed' ? b : null;
1061
+ const runtimeEntry = a.source === 'runtime' ? a : b.source === 'runtime' ? b : null;
1062
+ if (parsedEntry && runtimeEntry && isAutoApprovalRuntimeOverlay(runtimeEntry) && getTime(parsedEntry.message) === 0 && getTime(runtimeEntry.message) > 0) {
1063
+ if (shouldKeepParsedBeforeUntimedRuntime(parsedEntry.message)) {
1064
+ return a.source === 'parsed' ? -1 : 1;
1065
+ }
1066
+ if (shouldKeepParsedAfterUntimedRuntime(parsedEntry.message)) {
1067
+ return a.source === 'parsed' ? 1 : -1;
1068
+ }
1069
+ }
1070
+ }
1035
1071
  // Many provider-owned CLI transcripts (including Hermes CLI in debug bundles)
1036
1072
  // do not carry timestamps on parsed messages. In that case there is no safe
1037
1073
  // clock basis for interleaving timestamped runtime/system messages into the
1038
- // provider transcript, so preserve parsed order and append runtime entries by
1039
- // their insertion index instead of moving them ahead of the whole transcript.
1074
+ // provider transcript. Keep user prompts before runtime overlays, but do not
1075
+ // let timed runtime/system overlays become the final chat turns after an
1076
+ // untimed parsed assistant transcript.
1040
1077
  return a.index - b.index;
1041
1078
  })
1042
1079
  .map((entry) => entry.message));