Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
31 changes: 31 additions & 0 deletions apps/docs/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1302,6 +1302,37 @@ export function GoogleCalendarIcon(props: SVGProps<SVGSVGElement>) {
)
}

export function GoogleChatIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} viewBox='0 0 311 320' fill='none' xmlns='http://www.w3.org/2000/svg'>
<path
fill='#0066da'
d='M76.37 0.51L76.38 76.98L0 76.96L0 20.77Q0.85 14.81 3.53 10.76Q10.14 0.74 22.75 0.67Q49.41 0.53 76.37 0.51Z'
/>
<path
fill='#fbbc04'
d='M76.37 0.51L233.79 0.53A1.61 1.57-26.7 0 1 234.71 0.82L235.08 1.09Q234.92 1.15 234.81 1.22Q234.64 1.31 234.64 1.5L234.62 77.01Q234.6 77.01 234.57 77.01L76.41 77.01Q76.4 77 76.38 76.98L76.37 0.51Z'
/>
<path
fill='#ea4335'
d='M235.08 1.09L310.53 76.77L234.62 77.01L234.64 1.5Q234.64 1.31 234.81 1.22Q234.92 1.15 235.08 1.09Z'
/>
<path
fill='#2684fc'
d='M0 76.96L76.38 76.98Q76.4 77 76.41 77.01L76.43 182.69L0 182.67L0 76.96Z'
/>
<path
fill='#00ac47'
d='M310.53 76.77L311 77.11L311 239.01Q308.34 253.54 295.94 257.78Q291.52 259.3 282.91 259.28Q227.02 259.19 169.99 259.11Q161.71 259.1 153.19 259.23Q152.72 259.24 152.39 259.57Q124.49 287.34 96.39 315.59C93.52 318.48 90.27 320.09 86.15 319.48Q80.39 318.63 77.66 313.54Q76.51 311.38 76.49 305.66Q76.42 282.47 76.44 259.13L76.43 220.85L114.21 183.07A1.79 1.77 22.3 0 1 115.47 182.55L233.77 182.59A0.83 0.83 0 0 0 234.6 181.76L234.57 77.01Q234.6 77.01 234.62 77.01L310.53 76.77Z'
/>
<path
fill='#00832d'
d='M76.43 182.69L76.43 220.85L76.44 259.13Q52.47 259.27 28.91 259.22Q19.09 259.2 14.76 257.68Q2.62 253.44 0 238.88L0 182.67L76.43 182.69Z'
/>
</svg>
)
}

export function SupabaseIcon(props: SVGProps<SVGSVGElement>) {
const id = useId()
const gradient0 = `supabase_paint0_${id}`
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/components/ui/icon-mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {
GongIcon,
GoogleBooksIcon,
GoogleCalendarIcon,
GoogleChatIcon,
GoogleDocsIcon,
GoogleDriveIcon,
GoogleFormsIcon,
Expand Down Expand Up @@ -189,6 +190,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
gong: GongIcon,
google_books: GoogleBooksIcon,
google_calendar_v2: GoogleCalendarIcon,
google_chat: GoogleChatIcon,
google_docs: GoogleDocsIcon,
google_drive: GoogleDriveIcon,
google_forms: GoogleFormsIcon,
Expand Down
62 changes: 62 additions & 0 deletions apps/docs/content/docs/en/tools/google_chat.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
title: Google Chat
description: Send messages and manage Google Chat spaces
---

import { BlockInfoCard } from "@/components/ui/block-info-card"

<BlockInfoCard
type="google_chat"
color="#E0E0E0"
/>

## Usage Instructions

Integrate with Google Chat to send messages to spaces and list available spaces using OAuth.



## Tools

### `google_chat_send_message`

Send a message to a Google Chat space

#### Input

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `spaceId` | string | Yes | The Google Chat space ID \(e.g., spaces/AAAA1234\) |
| `message` | string | Yes | Message text to send |
| `threadKey` | string | No | Thread key for sending a threaded reply |

#### Output

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `messageName` | string | Google Chat message resource name |
| `spaceName` | string | Space the message was sent to |
| `threadName` | string | Thread resource name |
| `text` | string | Message text that was sent |
| `createTime` | string | Timestamp when the message was created |

### `google_chat_list_spaces`

List Google Chat spaces the user is a member of

#### Input

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `pageSize` | number | No | Maximum number of spaces to return \(default 100, max 1000\) |
| `pageToken` | string | No | Token for fetching the next page of results |
| `filter` | string | No | Filter by space type \(e.g., spaceType = "SPACE", spaceType = "GROUP_CHAT" OR spaceType = "DIRECT_MESSAGE"\) |

#### Output

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `spaces` | json | Array of Google Chat space objects |
| `nextPageToken` | string | Token for fetching the next page of results |


1 change: 1 addition & 0 deletions apps/docs/content/docs/en/tools/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"gong",
"google_books",
"google_calendar",
"google_chat",
"google_docs",
"google_drive",
"google_forms",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ const SCOPE_DESCRIPTIONS: Record<string, string> = {
'https://www.googleapis.com/auth/admin.directory.group.readonly': 'View Google Workspace groups',
'https://www.googleapis.com/auth/admin.directory.group.member.readonly':
'View Google Workspace group memberships',
'https://www.googleapis.com/auth/chat.spaces.readonly': 'View Google Chat spaces',
'https://www.googleapis.com/auth/chat.messages.create': 'Send messages in Google Chat',
'https://www.googleapis.com/auth/cloud-platform':
'Full access to Google Cloud resources for Vertex AI',
'read:confluence-content.all': 'Read all Confluence content',
Expand Down
143 changes: 143 additions & 0 deletions apps/sim/blocks/blocks/google_chat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { GoogleChatIcon } from '@/components/icons'
import type { BlockConfig } from '@/blocks/types'
import { AuthMode } from '@/blocks/types'
import type { GoogleChatResponse } from '@/tools/google_chat/types'

export const GoogleChatBlock: BlockConfig<GoogleChatResponse> = {
type: 'google_chat',
name: 'Google Chat',
description: 'Send messages and manage Google Chat spaces',
authMode: AuthMode.OAuth,
longDescription:
'Integrate with Google Chat to send messages to spaces and list available spaces using OAuth.',
docsLink: 'https://docs.sim.ai/tools/google_chat',
category: 'tools',
bgColor: '#E0E0E0',
icon: GoogleChatIcon,
subBlocks: [
{
id: 'operation',
title: 'Operation',
type: 'dropdown',
options: [
{ label: 'Send Message', id: 'send_message' },
{ label: 'List Spaces', id: 'list_spaces' },
],
value: () => 'send_message',
},
{
id: 'credential',
title: 'Google Chat Account',
type: 'oauth-input',
canonicalParamId: 'oauthCredential',
mode: 'basic',
required: true,
serviceId: 'google-chat',
requiredScopes: [
'https://www.googleapis.com/auth/chat.spaces.readonly',
'https://www.googleapis.com/auth/chat.messages.create',
],
placeholder: 'Select Google account',
},
{
id: 'manualCredential',
title: 'Google Chat Account',
type: 'short-input',
canonicalParamId: 'oauthCredential',
mode: 'advanced',
placeholder: 'Enter credential ID',
required: true,
},
{
id: 'spaceId',
title: 'Space ID',
type: 'short-input',
placeholder: 'e.g., spaces/AAAA1234 or AAAA1234',
required: { field: 'operation', value: 'send_message' },
condition: { field: 'operation', value: 'send_message' },
},
{
id: 'message',
title: 'Message',
type: 'long-input',
placeholder: 'Enter your message',
required: { field: 'operation', value: 'send_message' },
condition: { field: 'operation', value: 'send_message' },
},
{
id: 'threadKey',
title: 'Thread Key',
type: 'short-input',
placeholder: 'Optional thread key for threaded replies',
condition: { field: 'operation', value: 'send_message' },
},
{
id: 'filter',
title: 'Filter',
type: 'short-input',
placeholder: 'e.g., spaceType = "SPACE"',
condition: { field: 'operation', value: 'list_spaces' },
},
{
id: 'pageSize',
title: 'Max Results',
type: 'short-input',
placeholder: 'Maximum spaces to return (default 100)',
condition: { field: 'operation', value: 'list_spaces' },
},
],
tools: {
access: ['google_chat_send_message', 'google_chat_list_spaces'],
config: {
tool: (params) => {
switch (params.operation) {
case 'send_message':
return 'google_chat_send_message'
case 'list_spaces':
return 'google_chat_list_spaces'
default:
throw new Error(`Invalid Google Chat operation: ${params.operation}`)
}
},
params: (params) => {
const { oauthCredential, operation, ...rest } = params

switch (operation) {
case 'send_message':
return {
oauthCredential,
spaceId: rest.spaceId,
message: rest.message,
threadKey: rest.threadKey,
}
case 'list_spaces':
return {
oauthCredential,
pageSize: rest.pageSize ? Number(rest.pageSize) : undefined,
filter: rest.filter,
}
Comment on lines +116 to +121
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.

P1 pageToken not wired through for list_spaces pagination

The pageToken parameter is defined in GoogleChatListSpacesParams and correctly forwarded to the Google API in list_spaces.ts, but it is silently dropped at the block level — it is absent from inputs, subBlocks, and the params return for the list_spaces case.

The block already outputs nextPageToken, but there is no corresponding input to feed that token back into a subsequent call, making pagination non-functional through the block.

Add pageToken to the returned params:

Suggested change
case 'list_spaces':
return {
oauthCredential,
pageSize: rest.pageSize ? Number(rest.pageSize) : undefined,
filter: rest.filter,
}
case 'list_spaces':
return {
oauthCredential,
pageSize: rest.pageSize ? Number(rest.pageSize) : undefined,
pageToken: rest.pageToken,
filter: rest.filter,
}

Also add pageToken to the inputs object:

pageToken: { type: 'string', description: 'Token for fetching the next page of results' },

And add a subBlock (in advanced mode) so users can wire a previous call's nextPageToken output into this field:

{
  id: 'pageToken',
  title: 'Page Token',
  type: 'short-input',
  placeholder: 'Token from previous list_spaces call',
  condition: { field: 'operation', value: 'list_spaces' },
  mode: 'advanced',
},

default:
return { oauthCredential, ...rest }
}
},
},
},
inputs: {
operation: { type: 'string', description: 'Operation to perform' },
oauthCredential: { type: 'string', description: 'Google Chat OAuth credential' },
spaceId: { type: 'string', description: 'Google Chat space ID' },
message: { type: 'string', description: 'Message text to send' },
threadKey: { type: 'string', description: 'Thread key for threaded replies' },
filter: { type: 'string', description: 'Filter by space type' },
pageSize: { type: 'number', description: 'Maximum number of spaces to return' },
},
outputs: {
messageName: { type: 'string', description: 'Message resource name' },
spaceName: { type: 'string', description: 'Space resource name' },
threadName: { type: 'string', description: 'Thread resource name' },
text: { type: 'string', description: 'Message text that was sent' },
createTime: { type: 'string', description: 'Message creation timestamp' },
spaces: { type: 'json', description: 'Array of Google Chat space objects' },
nextPageToken: { type: 'string', description: 'Token for next page of results' },
},
}
2 changes: 2 additions & 0 deletions apps/sim/blocks/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import { GongBlock } from '@/blocks/blocks/gong'
import { GoogleSearchBlock } from '@/blocks/blocks/google'
import { GoogleBooksBlock } from '@/blocks/blocks/google_books'
import { GoogleCalendarBlock, GoogleCalendarV2Block } from '@/blocks/blocks/google_calendar'
import { GoogleChatBlock } from '@/blocks/blocks/google_chat'
import { GoogleDocsBlock } from '@/blocks/blocks/google_docs'
import { GoogleDriveBlock } from '@/blocks/blocks/google_drive'
import { GoogleFormsBlock } from '@/blocks/blocks/google_forms'
Expand Down Expand Up @@ -227,6 +228,7 @@ export const registry: Record<string, BlockConfig> = {
gmail: GmailBlock,
gmail_v2: GmailV2Block,
google_calendar: GoogleCalendarBlock,
google_chat: GoogleChatBlock,
google_calendar_v2: GoogleCalendarV2Block,
google_books: GoogleBooksBlock,
google_docs: GoogleDocsBlock,
Expand Down
31 changes: 31 additions & 0 deletions apps/sim/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1302,6 +1302,37 @@ export function GoogleCalendarIcon(props: SVGProps<SVGSVGElement>) {
)
}

export function GoogleChatIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} viewBox='0 0 311 320' fill='none' xmlns='http://www.w3.org/2000/svg'>
<path
fill='#0066da'
d='M76.37 0.51L76.38 76.98L0 76.96L0 20.77Q0.85 14.81 3.53 10.76Q10.14 0.74 22.75 0.67Q49.41 0.53 76.37 0.51Z'
/>
<path
fill='#fbbc04'
d='M76.37 0.51L233.79 0.53A1.61 1.57-26.7 0 1 234.71 0.82L235.08 1.09Q234.92 1.15 234.81 1.22Q234.64 1.31 234.64 1.5L234.62 77.01Q234.6 77.01 234.57 77.01L76.41 77.01Q76.4 77 76.38 76.98L76.37 0.51Z'
/>
<path
fill='#ea4335'
d='M235.08 1.09L310.53 76.77L234.62 77.01L234.64 1.5Q234.64 1.31 234.81 1.22Q234.92 1.15 235.08 1.09Z'
/>
<path
fill='#2684fc'
d='M0 76.96L76.38 76.98Q76.4 77 76.41 77.01L76.43 182.69L0 182.67L0 76.96Z'
/>
<path
fill='#00ac47'
d='M310.53 76.77L311 77.11L311 239.01Q308.34 253.54 295.94 257.78Q291.52 259.3 282.91 259.28Q227.02 259.19 169.99 259.11Q161.71 259.1 153.19 259.23Q152.72 259.24 152.39 259.57Q124.49 287.34 96.39 315.59C93.52 318.48 90.27 320.09 86.15 319.48Q80.39 318.63 77.66 313.54Q76.51 311.38 76.49 305.66Q76.42 282.47 76.44 259.13L76.43 220.85L114.21 183.07A1.79 1.77 22.3 0 1 115.47 182.55L233.77 182.59A0.83 0.83 0 0 0 234.6 181.76L234.57 77.01Q234.6 77.01 234.62 77.01L310.53 76.77Z'
/>
<path
fill='#00832d'
d='M76.43 182.69L76.43 220.85L76.44 259.13Q52.47 259.27 28.91 259.22Q19.09 259.2 14.76 257.68Q2.62 253.44 0 238.88L0 182.67L76.43 182.69Z'
/>
</svg>
)
}

export function SupabaseIcon(props: SVGProps<SVGSVGElement>) {
const id = useId()
const gradient0 = `supabase_paint0_${id}`
Expand Down
12 changes: 12 additions & 0 deletions apps/sim/lib/oauth/oauth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
GithubIcon,
GmailIcon,
GoogleCalendarIcon,
GoogleChatIcon,
GoogleDocsIcon,
GoogleDriveIcon,
GoogleFormsIcon,
Expand Down Expand Up @@ -141,6 +142,17 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
'https://www.googleapis.com/auth/admin.directory.group.member',
],
},
'google-chat': {
name: 'Google Chat',
description: 'Send messages and manage Google Chat spaces.',
providerId: 'google-chat',
icon: GoogleChatIcon,
baseProviderIcon: GoogleIcon,
scopes: [
'https://www.googleapis.com/auth/chat.spaces.readonly',
'https://www.googleapis.com/auth/chat.messages.create',
],
},
Comment thread
waleedlatif1 marked this conversation as resolved.
'vertex-ai': {
name: 'Vertex AI',
description: 'Access Google Cloud Vertex AI for Gemini models with OAuth.',
Expand Down
2 changes: 2 additions & 0 deletions apps/sim/lib/oauth/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type OAuthProvider =
| 'google-vault'
| 'google-forms'
| 'google-groups'
| 'google-chat'
| 'vertex-ai'
| 'github'
| 'github-repo'
Expand Down Expand Up @@ -55,6 +56,7 @@ export type OAuthService =
| 'google-vault'
| 'google-forms'
| 'google-groups'
| 'google-chat'
| 'vertex-ai'
| 'github'
| 'x'
Expand Down
5 changes: 5 additions & 0 deletions apps/sim/tools/google_chat/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { listSpacesTool } from './list_spaces'
import { sendMessageTool } from './send_message'

export const googleChatSendMessageTool = sendMessageTool
export const googleChatListSpacesTool = listSpacesTool
Loading