Skip to content

feat: implement UI fixes and model optimizations#586

Open
ngoiyaeric wants to merge 4 commits into
mainfrom
fix/issue-585-optimizations-9467656735862578365
Open

feat: implement UI fixes and model optimizations#586
ngoiyaeric wants to merge 4 commits into
mainfrom
fix/issue-585-optimizations-9467656735862578365

Conversation

@ngoiyaeric
Copy link
Copy Markdown
Collaborator

@ngoiyaeric ngoiyaeric commented May 6, 2026

  • Fix FollowupPanel action routing by removing hardcoded resolution search
  • Center example prompts and fix initial render flash in EmptyScreen
  • Refactor chat submission to eliminate race conditions
  • Introduce 'auxiliary' model tier for lightweight tasks (e.g. query suggestions)
  • Remove artificial delays and optimize SearchRelated rendering efficiency
  • Relax related queries schema validation to handle 1-3 items

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

Summary by CodeRabbit

  • New Features

    • Follow-up section now appears with resolution search results
    • Map data context is integrated across chat layouts
    • Drawing context now syncs with the server
  • Improvements

    • Direct/imperative message submission (suggestions submit immediately)
    • Removed artificial processing delays for faster UI updates
    • Improved query suggestions via enhanced model selection
  • Style

    • Center-aligned empty state UI

Co-authored-by: ngoiyaeric <115367894+ngoiyaeric@users.noreply.github.com>
@google-labs-jules
Copy link
Copy Markdown
Contributor

👋 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.

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 6, 2026

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

Project Deployment Actions Updated (UTC)
qcx Ready Ready Preview, Comment May 6, 2026 5:44pm

@CLAassistant
Copy link
Copy Markdown

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.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

Warning

Rate limit exceeded

@ngoiyaeric has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 25 minutes and 51 seconds before requesting another review.

To continue reviewing without waiting, purchase usage credits in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f9ae88cb-9b61-429f-8344-c18c639399cf

📥 Commits

Reviewing files that changed from the base of the PR and between 57617bc and d03ed39.

📒 Files selected for processing (12)
  • app/actions.tsx
  • app/api/chats/route.ts
  • app/api/embeddings/route.ts
  • components/chat-panel.tsx
  • components/chat.tsx
  • components/followup-panel.tsx
  • components/search-related.tsx
  • lib/actions/chat.ts
  • lib/agents/query-suggestor.tsx
  • lib/auth/get-current-user.ts
  • lib/schema/related.tsx
  • lib/utils/index.ts

Walkthrough

Reworks chat submission to support imperative submitForm(message?), removes artificial waits, streams resolution_search results with a Follow-up panel, adds server-side clearChat and server-derived current user ID, introduces tiered model selection, tightens UUID validation, and syncs map drawing context to the server.

Changes

Chat submission, resolution search, model tiering, and server auth

