Flatten Schemas for AI Compatibility#633
Conversation
This commit implements schema flattening and documentation to ensure compatibility with OpenAI-compatible endpoints (xAI, Gemini, etc.). Key changes: 1. Created lib/schema/README.md with AI schema compatibility rules. 2. Flattened 'coordinates' into 'latitude' and 'longitude' in geospatialQuerySchema and updated geospatial tool. 3. Simplified relatedSchema from array of objects to array of strings and updated all UI consumers (SearchRelated, SuggestionsDropdown). 4. Fixed type mismatches and build errors resulting from schema changes. Co-authored-by: ngoiyaeric <115367894+ngoiyaeric@users.noreply.github.com>
|
👋 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 New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
|
WalkthroughThis PR simplifies two schema structures: related queries ChangesData Shape Simplification for Related Queries and Geospatial Input
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@components/search-related.tsx`:
- Line 53: The filter currently in the search-related rendering uses query =>
query !== '' which allows null/undefined through; change the filter to remove
all falsy values (e.g., use a truthy check like Boolean(query) or query =>
!!query) so undefined/null are filtered out the same way as
suggestions-dropdown.tsx; update the filter applied to the array being mapped in
components/search-related.tsx (the expression using ?.filter(...)) to use the
truthy check so no blank button is rendered and onClick never submits an empty
related_query.
In `@lib/agents/tools/geospatial.tsx`:
- Around line 244-245: The Gemini branch currently builds its prompt from
"location || query" which breaks reverse geocoding because flattened reverse
inputs only have latitude/longitude; update the code in the GeospatialTool
execution path (look for the destructuring of queryType, includeMap, latitude,
longitude and the mapProvider usage) to detect queryType === 'reverse' and
construct the Gemini input from the coordinate pair (e.g., `${latitude},
${longitude}`) or skip the Gemini prompt branch for reverse queries so the
reverse-geocoding flow is used; apply the same change where the prompt is built
around lines referencing "location || query" (also at the corresponding 262-263
area).
In `@lib/schema/geospatial.tsx`:
- Around line 32-35: Update the latitude/longitude field descriptions in
lib/schema/geospatial.tsx to match the executor behavior in
lib/agents/tools/geospatial.tsx: explicitly state that coordinates are optional
in general but are required when queryType === 'map' (or that 'map' queries
require a full location object), so the schema text for latitude and longitude
reflects the executor's requirement and avoids implying map-centering works with
coordinates-only payloads.
- Around line 32-35: The latitude and longitude fields are independently
optional which allows partial coordinates to pass validation; update the Zod
schema that defines these fields (the object containing latitude and longitude
in lib/schema/geospatial.tsx) to add a cross-field refinement (using .refine or
.superRefine on the parent schema) that enforces either both latitude and
longitude are present or both are absent and returns a clear validation error
when one is provided without the other; reference the latitude and longitude
field names in the refinement to check presence and reject partial coordinate
payloads before tool execution.
In `@lib/schema/README.md`:
- Around line 15-21: Add a blank line immediately after each subheading line
shown in the diff—specifically after the "### Flat Schema with Conditional
Requirements", "### Avoiding Const and Nested GeoJSON", and "### Runtime
Reconstruction" headings in lib/schema/README.md—so that markdownlint rule MD022
is satisfied; edit the file to insert a single empty line following each of
those heading lines.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: a2f4c0ae-c00b-4ba9-aa88-3464f18d4a2e
📒 Files selected for processing (9)
app/actions.tsxcomponents/search-related-optimized.tsxcomponents/search-related.tsxcomponents/suggestions-dropdown.tsxlib/agents/query-suggestor.tsxlib/agents/tools/geospatial.tsxlib/schema/README.mdlib/schema/geospatial.tsxlib/schema/related.tsx
📜 Review details
🧰 Additional context used
🪛 markdownlint-cli2 (0.22.1)
lib/schema/README.md
[warning] 15-15: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 18-18: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 21-21: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
🔇 Additional comments (5)
components/search-related-optimized.tsx (1)
53-53: Same falsy-filter concern as flagged incomponents/search-related.tsx(line 53): replacequery !== ''with a truthy filter to dropundefined/nullduring partial streaming.lib/schema/related.tsx (1)
4-12: LGTM!lib/agents/query-suggestor.tsx (1)
60-60: LGTM!app/actions.tsx (1)
32-34: LGTM!components/suggestions-dropdown.tsx (1)
26-26: LGTM!Also applies to: 50-50, 95-109
| return data?.items | ||
| ?.filter(item => item?.query !== '') | ||
| .map((item, index) => ( | ||
| ?.filter(query => query !== '') |
There was a problem hiding this comment.
Filter out falsy items, not just empty strings.
query => query !== '' lets undefined/null through, which can occur for not-yet-filled elements during partial streamObject streaming. That renders a blank button whose onClick submits an empty related_query. suggestions-dropdown.tsx already uses a truthy filter; align here for consistency.
🛡️ Proposed fix
- ?.filter(query => query !== '')
+ ?.filter((query): query is string => Boolean(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.
| ?.filter(query => query !== '') | |
| ?.filter((query): query is string => Boolean(query)) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@components/search-related.tsx` at line 53, The filter currently in the
search-related rendering uses query => query !== '' which allows null/undefined
through; change the filter to remove all falsy values (e.g., use a truthy check
like Boolean(query) or query => !!query) so undefined/null are filtered out the
same way as suggestions-dropdown.tsx; update the filter applied to the array
being mapped in components/search-related.tsx (the expression using
?.filter(...)) to use the truthy check so no blank button is rendered and
onClick never submits an empty related_query.
| const { queryType, includeMap = true, latitude, longitude } = params; | ||
| console.log('[GeospatialTool] Execute called with:', params, 'and map provider:', mapProvider); |
There was a problem hiding this comment.
Handle reverse queries in the Gemini branch.
After flattening, reverse inputs only carry latitude/longitude, but this path still builds its prompt from location || query. In Google mode, a reverse request now becomes Find the location for: undefined and falls into the generic error path instead of reverse-geocoding. Build the Gemini input from the coordinate pair for queryType === 'reverse', or bypass this branch for that query type.
Suggested fix
- const searchText = (params as any).location || (params as any).query;
+ const searchText =
+ queryType === 'reverse' && latitude !== undefined && longitude !== undefined
+ ? `${latitude},${longitude}`
+ : params.location || params.query;
+
+ if (!searchText) {
+ throw new Error(`'${queryType}' query is not supported by the Gemini grounding path`);
+ }
const prompt = `Find the location for: ${searchText}`;Also applies to: 262-263
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@lib/agents/tools/geospatial.tsx` around lines 244 - 245, The Gemini branch
currently builds its prompt from "location || query" which breaks reverse
geocoding because flattened reverse inputs only have latitude/longitude; update
the code in the GeospatialTool execution path (look for the destructuring of
queryType, includeMap, latitude, longitude and the mapProvider usage) to detect
queryType === 'reverse' and construct the Gemini input from the coordinate pair
(e.g., `${latitude}, ${longitude}`) or skip the Gemini prompt branch for reverse
queries so the reverse-geocoding flow is used; apply the same change where the
prompt is built around lines referencing "location || query" (also at the
corresponding 262-263 area).
| latitude: z.number().min(-90).max(90).optional() | ||
| .describe("Latitude for reverse geocoding or map centering (used by 'reverse', optional for 'search')"), | ||
| longitude: z.number().min(-180).max(180).optional() | ||
| .describe("Longitude for reverse geocoding or map centering (used by 'reverse', optional for 'search')"), |
There was a problem hiding this comment.
Keep the field descriptions aligned with the executor.
These descriptions mention map centering, but lib/agents/tools/geospatial.tsx still rejects queryType === 'map' unless location is present. That mismatch makes the schema more likely to steer the model into coordinate-only map payloads that fail at runtime.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@lib/schema/geospatial.tsx` around lines 32 - 35, Update the
latitude/longitude field descriptions in lib/schema/geospatial.tsx to match the
executor behavior in lib/agents/tools/geospatial.tsx: explicitly state that
coordinates are optional in general but are required when queryType === 'map'
(or that 'map' queries require a full location object), so the schema text for
latitude and longitude reflects the executor's requirement and avoids implying
map-centering works with coordinates-only payloads.
Require latitude and longitude together.
Flattening made the two coordinate fields independently optional, so malformed payloads like { queryType: 'reverse', latitude: 40.7 } now pass schema validation and only fail later in lib/agents/tools/geospatial.tsx. Add a cross-field refinement so partial coordinates are rejected before tool execution.
Suggested fix
export const geospatialQuerySchema = z.object({
queryType: z.enum(['search', 'geocode', 'reverse', 'directions', 'distance', 'map'])
@@
includeMap: z.boolean()
.optional()
.default(true)
.describe("Whether to include a map preview/URL in the response"),
-});
+}).superRefine(({ latitude, longitude }, ctx) => {
+ if ((latitude === undefined) !== (longitude === undefined)) {
+ ctx.addIssue({
+ code: z.ZodIssueCode.custom,
+ path: [latitude === undefined ? 'latitude' : 'longitude'],
+ message: 'latitude and longitude must be provided together',
+ });
+ }
+});📝 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.
| latitude: z.number().min(-90).max(90).optional() | |
| .describe("Latitude for reverse geocoding or map centering (used by 'reverse', optional for 'search')"), | |
| longitude: z.number().min(-180).max(180).optional() | |
| .describe("Longitude for reverse geocoding or map centering (used by 'reverse', optional for 'search')"), | |
| export const geospatialQuerySchema = z.object({ | |
| queryType: z.enum(['search', 'geocode', 'reverse', 'directions', 'distance', 'map']) | |
| .describe("Type of geospatial query"), | |
| latitude: z.number().min(-90).max(90).optional() | |
| .describe("Latitude for reverse geocoding or map centering (used by 'reverse', optional for 'search')"), | |
| longitude: z.number().min(-180).max(180).optional() | |
| .describe("Longitude for reverse geocoding or map centering (used by 'reverse', optional for 'search')"), | |
| includeMap: z.boolean() | |
| .optional() | |
| .default(true) | |
| .describe("Whether to include a map preview/URL in the response"), | |
| }).superRefine(({ latitude, longitude }, ctx) => { | |
| if ((latitude === undefined) !== (longitude === undefined)) { | |
| ctx.addIssue({ | |
| code: z.ZodIssueCode.custom, | |
| path: [latitude === undefined ? 'latitude' : 'longitude'], | |
| message: 'latitude and longitude must be provided together', | |
| }); | |
| } | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@lib/schema/geospatial.tsx` around lines 32 - 35, The latitude and longitude
fields are independently optional which allows partial coordinates to pass
validation; update the Zod schema that defines these fields (the object
containing latitude and longitude in lib/schema/geospatial.tsx) to add a
cross-field refinement (using .refine or .superRefine on the parent schema) that
enforces either both latitude and longitude are present or both are absent and
returns a clear validation error when one is provided without the other;
reference the latitude and longitude field names in the refinement to check
presence and reject partial coordinate payloads before tool execution.
| ### Flat Schema with Conditional Requirements | ||
| See `lib/schema/geospatial.tsx` for how `queryType` guides the use of other optional top-level fields. | ||
|
|
||
| ### Avoiding Const and Nested GeoJSON | ||
| See `lib/schema/resolution-search.ts` for a flattened GeoJSON structure that avoids `z.literal()` and `z.any()`. | ||
|
|
||
| ### Runtime Reconstruction |
There was a problem hiding this comment.
Add missing blank lines after subheadings (MD022).
markdownlint flags missing blank lines below headings at Line 15, Line 18, and Line 21. This can cause lint failures in CI/doc checks.
Proposed fix
### Flat Schema with Conditional Requirements
+
See `lib/schema/geospatial.tsx` for how `queryType` guides the use of other optional top-level fields.
### Avoiding Const and Nested GeoJSON
+
See `lib/schema/resolution-search.ts` for a flattened GeoJSON structure that avoids `z.literal()` and `z.any()`.
### Runtime Reconstruction
+
See `app/actions.tsx` (specifically the `processResolutionSearch` function) for how flattened features are reconstructed into a standard `FeatureCollection`.🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 15-15: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 18-18: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 21-21: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@lib/schema/README.md` around lines 15 - 21, Add a blank line immediately
after each subheading line shown in the diff—specifically after the "### Flat
Schema with Conditional Requirements", "### Avoiding Const and Nested GeoJSON",
and "### Runtime Reconstruction" headings in lib/schema/README.md—so that
markdownlint rule MD022 is satisfied; edit the file to insert a single empty
line following each of those heading lines.
Audited and refactored schemas for better AI compatibility. Created documentation guidelines, flattened the geospatial query schema, and simplified the related queries schema. Updated all downstream consumers in tools and UI components to handle the new flattened structures.
PR created automatically by Jules for task 9024415414590610865 started by @ngoiyaeric
Summary by CodeRabbit
Documentation
Refactor