@adhdev/daemon-core 0.9.76-rc.54 → 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/dist/index.js +49 -24
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +49 -24
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/commands/chat-commands.ts +10 -14
- package/src/providers/chat-message-normalization.ts +19 -38
- package/src/providers/cli-provider-instance.ts +41 -4
package/package.json
CHANGED
|
@@ -18,8 +18,8 @@ import { LOG, getRecentLogs } from '../logging/logger.js';
|
|
|
18
18
|
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
|
-
import { filterUserFacingChatMessages } from '../providers/chat-message-normalization.js';
|
|
22
21
|
import type { SessionTransport } from '../shared-types.js';
|
|
22
|
+
import { filterUserFacingChatMessages, normalizeChatMessages } from '../providers/chat-message-normalization.js';
|
|
23
23
|
|
|
24
24
|
const RECENT_SEND_WINDOW_MS = 1200;
|
|
25
25
|
export const READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS = 25_000;
|
|
@@ -196,7 +196,7 @@ function normalizeReadChatTailLimit(args: any): number {
|
|
|
196
196
|
|
|
197
197
|
function normalizeReadChatMessages(payload: Record<string, any>): ChatMessage[] {
|
|
198
198
|
const messages = Array.isArray(payload.messages) ? payload.messages as ChatMessage[] : [];
|
|
199
|
-
return messages;
|
|
199
|
+
return normalizeChatMessages(messages);
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
|
|
@@ -320,23 +320,19 @@ function buildReadChatCommandResult(payload: Record<string, any>, args: any): Co
|
|
|
320
320
|
const visibleMessages = filterUserFacingChatMessages(messages);
|
|
321
321
|
const sync = buildFullTail(visibleMessages, normalizeReadChatTailLimit(args));
|
|
322
322
|
const hiddenMsgCount = Math.max(0, messages.length - visibleMessages.length);
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
hiddenMsgCount,
|
|
331
|
-
returnedMsgCount: sync.messages.length,
|
|
332
|
-
}
|
|
333
|
-
: undefined;
|
|
323
|
+
const nextDebugReadChat = {
|
|
324
|
+
...(debugReadChat || {}),
|
|
325
|
+
fullMsgCount: messages.length,
|
|
326
|
+
visibleMsgCount: visibleMessages.length,
|
|
327
|
+
hiddenMsgCount,
|
|
328
|
+
returnedMsgCount: sync.messages.length,
|
|
329
|
+
};
|
|
334
330
|
return {
|
|
335
331
|
success: true,
|
|
336
332
|
...validatedPayload,
|
|
337
333
|
messages: sync.messages,
|
|
338
334
|
totalMessages: sync.totalMessages,
|
|
339
|
-
|
|
335
|
+
debugReadChat: nextDebugReadChat,
|
|
340
336
|
};
|
|
341
337
|
}
|
|
342
338
|
|
|
@@ -179,44 +179,25 @@ function readMessageMeta(message: ChatMessage): Record<string, unknown> | null {
|
|
|
179
179
|
: null;
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
function
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const record = message as ChatMessage & Record<string, unknown>;
|
|
188
|
-
const visibility = readStringField(record.visibility || meta?.visibility || meta?.transcriptVisibility);
|
|
189
|
-
const audience = readStringField(record.audience || meta?.audience);
|
|
190
|
-
const source = readStringField(record.source || meta?.source);
|
|
191
|
-
|
|
182
|
+
function isExplicitlyHiddenFromTranscript(meta: Record<string, unknown> | null): boolean {
|
|
183
|
+
if (!meta) return false;
|
|
184
|
+
const visibility = typeof meta.transcriptVisibility === 'string'
|
|
185
|
+
? meta.transcriptVisibility.trim().toLowerCase()
|
|
186
|
+
: '';
|
|
192
187
|
return visibility === 'hidden'
|
|
193
188
|
|| visibility === 'debug'
|
|
194
|
-
||
|
|
195
|
-
||
|
|
196
|
-
||
|
|
197
|
-
||
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|| meta?.debug === true
|
|
207
|
-
|| meta?.statusOnly === true
|
|
208
|
-
|| meta?.controlOnly === true;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
function isExplicitlyVisibleInTranscript(message: ChatMessage, meta: Record<string, unknown> | null): boolean {
|
|
212
|
-
const record = message as ChatMessage & Record<string, unknown>;
|
|
213
|
-
const visibility = readStringField(record.visibility || meta?.visibility || meta?.transcriptVisibility);
|
|
214
|
-
const audience = readStringField(record.audience || meta?.audience);
|
|
215
|
-
return visibility === 'visible'
|
|
216
|
-
|| visibility === 'user'
|
|
217
|
-
|| audience === 'chat'
|
|
218
|
-
|| record.userFacing === true
|
|
219
|
-
|| meta?.userFacing === true;
|
|
189
|
+
|| meta.internal === true
|
|
190
|
+
|| meta.debug === true
|
|
191
|
+
|| meta.statusOnly === true
|
|
192
|
+
|| meta.controlOnly === true;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function isExplicitlyVisibleInTranscript(meta: Record<string, unknown> | null): boolean {
|
|
196
|
+
if (!meta) return false;
|
|
197
|
+
const visibility = typeof meta.transcriptVisibility === 'string'
|
|
198
|
+
? meta.transcriptVisibility.trim().toLowerCase()
|
|
199
|
+
: '';
|
|
200
|
+
return visibility === 'visible' || meta.userFacing === true;
|
|
220
201
|
}
|
|
221
202
|
|
|
222
203
|
/**
|
|
@@ -231,8 +212,8 @@ function isExplicitlyVisibleInTranscript(message: ChatMessage, meta: Record<stri
|
|
|
231
212
|
export function isUserFacingChatMessage(message: ChatMessage | null | undefined): boolean {
|
|
232
213
|
if (!message) return false;
|
|
233
214
|
const meta = readMessageMeta(message);
|
|
234
|
-
if (isExplicitlyHiddenFromTranscript(
|
|
235
|
-
if (isExplicitlyVisibleInTranscript(
|
|
215
|
+
if (isExplicitlyHiddenFromTranscript(meta)) return false;
|
|
216
|
+
if (isExplicitlyVisibleInTranscript(meta)) return true;
|
|
236
217
|
|
|
237
218
|
const role = typeof message.role === 'string' ? message.role.trim().toLowerCase() : '';
|
|
238
219
|
const kind = resolveChatMessageKind(message);
|
|
@@ -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
|
|
1039
|
-
//
|
|
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));
|