Skip to content

Commit 11e2313

Browse files
authored
feat(google): Maps Pollen/Solar, Custom Search expansion, and live-API fixes across Google integrations (#5113)
* feat(google): add Maps Pollen/Solar, expand Custom Search, fix Ads/Groups/Contacts/Slides New capability: - Google Maps: add Pollen Forecast and Solar Potential tools (API-key, google_cloud BYOK) - Google Custom Search: add start/dateRestrict/fileType/safe/searchType/siteSearch/ siteSearchFilter/lr/gl/sort params, htmlTitle/htmlSnippet/formattedUrl/mime/fileFormat/ cacheId/image result fields, and nextPageStartIndex pagination Fixes (validated against live API docs): - Google Ads: bump all tools from sunset v19 to v24 - Google Groups: forward OAuth credential under oauthCredential (was dropping token in 11 ops), forward all update_settings fields, JSON.stringify update_settings/add_alias bodies - Google Contacts: include required metadata.sources[].etag in updateContact body (fixed 400) - Google Slides: remove unsupported GIF thumbnail mimeType (API only allows PNG) - Google Sheets: wire delete_rows/delete_sheet/delete_spreadsheet into the V2 block - Google Custom Search: throw on API error responses instead of returning empty success; num optional + Number-coerced; pagemap typed unknown * docs(google): regenerate integration docs for new and updated operations * fix(google_maps): correct Solar requiredQuality enum to BASE The Solar API ImageryQuality enum is HIGH/MEDIUM/BASE (+ UNSPECIFIED) per the live docs; there is no LOW. Selecting "Low" sent requiredQuality=LOW which the API rejects as INVALID_ARGUMENT, and the valid BASE tier was unreachable. Replace LOW with BASE in the tool param/output descriptions, the type union, and the block dropdown. * fix(google_maps): guard !response.ok in Pollen/Solar; use ?? for color channels Address Greptile review: - Pollen and Solar transformResponse now check !response.ok || data.error (matches the Custom Search fix); a gateway error without an error key in the body no longer returns empty/zeroed output silently. - Pollen color channels use ?? instead of || so a legitimate 0 isn't treated as missing (consistent with the other numeric fields in the file). * fix(google_maps): guard against NaN days in Pollen forecast Address Cursor Bugbot: a non-numeric `days` input parsed to NaN and was forwarded as `days=NaN` (the tool's `?? 1` only catches undefined, not NaN), breaking the forecast call. The block now coerces invalid input to undefined, and the tool defaults to 1 unless `days` is a finite number. * fix(google): clamp Pollen days to 1-5; stop forwarding stale group settings fields Address Cursor Bugbot: - Pollen: clamp days to the documented 1-5 range (truncating fractionals) so 0, negatives, or >5 can't be sent to the API. - Google Groups update_settings: the block has no dedicated settings subblocks, so forwarding name/description from params could leak stale values from create_group/update_group and unintentionally rename the group. Forward only oauthCredential + groupEmail from the block (the tool's own param schema still exposes the settings fields for the agent path). * fix(google_sheets): fail fast on non-numeric delete indices Address Cursor Bugbot: delete_sheet/delete_rows parsed deleteSheetId/startIndex/ endIndex with Number.parseInt but didn't validate, so non-numeric UI input became NaN and was forwarded (the v2 delete tools only reject null/undefined), breaking the batchUpdate. The block now throws a clear error when any of these is not a valid number. * fix(google_search): clamp num to 1-10 and normalize start Address Cursor Bugbot: num was coerced with Number() but not bounded, so values like 11 or fractionals reached the API and failed. The tool now truncates and clamps num to the documented 1-10 range and only sends a positive integer start, ignoring non-numeric/out-of-range input.
1 parent d7fd040 commit 11e2313

28 files changed

Lines changed: 1224 additions & 59 deletions

