mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-31 16:33:34 +08:00
fix(desktop): keep image-only messages in turn order #1095
This commit is contained in:
parent
d141543794
commit
eef49d3395
@ -5559,6 +5559,56 @@ describe('chatStore history mapping', () => {
|
||||
expect(userMessages).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('keeps an image-only replay before the assistant response', () => {
|
||||
useChatStore.setState({
|
||||
sessions: {
|
||||
[TEST_SESSION_ID]: makeSession({
|
||||
messages: [
|
||||
{
|
||||
id: 'live-user',
|
||||
type: 'user_text',
|
||||
content: '',
|
||||
attachments: [{
|
||||
type: 'image',
|
||||
name: 'screenshot.png',
|
||||
data: 'data:image/png;base64,AAAA',
|
||||
mimeType: 'image/png',
|
||||
}],
|
||||
timestamp: 1,
|
||||
},
|
||||
{
|
||||
id: 'assistant-answer',
|
||||
type: 'assistant_text',
|
||||
content: 'The screenshot shows a repository list.',
|
||||
timestamp: 2,
|
||||
},
|
||||
],
|
||||
chatState: 'thinking',
|
||||
}),
|
||||
},
|
||||
})
|
||||
|
||||
useChatStore.getState().handleServerMessage(TEST_SESSION_ID, {
|
||||
type: 'user_message_replay',
|
||||
content: [
|
||||
'Please analyze the attached image.',
|
||||
'[Image source: /Users/me/.claude/uploads/session/screenshot.png]',
|
||||
].join('\n'),
|
||||
})
|
||||
|
||||
expect(useChatStore.getState().sessions[TEST_SESSION_ID]?.messages).toMatchObject([
|
||||
{
|
||||
type: 'user_text',
|
||||
content: '',
|
||||
attachments: [{ type: 'image', name: 'screenshot.png' }],
|
||||
},
|
||||
{
|
||||
type: 'assistant_text',
|
||||
content: 'The screenshot shows a repository list.',
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it('dedupes a path-backed image after the server inlines it into replay content', () => {
|
||||
const prompt = '检查这张截图'
|
||||
const imagePath = 'C:\\Users\\tester\\Desktop\\screen.png'
|
||||
|
||||
@ -3749,6 +3749,7 @@ function extractRestoredUserDisplay(text: string): RestoredUserDisplay {
|
||||
// ConversationService stores data-only files as `${randomUUID()}-${sanitizedName}`
|
||||
// and omits successfully inlined images from the replayed text content.
|
||||
const MATERIALIZED_UPLOAD_NAME_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}-(.+)$/i
|
||||
const IMAGE_ONLY_REPLAY_FALLBACK = 'Please analyze the attached image.'
|
||||
|
||||
function isLikelyInlineImageAttachment(attachment: UIAttachment): boolean {
|
||||
if (attachment.type === 'image') return true
|
||||
@ -3800,12 +3801,23 @@ function replayMatchesCurrentUserMessage(
|
||||
const currentModelContent = (message.modelContent ?? message.content).trim()
|
||||
if (currentModelContent === replayModelContent) return true
|
||||
|
||||
const currentAttachments = message.attachments ?? []
|
||||
if (
|
||||
message.content.trim() === '' &&
|
||||
replayDisplay.content.trim() === IMAGE_ONLY_REPLAY_FALLBACK &&
|
||||
!replayDisplay.attachments?.length &&
|
||||
currentAttachments.length > 0 &&
|
||||
currentAttachments.every(isLikelyInlineImageAttachment)
|
||||
) {
|
||||
return true
|
||||
}
|
||||
|
||||
const currentDisplay = extractRestoredUserDisplay(currentModelContent)
|
||||
if (currentDisplay.content.trim() !== replayDisplay.content.trim()) return false
|
||||
|
||||
return replayAttachmentsMatchCurrent(
|
||||
replayDisplay.attachments ?? [],
|
||||
message.attachments ?? [],
|
||||
currentAttachments,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user