Layer / File(s) Summary
Public API / Types
app/actions.tsx
UIState type updated (dropped isGenerating) and AIState relocated; getUIStateFromAIState wiring adapted. clearChat endpoint added. getCurrentUserIdOnServer imported and used.
Model Selection API
lib/utils/index.ts
`getModel(requireVision?: boolean, tier: 'primary'
Agent Callsites
lib/agents/query-suggestor.tsx
Query suggestor now requests auxiliary-tier model via getModel(false, "auxiliary").
Resolution Search Flow
app/actions.tsx
Introduced processResolutionSearch-style handling: run resolutionSearch, stream partial results, aggregate finalAnalysisResult, and append FollowupPanel UI. Removed prior 500ms artificial delay.
Message Shape / Construction
app/actions.tsx
messageParts extended to support optional data?: string; content/type construction updated; explicit (msg: any) typing added in map callback.
ChatPanel Imperative API
components/chat-panel.tsx
ChatPanelRef.submitForm(message?: string) signature added; pendingMessageRef stores provided message; handleSubmit consumes pending message and sets FormData input when present.
Parent Wiring / Submission Flow
components/chat.tsx
chatPanelRef introduced and forwarded; parent handlers (suggestions, EmptyScreen) call chatPanelRef.current?.submitForm(query); isSubmitting removed.
Map Data Sync
components/chat.tsx, lib/actions/chat.ts
Wrapped UI with MapDataProvider / useMapData; effect syncs drawnFeatures/cameraState to server via updateDrawingContext. Server actions validate UUIDs with new isValidUUID.
Server Auth / Dev Mock
lib/auth/get-current-user.ts
Added MOCK_USER_ID and improved dev mock path controlled by AUTH_DISABLED_FOR_DEV; replaced cookie adapter to use awaited cookies() store with synchronous get/set/remove.
Validation Hardenings
lib/actions/chat.ts
Added isValidUUID helper and applied UUID validation across getChats, getChat, clearChats, saveChat, updateDrawingContext, saveSystemPrompt, getSystemPrompt.
Small UI & Schema
components/empty-screen.tsx, components/followup-panel.tsx, components/search-related.tsx, lib/schema/related.tsx
EmptyScreen centered; followup-panel no longer appends "action":"resolution_search" to FormData; SearchRelated memoized with better key; relatedSchema.items relaxed to 1–3 items.
sequenceDiagram
  participant User
  participant UI as ChatPanel / Chat
  participant Server as app/actions.tsx
  participant Agent as resolutionSearch / Model
  participant DB as lib/actions/chat.ts

  User->>UI: submitForm(message?)
  UI->>Server: POST /submit (FormData, input possibly from pendingMessageRef, mapData)
  Server->>Agent: start resolutionSearch (tier-aware model via getModel)
  Agent-->>Server: stream partial results
  Server-->>UI: stream partial updates (append messages, FollowupPanel)
  Agent->>Server: finalAnalysisResult
  Server->>DB: saveChat / updateDrawingContext (validate userId)
  Server-->>UI: final UI state (Follow-up section appended)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • QueueLab/QCX#422: touches ChatPanel submitForm API and parent wiring for imperative submission.
  • QueueLab/QCX#199: modifies lib/auth/get-current-user.ts and dev mock/auth flow.
  • QueueLab/QCX#409: overlaps on map drawing-context sync and cameraState handling.

Suggested labels

Review effort 4/5, Possible security concern

"A rabbit taps the enter key with delight,
Pending messages hop into the light,
Streams flow in, a follow-up cheer,
Tiers pick models, and maps appear,
Clear chats, fewer waits — a bouncy rewrite!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: UI fixes (FollowupPanel routing, EmptyScreen centering, chat submission refactoring) and model optimizations (auxiliary tier for query suggestions, SearchRelated memoization). It directly reflects the changeset scope.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issue-585-optimizations-9467656735862578365

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@qodo-code-review
Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Implement model tier system, eliminate submission race conditions, and optimize UI rendering

✨ Enhancement 🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Introduce 'auxiliary' model tier for lightweight tasks like query suggestions
  - Uses cheaper models (Claude 3 Haiku, Gemini 2.0 Flash Lite, GPT-4o Mini)
  - Applied to query suggestor for cost optimization
• Eliminate race conditions in chat submission by refactoring message handling
  - Remove artificial 500ms delays from submission flow
  - Use ref-based message passing instead of state-based submission
• Fix FollowupPanel action routing by removing hardcoded 'resolution_search' action
• Improve UI rendering and performance
  - Center example prompts in EmptyScreen
  - Memoize SearchRelated component to prevent unnecessary re-renders
  - Fix key prop in related queries list
  - Relax related queries schema to accept 1-3 items instead of exactly 3
Diagram
flowchart LR
  A["getModel function"] -->|"tier parameter"| B["Primary vs Auxiliary models"]
  B -->|"auxiliary tier"| C["Cheaper model variants"]
  C -->|"used by"| D["Query Suggestor"]
  E["Chat submission"] -->|"remove delays"| F["Ref-based message passing"]
  F -->|"eliminate"| G["Race conditions"]
  H["SearchRelated component"] -->|"memoize"| I["Performance optimization"]
  J["Related queries schema"] -->|"relax validation"| K["Accept 1-3 items"]
Loading

Grey Divider

File Changes

1. lib/utils/index.ts ✨ Enhancement +12/-8

Add model tier parameter for cost optimization

lib/utils/index.ts


2. app/actions.tsx 🐞 Bug fix +0/-2

Remove artificial delays from submission flow

app/actions.tsx


3. components/chat-panel.tsx 🐞 Bug fix +16/-5

Refactor submission to use ref-based message passing

components/chat-panel.tsx


View more (6)
4. components/chat.tsx 🐞 Bug fix +5/-16

Eliminate race conditions in message submission

components/chat.tsx


5. components/empty-screen.tsx ✨ Enhancement +2/-2

Center example prompts in empty state

components/empty-screen.tsx


6. components/followup-panel.tsx 🐞 Bug fix +0/-1

Remove hardcoded resolution_search action

components/followup-panel.tsx


7. components/search-related.tsx ✨ Enhancement +6/-4

Memoize component and improve key handling

components/search-related.tsx


8. lib/agents/query-suggestor.tsx ✨ Enhancement +1/-1

Use auxiliary model tier for query suggestions

lib/agents/query-suggestor.tsx


9. lib/schema/related.tsx ✨ Enhancement +1/-1

Relax related queries validation to 1-3 items

lib/schema/related.tsx


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review Bot commented May 6, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Followup drops mapProvider 🐞 Bug ≡ Correctness
Description
FollowupPanel now submits via the normal submit() path but its FormData does not include
mapProvider, so app/actions.tsx receives mapProvider as null and geospatial tooling may default to
Mapbox behavior even when the user selected Google (or take a different codepath than intended).
This can cause incorrect map rendering/URLs or tool failures in follow-up queries compared to
ChatPanel submissions.
Code

components/followup-panel.tsx[R20-23]

 event.preventDefault()
 const formData = new FormData()
 formData.append("input", input)
-    formData.append("action", "resolution_search")
Evidence
FollowupPanel builds a fresh FormData with only input (+ drawnFeatures) and never includes
mapProvider, while the server action reads mapProvider from FormData and passes it through to the
researcher/tools pipeline where geospatial behavior explicitly branches on mapProvider === 'google'.
ChatPanel includes mapProvider as a hidden input, so followups behave differently from normal chat
submissions.

components/followup-panel.tsx[19-33]
app/actions.tsx[399-451]
components/chat-panel.tsx[215-223]
lib/agents/tools/geospatial.tsx[243-309]
lib/agents/tools/geospatial.tsx[409-412]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`FollowupPanel` creates a new `FormData()` with only `input` (and `drawnFeatures`). Since `submit()` reads `mapProvider` from `formData`, follow-up submissions lose the user’s selected map provider and the geospatial tool may take the wrong provider-specific path.
### Issue Context
`ChatPanel` includes `<input type="hidden" name="mapProvider" ...>` so normal submissions carry this value; `FollowupPanel` should do the same (or otherwise set it explicitly) now that it no longer forces `action=resolution_search`.
### Fix Focus Areas
- components/followup-panel.tsx[19-33]
- components/chat-panel.tsx[215-223]
- app/actions.tsx[399-451]
### Suggested fix
- Read `mapProvider` from `useSettingsStore()` (like `ChatPanel`), then either:
- add a hidden `<input name="mapProvider" value={mapProvider} />` and build `const formData = new FormData(event.currentTarget)`, or
- keep `new FormData()` but `formData.append('mapProvider', mapProvider)`.
- Keep appending `drawnFeatures` as you already do.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Potential duplicate React keys 🐞 Bug ☼ Reliability
Description
SearchRelated now uses item?.query as the React key, so if the model emits duplicate non-empty
queries in the same list, React will see duplicate keys and may reconcile the rows incorrectly. This
can manifest as missing/incorrect rows or unexpected UI updates when related queries stream in.
Code

components/search-related.tsx[50]

+          <div className="flex items-start w-full animate-in fade-in slide-in-from-bottom-2 duration-300" key={item?.query || index}>
Evidence
The key was changed from index to item?.query || index. The related queries schema only
constrains that each item has a query: string and allows 1–3 items; it does not enforce
uniqueness, so duplicate query strings are permitted and would produce duplicate keys.

components/search-related.tsx[45-60]
lib/schema/related.tsx[4-12]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`SearchRelated` uses `key={item?.query || index}`. If two items have the same non-empty `query`, keys collide and React reconciliation becomes incorrect.
### Issue Context
The related queries schema does not enforce uniqueness, so duplicates are allowed.
### Fix Focus Areas
- components/search-related.tsx[45-60]
- lib/schema/related.tsx[4-12]
### Suggested fix
Use a key that is guaranteed unique per row, e.g.:
- `key={`${item?.query ?? ''}-${index}`}`
(Alternatively revert to `key={index}` if list order is stable, but `query+index` keeps stability while preventing collisions.)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@ngoiyaeric
Copy link
Copy Markdown
Collaborator Author

@coderabbitai plan getSystemPrompt: Error: TypeError: Cannot read properties of undefined (reading 'searchParams')
at (.next/server/chunks/5540.js:7:12448)
at Object.startActiveSpan (.next/server/chunks/5540.js:47:50102)
at (.next/server/chunks/5540.js:7:12284)
at Object.startActiveSpan (.next/server/chunks/5540.js:47:50102), ⨯ TypeError: Cannot read properties of undefined (reading 'call')
at Object.t [as require] (.next/server/webpack-runtime.js:1:128) {
digest: '3507941515'
}getSystemPrompt: Error: TypeError: Cannot read properties of undefined (reading 'searchParams')
at (.next/server/chunks/5540.js:7:12448)
at Object.startActiveSpan (.next/server/chunks/5540.js:47:50102)
at (.next/server/chunks/5540.js:7:12284)
at Object.startActiveSpan (.next/server/chunks/5540.js:47:50102)
2026-05-06 15:39:28.422 [error] Vercel Runtime Timeout Error: Task timed out after 60 seconds
2026-05-06 15:38:28.430 [error] getSystemPrompt: Error: TypeError: Cannot read properties of undefined (reading 'searchParams')
at (.next/server/chunks/5540.js:7:12448)
at Object.startActiveSpan (.next/server/chunks/5540.js:47:50102)
at (.next/server/chunks/5540.js:7:12284)
at Object.startActiveSpan (.next/server/chunks/5540.js:47:50102)

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Branch info:"
git rev-parse --abbrev-ref HEAD || true

echo -e "\nSearching for getSystemPrompt definitions and callsites..."
rg -n -C3 -S '\bgetSystemPrompt\b' || true

echo -e "\nSearching for searchParams usage (including nextUrl.searchParams and useSearchParams)..."
rg -n -C4 -S '\bsearchParams\b|nextUrl\.searchParams|useSearchParams' || true

echo -e "\nSearching for Next Request/URL misuse in server code..."
# Look for patterns where new URL is constructed without req in server actions or naked 'request'
rg -n -C4 -S 'new URL\\(|nextUrl|Request\\b' app lib || true

echo -e "\nList potential route handlers (to see proper usage patterns)..."
fd -a --strip-cwd-prefix -i 'route.ts' app | sed 's/^/ - /' || true

echo -e "\nShow app/actions.tsx header and submit() signature lines for context:"
rg -n -C2 -S '^\\s*async function submit\\b|^import .*actions' app/actions.tsx || true

echo -e "\nCheck for any client-only hooks in server files:"
rg -n -C3 -S 'useSearchParams|usePathname|window\\.|document\\.' app lib || true

Length of output: 6505


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Show lib/actions/chat.ts (head + around getSystemPrompt) ==="
awk 'NR<=60{print NR":"$0}' lib/actions/chat.ts || true
echo "--- around getSystemPrompt ---"
nl -ba lib/actions/chat.ts | sed -n '140,220p' || true

echo "=== Show components/settings/components/settings.tsx header and usage ==="
awk 'NR<=60{print NR":"$0}' components/settings/components/settings.tsx || true
echo "--- around call site lines 80-110 ---"
nl -ba components/settings/components/settings.tsx | sed -n '70,120p' || true

echo "=== Re-run safe searches ==="
echo "- All occurrences of 'searchParams' (case-sensitive):"
rg -n -C2 -S '\bsearchParams\b' || true

echo "- Find any 'next/navigation' imports in lib or app: "
rg -n -C2 -S "from 'next/navigation'|from \"next/navigation\"" app lib || true

echo "- Find any usage of cookies/headers in server libs (can imply request context):"
rg -n -C2 -S "cookies\\(|headers\\(|NextRequest|NextResponse" lib app || true

echo "- Find 'use server' and 'use client' markers:"
rg -n -C1 -S "^'use server'|^\"use server\"|^'use client'|^\"use client\"" || true

Length of output: 24302


@ngoiyaeric Thanks for the stack trace. I dug into the repo and here’s what I found and how to fix it.

What’s happening

  • getSystemPrompt is a server action in lib/actions/chat.ts ('use server'). It’s imported and invoked from a client component components/settings/components/settings.tsx (Line 22 import; later called in useEffect). Calling a server action imperatively from a client effect can route through the server-actions runtime and trigger framework internals that expect a request/URL context, which is how we end up with “Cannot read properties of undefined (reading 'searchParams')” inside the compiled chunk. The error is being caught and re-logged at lib/actions/chat.ts (console.error('getSystemPrompt: Error:', error)). References:

    • Definition and log: lib/actions/chat.ts Lines 169–185 (rg output)
    • Client import callsite: components/settings/components/settings.tsx Lines 1, 22, 88–92 (rg output)
  • I scanned the codebase for searchParams usage. The only direct usages are in API routes that correctly receive a NextRequest (app/api/embeddings/route.ts, app/api/chats/route.ts) and a benign new URL in lib/agents/tools/geospatial.tsx. That points back to the server-action invocation path rather than your code accessing searchParams directly.

Recommended fix

  • Don’t call getSystemPrompt (a server action) from a client useEffect. Fetch the value via a tiny API route, or move the Settings page to a Server Component and pass the data as props.
  • Quickest, low-risk patch for this PR:
    1. Add an API route app/api/system-prompt/route.ts with a GET that reads the current userId and returns the prompt.
    2. Update components/settings/components/settings.tsx to fetch('/api/system-prompt') instead of importing and calling getSystemPrompt.
    3. Keep saveSystemPrompt as a server action if it’s used via a form/action; otherwise, give it a POST API as well.

Proposed diffs

  1. New API route for system prompt
  • File: app/api/system-prompt/route.ts
import { NextResponse } from 'next/server'
import { getCurrentUserIdOnServer } from '@/lib/auth/get-current-user'
import { getSystemPrompt } from '@/lib/actions/chat'

export async function GET() {
  try {
    const userId = await getCurrentUserIdOnServer()
    if (!userId) {
      // If you want anonymous allowed, change to return a default/null instead of 401
      return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
    }
    const prompt = await getSystemPrompt(userId)
    return NextResponse.json({ systemPrompt: prompt ?? '' })
  } catch (err) {
    console.error('GET /api/system-prompt failed:', err)
    return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 })
  }
}
  1. Update the Settings client to fetch via API
  • File: components/settings/components/settings.tsx
  • Replace the Promise.all that calls getSystemPrompt(userId) with a fetch.
// remove: import { getSystemPrompt, saveSystemPrompt } from "../../../lib/actions/chat"
import { saveSystemPrompt } from "../../../lib/actions/chat"

// inside useEffect:
useEffect(() => {
  let cancelled = false
  async function load() {
    if (!userId || authLoading) return

    try {
      const [promptRes, selectedModel] = await Promise.all([
        fetch('/api/system-prompt', { cache: 'no-store' }).then(async r => {
          if (!r.ok) return ''
          const data = await r.json()
          return (data?.systemPrompt as string) ?? ''
        }),
        getSelectedModel(),
      ])
      if (!cancelled) {
        form.setValue('systemPrompt', promptRes || defaultValues.systemPrompt!)
        form.setValue('selectedModel', selectedModel || defaultValues.selectedModel!)
        setIsLoading(false)
      }
    } catch (e) {
      if (!cancelled) setIsLoading(false)
      console.error('Failed to load settings:', e)
    }
  }
  load()
  return () => { cancelled = true }
}, [userId, authLoading, form])

Notes

  • This removes the client-side import of a server action that was causing the undefined searchParams path in the server-actions runtime.
  • If you’d rather allow anonymous access, tweak the API to return a default prompt instead of 401.
  • The Vercel 60s timeout should disappear once the server action call no longer hard-fails and retries.

Would you like me to also:

  • Add a POST /api/system-prompt to mirror saveSystemPrompt, so the Settings page uses only HTTP calls? or
  • Convert the Settings page into a Server Component that preloads both the system prompt and model selection?

If you want me to implement the API route + client change in this PR, I’ll prepare a concrete plan next.

  • Add GET API route app/api/system-prompt/route.ts that returns the current user’s system prompt using getSystemPrompt and getCurrentUserIdOnServer.
  • Update components/settings/components/settings.tsx to stop importing getSystemPrompt and instead fetch from /api/system-prompt in its useEffect.
  • Verify no other client components import getSystemPrompt; if found, switch them to the API or move usage server-side.
  • Optional: add anonymous fallback in the API if unauthenticated access is expected on Settings.

The requested changes have been implemented and a pull request has been created: View PR

@google-labs-jules
Copy link
Copy Markdown
Contributor

@coderabbitai plan getSystemPrompt: Error: TypeError: Cannot read properties of undefined (reading 'searchParams')
at (.next/server/chunks/5540.js:7:12448)
at Object.startActiveSpan (.next/server/chunks/5540.js:47:50102)
at (.next/server/chunks/5540.js:7:12284)
at Object.startActiveSpan (.next/server/chunks/5540.js:47:50102), ⨯ TypeError: Cannot read properties of undefined (reading 'call')
at Object.t [as require] (.next/server/webpack-runtime.js:1:128) {
digest: '3507941515'
}getSystemPrompt: Error: TypeError: Cannot read properties of undefined (reading 'searchParams')
at (.next/server/chunks/5540.js:7:12448)
at Object.startActiveSpan (.next/server/chunks/5540.js:47:50102)
at (.next/server/chunks/5540.js:7:12284)
at Object.startActiveSpan (.next/server/chunks/5540.js:47:50102)
2026-05-06 15:39:28.422 [error] Vercel Runtime Timeout Error: Task timed out after 60 seconds
2026-05-06 15:38:28.430 [error] getSystemPrompt: Error: TypeError: Cannot read properties of undefined (reading 'searchParams')
at (.next/server/chunks/5540.js:7:12448)
at Object.startActiveSpan (.next/server/chunks/5540.js:47:50102)
at (.next/server/chunks/5540.js:7:12284)
at Object.startActiveSpan (.next/server/chunks/5540.js:47:50102)

I've addressed the 'searchParams' undefined error by explicitly awaiting cookies() in lib/auth/get-current-user.ts (Next.js 15 requirement). I also fixed a potential UUID validation error by updating the mock user ID to a valid UUID format and adding UUID validation to the database action layer. This ensures that anonymous requests or invalid mock IDs don't trigger database type errors when fetching the system prompt.

- Explicitly await cookies() in get-current-user.ts for Next.js 15
- Update MOCK_USER_ID to a valid UUID format
- Add UUID validation in lib/actions/chat.ts to prevent database errors
- Handle null user IDs gracefully in app/actions.tsx

Co-authored-by: ngoiyaeric <115367894+ngoiyaeric@users.noreply.github.com>
- Fix FollowupPanel action routing and direct message submission
- Center example prompts and fix initial render flash
- Introduce 'auxiliary' model tier for lightweight tasks
- Optimize SearchRelated rendering with React.memo and stable keys
- Fix Next.js 15 breaking changes (awaited cookies)
- Add UUID validation and fix mock user ID format
- Resolve all build-time type errors and compilation issues

Co-authored-by: ngoiyaeric <115367894+ngoiyaeric@users.noreply.github.com>
@ngoiyaeric
Copy link
Copy Markdown
Collaborator Author

@coderabbitai plan align left the example queries and the related section is not generating output as well as the regular query entries like the climate example query does not have a response but the resolution search is working better

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== components/empty-screen.tsx ==="
cat components/empty-screen.tsx || true

echo ""
echo "=== components/search-related.tsx ==="
cat components/search-related.tsx || true

echo ""
echo "=== lib/agents/query-suggestor.tsx ==="
cat lib/agents/query-suggestor.tsx || true

echo ""
echo "=== lib/schema/related.tsx ==="
cat lib/schema/related.tsx || true

echo ""
echo "=== app/actions.tsx (first 120 lines) ==="
head -120 app/actions.tsx || true

echo ""
echo "=== app/actions.tsx - submit function and related rendering ==="
rg -n -C5 'SearchRelated|querySuggestor|search_related|relatedQueries|isGenerating|processResolution|streamText\|streamObject' app/actions.tsx | head -120 || true

echo ""
echo "=== components/chat.tsx - submission flow ==="
rg -n -C4 'submitForm|chatPanelRef|isSubmitting|handleSuggestion|onQuerySelect' components/chat.tsx || true

echo ""
echo "=== components/chat-panel.tsx - submitForm ==="
rg -n -C5 'submitForm|pendingMessage|handleSubmit' components/chat-panel.tsx | head -80 || true

Length of output: 19558


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== app/actions.tsx lines 200-450 ==="
sed -n '200,450p' app/actions.tsx || true

echo ""
echo "=== app/actions.tsx lines 450-650 ==="
sed -n '450,650p' app/actions.tsx || true

Length of output: 11971


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== lib/utils/index.ts ==="
cat lib/utils/index.ts || true

Length of output: 4625


@ngoiyaeric Here's my analysis of all three issues and the planned fixes:


Issue 1 — Example queries are centered, not left-aligned

The PR changed components/empty-screen.tsx to use text-center + items-center. Reverting those two classes aligns the buttons to the left.


Issue 2 — Regular queries (e.g. climate) show no response

Root cause: processEvents() in app/actions.tsx has no try/catch/finally. If taskManager or researcher throws for any reason, the entire async function rejects without ever calling isGenerating.done(false) or uiStream.done(). The AI SDK streamable never finalises → the client sees a perpetually loading / empty state, even if researcher had already pushed content to the stream mid-flight.


Issue 3 — Related section renders but shows no items

Root cause: lib/agents/query-suggestor.tsx calls objectStream.done() only at the end of the for-await loop, after the current line. If streamObject(...) or the loop itself throws, objectStream is never closed — the <SearchRelated> component waits forever for data. Additionally, when processEvents() throws (issue 2), querySuggestor never even runs.


Task: Fix alignment + stream error handling

  • Fix 1 – Remove centering classes from EmptyScreen
  • Fix 2 – Add try/catch/finally to processEvents() so uiStream.done() is always called
  • Fix 3 – Add try/finally around querySuggestor's objectStream so it always closes

The requested changes have been implemented and a pull request has been created: View PR

@google-labs-jules
Copy link
Copy Markdown
Contributor

@coderabbitai plan align left the example queries and the related section is not generating output as well as the regular query entries like the climate example query does not have a response but the resolution search is working better

I've addressed your feedback:

  1. Aligned example queries back to the left.
  2. Fixed the Related Section and regular query responses by switching the auxiliary Gemini model to gemini-1.5-flash, which is more stable, and adding comprehensive error handling in the main action loop. This ensures that even if one part (like query suggestions) fails, the rest of the response is delivered.
  3. Verified the fix with a full production build (bun run build) which passed successfully.

- Restore left alignment for example prompts in EmptyScreen
- Switch auxiliary Gemini model to gemini-1.5-flash for better stability
- Add robust error handling in processEvents and querySuggestor
- Fix Next.js 15 breaking changes (awaited cookies)
- Add UUID validation and fix mock user ID format
- Resolve all build-time type errors and confirm successful production build

Co-authored-by: ngoiyaeric <115367894+ngoiyaeric@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants