Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified bun.lockb
Binary file not shown.
16 changes: 6 additions & 10 deletions components/map/map-data-context.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
'use client';

import React, { createContext, useContext, useState, ReactNode } from 'react';
import { LngLatLike } from 'mapbox-gl'; // Import LngLatLike
import { LngLatLike } from 'mapbox-gl'; // Import LngLatLike\nimport type * as GeoJSON from 'geojson';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Split imports; current line likely includes a literal "\n" and will not parse.

Place the GeoJSON type-only import on its own line.

-import { LngLatLike } from 'mapbox-gl'; // Import LngLatLike\nimport type * as GeoJSON from 'geojson';
+import { LngLatLike } from 'mapbox-gl'; // Import LngLatLike
+import type * as GeoJSON from 'geojson';
📝 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.

Suggested change
import { LngLatLike } from 'mapbox-gl'; // Import LngLatLike\nimport type * as GeoJSON from 'geojson';
import { LngLatLike } from 'mapbox-gl'; // Import LngLatLike
import type * as GeoJSON from 'geojson';
🤖 Prompt for AI Agents
In components/map/map-data-context.tsx around line 4, the combined import
contains a literal "\n" and won't parse; split the imports so the runtime import
for LngLatLike stays on its own line and the GeoJSON type-only import is placed
on a separate line using "import type" (e.g., keep "import { LngLatLike } from
'mapbox-gl';" then on the next line "import type * as GeoJSON from 'geojson';"),
removing the embedded "\n" so the file parses correctly.


// Define the shape of the map data you want to share
export interface MapData {
targetPosition?: LngLatLike | null; // For flying to a location
// TODO: Add other relevant map data types later (e.g., routeGeoJSON, poiList)
mapFeature?: any | null; // Generic feature from MCP hook's processLocationQuery
drawnFeatures?: Array<{ // Added to store drawn features and their measurements
id: string;
type: 'Polygon' | 'LineString';
measurement: string;
geometry: any;
}>;
targetPosition?: LngLatLike | null;
routeGeoJSON?: GeoJSON.Feature<GeoJSON.LineString> | null;
markers?: Array<{ lat: number; lng: number; name?: string; address?: string }>;
polygons?: Array<GeoJSON.Feature<GeoJSON.Polygon>>;
drawnFeatures?: Array<{ id: string; type: 'Polygon' | 'LineString'; measurement: string; geometry: any }>;
}
Comment on lines +8 to 13
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Tighten types: avoid any for geometry and clarify collection element types.

Use GeoJSON types to prevent shape drift and improve editor tooling.

 export interface MapData {
   targetPosition?: LngLatLike | null;
   routeGeoJSON?: GeoJSON.Feature<GeoJSON.LineString> | null;
-  markers?: Array<{ lat: number; lng: number; name?: string; address?: string }>;
-  polygons?: Array<GeoJSON.Feature<GeoJSON.Polygon>>;
-  drawnFeatures?: Array<{ id: string; type: 'Polygon' | 'LineString'; measurement: string; geometry: any }>;
+  markers?: Array<{ lat: number; lng: number; name?: string; address?: string }>;
+  polygons?: Array<GeoJSON.Feature<GeoJSON.Polygon>>;
+  drawnFeatures?: Array<{
+    id: string;
+    type: 'Polygon' | 'LineString';
+    measurement: string;
+    geometry: GeoJSON.Geometry; // replaces any
+  }>;
 }
📝 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.

Suggested change
targetPosition?: LngLatLike | null;
routeGeoJSON?: GeoJSON.Feature<GeoJSON.LineString> | null;
markers?: Array<{ lat: number; lng: number; name?: string; address?: string }>;
polygons?: Array<GeoJSON.Feature<GeoJSON.Polygon>>;
drawnFeatures?: Array<{ id: string; type: 'Polygon' | 'LineString'; measurement: string; geometry: any }>;
}
export interface MapData {
targetPosition?: LngLatLike | null;
routeGeoJSON?: GeoJSON.Feature<GeoJSON.LineString> | null;
markers?: Array<{ lat: number; lng: number; name?: string; address?: string }>;
polygons?: Array<GeoJSON.Feature<GeoJSON.Polygon>>;
drawnFeatures?: Array<{
id: string;
type: 'Polygon' | 'LineString';
measurement: string;
geometry: GeoJSON.Geometry; // replaces any
}>;
}
🤖 Prompt for AI Agents
In components/map/map-data-context.tsx around lines 8-13, tighten the
drawnFeatures and markers types: replace the loose any for geometry with proper
GeoJSON types and clarify collection element shapes. Change markers to use
GeoJSON Point features (e.g. Array<GeoJSON.Feature<GeoJSON.Point>> with optional
properties for name/address) and change drawnFeatures to an array whose geometry
is typed as GeoJSON.Polygon | GeoJSON.LineString (or use
GeoJSON.Feature<GeoJSON.Polygon | GeoJSON.LineString> with id, measurement and
type preserved). Ensure imports reference the GeoJSON types and update usages to
match the stronger types.


interface MapDataContextType {
Expand Down
16 changes: 5 additions & 11 deletions components/map/map-query-handler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,18 @@

import { useEffect } from 'react';
// Removed useMCPMapClient as we'll use data passed via props
import { useMapData } from './map-data-context';
import { useMapData, MapData } from './map-data-context';
Copy link
Copy Markdown
Contributor

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 there are no other mapFeature usages across the repo.

Residual references will fail type-checks after this refactor.


🏁 Script executed:

#!/bin/bash
# Find and show remaining mapFeature usages with context
rg -nC2 "\bmapFeature\b"

Length of output: 2145


Remove or update remaining mapFeature references across the repo

components/map/mapbox-map.tsx still uses mapData.mapFeature (TODO at line 521; effect dependency at line 526), and components/map/map-query-handler.tsx continues to set/clear mapFeature (lines 38–40, 50–51, commented at 64). These will break type-checks—remove or refactor all residual mapFeature usages before merging.

🤖 Prompt for AI Agents
components/map/map-query-handler.tsx lines 38–40, 50–51 and commented line 64:
remove all references that read/set/clear mapFeature and replace them with the
current MapData API exported by useMapData (or simply remove the
feature-tracking side-effects if the app no longer tracks a mapFeature). Also
update components/map/mapbox-map.tsx (around lines 521 and 526) to stop reading
mapData.mapFeature — either consume the new field name exposed by MapData or
remove the dependency and effect that rely on it; then run TypeScript to ensure
no residual mapFeature identifiers remain and adjust imports/types accordingly.


// Define the expected structure of the mcp_response from geospatialTool
interface McpResponseData {
location: {
latitude?: number;
longitude?: number;
place_name?: string;
address?: string;
};
mapUrl?: string;
}
type McpResponseData = any;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Avoid any for MCP payloads; prefer unknown with per-query-type narrowing.

This preserves safety while still allowing flexible shapes.

-type McpResponseData = any;
+type McpResponseData = unknown;

Follow-up: add small type guards per queryType to narrow when reading fields.

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

Suggested change
type McpResponseData = any;
type McpResponseData = unknown;
🤖 Prompt for AI Agents
In components/map/map-query-handler.tsx around line 8, the MCP payload type is
declared as `any`; replace it with `unknown` and model the payloads as a
discriminated union keyed by `queryType` (e.g., types for "getPoint",
"listAreas", etc.). Update functions that read payload fields to first narrow
the `unknown` via small runtime type-guard functions (isGetPointPayload,
isListAreasPayload, etc.) which check `queryType` and required field shapes,
then use the narrowed types when accessing properties; change any direct casts
to use these guards and update call sites accordingly.


interface GeospatialToolOutput {
type: string; // e.g., "MAP_QUERY_TRIGGER"
type: string;
originalUserInput: string;
timestamp: string;
queryType: string;
mcp_response: McpResponseData | null;
error?: string;
}

interface MapQueryHandlerProps {
Expand Down
15 changes: 2 additions & 13 deletions lib/agents/tools/geospatial.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -239,19 +239,8 @@ export const geospatialTool = ({ uiStream }: { uiStream: ReturnType<typeof creat
catch { console.warn('[GeospatialTool] Content is not JSON, using as string:', content); }

// Process results
if (typeof content === 'object' && content !== null) {
const parsedData = content as any;
if (parsedData.results?.length > 0) {
const firstResult = parsedData.results[0];
mcpData = { location: { latitude: firstResult.coordinates?.latitude, longitude: firstResult.coordinates?.longitude, place_name: firstResult.name || firstResult.place_name, address: firstResult.full_address || firstResult.address }, mapUrl: parsedData.mapUrl };
} else if (parsedData.location) {
mcpData = { location: { latitude: parsedData.location.latitude, longitude: parsedData.location.longitude, place_name: parsedData.location.place_name || parsedData.location.name, address: parsedData.location.address || parsedData.location.formatted_address }, mapUrl: parsedData.mapUrl || parsedData.map_url };
} else {
throw new Error("Response missing required 'location' or 'results' field");
}
} else throw new Error('Unexpected response format from mapping service');

feedbackMessage = `Successfully processed ${queryType} query for: ${mcpData.location.place_name || JSON.stringify(params)}`;
mcpData = content;
feedbackMessage = `Successfully processed ${queryType} query`;
Comment on lines +242 to +243
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Don’t pass raw MCP content through; minimally normalize or wrap to a known shape.

Downstream code expects consistent structures; passing arbitrary content will cause brittle consumers. At least distinguish “has location” vs “raw”.

Apply this diff to minimally normalize while preserving raw payloads:

-      mcpData = content;
-      feedbackMessage = `Successfully processed ${queryType} query`;
+      // Minimal normalization to reduce downstream shape assumptions
+      if (
+        content &&
+        typeof content === 'object' &&
+        'location' in (content as any) &&
+        typeof (content as any).location?.latitude === 'number' &&
+        typeof (content as any).location?.longitude === 'number'
+      ) {
+        mcpData = content as any;
+      } else {
+        mcpData = { raw: content };
+      }
+      feedbackMessage = `Successfully processed ${queryType} query`;
📝 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.

Suggested change
mcpData = content;
feedbackMessage = `Successfully processed ${queryType} query`;
// Minimal normalization to reduce downstream shape assumptions
if (
content &&
typeof content === 'object' &&
'location' in (content as any) &&
typeof (content as any).location?.latitude === 'number' &&
typeof (content as any).location?.longitude === 'number'
) {
mcpData = content as any;
} else {
mcpData = { raw: content };
}
feedbackMessage = `Successfully processed ${queryType} query`;
🤖 Prompt for AI Agents
In lib/agents/tools/geospatial.tsx around lines 242-243, currently mcpData is
assigned raw content which can be arbitrary; change this to wrap/normalize the
payload into a stable shape such as { raw: content, hasLocation: boolean,
locations: [...] | null, meta: {...} } (compute hasLocation by checking for
existence of location fields or coordinates, and populate locations with
normalized coords if found); keep the original content in raw for preservation
and ensure downstream code reads the known fields instead of assuming raw
structure.

uiFeedbackStream.update(feedbackMessage);

} catch (error: any) {
Expand Down