fix(chat): hide internal system messages from webchat (#710)

This commit is contained in:
Kagura
2026-03-30 14:57:26 +08:00
committed by GitHub
Unverified
parent 47c9560b9e
commit ef3cf64484
5 changed files with 129 additions and 3 deletions

View File

@@ -777,6 +777,16 @@ function isToolResultRole(role: unknown): boolean {
return normalized === 'toolresult' || normalized === 'tool_result';
}
/** True for internal plumbing messages that should never be shown in the UI. */
function isInternalMessage(msg: { role?: unknown; content?: unknown }): boolean {
if (msg.role === 'system') return true;
if (msg.role === 'assistant') {
const text = getMessageText(msg.content);
if (/^(HEARTBEAT_OK|NO_REPLY)\s*$/.test(text)) return true;
}
return false;
}
function extractTextFromContent(content: unknown): string {
if (typeof content === 'string') return content;
if (!Array.isArray(content)) return '';
@@ -1314,7 +1324,7 @@ export const useChatStore = create<ChatState>((set, get) => ({
// Before filtering: attach images/files from tool_result messages to the next assistant message
const messagesWithToolImages = enrichWithToolResultFiles(rawMessages);
const filteredMessages = messagesWithToolImages.filter((msg) => !isToolResultRole(msg.role));
const filteredMessages = messagesWithToolImages.filter((msg) => !isToolResultRole(msg.role) && !isInternalMessage(msg));
// Restore file attachments for user/assistant messages (from cache + text patterns)
const enrichedMessages = enrichWithCachedImages(filteredMessages);

View File

@@ -598,6 +598,16 @@ function isToolResultRole(role: unknown): boolean {
return normalized === 'toolresult' || normalized === 'tool_result';
}
/** True for internal plumbing messages that should never be shown in the UI. */
function isInternalMessage(msg: { role?: unknown; content?: unknown }): boolean {
if (msg.role === 'system') return true;
if (msg.role === 'assistant') {
const text = getMessageText(msg.content);
if (/^(HEARTBEAT_OK|NO_REPLY)\s*$/.test(text)) return true;
}
return false;
}
function extractTextFromContent(content: unknown): string {
if (typeof content === 'string') return content;
if (!Array.isArray(content)) return '';
@@ -824,6 +834,7 @@ export {
extractRawFilePaths,
makeAttachedFile,
enrichWithToolResultFiles,
isInternalMessage,
isToolResultRole,
enrichWithCachedImages,
loadMissingPreviews,

View File

@@ -6,6 +6,7 @@ import {
enrichWithToolResultFiles,
getMessageText,
hasNonToolAssistantContent,
isInternalMessage,
isToolResultRole,
loadMissingPreviews,
toMs,
@@ -39,7 +40,7 @@ export function createHistoryActions(
const applyLoadedMessages = (rawMessages: RawMessage[], thinkingLevel: string | null) => {
// Before filtering: attach images/files from tool_result messages to the next assistant message
const messagesWithToolImages = enrichWithToolResultFiles(rawMessages);
const filteredMessages = messagesWithToolImages.filter((msg) => !isToolResultRole(msg.role));
const filteredMessages = messagesWithToolImages.filter((msg) => !isToolResultRole(msg.role) && !isInternalMessage(msg));
// Restore file attachments for user/assistant messages (from cache + text patterns)
const enrichedMessages = enrichWithCachedImages(filteredMessages);