-
-
Notifications
You must be signed in to change notification settings - Fork 7
feat: Connect generated map to Mapbox MCP workflow #231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This commit integrates the `GeneratedMap` component with the `mapbox_mcp` workflow. The `useMCPMapClient` hook is updated to extract location information from the user's query. This location data is then passed through the `ChatPanel` and `app/actions.tsx` to the `searchTool`. The `searchTool` now includes the location in the search results, which allows the `SearchSection` to render the `GeneratedMap` component with the correct position. This change enables the display of a map related to the user's query in parallel with the existing map render.
|
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughSubmit flow and agent tooling now accept and propagate a mapLocation object; ChatPanel derives mapLocation via Mapbox MCP hook; search results can include a position and render a GeneratedMap; researcher/getTools/searchTool signatures updated to accept mapLocation; types and mapbox hook shape adjusted accordingly. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant U as User
participant CP as ChatPanel
participant MQ as Mapbox MCP Hook
participant S as submit (app/actions)
participant R as researcher
participant T as getTools / tools
participant UI as UI Stream
participant SS as SearchSection
participant GM as GeneratedMap
U->>CP: Enter message
CP->>MQ: processLocationQuery(input)
MQ-->>CP: { mapLocation? }
CP->>S: submit(formData, mapLocation)
activate S
S->>S: getSystemPrompt(userId)
S->>R: researcher(dynamicSystemPrompt, uiStream, streamText, messages, useSpecificModel?, mapLocation)
activate R
R->>T: getTools({ uiStream, fullResponse, mapLocation })
T-->>R: tools (search, geospatial, ...)
R->>T: invoke tools as needed
T-->>UI: tool outputs (search results [+position], ...)
UI-->>S: streamed UI updates
S->>SS: render search results
alt position present
SS->>GM: render GeneratedMap(position)
end
deactivate R
S-->>CP: completion
deactivate S
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Explore these optional code suggestions:
|
|||||||||
PR Code Suggestions ✨Explore these optional code suggestions:
|
||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
components/search-section.tsx (1)
18-18: Fix TypeScript type error for searchResults initialization.
const searchResults: TypeSearchResults = data ? JSON.parse(data) : undefinedassignsundefinedto a non-optional type. This will fail type-checking.One simple fix is to compute inside the guarded block:
- const searchResults: TypeSearchResults = data ? JSON.parse(data) : undefined + // Defer JSON parsing to the guarded render block below to keep types sound.And just before first use inside the truthy branch:
const searchResults = JSON.parse(data) as TypeSearchResultsAlternatively, keep it here but type it as union:
- const searchResults: TypeSearchResults = data ? JSON.parse(data) : undefined + const searchResults: TypeSearchResults | undefined = data ? (JSON.parse(data) as TypeSearchResults) : undefinedThen narrow with a guard before usage.
🧹 Nitpick comments (7)
lib/types/index.ts (1)
5-8: Align position shape with upstream mapLocation (add optional zoom or standardize via a shared type).searchTool sets
searchResult.position = mapLocation, andmapLocationcurrently includes{ latitude, longitude, zoom }. YourSearchResults.positionomitszoom, creating a silent type drift. Either:
- Add
zoom?: numberhere, or- Ensure tools only pass
{ latitude, longitude }.Given future UI needs, adding
zoom?: numberis pragmatic.Apply this diff:
position?: { latitude: number longitude: number + zoom?: number }mapbox_mcp/hooks.ts (1)
126-129: Good: standardized to latitude/longitude keys and consistent with downstream types.This aligns with
SearchResults.positionand generated-map prop shape.Two minor improvements to consider:
- Make the coordinate regex accept integers too (some APIs may return whole degrees).
- Decide whether
zoomshould be propagated through types (see lib/types comment).You can broaden the regex as follows (outside this hunk):
const coordPattern = /(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)/;components/search-section.tsx (1)
28-41: Make the images/map layout responsive and ensure map remounts when position changes.
- Current
w-1/2splits on all breakpoints; on narrow screens, this will squash content. Prefer stacking on mobile and split on md+.- GeneratedMap initializes once; if position changes across searches, the map may not recenter. Force re-mount by keying on coordinates.
Apply this diff:
- <div className="flex space-x-4"> - <div className="w-1/2"> + <div className="flex flex-col md:flex-row md:space-x-4 space-y-4 md:space-y-0"> + <div className="w-full md:w-1/2"> <SearchResultsImageSection images={searchResults.images} query={searchResults.query} /> </div> {searchResults.position && ( - <div className="w-1/2 h-64"> - <GeneratedMap position={searchResults.position} /> + <div className="w-full md:w-1/2 h-64"> + <GeneratedMap + key={`${searchResults.position.latitude},${searchResults.position.longitude}`} + position={searchResults.position} + /> </div> )} </div>components/map/generated-map.tsx (1)
7-7: Guard against missing Mapbox access tokenIf NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN is undefined, map initialization will fail at runtime. Add a defensive check (as shown in the previous diff) to fail gracefully and log a clear warning.
lib/agents/tools/index.tsx (1)
7-11: Strongly type mapLocation instead of using objectUsing object loses type safety downstream. Define an explicit shape to ensure latitude/longitude correctness and optional zoom propagation.
export interface ToolProps { uiStream: ReturnType<typeof createStreamableUI> fullResponse: string - mapLocation?: object + mapLocation?: { latitude: number; longitude: number; zoom?: number } }lib/agents/researcher.tsx (2)
19-21: Strongly type mapLocation param for safetyMirror the ToolProps shape to maintain consistent typing and avoid accidental misuse.
messages: CoreMessage[], useSpecificModel?: boolean, - mapLocation?: object + mapLocation?: { latitude: number; longitude: number; zoom?: number } )
56-60: Note: fullResponse passed into getTools is not effectively mutatedTools (e.g., searchTool) mutate their captured fullResponse string, but since strings are immutable and you don’t read it back from tools, those mutations won’t propagate. Consider removing fullResponse from ToolProps in a follow-up to reduce confusion.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (9)
app/actions.tsx(3 hunks)components/chat-panel.tsx(3 hunks)components/map/generated-map.tsx(1 hunks)components/search-section.tsx(2 hunks)lib/agents/researcher.tsx(2 hunks)lib/agents/tools/index.tsx(1 hunks)lib/agents/tools/search.tsx(2 hunks)lib/types/index.ts(1 hunks)mapbox_mcp/hooks.ts(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (8)
components/map/generated-map.tsx (2)
components/map/mapbox-map.tsx (6)
mapContainer(17-614)map(501-505)mapContainer(391-488)map(419-455)map(62-163)map(316-323)components/map/map-query-handler.tsx (1)
useMapData(30-83)
components/search-section.tsx (2)
components/search-results-image.tsx (2)
SearchResultsImageSection(29-139)SearchResultsImageSectionProps(24-27)components/map/generated-map.tsx (1)
GeneratedMap(9-33)
lib/agents/tools/search.tsx (2)
lib/agents/tools/index.tsx (1)
ToolProps(7-11)lib/agents/tools/video-search.tsx (1)
ToolProps(8-50)
components/chat-panel.tsx (2)
mapbox_mcp/hooks.ts (1)
useMCPMapClient(48-225)components/map/map-query-handler.tsx (3)
toolOutput(33-74)useMapData(30-83)prevData(39-49)
mapbox_mcp/hooks.ts (2)
components/map/map-query-handler.tsx (3)
toolOutput(33-74)prevData(39-49)McpResponseData(8-16)lib/agents/tools/geospatial.tsx (1)
McpResponse(22-25)
app/actions.tsx (2)
components/search-section.tsx (1)
SearchSection(16-54)lib/agents/tools/geospatial.tsx (2)
uiStream(144-269)params(153-268)
lib/agents/tools/index.tsx (2)
lib/agents/tools/search.tsx (1)
searchTool(8-58)lib/agents/tools/geospatial.tsx (6)
uiStream(144-269)McpResponse(22-25)params(153-268)mcpClient(180-192)tools(181-181)Location(15-20)
lib/agents/researcher.tsx (2)
lib/agents/tools/geospatial.tsx (2)
uiStream(144-269)params(153-268)components/map/map-query-handler.tsx (1)
prevData(39-49)
🪛 Biome (2.1.2)
app/actions.tsx
[error] 438-438: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
🔇 Additional comments (5)
lib/types/index.ts (1)
66-78: LGTM: AIMessage metadata extensions look good.Optional
createdAtand the new'drawing_context'discriminator are reasonable evolutions and should be non-breaking.components/search-section.tsx (1)
6-6: LGTM: Imported GeneratedMap for colocated render.Import path and usage align with the new position prop shape.
components/chat-panel.tsx (1)
7-7: LGTM: Introducing MCP hook is the right integration point.Proceeding to connect and guard for readiness will make it robust (see below).
lib/agents/tools/search.tsx (1)
8-8: LGTM: Tool now accepts mapLocation to enrich results.Signature expansion is minimal and keeps existing behavior intact.
lib/agents/tools/index.tsx (1)
14-20: LGTM: mapLocation plumbed into searchToolPassing mapLocation through getTools to searchTool aligns with the new UI flow where SearchSection can render a GeneratedMap using result.position.
| async function submit(formData?: FormData, mapLocation?: object, skip?: boolean) { | ||
| 'use server'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Confirm all submit(...) call sites updated for the new signature
submit now accepts (formData?: FormData, mapLocation?: object, skip?: boolean). Ensure all callers (e.g., chat-panel) pass mapLocation as the second arg. If any call site still passes skip as second arg, behavior will be off.
Run this to find submit invocations and quickly spot incorrect arity/ordering:
🏁 Script executed:
#!/bin/bash
# Search for submit( usages and show 3 lines of context
rg -nC3 --type=ts --type=tsx '\bsubmit\s*\('Length of output: 74
Let’s retry searching without relying on --type. This will scan all .ts and .tsx files:
🏁 Script executed:
#!/bin/bash
# Search for all submit( calls in TS/TSX files
rg -nC3 '\bsubmit\s*\(' --glob '*.ts' --glob '*.tsx'Length of output: 2179
Ensure submit call in components/copilot.tsx passes mapLocation before skip
The only incorrect invocation is in components/copilot.tsx (line 83), which currently does:
const response = await submit(formData, skip)This assigns your boolean skip to the mapLocation parameter, leaving skip undefined. Update it to explicitly pass a (possibly undefined) mapLocation as the second argument:
components/copilot.tsx:83
- const response = await submit(formData, skip)
- const response = await submit(formData, undefined, skip)
All other call sites either only pass formData or correctly pass (formData, mapLocation).
🤖 Prompt for AI Agents
components/copilot.tsx around line 83; app/actions.tsx lines 35-36 — the submit
signature is submit(formData?: FormData, mapLocation?: object, skip?: boolean)
but the call at components/copilot.tsx:83 passes submit(formData, skip) which
assigns the boolean to mapLocation and leaves skip undefined; update that call
to pass an explicit second argument (e.g., undefined) and the boolean as the
third argument so it becomes submit(formData, undefined, skip).
| case 'search': | ||
| const searchResult = JSON.parse(searchResults.value); | ||
| if (toolOutput.position) { | ||
| searchResult.position = toolOutput.position; | ||
| } | ||
| return { | ||
| id, | ||
| component: <SearchSection result={searchResults.value} />, | ||
| component: <SearchSection result={JSON.stringify(searchResult)} />, | ||
| isCollapsed: isCollapsed.value, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix: SearchSection integration and linter error in switch case
Two issues here:
- noSwitchDeclarations: const declared directly in a case without a block can leak across clauses.
- SearchSection expects a StreamableValue, but you’re passing a plain string and attempting to JSON.parse searchResults.value (which is a StreamableValue, not a string).
Wrap the case in a block and pass a proper streamable with the augmented position.
- const searchResults = createStreamableValue();
- searchResults.done(JSON.stringify(toolOutput));
+ const searchResults = createStreamableValue<string>();
+ searchResults.done(JSON.stringify(toolOutput));
switch (name) {
case 'search':
- const searchResult = JSON.parse(searchResults.value);
- if (toolOutput.position) {
- searchResult.position = toolOutput.position;
- }
- return {
- id,
- component: <SearchSection result={JSON.stringify(searchResult)} />,
- isCollapsed: isCollapsed.value,
- };
+ {
+ const augmented = typeof toolOutput === 'string'
+ ? JSON.parse(toolOutput)
+ : { ...toolOutput };
+ if (toolOutput.position) {
+ augmented.position = toolOutput.position;
+ }
+ const augmentedResults = createStreamableValue<string>();
+ augmentedResults.done(JSON.stringify(augmented));
+ return {
+ id,
+ component: <SearchSection result={augmentedResults.value} />,
+ isCollapsed: isCollapsed.value,
+ };
+ }Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 Biome (2.1.2)
[error] 438-438: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
🤖 Prompt for AI Agents
In app/actions.tsx around lines 437 to 445, the switch 'search' case declares
consts directly and passes a plain string to SearchSection; wrap the case body
in a block ({ ... }) to fix noSwitchDeclarations, parse the streamable's current
value into an object, augment position if present, then stringify it and pass a
StreamableValue<string> (do not pass a raw string) — e.g., produce a new
streamable from the existing searchResults (using the streamable's map/creation
helper) containing the updated JSON string and use that as the result prop for
<SearchSection />.
| const [, setMessages] = useUIState<typeof AI>() | ||
| const { submit } = useActions() | ||
| // Removed mcp instance as it's no longer passed to submit | ||
| const { processLocationQuery } = useMCPMapClient() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Establish MCP connection lifecycle to avoid "MCP client not connected" errors.
processLocationQuery requires the MCP client to be ready and toolsRef to be populated via connect(), but connect() is never called here.
Apply this diff to pull in connect and then connect on mount:
- const { processLocationQuery } = useMCPMapClient()
+ const { processLocationQuery, connect } = useMCPMapClient()Add this effect (outside the changed hunk):
useEffect(() => {
let mounted = true
;(async () => {
try {
await connect()
} catch (e) {
console.warn('MCP connect failed, continuing without map location:', e)
}
})()
return () => {
mounted = false
}
}, [connect])🤖 Prompt for AI Agents
In components/chat-panel.tsx around line 24, the MCP client connection lifecycle
is missing: you only destructured processLocationQuery from useMCPMapClient but
never call connect(), causing "MCP client not connected" errors; update the hook
destructuring to also pull connect, and add a useEffect that runs on mount which
calls connect() asynchronously, awaits it, catches and logs any error
(console.warn with context), and returns a cleanup that marks unmounted (or
otherwise ignores late results); include connect in the effect dependency array.
| const { mapLocation } = await processLocationQuery(input) | ||
|
|
||
| const formData = new FormData(e.currentTarget) | ||
| // Removed mcp argument from submit call | ||
| const responseMessage = await submit(formData) | ||
| const responseMessage = await submit(formData, mapLocation) | ||
| setMessages(currentMessages => [...currentMessages, responseMessage as any]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Guard MCP failures and gracefully fall back to submit without mapLocation.
If MCP isn’t ready or processing fails, current code will throw and block the chat flow.
Apply this diff:
- const { mapLocation } = await processLocationQuery(input)
+ let mapLocation: any = undefined
+ try {
+ const res = await processLocationQuery(input)
+ mapLocation = res?.mapLocation
+ } catch (e) {
+ console.warn('processLocationQuery failed, submitting without mapLocation:', e)
+ }
const formData = new FormData(e.currentTarget)
const responseMessage = await submit(formData, mapLocation)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const { mapLocation } = await processLocationQuery(input) | |
| const formData = new FormData(e.currentTarget) | |
| // Removed mcp argument from submit call | |
| const responseMessage = await submit(formData) | |
| const responseMessage = await submit(formData, mapLocation) | |
| setMessages(currentMessages => [...currentMessages, responseMessage as any]) | |
| let mapLocation: any = undefined | |
| try { | |
| const res = await processLocationQuery(input) | |
| mapLocation = res?.mapLocation | |
| } catch (e) { | |
| console.warn('processLocationQuery failed, submitting without mapLocation:', e) | |
| } | |
| const formData = new FormData(e.currentTarget) | |
| const responseMessage = await submit(formData, mapLocation) | |
| setMessages(currentMessages => [...currentMessages, responseMessage as any]) |
This commit fixes a build error caused by incorrectly handling the search results in the `getUIStateFromAIState` function. The previous implementation attempted to parse a `StreamableValue` object as a string, which resulted in a type error. The logic for adding the map position to the search results was also redundant, as the position is already added in the `searchTool`. This commit reverts the incorrect changes in `app/actions.tsx`, which resolves the build error.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (4)
components/map/generated-map.tsx (4)
47-63: Avoid redundant flyTo calls and honor prefers-reduced-motion.Small UX/perf wins: skip re-centering when the new position is effectively the same, and use
jumpToif the user prefers reduced motion.Apply this diff:
// Update map center/zoom and marker when position changes useEffect(() => { if (!map.current) return const lngLat: [number, number] = [position.longitude, position.latitude] - map.current.flyTo({ - center: lngLat, - zoom: position.zoom ?? map.current.getZoom(), - essential: true - }) + const currentCenter = map.current.getCenter() + const currentZoom = map.current.getZoom() + const targetZoom = position.zoom ?? currentZoom + // Skip if delta is negligible to avoid jitter + const delta = + Math.abs(currentCenter.lng - lngLat[0]) + + Math.abs(currentCenter.lat - lngLat[1]) + + Math.abs(currentZoom - targetZoom) + if (delta < 1e-6) return + + const prefersReducedMotion = + typeof window !== 'undefined' && + window.matchMedia?.('(prefers-reduced-motion: reduce)').matches + + if (prefersReducedMotion) { + map.current.jumpTo({ center: lngLat, zoom: targetZoom }) + } else { + map.current.flyTo({ center: lngLat, zoom: targetZoom, essential: true }) + }
5-5: Move Mapbox global CSS import to a single global entry point.Importing global CSS from a component can break Next.js builds depending on your setup and can also lead to duplicate style injection. Prefer adding it once in
app/layout.tsx(App Router) or_app.tsx(Pages Router). Remove it here if it’s already globally included.Apply this diff to this file:
-import 'mapbox-gl/dist/mapbox-gl.css'Then, ensure it’s imported once globally, e.g., in
app/layout.tsx:// app/layout.tsx import 'mapbox-gl/dist/mapbox-gl.css'
15-17: Centralize the position shape for reuse and consistency.Inline prop shapes are easy to drift. Introduce a small
MapPositiontype and reuse it here and anywhere else that passes the same object.Apply this diff to the signature:
-export const GeneratedMap: React.FC<{ - position: { latitude: number; longitude: number; zoom?: number } -}> = ({ position }) => { +export const GeneratedMap: React.FC<{ position: MapPosition }> = ({ position }) => {Add this type near the top of the file (above the component):
type MapPosition = { latitude: number; longitude: number; zoom?: number }
25-28: Access token handling: consider failing fast in dev.Right now we only warn and return. To surface misconfiguration early, consider throwing in development and logging an error in production.
Apply this diff:
- if (!mapboxgl.accessToken) { - console.warn('GeneratedMap: NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN is not set.') - return - } + if (!mapboxgl.accessToken) { + if (process.env.NODE_ENV !== 'production') { + throw new Error('GeneratedMap: NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN is not set.') + } + console.error('GeneratedMap: NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN is not set.') + return + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
components/map/generated-map.tsx(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
components/map/generated-map.tsx (1)
components/map/mapbox-map.tsx (5)
mapContainer(17-614)map(501-505)mapContainer(391-488)map(419-455)map(62-163)
🪛 Biome (2.1.2)
components/map/generated-map.tsx
[error] 14-65: Illegal use of an export declaration not at the top level
move this declaration to the top level
(parse)
[error] 65-65: expected } but instead the file ends
the file ends here
(parse)
🔇 Additional comments (1)
components/map/generated-map.tsx (1)
22-45: Initialization, marker ref, and cleanup look solid.Map is initialized once, marker is retained in a ref, and both map and marker are removed on unmount. This addresses stale marker/positioning and cleanup concerns from earlier feedback.
| export const GeneratedMap: React.FC<{ | ||
| position: { latitude: number; longitude: number } | ||
| }> = ({ position }) => { | ||
| const mapContainer = useRef<HTMLDivElement>(null) | ||
| const map = useRef<mapboxgl.Map | null>(null) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix duplicate/unfinished component declaration (parsing/build will fail).
There’s a half-defined GeneratedMap export preceding the real one. It never closes, which nests the second export and causes Biome/TS parser errors (“export not at top level”, “expected } before EOF”). Remove the first stub entirely.
Apply this diff:
-export const GeneratedMap: React.FC<{
- position: { latitude: number; longitude: number }
-}> = ({ position }) => {
- const mapContainer = useRef<HTMLDivElement>(null)
- const map = useRef<mapboxgl.Map | null>(null)
-📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export const GeneratedMap: React.FC<{ | |
| position: { latitude: number; longitude: number } | |
| }> = ({ position }) => { | |
| const mapContainer = useRef<HTMLDivElement>(null) | |
| const map = useRef<mapboxgl.Map | null>(null) |
🤖 Prompt for AI Agents
In components/map/generated-map.tsx around lines 9 to 14, there is a
duplicate/unfinished export of GeneratedMap (a stub that opens but never closes)
which causes parsing/TS errors; remove that entire stub export (the first export
const GeneratedMap ... block and its open braces/ref declarations) so only the
real, complete GeneratedMap component remains at top level, ensuring no nested
or duplicate export declarations are left.
User description
This commit integrates the
GeneratedMapcomponent with themapbox_mcpworkflow.The
useMCPMapClienthook is updated to extract location information from the user's query. This location data is then passed through theChatPanelandapp/actions.tsxto thesearchTool.The
searchToolnow includes the location in the search results, which allows theSearchSectionto render theGeneratedMapcomponent with the correct position.This change enables the display of a map related to the user's query in parallel with the existing map render.
PR Type
Enhancement
Description
Integrate GeneratedMap component with Mapbox MCP workflow
Extract location data from user queries for map rendering
Add position coordinates to search results structure
Display maps alongside search images when location available
Diagram Walkthrough
File Walkthrough
9 files
Add position coordinates to SearchResults typeUpdate coordinate property names to latitude/longitudePass mapLocation through submit and researcher functionsProcess location queries using MCP clientCreate new Mapbox map componentRender GeneratedMap alongside search imagesAccept mapLocation parameter in researcher functionUpdate ToolProps interface with mapLocationInclude position data in search resultsSummary by CodeRabbit