apps/docs/content/docs/en/integrations/google_groups.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ Update the settings for a Google Group including access permissions, moderation,
352352
| `description` | string | No | The group description \(max 4096 characters\) |
353353
| `whoCanJoin` | string | No | Who can join: ANYONE_CAN_JOIN, ALL_IN_DOMAIN_CAN_JOIN, INVITED_CAN_JOIN, CAN_REQUEST_TO_JOIN |
354354
| `whoCanViewMembership` | string | No | Who can view membership: ALL_IN_DOMAIN_CAN_VIEW, ALL_MEMBERS_CAN_VIEW, ALL_MANAGERS_CAN_VIEW |
355-
| `whoCanViewGroup` | string | No | Who can view group messages: ANYONE_CAN_VIEW, ALL_IN_DOMAIN_CAN_VIEW, ALL_MEMBERS_CAN_VIEW, ALL_MANAGERS_CAN_VIEW |
355+
| `whoCanViewGroup` | string | No | Who can view group messages: ANYONE_CAN_VIEW, ALL_IN_DOMAIN_CAN_VIEW, ALL_MEMBERS_CAN_VIEW, ALL_MANAGERS_CAN_VIEW, ALL_OWNERS_CAN_VIEW |
356356
| `whoCanPostMessage` | string | No | Who can post: NONE_CAN_POST, ALL_MANAGERS_CAN_POST, ALL_MEMBERS_CAN_POST, ALL_OWNERS_CAN_POST, ALL_IN_DOMAIN_CAN_POST, ANYONE_CAN_POST |
357357
| `allowExternalMembers` | string | No | Whether external users can be members: true or false |
358358
| `allowWebPosting` | string | No | Whether web posting is allowed: true or false |
@@ -373,7 +373,7 @@ Update the settings for a Google Group including access permissions, moderation,
373373
| `whoCanContactOwner` | string | No | Who can contact owner: ALL_IN_DOMAIN_CAN_CONTACT, ALL_MANAGERS_CAN_CONTACT, ALL_MEMBERS_CAN_CONTACT, ANYONE_CAN_CONTACT |
374374
| `favoriteRepliesOnTop` | string | No | Whether favorite replies appear at top: true or false |
375375
| `whoCanApproveMembers` | string | No | Who can approve members: ALL_OWNERS_CAN_APPROVE, ALL_MANAGERS_CAN_APPROVE, ALL_MEMBERS_CAN_APPROVE, NONE_CAN_APPROVE |
376-
| `whoCanBanUsers` | string | No | Who can ban users: OWNERS_ONLY, OWNERS_AND_MANAGERS, NONE |
376+
| `whoCanBanUsers` | string | No | Who can ban users: ALL_MEMBERS, OWNERS_AND_MANAGERS, OWNERS_ONLY, NONE |
377377
| `whoCanModerateMembers` | string | No | Who can manage members: OWNERS_ONLY, OWNERS_AND_MANAGERS, ALL_MEMBERS, NONE |
378378
| `whoCanModerateContent` | string | No | Who can moderate content: OWNERS_ONLY, OWNERS_AND_MANAGERS, ALL_MEMBERS, NONE |
379379
| `whoCanAssistContent` | string | No | Who can assist with content metadata: OWNERS_ONLY, OWNERS_AND_MANAGERS, ALL_MEMBERS, NONE |

apps/docs/content/docs/en/integrations/google_maps.mdx

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,43 @@ Search for places using a text query
326326
|`businessStatus` | string | Business status |
327327
| `nextPageToken` | string | Token for fetching the next page of results |
328328

