@@ -533,8 +533,11 @@ export function convertMessagesToInputItems(
533533/**
534534 * When model fallback retries inject duplicate user messages and the
535535 * intervening error-assistant entries are dropped (empty content), the input
536- * ends up with consecutive user messages. Collapse each run down to the last
537- * entry so the model sees the prompt exactly once.
536+ * ends up with consecutive user messages. Deduplicate by removing consecutive
537+ * user messages with identical text content, keeping the last occurrence.
538+ *
539+ * Distinct consecutive user messages (e.g. user sends two different messages
540+ * before the model responds) are preserved.
538541 */
539542function collapseConsecutiveUserMessages ( items : InputItem [ ] ) : InputItem [ ] {
540543 if ( items . length <= 1 ) return items ;
@@ -546,9 +549,9 @@ function collapseConsecutiveUserMessages(items: InputItem[]): InputItem[] {
546549 "role" in prev &&
547550 prev . role === "user" &&
548551 "role" in item &&
549- item . role === "user"
552+ item . role === "user" &&
553+ inputItemTextFingerprint ( prev ) === inputItemTextFingerprint ( item )
550554 ) {
551- // Replace previous with current (keep the later/more recent one)
552555 out [ out . length - 1 ] = item ;
553556 continue ;
554557 }
@@ -557,6 +560,18 @@ function collapseConsecutiveUserMessages(items: InputItem[]): InputItem[] {
557560 return out ;
558561}
559562
563+ /** Extract a comparable text fingerprint from a user input item. */
564+ function inputItemTextFingerprint ( item : InputItem ) : string {
565+ if ( ! ( "content" in item ) ) return "" ;
566+ const content = ( item as { content ?: unknown } ) . content ;
567+ if ( typeof content === "string" ) return content ;
568+ if ( ! Array . isArray ( content ) ) return "" ;
569+ return content
570+ . filter ( ( c : { type ?: string } ) => c . type === "input_text" )
571+ . map ( ( c : { text ?: string } ) => c . text ?? "" )
572+ . join ( "\n" ) ;
573+ }
574+
560575// ─────────────────────────────────────────────────────────────────────────────
561576// Response object → AssistantMessage
562577// ─────────────────────────────────────────────────────────────────────────────
0 commit comments