mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-06 03:00:16 -04:00
changed zapier to use oauth
This commit is contained in:
@@ -262,6 +262,8 @@ const SCOPE_DESCRIPTIONS: Record<string, string> = {
|
||||
'sharing.write': 'Share files and folders with others',
|
||||
// WordPress.com scopes
|
||||
global: 'Full access to manage your WordPress.com sites, posts, pages, media, and settings',
|
||||
// Zapier AI Actions scopes
|
||||
'nla:exposed_actions:execute': 'Execute Zapier AI Actions on your behalf',
|
||||
}
|
||||
|
||||
function getScopeDescription(scope: string): string {
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import { ZapierIcon } from '@/components/icons'
|
||||
import type { BlockConfig } from '@/blocks/types'
|
||||
import { AuthMode } from '@/blocks/types'
|
||||
import type { ZapierResponse } from '@/tools/zapier/types'
|
||||
|
||||
export const ZapierBlock: BlockConfig<ZapierResponse> = {
|
||||
type: 'zapier',
|
||||
name: 'Zapier',
|
||||
description: 'Execute actions across 7,000+ apps using Zapier AI Actions',
|
||||
authMode: AuthMode.OAuth,
|
||||
longDescription:
|
||||
'Connect to Zapier AI Actions to execute any of 30,000+ actions across 7,000+ apps. Send emails, create documents, update CRMs, post messages, and more - all through natural language instructions. Requires a Zapier AI Actions API key.',
|
||||
'Connect to Zapier AI Actions to execute any of 30,000+ actions across 7,000+ apps. Send emails, create documents, update CRMs, post messages, and more - all through natural language instructions.',
|
||||
docsLink: 'https://docs.sim.ai/tools/zapier',
|
||||
category: 'tools',
|
||||
bgColor: '#FFFFFF',
|
||||
@@ -32,11 +34,12 @@ export const ZapierBlock: BlockConfig<ZapierResponse> = {
|
||||
value: () => 'execute',
|
||||
},
|
||||
{
|
||||
id: 'apiKey',
|
||||
title: 'API Key',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter your Zapier AI Actions API key',
|
||||
password: true,
|
||||
id: 'credential',
|
||||
title: 'Zapier Account',
|
||||
type: 'oauth-input',
|
||||
serviceId: 'zapier',
|
||||
requiredScopes: ['openid', 'nla:exposed_actions:execute'],
|
||||
placeholder: 'Select Zapier account',
|
||||
required: true,
|
||||
},
|
||||
// Execute Action fields
|
||||
@@ -487,7 +490,7 @@ export const ZapierBlock: BlockConfig<ZapierResponse> = {
|
||||
params: (params) => {
|
||||
const {
|
||||
operation,
|
||||
apiKey,
|
||||
credential,
|
||||
actionId,
|
||||
instructions,
|
||||
params: execParams,
|
||||
@@ -521,7 +524,7 @@ export const ZapierBlock: BlockConfig<ZapierResponse> = {
|
||||
deleteActionId,
|
||||
} = params
|
||||
|
||||
const baseParams: Record<string, any> = { apiKey }
|
||||
const baseParams: Record<string, any> = { credential }
|
||||
|
||||
// Helper to parse JSON params
|
||||
const parseJsonParams = (jsonParams: any) => {
|
||||
@@ -622,7 +625,7 @@ export const ZapierBlock: BlockConfig<ZapierResponse> = {
|
||||
},
|
||||
inputs: {
|
||||
operation: { type: 'string', description: 'Operation to perform' },
|
||||
apiKey: { type: 'string', description: 'Zapier AI Actions API key' },
|
||||
credential: { type: 'string', description: 'Zapier OAuth credential' },
|
||||
// Execute inputs
|
||||
actionId: { type: 'string', description: 'AI Action ID to execute' },
|
||||
instructions: { type: 'string', description: 'Plain English instructions for the action' },
|
||||
|
||||
@@ -1847,6 +1847,59 @@ export const auth = betterAuth({
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
// Zapier AI Actions provider
|
||||
{
|
||||
providerId: 'zapier',
|
||||
clientId: env.ZAPIER_CLIENT_ID as string,
|
||||
clientSecret: env.ZAPIER_CLIENT_SECRET as string,
|
||||
authorizationUrl: 'https://actions.zapier.com/oauth/authorize/',
|
||||
tokenUrl: 'https://actions.zapier.com/oauth/token/',
|
||||
userInfoUrl: 'https://actions.zapier.com/api/v2/check/',
|
||||
scopes: ['openid', 'nla:exposed_actions:execute'],
|
||||
responseType: 'code',
|
||||
pkce: true,
|
||||
accessType: 'offline',
|
||||
prompt: 'consent',
|
||||
redirectURI: `${getBaseUrl()}/api/auth/oauth2/callback/zapier`,
|
||||
getUserInfo: async (tokens) => {
|
||||
try {
|
||||
logger.info('Fetching Zapier user profile')
|
||||
|
||||
// Zapier's check endpoint returns account info when using OAuth
|
||||
const response = await fetch('https://actions.zapier.com/api/v2/check/', {
|
||||
headers: {
|
||||
Authorization: `Bearer ${tokens.accessToken}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
logger.error('Failed to fetch Zapier user info', {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
})
|
||||
throw new Error('Failed to fetch user info')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
// Zapier check endpoint returns account_id and other info
|
||||
const userId = data.account_id || data.user_id || `zapier-${Date.now()}`
|
||||
|
||||
return {
|
||||
id: userId.toString(),
|
||||
name: data.email || 'Zapier User',
|
||||
email: data.email || `${userId}@zapier.user`,
|
||||
emailVerified: !!data.email,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error in Zapier getUserInfo:', { error })
|
||||
return null
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
// Include SSO plugin when enabled
|
||||
|
||||
@@ -230,6 +230,8 @@ export const env = createEnv({
|
||||
ZOOM_CLIENT_SECRET: z.string().optional(), // Zoom OAuth client secret
|
||||
WORDPRESS_CLIENT_ID: z.string().optional(), // WordPress.com OAuth client ID
|
||||
WORDPRESS_CLIENT_SECRET: z.string().optional(), // WordPress.com OAuth client secret
|
||||
ZAPIER_CLIENT_ID: z.string().optional(), // Zapier AI Actions OAuth client ID
|
||||
ZAPIER_CLIENT_SECRET: z.string().optional(), // Zapier AI Actions OAuth client secret
|
||||
|
||||
// E2B Remote Code Execution
|
||||
E2B_ENABLED: z.string().optional(), // Enable E2B remote code execution
|
||||
|
||||
@@ -37,6 +37,7 @@ import {
|
||||
WebflowIcon,
|
||||
WordpressIcon,
|
||||
xIcon,
|
||||
ZapierIcon,
|
||||
ZoomIcon,
|
||||
} from '@/components/icons'
|
||||
import { env } from '@/lib/core/config/env'
|
||||
@@ -70,6 +71,7 @@ export type OAuthProvider =
|
||||
| 'shopify'
|
||||
| 'zoom'
|
||||
| 'wordpress'
|
||||
| 'zapier'
|
||||
| string
|
||||
|
||||
export type OAuthService =
|
||||
@@ -111,6 +113,7 @@ export type OAuthService =
|
||||
| 'shopify'
|
||||
| 'zoom'
|
||||
| 'wordpress'
|
||||
| 'zapier'
|
||||
export interface OAuthProviderConfig {
|
||||
id: OAuthProvider
|
||||
name: string
|
||||
@@ -891,6 +894,23 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
|
||||
},
|
||||
defaultService: 'wordpress',
|
||||
},
|
||||
zapier: {
|
||||
id: 'zapier',
|
||||
name: 'Zapier',
|
||||
icon: (props) => ZapierIcon(props),
|
||||
services: {
|
||||
zapier: {
|
||||
id: 'zapier',
|
||||
name: 'Zapier AI Actions',
|
||||
description: 'Execute actions across 7,000+ apps using Zapier AI Actions.',
|
||||
providerId: 'zapier',
|
||||
icon: (props) => ZapierIcon(props),
|
||||
baseProviderIcon: (props) => ZapierIcon(props),
|
||||
scopes: ['openid', 'nla:exposed_actions:execute'],
|
||||
},
|
||||
},
|
||||
defaultService: 'zapier',
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1470,6 +1490,20 @@ function getProviderAuthConfig(provider: string): ProviderAuthConfig {
|
||||
supportsRefreshTokenRotation: false,
|
||||
}
|
||||
}
|
||||
case 'zapier': {
|
||||
// Zapier AI Actions OAuth - tokens expire after 10 hours
|
||||
const { clientId, clientSecret } = getCredentials(
|
||||
env.ZAPIER_CLIENT_ID,
|
||||
env.ZAPIER_CLIENT_SECRET
|
||||
)
|
||||
return {
|
||||
tokenEndpoint: 'https://actions.zapier.com/oauth/token/',
|
||||
clientId,
|
||||
clientSecret,
|
||||
useBasicAuth: false,
|
||||
supportsRefreshTokenRotation: true,
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw new Error(`Unsupported provider: ${provider}`)
|
||||
}
|
||||
|
||||
@@ -11,12 +11,17 @@ export const zapierCreateAiActionTool: ToolConfig<
|
||||
'Create a new stored AI Action in Zapier. The action can then be executed with zapier_execute_action.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Zapier AI Actions API key from actions.zapier.com/credentials',
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
app: {
|
||||
type: 'string',
|
||||
@@ -79,7 +84,7 @@ export const zapierCreateAiActionTool: ToolConfig<
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': params.apiKey,
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => ({
|
||||
app: params.app,
|
||||
|
||||
@@ -10,12 +10,17 @@ export const zapierDeleteAiActionTool: ToolConfig<
|
||||
description: 'Delete a stored AI Action from Zapier.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Zapier AI Actions API key from actions.zapier.com/credentials',
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
actionId: {
|
||||
type: 'string',
|
||||
@@ -31,7 +36,7 @@ export const zapierDeleteAiActionTool: ToolConfig<
|
||||
method: 'DELETE',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': params.apiKey,
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
},
|
||||
|
||||
|
||||
@@ -11,12 +11,17 @@ export const zapierExecuteActionTool: ToolConfig<
|
||||
'Execute a stored AI Action in Zapier. Runs any of the 30,000+ actions across 7,000+ apps that Zapier supports.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Zapier AI Actions API key from actions.zapier.com/credentials',
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
actionId: {
|
||||
type: 'string',
|
||||
@@ -53,7 +58,7 @@ export const zapierExecuteActionTool: ToolConfig<
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': params.apiKey,
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {
|
||||
|
||||
@@ -14,12 +14,17 @@ export const zapierGetActionDetailsTool: ToolConfig<
|
||||
'Get detailed information about a specific action including its required inputs (needs) and outputs (gives).',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Zapier AI Actions API key from actions.zapier.com/credentials',
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
app: {
|
||||
type: 'string',
|
||||
@@ -109,7 +114,7 @@ export const zapierGetActionDetailsTool: ToolConfig<
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': params.apiKey,
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => ({
|
||||
params: params.params || {},
|
||||
|
||||
@@ -11,12 +11,17 @@ export const zapierGuessActionsTool: ToolConfig<
|
||||
'Find relevant Zapier actions using natural language. Searches across 30,000+ actions to find the best matches for your query.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Zapier AI Actions API key from actions.zapier.com/credentials',
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
query: {
|
||||
type: 'string',
|
||||
@@ -46,7 +51,7 @@ export const zapierGuessActionsTool: ToolConfig<
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': params.apiKey,
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {
|
||||
|
||||
@@ -9,12 +9,17 @@ export const zapierListActionsTool: ToolConfig<ZapierListActionsParams, ZapierLi
|
||||
'List all AI Actions configured in your Zapier account. Returns stored actions that can be executed.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Zapier AI Actions API key from actions.zapier.com/credentials',
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -23,7 +28,7 @@ export const zapierListActionsTool: ToolConfig<ZapierListActionsParams, ZapierLi
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': params.apiKey,
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
},
|
||||
|
||||
|
||||
@@ -14,12 +14,17 @@ export const zapierSearchAppActionsTool: ToolConfig<
|
||||
'Search for available actions within a specific Zapier app. Returns all actions the app supports.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Zapier AI Actions API key from actions.zapier.com/credentials',
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
app: {
|
||||
type: 'string',
|
||||
@@ -59,7 +64,7 @@ export const zapierSearchAppActionsTool: ToolConfig<
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': params.apiKey,
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
},
|
||||
|
||||
|
||||
@@ -8,12 +8,17 @@ export const zapierSearchAppsTool: ToolConfig<ZapierSearchAppsParams, ZapierSear
|
||||
'Search for apps available in Zapier. Returns apps with their available action counts.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Zapier AI Actions API key from actions.zapier.com/credentials',
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
query: {
|
||||
type: 'string',
|
||||
@@ -34,7 +39,7 @@ export const zapierSearchAppsTool: ToolConfig<ZapierSearchAppsParams, ZapierSear
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': params.apiKey,
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
},
|
||||
|
||||
|
||||
@@ -14,12 +14,17 @@ export const zapierStatelessExecuteTool: ToolConfig<
|
||||
'Execute any Zapier action directly without creating a stored AI Action first. Provide the app, action, and instructions.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Zapier AI Actions API key from actions.zapier.com/credentials',
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
app: {
|
||||
type: 'string',
|
||||
@@ -113,7 +118,7 @@ export const zapierStatelessExecuteTool: ToolConfig<
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': params.apiKey,
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
// Base params - all Zapier tools require API key
|
||||
// Base params - all Zapier tools require OAuth access token
|
||||
export interface ZapierBaseParams {
|
||||
apiKey: string
|
||||
accessToken: string
|
||||
}
|
||||
|
||||
// Parameter constraint for execute action
|
||||
|
||||
@@ -10,12 +10,17 @@ export const zapierUpdateAiActionTool: ToolConfig<
|
||||
description: 'Update an existing stored AI Action configuration in Zapier.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Zapier AI Actions API key from actions.zapier.com/credentials',
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
actionId: {
|
||||
type: 'string',
|
||||
@@ -84,7 +89,7 @@ export const zapierUpdateAiActionTool: ToolConfig<
|
||||
method: 'PUT',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': params.apiKey,
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => ({
|
||||
app: params.app,
|
||||
|
||||
Reference in New Issue
Block a user