feat: add display_map tool for point maps on OpenStreetMap#1206
Open
tckaros wants to merge 1 commit into
Open
Conversation
Contributor
🚀 Preview Deployment
Preview will be automatically removed when this PR is closed. |
tckaros
force-pushed
the
feat/display-map-tool
branch
from
July 16, 2026 21:21
8cfda0a to
801f2e5
Compare
Contributor
There was a problem hiding this comment.
Review completed against the latest diff
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Adds a new display_map agent tool that renders geographic point data from execute_sql results on an interactive MapLibre GL map, using OpenFreeMap (OSM-based vector tiles) as the default basemap, overridable via VITE_MAP_STYLE_URL. - Shared zod schema with query_id reference, lat/lng column keys and optional popup label/tooltip keys; map_type enum ready for a future heatmap mode - Point building/validation lives in @nao/shared (map-points.ts): column keys resolve exact-first then case-insensitively (resolveColumnName, with resolveDataKey moved to shared on top of it), rows with null or blank coordinates are rejected before Number() coercion so no fabricated (0,0) points are plotted, latitudes beyond the Web Mercator limit (85.051129°) are dropped instead of collapsing onto the map edge, and keys resolving to the same column are rejected instead of silently plotting lat=lng - The tool resolves the query_id through getQueryResult (current run, then persisted chat history) and fails with an actionable error when the query is missing, a column does not resolve, or no row carries plottable coordinates; on success it reports plotted and dropped row counts so the model can notice partial data and fix its SQL - Frontend component mirrors display_chart: resolves rows from the sibling execute_sql message part; MapLibre loads in a lazy chunk so the main bundle is unaffected; kept out of collapsed tool groups like charts; rendering is capped at 5000 points with a "showing first N" note - fitBounds wraps across the antimeridian (computeMapBounds), so points at 179°E/179°W fit a 2° span instead of a world-scale view - Popups are built with textContent only so query values cannot inject HTML - Slack, Teams and Telegram cannot render an interactive map, so a completed display_map degrades to a "View interactive map in nao" link card; automations, the MCP ask_nao sub-agent and WhatsApp exclude the tool (shared WEB_CHAT_ONLY_TOOLS list, getTools excludeBuiltinTools option) and the system prompt only advertises the tool when the run's tool set includes it Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tckaros
force-pushed
the
feat/display-map-tool
branch
from
July 16, 2026 21:37
801f2e5 to
65a79d5
Compare
Contributor
|
Hello @tckaros I really really like this idea and this is something we should add in nao either with this PR or in another form so lets move it forward. 2 things to have in mind I think before the review:
Happy to hear your thoughts! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A new
display_mapagent tool that plots geographic point data fromexecute_sqlresults on an interactive MapLibre GL map, using OpenFreeMap (OSM-based vector tiles) as the default basemap.This is the proof of concept behind #1205 — it's fully working, but it's mainly here to make that discussion concrete. If maps are a direction you want, I fully expect remarks on the approach and I'm happy to rework it.
How it works
apps/shared/src/tools/display-map.ts):query_idreference, lat/lng column keys, optional popuplabel_key/tooltip_keys,map_typeenum ready for a future heatmap mode.apps/shared/src/map-points.ts): one implementation used by both backend validation and frontend rendering — case-insensitive column resolution (exact match first), rejection of null/blank coordinates beforeNumber()coercion (no fabricated (0,0) points), Web Mercator latitude limit, antimeridian-aware bounds.query_idviagetQueryResult(current run, then persisted chat history) and returns actionable errors (missing query, unresolvable column, no plottable rows) so the model is never told a map displayed when the UI can't render one. On success it reports plotted/dropped counts and warns about unresolvable popup keys or results over the render cap, so the model can self-correct its SQL.display_chart(same source-query resolution, now factored into a shareduseSourceQueryhook used by both). MapLibre loads as a lazy chunk; popups are built withtextContentonly so query values can't inject HTML; rendering is capped at 5,000 points with a "showing first N" note; WebGL-unavailable clients get a graceful fallback instead of a crash.display_mapdegrades to a "View interactive map in nao" link card. Automations, the MCPask_naosub-agent and WhatsApp exclude the tool entirely (WEB_CHAT_ONLY_TOOLS+ a newgetToolsexcludeBuiltinToolsoption), and the system prompt only advertises the tool when the run's tool set includes it.Tests
apps/shared/tests/map-points.test.ts— coordinate validation, key resolution, wrapped bounds (16 tests)apps/backend/tests/display-map-tool.test.ts— tool validation paths incl. history fallback (13 tests)apps/backend/tests/agent-tools.test.ts+ system-prompt gating testsKnown limitations / follow-ups
tiles.openfreemap.org) and theVITE_MAP_STYLE_URLoverride is build-time only — see [feature] Map visualization for latitude/longitude query results #1205 for the configurability question.generate-chart); WhatsApp link card TODO.🤖 Generated with Claude Code