Fix duplicate image rendering in chat bubble tool calls
This commit is contained in:
		
							
								
								
									
										81
									
								
								index.js
									
									
									
									
									
								
							
							
						
						
									
										81
									
								
								index.js
									
									
									
									
									
								
							@@ -241,25 +241,35 @@ function processToolCallMessages() {
 | 
				
			|||||||
                    renderContainer.html(tool.result);
 | 
					                    renderContainer.html(tool.result);
 | 
				
			||||||
                  }
 | 
					                  }
 | 
				
			||||||
                  
 | 
					                  
 | 
				
			||||||
                  // Remove any existing rendered images
 | 
					                  // Clean up all images for this message
 | 
				
			||||||
                  $(this).find('.sillybubble-rendered-image').remove();
 | 
					                  $(this).find('.sillybubble-rendered-image').remove();
 | 
				
			||||||
                  $('.sillybubble-collapsed-image').remove();
 | 
					                  $(this).find('.sillybubble-collapsed-image').remove();
 | 
				
			||||||
                  
 | 
					                  
 | 
				
			||||||
                  // Create a special always-visible container for collapsed state
 | 
					                  // Create a special always-visible container for collapsed state
 | 
				
			||||||
                  const collapsedContainer = $('<div class="sillybubble-collapsed-image"></div>');
 | 
					                  const collapsedContainer = $('<div class="sillybubble-collapsed-image"></div>');
 | 
				
			||||||
                  collapsedContainer.html(renderContainer.html());
 | 
					                  collapsedContainer.html(renderContainer.html());
 | 
				
			||||||
                  
 | 
					                  
 | 
				
			||||||
                  // Add the image to the mes_block, BEFORE the details element
 | 
					                  // Get the message text element (where tool calls are shown)
 | 
				
			||||||
                  // This ensures it's visible when details is collapsed
 | 
					                  const messageTextDiv = $(this).find('.mes_text');
 | 
				
			||||||
                  detailsElement.before(collapsedContainer);
 | 
					 | 
				
			||||||
                  
 | 
					                  
 | 
				
			||||||
                  // Also add inside the details for when it's open
 | 
					                  // Check if the details element is part of mes_text (most common case)
 | 
				
			||||||
                  if (summaryElement.length) {
 | 
					                  const detailsInText = messageTextDiv.find('details').length > 0;
 | 
				
			||||||
                    // Add inside the details content for when it's expanded
 | 
					                  
 | 
				
			||||||
                    const reasoningDiv = $(this).find('.mes_reasoning');
 | 
					                  if (detailsInText) {
 | 
				
			||||||
                    if (reasoningDiv.length) {
 | 
					                    // For typical tool calls, add collapsed image just before the details element in mes_text
 | 
				
			||||||
                      reasoningDiv.prepend(renderContainer.clone());
 | 
					                    messageTextDiv.find('details').before(collapsedContainer);
 | 
				
			||||||
                    }
 | 
					                  } else {
 | 
				
			||||||
 | 
					                    // Fallback - add it before the details element wherever it is
 | 
				
			||||||
 | 
					                    detailsElement.before(collapsedContainer);
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					                  
 | 
				
			||||||
 | 
					                  // ONLY add image in the reasoning div, NOT in the details summary
 | 
				
			||||||
 | 
					                  const reasoningDiv = $(this).find('.mes_reasoning');
 | 
				
			||||||
 | 
					                  if (reasoningDiv.length) {
 | 
				
			||||||
 | 
					                    // Make sure no existing image is there
 | 
				
			||||||
 | 
					                    reasoningDiv.find('.sillybubble-rendered-image').remove();
 | 
				
			||||||
 | 
					                    // Add the image to the reasoning section
 | 
				
			||||||
 | 
					                    reasoningDiv.prepend(renderContainer);
 | 
				
			||||||
                  }
 | 
					                  }
 | 
				
			||||||
                  
 | 
					                  
 | 
				
			||||||
                  // Mark this message as processed
 | 
					                  // Mark this message as processed
 | 
				
			||||||
@@ -285,29 +295,29 @@ function processToolCallMessages() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Helper function to handle visibility of images based on details open state
 | 
					// Helper function to handle visibility of images based on details open state
 | 
				
			||||||
function handleDetailsVisibility(messageElement, detailsElement) {
 | 
					function handleDetailsVisibility(messageElement, detailsElement) {
 | 
				
			||||||
  if (detailsElement.prop('open')) {
 | 
					  // Add a class to the details element to mark it as containing a bubble image
 | 
				
			||||||
    // If details is open, hide the collapsed version
 | 
					  detailsElement.addClass('has-bubble-image');
 | 
				
			||||||
    messageElement.find('.sillybubble-collapsed-image').hide();
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    // If details is closed, show the collapsed version
 | 
					 | 
				
			||||||
    messageElement.find('.sillybubble-collapsed-image').show();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  // Set up a mutation observer to watch for the open attribute changing
 | 
					  // Set up a click handler for the details/summary to ensure proper rendering
 | 
				
			||||||
  const observer = new MutationObserver((mutations) => {
 | 
					  detailsElement.on('click', function() {
 | 
				
			||||||
    mutations.forEach((mutation) => {
 | 
					    // Small delay to ensure the open state has changed
 | 
				
			||||||
      if (mutation.attributeName === 'open') {
 | 
					    setTimeout(() => {
 | 
				
			||||||
        if (detailsElement.prop('open')) {
 | 
					      // Use the CSS-based visibility approach defined in our styles
 | 
				
			||||||
          messageElement.find('.sillybubble-collapsed-image').hide();
 | 
					      // This is more reliable than show/hide in the DOM
 | 
				
			||||||
        } else {
 | 
					      if (detailsElement.prop('open')) {
 | 
				
			||||||
          messageElement.find('.sillybubble-collapsed-image').show();
 | 
					        messageElement.addClass('details-open');
 | 
				
			||||||
        }
 | 
					      } else {
 | 
				
			||||||
 | 
					        messageElement.removeClass('details-open');
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    }, 10);
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  // Start observing the details element
 | 
					  // Set initial state
 | 
				
			||||||
  observer.observe(detailsElement[0], { attributes: true });
 | 
					  if (detailsElement.prop('open')) {
 | 
				
			||||||
 | 
					    messageElement.addClass('details-open');
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    messageElement.removeClass('details-open');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Observer function to watch for new messages
 | 
					// Observer function to watch for new messages
 | 
				
			||||||
@@ -436,6 +446,15 @@ jQuery(async () => {
 | 
				
			|||||||
          box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
 | 
					          box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        /* Hide the collapsed image when details is open using classes */
 | 
				
			||||||
 | 
					        .details-open .sillybubble-collapsed-image,
 | 
				
			||||||
 | 
					        details[open] ~ .sillybubble-collapsed-image,
 | 
				
			||||||
 | 
					        details[open] + .sillybubble-collapsed-image,
 | 
				
			||||||
 | 
					        .mes_text details[open] ~ .sillybubble-collapsed-image,
 | 
				
			||||||
 | 
					        .mes_text details[open] + .sillybubble-collapsed-image {
 | 
				
			||||||
 | 
					          display: none !important;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        /* Hide the "Tool calls: Chat Bubble Image" summary text when collapsed */
 | 
					        /* Hide the "Tool calls: Chat Bubble Image" summary text when collapsed */
 | 
				
			||||||
        .smallSysMes.toolCall[data-sb-processed="true"] summary {
 | 
					        .smallSysMes.toolCall[data-sb-processed="true"] summary {
 | 
				
			||||||
          font-size: 0.8em;
 | 
					          font-size: 0.8em;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user