329+
### `google_maps_pollen`
330+
331+
Get a daily pollen forecast (grass, tree, weed) for a location
332+
333+
#### Input
334+
335+
| Parameter | Type | Required | Description |
336+
| --------- | ---- | -------- | ----------- |
337+
| `apiKey` | string | Yes | Google Maps API key with Pollen API enabled |
338+
| `lat` | number | Yes | Latitude coordinate |
339+
| `lng` | number | Yes | Longitude coordinate |
340+
| `days` | number | No | Number of forecast days to return \(1-5, defaults to 1\) |
341+
| `languageCode` | string | No | Language code for the response \(e.g., "en", "es"\) |
342+
| `plantsDescription` | boolean | No | Include detailed plant descriptions \(defaults to true\) |
343+
| `pricing` | per_request | No | No description |
344+
| `rateLimit` | string | No | No description |
345+
346+
#### Output
347+
348+
| Parameter | Type | Description |
349+
| --------- | ---- | ----------- |
350+
| `regionCode` | string | Region code \(ISO 3166-1 alpha-2\) for the location |
351+
| `dailyInfo` | array | Daily pollen forecast entries |
352+
|`date` | object | Calendar date of the forecast entry |
353+
|`pollenTypeInfo` | array | Pollen type indices \(grass, tree, weed\) |
354+
|`code` | string | Pollen type code \(GRASS, TREE, WEED\) |
355+
|`displayName` | string | Display name |
356+
|`inSeason` | boolean | Whether the pollen type is in season |
357+
|`indexInfo` | object | Universal Pollen Index \(UPI\) info |
358+
|`healthRecommendations` | array | Health recommendations |
359+
|`plantInfo` | array | Per-plant forecast with descriptions |
360+
|`code` | string | Plant code \(e.g., BIRCH, RAGWEED\) |
361+
|`displayName` | string | Display name |
362+
|`inSeason` | boolean | Whether the plant is in season |
363+
|`indexInfo` | object | Universal Pollen Index \(UPI\) info |
364+
|`plantDescription` | object | Plant details \(type, family, season, cross-reactions\) |
365+
329366
### `google_maps_reverse_geocode`
330367

331368
Convert geographic coordinates (latitude and longitude) into a human-readable address
@@ -379,6 +416,36 @@ Snap GPS coordinates to the nearest road segment
379416
|`placeId` | string | Place ID for this road segment |
380417
| `warningMessage` | string | Warning message if any \(e.g., if points could not be snapped\) |
381418

419+
### `google_maps_solar`
420+
421+
Get solar potential and panel insights for the building nearest a location
422+
423+
#### Input
424+
425+
| Parameter | Type | Required | Description |
426+
| --------- | ---- | -------- | ----------- |
427+
| `apiKey` | string | Yes | Google Maps API key with Solar API enabled |
428+
| `lat` | number | Yes | Latitude coordinate |
429+
| `lng` | number | Yes | Longitude coordinate |
430+
| `requiredQuality` | string | No | Minimum imagery quality to accept \(HIGH, MEDIUM, or BASE\) |
431+
| `pricing` | per_request | No | No description |
432+
| `rateLimit` | string | No | No description |
433+
434+
#### Output
435+
436+
| Parameter | Type | Description |
437+
| --------- | ---- | ----------- |
438+
| `name` | string | Resource name of the building \(e.g., "buildings/ChIJ..."\) |
439+
| `center` | object | Center coordinate of the building |
440+
|`lat` | number | Latitude |
441+
|`lng` | number | Longitude |
442+
| `imageryDate` | object | Date the underlying imagery was captured |
443+
| `imageryQuality` | string | Quality of the imagery used \(HIGH, MEDIUM, BASE\) |
444+
| `regionCode` | string | Region code \(ISO 3166-1 alpha-2\) for the building |
445+
| `postalCode` | string | Postal code of the building |
446+
| `administrativeArea` | string | Administrative area \(e.g., state or province\) |
447+
| `solarPotential` | object | Solar potential: max panel count/area, sunshine hours, carbon offset, panel specs, and configs |
448+
382449
### `google_maps_speed_limits`
383450

384451
Get speed limits for road segments. Requires either path coordinates or placeIds.

apps/docs/content/docs/en/integrations/google_search.mdx

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,17 @@ Search the web with the Custom Search API
3939
| --------- | ---- | -------- | ----------- |
4040
| `query` | string | Yes | The search query to execute |
4141
| `searchEngineId` | string | Yes | Custom Search Engine ID |
42-
| `num` | string | No | Number of results to return \(default: 10, max: 10\) |
42+
| `num` | string | No | Number of results to return \(1-10, default 10\) |
43+
| `start` | number | No | Index of the first result \(1-based, for pagination; start + num must be <= 100\) |
44+
| `dateRestrict` | string | No | Restrict results by recency: d\[n\] days, w\[n\] weeks, m\[n\] months, y\[n\] years |
45+
| `fileType` | string | No | Restrict to a file extension \(e.g., pdf, doc\) |
46+
| `safe` | string | No | SafeSearch level: "active" or "off" \(default off\) |
47+
| `searchType` | string | No | Set to "image" to perform an image search |
48+
| `siteSearch` | string | No | A site to include or exclude from results |
49+
| `siteSearchFilter` | string | No | Whether to include \("i"\) or exclude \("e"\) the siteSearch site |
50+
| `lr` | string | No | Restrict to a language, e.g. "lang_en" |
51+
| `gl` | string | No | Two-letter country code to boost geographically relevant results |
52+
| `sort` | string | No | Sort expression, e.g. "date" |
4353
| `apiKey` | string | Yes | Google API key |
4454

4555
#### Output
@@ -48,14 +58,29 @@ Search the web with the Custom Search API
4858
| --------- | ---- | ----------- |
4959
| `items` | array | Array of search results from Google |
5060
|`title` | string | Title of the search result |
61+
|`htmlTitle` | string | Title of the search result with HTML markup |
5162
|`link` | string | URL of the search result |
52-
|`snippet` | string | Snippet or description of the search result |
5363
|`displayLink` | string | Display URL \(abbreviated form\) |
64+
|`snippet` | string | Snippet or description of the search result |
65+
|`htmlSnippet` | string | Snippet of the search result with HTML markup |
66+
|`formattedUrl` | string | Display URL shown beneath the result |
67+
|`mime` | string | MIME type of the result |
68+
|`fileFormat` | string | File format of the result |
69+
|`cacheId` | string | ID of Google's cached version |
5470
|`pagemap` | object | PageMap information for the result \(structured data\) |
71+
|`image` | object | Image metadata \(present when searchType is image\) |
72+
|`contextLink` | string | URL of the page hosting the image |
73+
|`height` | number | Image height in pixels |
74+
|`width` | number | Image width in pixels |
75+
|`byteSize` | number | Image file size in bytes |
76+
|`thumbnailLink` | string | Thumbnail image URL |
77+
|`thumbnailHeight` | number | Thumbnail height in pixels |
78+
|`thumbnailWidth` | number | Thumbnail width in pixels |
5579
| `searchInformation` | object | Information about the search query and results |
5680
|`totalResults` | string | Total number of search results available |
5781
|`searchTime` | number | Time taken to perform the search in seconds |
5882
|`formattedSearchTime` | string | Formatted search time for display |
5983
|`formattedTotalResults` | string | Formatted total results count for display |
84+
| `nextPageStartIndex` | number | Start index for the next page of results \(null if no further results\) |
6085

6186

apps/docs/content/docs/en/integrations/google_sheets.mdx

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,68 @@ Copy a sheet from one spreadsheet to another
320320
| `destinationSpreadsheetId` | string | The ID of the destination spreadsheet |
321321
| `destinationSpreadsheetUrl` | string | URL to the destination spreadsheet |
322322

323+
### `google_sheets_delete_rows`
324+
325+
Delete rows from a sheet in a Google Sheets spreadsheet
326+
327+
#### Input
328+
329+
| Parameter | Type | Required | Description |
330+
| --------- | ---- | -------- | ----------- |
331+
| `spreadsheetId` | string | Yes | Google Sheets spreadsheet ID |
332+
| `sheetId` | number | Yes | The numeric ID of the sheet/tab \(not the sheet name\). Use Get Spreadsheet to find sheet IDs. |
333+
| `startIndex` | number | Yes | The start row index \(0-based, inclusive\) of the rows to delete |
334+
| `endIndex` | number | Yes | The end row index \(0-based, exclusive\) of the rows to delete |
335+
336+
#### Output
337+
338+
| Parameter | Type | Description |
339+
| --------- | ---- | ----------- |
340+
| `spreadsheetId` | string | Google Sheets spreadsheet ID |
341+
| `sheetId` | number | The numeric ID of the sheet |
342+
| `deletedRowRange` | string | Description of the deleted row range |
343+
| `metadata` | json | Spreadsheet metadata including ID and URL |
344+
|`spreadsheetId` | string | Google Sheets spreadsheet ID |
345+
|`spreadsheetUrl` | string | Spreadsheet URL |
346+
347+
### `google_sheets_delete_sheet`
348+
349+
Delete a sheet/tab from a Google Sheets spreadsheet
350+
351+
#### Input
352+
353+
| Parameter | Type | Required | Description |
354+
| --------- | ---- | -------- | ----------- |
355+
| `spreadsheetId` | string | Yes | Google Sheets spreadsheet ID |
356+
| `sheetId` | number | Yes | The numeric ID of the sheet/tab to delete \(not the sheet name\). Use Get Spreadsheet to find sheet IDs. |
357+
358+
#### Output
359+
360+
| Parameter | Type | Description |
361+
| --------- | ---- | ----------- |
362+
| `spreadsheetId` | string | Google Sheets spreadsheet ID |
363+
| `deletedSheetId` | number | The numeric ID of the deleted sheet |
364+
| `metadata` | json | Spreadsheet metadata including ID and URL |
365+
|`spreadsheetId` | string | Google Sheets spreadsheet ID |
366+
|`spreadsheetUrl` | string | Spreadsheet URL |
367+
368+
### `google_sheets_delete_spreadsheet`
369+
370+
Permanently delete a Google Sheets spreadsheet using the Google Drive API
371+
372+
#### Input
373+
374+
| Parameter | Type | Required | Description |
375+
| --------- | ---- | -------- | ----------- |
376+
| `spreadsheetId` | string | Yes | The ID of the Google Sheets spreadsheet to delete |
377+
378+
#### Output
379+
380+
| Parameter | Type | Description |
381+
| --------- | ---- | ----------- |
382+
| `spreadsheetId` | string | The ID of the deleted spreadsheet |
383+
| `deleted` | boolean | Whether the spreadsheet was successfully deleted |
384+
323385

324386

325387
## Triggers

apps/docs/content/docs/en/integrations/google_slides.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ Generate a thumbnail image of a specific slide in a Google Slides presentation
193193
| `presentationId` | string | Yes | Google Slides presentation ID |
194194
| `pageObjectId` | string | Yes | The object ID of the slide/page to get a thumbnail for |
195195
| `thumbnailSize` | string | No | The size of the thumbnail: SMALL \(200px\), MEDIUM \(800px\), or LARGE \(1600px\). Defaults to MEDIUM. |
196-
| `mimeType` | string | No | The MIME type of the thumbnail image: PNG or GIF. Defaults to PNG. |
196+
| `mimeType` | string | No | The MIME type of the thumbnail image: PNG. Defaults to PNG. |
197197

198198
#### Output
199199

apps/sim/blocks/blocks/google.ts

