Skip to content

Conversation

@google-labs-jules
Copy link
Contributor

@google-labs-jules google-labs-jules bot commented Jan 16, 2026

User description

This change enables context-aware follow-up questions and a follow-up panel after a resolution search (satellite/map image analysis), mirroring the behavior of regular queries. It fixes an issue where follow-up questions were not being generated, likely due to multimodal content in the conversation history which is now sanitized before being passed to the querySuggestor agent. It also ensures consistent AI state updates and proper TypeScript typing.


PR created automatically by Jules for task 14197512294429231241 started by @ngoiyaeric


PR Type

Enhancement, Bug fix


Description

  • Enable follow-up questions for resolution search results

  • Sanitize message context by filtering image parts before calling querySuggestor

  • Ensure compatibility with text-based models and consistent AI state updates


Diagram Walkthrough

flowchart LR
  A["Resolution Search"] --> B["Generate Summary"]
  B --> C["Sanitize Messages<br/>Remove Image Parts"]
  C --> D["Call querySuggestor"]
  D --> E["Append FollowupPanel UI"]
  E --> F["Update AI State"]
Loading

File Walkthrough

Relevant files
Enhancement
actions.tsx
Add message sanitization and follow-up panel for resolution searches

app/actions.tsx

  • Added message sanitization logic to filter out image parts from
    message content before passing to querySuggestor
  • Implemented sanitizedMessages transformation that preserves message
    structure while removing image content
  • Appended FollowupPanel UI component within a Section titled
    "Follow-up" after resolution search
  • Ensured TypeScript compatibility by casting sanitized messages as
    CoreMessage[] type
+11/-1   

- Implement sanitization of message context by filtering out image parts before calling `querySuggestor` to ensure compatibility with text-based models.
- Call `querySuggestor` and append the `FollowupPanel` UI in the `resolution_search` action.
- Update `aiState` with contextually relevant follow-up questions and markers, using a consistent `groupeId` for all assistant messages.
- Ensure TypeScript compatibility for the sanitized message array.
@vercel
Copy link
Contributor

vercel bot commented Jan 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
qcx Ready Ready Preview, Comment Jan 16, 2026 6:27am

@google-labs-jules
Copy link
Contributor Author

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 16, 2026

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Comment @coderabbitai help to get the list of available commands and usage tips.

@ngoiyaeric ngoiyaeric marked this pull request as ready for review January 16, 2026 06:27
@charliecreates charliecreates bot requested a review from CharlieHelps January 16, 2026 06:27
@ngoiyaeric ngoiyaeric merged commit 25e7bb4 into main Jan 16, 2026
4 checks passed
@qodo-code-review
Copy link
Contributor

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review
Copy link
Contributor

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Drop messages emptied by sanitization

Use flatMap to remove messages that become empty after image content is stripped
out, preventing the model from receiving blank inputs.

app/actions.tsx [97-105]

-const sanitizedMessages: CoreMessage[] = messages.map(m => {
+const sanitizedMessages: CoreMessage[] = messages.flatMap(m => {
   if (Array.isArray(m.content)) {
-    return {
-      ...m,
-      content: m.content.filter(part => part.type !== 'image')
-    } as CoreMessage
+    const filtered = m.content.filter(part => part.type !== 'image')
+    // Drop messages that become empty after stripping images
+    if (filtered.length === 0) return []
+    return [{ ...m, content: filtered }]
   }
-  return m
+  return [m]
 })
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that sanitizing messages can result in empty content, which could cause issues. The proposed use of flatMap is an elegant and robust solution to filter out these empty messages.

Medium
  • More

Copy link

@charliecreates charliecreates bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sanitization approach is directionally correct, but it may produce empty messages after filtering image parts, which can negatively affect or break follow-up suggestion prompting. The current as CoreMessage assertion is avoidable and can hide future schema mismatches; prefer returning properly typed objects without casting and consider dropping/normalizing empty-content messages.

Additional notes (1)
  • Compatibility | app/actions.tsx:97-105
    The sanitization currently only removes type === 'image'. If other non-text multimodal parts exist (e.g., file, audio, video, or future extensions), they’ll still be forwarded to a text-only model. Consider whitelisting supported part types (e.g., text) rather than blacklisting image, to make this resilient to future additions.
Summary of changes

What changed

  • Added a sanitizedMessages: CoreMessage[] transformation that filters out image parts from any message whose content is an array.
  • Updated the resolution_search path to call querySuggestor(uiStream, sanitizedMessages) instead of passing the raw messages.
  • Goal: ensure follow-up question generation works even when conversation history contains multimodal (image) parts.

Comment on lines +97 to +107
const sanitizedMessages: CoreMessage[] = messages.map(m => {
if (Array.isArray(m.content)) {
return {
...m,
content: m.content.filter(part => part.type !== 'image')
} as CoreMessage
}
return m
})

const relatedQueries = await querySuggestor(uiStream, sanitizedMessages);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sanitizedMessages currently preserves non-image parts but can leave a message with content: [] after filtering. Depending on how querySuggestor builds prompts, empty assistant/user messages can degrade results or cause edge-case failures (e.g., models or prompt builders expecting non-empty content). It’s safer to drop messages that become empty after sanitization, or replace them with a minimal text placeholder.

Also, this uses an as CoreMessage assertion even though you already annotated the array as CoreMessage[]. Prefer avoiding assertions here by constructing a value that naturally satisfies the type, or by narrowing in a way that doesn’t require casting—casts can mask future regressions when message shapes evolve.

Suggestion

Consider filtering out messages that become empty after removing image parts, and avoid the type assertion.

Example:

const sanitizedMessages: CoreMessage[] = messages
  .map(m => {
    if (!Array.isArray(m.content)) return m;
    const content = m.content.filter(part => part.type !== 'image');
    return { ...m, content };
  })
  .filter(m => !Array.isArray(m.content) || m.content.length > 0);

If you need to preserve message count, you could replace empty array content with a short text part instead.

Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this change.

@charliecreates charliecreates bot removed the request for review from CharlieHelps January 16, 2026 06:28
@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants