mirror of
https://github.com/simstudioai/sim.git
synced 2026-03-15 03:00:33 -04:00
Compare commits
7 Commits
fix/render
...
waleedlati
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
993ee3001a | ||
|
|
15c3fa4fb7 | ||
|
|
8d7d484355 | ||
|
|
f5c8c47fcf | ||
|
|
30cb108b30 | ||
|
|
5cccde3301 | ||
|
|
3d56ac9bb6 |
@@ -1346,6 +1346,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 GoogleTasksIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg {...props} viewBox='0 0 527.1 500' xmlns='http://www.w3.org/2000/svg'>
|
||||
|
||||
@@ -49,6 +49,7 @@ import {
|
||||
GoogleBigQueryIcon,
|
||||
GoogleBooksIcon,
|
||||
GoogleCalendarIcon,
|
||||
GoogleChatIcon,
|
||||
GoogleContactsIcon,
|
||||
GoogleDocsIcon,
|
||||
GoogleDriveIcon,
|
||||
@@ -205,6 +206,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
|
||||
google_bigquery: GoogleBigQueryIcon,
|
||||
google_books: GoogleBooksIcon,
|
||||
google_calendar_v2: GoogleCalendarIcon,
|
||||
google_chat: GoogleChatIcon,
|
||||
google_contacts: GoogleContactsIcon,
|
||||
google_docs: GoogleDocsIcon,
|
||||
google_drive: GoogleDriveIcon,
|
||||
|
||||
62
apps/docs/content/docs/en/tools/google_chat.mdx
Normal file
62
apps/docs/content/docs/en/tools/google_chat.mdx
Normal file
@@ -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 |
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
"google_bigquery",
|
||||
"google_books",
|
||||
"google_calendar",
|
||||
"google_chat",
|
||||
"google_contacts",
|
||||
"google_docs",
|
||||
"google_drive",
|
||||
|
||||
@@ -55,6 +55,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',
|
||||
|
||||
150
apps/sim/blocks/blocks/google_chat.ts
Normal file
150
apps/sim/blocks/blocks/google_chat.ts
Normal file
@@ -0,0 +1,150 @@
|
||||
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' },
|
||||
mode: 'advanced',
|
||||
},
|
||||
{
|
||||
id: 'filter',
|
||||
title: 'Filter',
|
||||
type: 'short-input',
|
||||
placeholder: 'e.g., spaceType = "SPACE"',
|
||||
condition: { field: 'operation', value: 'list_spaces' },
|
||||
mode: 'advanced',
|
||||
},
|
||||
{
|
||||
id: 'pageSize',
|
||||
title: 'Max Results',
|
||||
type: 'short-input',
|
||||
placeholder: 'Maximum spaces to return (default 100)',
|
||||
condition: { field: 'operation', value: 'list_spaces' },
|
||||
mode: 'advanced',
|
||||
},
|
||||
],
|
||||
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,
|
||||
}
|
||||
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 (name, displayName, spaceType, singleUserBotDm, threaded, type)',
|
||||
},
|
||||
nextPageToken: { type: 'string', description: 'Token for next page of results' },
|
||||
},
|
||||
}
|
||||
@@ -50,6 +50,7 @@ import { GoogleSearchBlock } from '@/blocks/blocks/google'
|
||||
import { GoogleBigQueryBlock } from '@/blocks/blocks/google_bigquery'
|
||||
import { GoogleBooksBlock } from '@/blocks/blocks/google_books'
|
||||
import { GoogleCalendarBlock, GoogleCalendarV2Block } from '@/blocks/blocks/google_calendar'
|
||||
import { GoogleChatBlock } from '@/blocks/blocks/google_chat'
|
||||
import { GoogleContactsBlock } from '@/blocks/blocks/google_contacts'
|
||||
import { GoogleDocsBlock } from '@/blocks/blocks/google_docs'
|
||||
import { GoogleDriveBlock } from '@/blocks/blocks/google_drive'
|
||||
@@ -242,6 +243,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_contacts: GoogleContactsBlock,
|
||||
|
||||
@@ -1346,6 +1346,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 GoogleTasksIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg {...props} viewBox='0 0 527.1 500' xmlns='http://www.w3.org/2000/svg'>
|
||||
|
||||
@@ -488,6 +488,7 @@ export const auth = betterAuth({
|
||||
'google-bigquery',
|
||||
'google-vault',
|
||||
'google-groups',
|
||||
'google-chat',
|
||||
'google-tasks',
|
||||
'vertex-ai',
|
||||
'github-repo',
|
||||
@@ -1232,6 +1233,47 @@ export const auth = betterAuth({
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
providerId: 'google-chat',
|
||||
clientId: env.GOOGLE_CLIENT_ID as string,
|
||||
clientSecret: env.GOOGLE_CLIENT_SECRET as string,
|
||||
discoveryUrl: 'https://accounts.google.com/.well-known/openid-configuration',
|
||||
accessType: 'offline',
|
||||
scopes: [
|
||||
'https://www.googleapis.com/auth/userinfo.email',
|
||||
'https://www.googleapis.com/auth/userinfo.profile',
|
||||
'https://www.googleapis.com/auth/chat.spaces.readonly',
|
||||
'https://www.googleapis.com/auth/chat.messages.create',
|
||||
],
|
||||
prompt: 'consent',
|
||||
redirectURI: `${getBaseUrl()}/api/auth/oauth2/callback/google-chat`,
|
||||
getUserInfo: async (tokens) => {
|
||||
try {
|
||||
const response = await fetch('https://openidconnect.googleapis.com/v1/userinfo', {
|
||||
headers: { Authorization: `Bearer ${tokens.accessToken}` },
|
||||
})
|
||||
if (!response.ok) {
|
||||
logger.error('Failed to fetch Google user info', { status: response.status })
|
||||
throw new Error(`Failed to fetch Google user info: ${response.statusText}`)
|
||||
}
|
||||
const profile = await response.json()
|
||||
const now = new Date()
|
||||
return {
|
||||
id: `${profile.sub}-${crypto.randomUUID()}`,
|
||||
name: profile.name || 'Google User',
|
||||
email: profile.email,
|
||||
image: profile.picture || undefined,
|
||||
emailVerified: profile.email_verified || false,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error in Google getUserInfo', { error })
|
||||
throw error
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
providerId: 'google-tasks',
|
||||
clientId: env.GOOGLE_CLIENT_ID as string,
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
GmailIcon,
|
||||
GoogleBigQueryIcon,
|
||||
GoogleCalendarIcon,
|
||||
GoogleChatIcon,
|
||||
GoogleContactsIcon,
|
||||
GoogleDocsIcon,
|
||||
GoogleDriveIcon,
|
||||
@@ -168,6 +169,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',
|
||||
],
|
||||
},
|
||||
'vertex-ai': {
|
||||
name: 'Vertex AI',
|
||||
description: 'Access Google Cloud Vertex AI for Gemini models with OAuth.',
|
||||
|
||||
@@ -13,6 +13,7 @@ export type OAuthProvider =
|
||||
| 'google-vault'
|
||||
| 'google-forms'
|
||||
| 'google-groups'
|
||||
| 'google-chat'
|
||||
| 'vertex-ai'
|
||||
| 'github'
|
||||
| 'github-repo'
|
||||
@@ -61,6 +62,7 @@ export type OAuthService =
|
||||
| 'google-vault'
|
||||
| 'google-forms'
|
||||
| 'google-groups'
|
||||
| 'google-chat'
|
||||
| 'vertex-ai'
|
||||
| 'github'
|
||||
| 'x'
|
||||
|
||||
6
apps/sim/tools/google_chat/index.ts
Normal file
6
apps/sim/tools/google_chat/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { listSpacesTool } from './list_spaces'
|
||||
import { sendMessageTool } from './send_message'
|
||||
|
||||
export const googleChatSendMessageTool = sendMessageTool
|
||||
export const googleChatListSpacesTool = listSpacesTool
|
||||
export * from './types'
|
||||
89
apps/sim/tools/google_chat/list_spaces.ts
Normal file
89
apps/sim/tools/google_chat/list_spaces.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import type { GoogleChatListSpacesParams, GoogleChatResponse } from '@/tools/google_chat/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const listSpacesTool: ToolConfig<GoogleChatListSpacesParams, GoogleChatResponse> = {
|
||||
id: 'google_chat_list_spaces',
|
||||
name: 'Google Chat List Spaces',
|
||||
description: 'List Google Chat spaces the user is a member of',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'google-chat',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'OAuth access token',
|
||||
},
|
||||
pageSize: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of spaces to return (default 100, max 1000)',
|
||||
},
|
||||
pageToken: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Token for fetching the next page of results',
|
||||
},
|
||||
filter: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Filter by space type (e.g., spaceType = "SPACE", spaceType = "GROUP_CHAT" OR spaceType = "DIRECT_MESSAGE")',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const url = new URL('https://chat.googleapis.com/v1/spaces')
|
||||
if (params.pageSize) {
|
||||
url.searchParams.set('pageSize', String(params.pageSize))
|
||||
}
|
||||
if (params.pageToken) {
|
||||
url.searchParams.set('pageToken', params.pageToken)
|
||||
}
|
||||
if (params.filter) {
|
||||
url.searchParams.set('filter', params.filter)
|
||||
}
|
||||
return url.toString()
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error?.message || 'Failed to list spaces')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
spaces: data.spaces ?? [],
|
||||
nextPageToken: data.nextPageToken ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
spaces: {
|
||||
type: 'json',
|
||||
description:
|
||||
'Array of Google Chat space objects (name, displayName, spaceType, singleUserBotDm, threaded, type)',
|
||||
},
|
||||
nextPageToken: {
|
||||
type: 'string',
|
||||
description: 'Token for fetching the next page of results',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
95
apps/sim/tools/google_chat/send_message.ts
Normal file
95
apps/sim/tools/google_chat/send_message.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import type { GoogleChatResponse, GoogleChatSendMessageParams } from '@/tools/google_chat/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const sendMessageTool: ToolConfig<GoogleChatSendMessageParams, GoogleChatResponse> = {
|
||||
id: 'google_chat_send_message',
|
||||
name: 'Google Chat Send Message',
|
||||
description: 'Send a message to a Google Chat space',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'google-chat',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'OAuth access token',
|
||||
},
|
||||
spaceId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The Google Chat space ID (e.g., spaces/AAAA1234)',
|
||||
},
|
||||
message: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Message text to send',
|
||||
},
|
||||
threadKey: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Thread key for sending a threaded reply',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const spaceId = params.spaceId?.trim()
|
||||
if (!spaceId) {
|
||||
throw new Error('Space ID is required')
|
||||
}
|
||||
const spaceName = spaceId.startsWith('spaces/') ? spaceId : `spaces/${spaceId}`
|
||||
const url = new URL(`https://chat.googleapis.com/v1/${spaceName}/messages`)
|
||||
if (params.threadKey) {
|
||||
url.searchParams.set('messageReplyOption', 'REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD')
|
||||
}
|
||||
return url.toString()
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, unknown> = {
|
||||
text: params.message,
|
||||
}
|
||||
if (params.threadKey) {
|
||||
body.thread = { threadKey: params.threadKey }
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error?.message || 'Failed to send message')
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
messageName: data.name ?? null,
|
||||
spaceName: data.space?.name ?? null,
|
||||
threadName: data.thread?.name ?? null,
|
||||
text: data.text ?? null,
|
||||
createTime: data.createTime ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
messageName: { type: 'string', description: 'Google Chat message resource name' },
|
||||
spaceName: { type: 'string', description: 'Space the message was sent to' },
|
||||
threadName: { type: 'string', description: 'Thread resource name', optional: true },
|
||||
text: { type: 'string', description: 'Message text that was sent' },
|
||||
createTime: { type: 'string', description: 'Timestamp when the message was created' },
|
||||
},
|
||||
}
|
||||
33
apps/sim/tools/google_chat/types.ts
Normal file
33
apps/sim/tools/google_chat/types.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
/**
|
||||
* Common parameters for Google Chat API calls
|
||||
*/
|
||||
export interface GoogleChatCommonParams {
|
||||
accessToken: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters for sending a message to a Google Chat space
|
||||
*/
|
||||
export interface GoogleChatSendMessageParams extends GoogleChatCommonParams {
|
||||
spaceId: string
|
||||
message: string
|
||||
threadKey?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters for listing Google Chat spaces
|
||||
*/
|
||||
export interface GoogleChatListSpacesParams extends GoogleChatCommonParams {
|
||||
pageSize?: number
|
||||
pageToken?: string
|
||||
filter?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard response for Google Chat operations
|
||||
*/
|
||||
export interface GoogleChatResponse extends ToolResponse {
|
||||
output: Record<string, unknown>
|
||||
}
|
||||
@@ -714,6 +714,7 @@ import {
|
||||
googleCalendarUpdateTool,
|
||||
googleCalendarUpdateV2Tool,
|
||||
} from '@/tools/google_calendar'
|
||||
import { googleChatListSpacesTool, googleChatSendMessageTool } from '@/tools/google_chat'
|
||||
import {
|
||||
googleContactsCreateTool,
|
||||
googleContactsDeleteTool,
|
||||
@@ -3150,6 +3151,8 @@ export const tools: Record<string, ToolConfig> = {
|
||||
google_docs_create: googleDocsCreateTool,
|
||||
google_books_volume_search: googleBooksVolumeSearchTool,
|
||||
google_books_volume_details: googleBooksVolumeDetailsTool,
|
||||
google_chat_list_spaces: googleChatListSpacesTool,
|
||||
google_chat_send_message: googleChatSendMessageTool,
|
||||
google_maps_air_quality: googleMapsAirQualityTool,
|
||||
google_maps_directions: googleMapsDirectionsTool,
|
||||
google_maps_distance_matrix: googleMapsDistanceMatrixTool,
|
||||
|
||||
Reference in New Issue
Block a user