Lines changed: 105 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,88 @@ Return ONLY the search query - no explanations, no quotes around the whole thing
6161
id: 'num',
6262
title: 'Number of Results',
6363
type: 'short-input',
64-
placeholder: '10',
65-
required: true,
64+
placeholder: '10 (1-10)',
65+
mode: 'advanced',
66+
},
67+
{
68+
id: 'start',
69+
title: 'Start Index',
70+
type: 'short-input',
71+
placeholder: '1 (for pagination; start + num <= 100)',
72+
mode: 'advanced',
73+
},
74+
{
75+
id: 'searchType',
76+
title: 'Search Type',
77+
type: 'dropdown',
78+
options: [
79+
{ label: 'Web', id: '' },
80+
{ label: 'Image', id: 'image' },
81+
],
82+
mode: 'advanced',
83+
},
84+
{
85+
id: 'dateRestrict',
86+
title: 'Date Restrict',
87+
type: 'short-input',
88+
placeholder: 'e.g., d7, w2, m1, y1',
89+
mode: 'advanced',
90+
},
91+
{
92+
id: 'fileType',
93+
title: 'File Type',
94+
type: 'short-input',
95+
placeholder: 'e.g., pdf, doc',
96+
mode: 'advanced',
97+
},
98+
{
99+
id: 'safe',
100+
title: 'SafeSearch',
101+
type: 'dropdown',
102+
options: [
103+
{ label: 'Off', id: '' },
104+
{ label: 'Active', id: 'active' },
105+
],
106+
mode: 'advanced',
107+
},
108+
{
109+
id: 'siteSearch',
110+
title: 'Site Search',
111+
type: 'short-input',
112+
placeholder: 'Domain to include or exclude (e.g., wikipedia.org)',
113+
mode: 'advanced',
114+
},
115+
{
116+
id: 'siteSearchFilter',
117+
title: 'Site Search Filter',
118+
type: 'dropdown',
119+
options: [
120+
{ label: 'Include', id: 'i' },
121+
{ label: 'Exclude', id: 'e' },
122+
],
123+
condition: { field: 'siteSearch', value: '', not: true },
124+
mode: 'advanced',
125+
},
126+
{
127+
id: 'lr',
128+
title: 'Language Restrict',
129+
type: 'short-input',
130+
placeholder: 'e.g., lang_en',
131+
mode: 'advanced',
132+
},
133+
{
134+
id: 'gl',
135+
title: 'Country (geolocation)',
136+
type: 'short-input',
137+
placeholder: 'Two-letter country code (e.g., us)',
138+
mode: 'advanced',
139+
},
140+
{
141+
id: 'sort',
142+
title: 'Sort',
143+
type: 'short-input',
144+
placeholder: 'e.g., date',
145+
mode: 'advanced',
66146
},
67147
],
68148

@@ -74,7 +154,17 @@ Return ONLY the search query - no explanations, no quotes around the whole thing
74154
query: params.query,
75155
apiKey: params.apiKey,
76156
searchEngineId: params.searchEngineId,
77-
num: params.num || undefined,
157+
num: params.num ? Number(params.num) : undefined,
158+
start: params.start ? Number(params.start) : undefined,
159+
dateRestrict: params.dateRestrict || undefined,
160+
fileType: params.fileType || undefined,
161+
safe: params.safe || undefined,
162+
searchType: params.searchType || undefined,
163+
siteSearch: params.siteSearch || undefined,
164+
siteSearchFilter: params.siteSearch ? params.siteSearchFilter || undefined : undefined,
165+
lr: params.lr || undefined,
166+
gl: params.gl || undefined,
167+
sort: params.sort || undefined,
78168
}),
79169
},
80170
},
@@ -83,12 +173,23 @@ Return ONLY the search query - no explanations, no quotes around the whole thing
83173
query: { type: 'string', description: 'Search query terms' },
84174
apiKey: { type: 'string', description: 'Google API key' },
85175
searchEngineId: { type: 'string', description: 'Custom search engine ID' },
86-
num: { type: 'string', description: 'Number of results' },
176+
num: { type: 'string', description: 'Number of results (1-10)' },
177+
start: { type: 'string', description: 'Start index for pagination (1-based)' },
178+
dateRestrict: { type: 'string', description: 'Restrict by recency (d/w/m/y notation)' },
179+
fileType: { type: 'string', description: 'Restrict to a file extension' },
180+
safe: { type: 'string', description: 'SafeSearch level (active/off)' },
181+
searchType: { type: 'string', description: 'Search type (image for image search)' },
182+
siteSearch: { type: 'string', description: 'Site to include or exclude' },
183+
siteSearchFilter: { type: 'string', description: 'Include (i) or exclude (e) the site' },
184+
lr: { type: 'string', description: 'Language restriction (e.g., lang_en)' },
185+
gl: { type: 'string', description: 'Country geolocation code' },
186+
sort: { type: 'string', description: 'Sort expression (e.g., date)' },
87187
},
88188

89189
outputs: {
90190
items: { type: 'json', description: 'Search result items' },
91191
searchInformation: { type: 'json', description: 'Search metadata' },
192+
nextPageStartIndex: { type: 'number', description: 'Start index for the next page of results' },
92193
},
93194
}
94195

0 commit comments

Comments
 (0)