mirror of
https://github.com/simstudioai/sim.git
synced 2026-02-14 08:25:03 -05:00
514 lines
18 KiB
TypeScript
514 lines
18 KiB
TypeScript
import { NotionIcon } from '@/components/icons'
|
|
import type { BlockConfig } from '@/blocks/types'
|
|
import { AuthMode } from '@/blocks/types'
|
|
import { createVersionedToolSelector } from '@/blocks/utils'
|
|
import type { NotionResponse } from '@/tools/notion/types'
|
|
|
|
// Legacy block - hidden from toolbar
|
|
export const NotionBlock: BlockConfig<NotionResponse> = {
|
|
type: 'notion',
|
|
name: 'Notion (Legacy)',
|
|
hideFromToolbar: true,
|
|
description: 'Manage Notion pages',
|
|
authMode: AuthMode.OAuth,
|
|
longDescription:
|
|
'Integrate with Notion into the workflow. Can read page, read database, create page, create database, append content, query database, and search workspace.',
|
|
docsLink: 'https://docs.sim.ai/tools/notion',
|
|
category: 'tools',
|
|
bgColor: '#181C1E',
|
|
icon: NotionIcon,
|
|
subBlocks: [
|
|
{
|
|
id: 'operation',
|
|
title: 'Operation',
|
|
type: 'dropdown',
|
|
options: [
|
|
{ label: 'Read Page', id: 'notion_read' },
|
|
{ label: 'Read Database', id: 'notion_read_database' },
|
|
{ label: 'Create Page', id: 'notion_create_page' },
|
|
{ label: 'Create Database', id: 'notion_create_database' },
|
|
{ label: 'Add Database Row', id: 'notion_add_database_row' },
|
|
{ label: 'Append Content', id: 'notion_write' },
|
|
{ label: 'Query Database', id: 'notion_query_database' },
|
|
{ label: 'Search Workspace', id: 'notion_search' },
|
|
],
|
|
value: () => 'notion_read',
|
|
},
|
|
{
|
|
id: 'credential',
|
|
title: 'Notion Account',
|
|
type: 'oauth-input',
|
|
canonicalParamId: 'oauthCredential',
|
|
mode: 'basic',
|
|
serviceId: 'notion',
|
|
placeholder: 'Select Notion account',
|
|
required: true,
|
|
},
|
|
{
|
|
id: 'manualCredential',
|
|
title: 'Notion Account',
|
|
type: 'short-input',
|
|
canonicalParamId: 'oauthCredential',
|
|
mode: 'advanced',
|
|
placeholder: 'Enter credential ID',
|
|
required: true,
|
|
},
|
|
// Read/Write operation - Page ID
|
|
{
|
|
id: 'pageId',
|
|
title: 'Page ID',
|
|
type: 'short-input',
|
|
placeholder: 'Enter Notion page ID',
|
|
condition: {
|
|
field: 'operation',
|
|
value: 'notion_read',
|
|
},
|
|
required: true,
|
|
},
|
|
{
|
|
id: 'databaseId',
|
|
title: 'Database ID',
|
|
type: 'short-input',
|
|
placeholder: 'Enter Notion database ID',
|
|
condition: {
|
|
field: 'operation',
|
|
value: 'notion_read_database',
|
|
},
|
|
required: true,
|
|
},
|
|
{
|
|
id: 'pageId',
|
|
title: 'Page ID',
|
|
type: 'short-input',
|
|
placeholder: 'Enter Notion page ID',
|
|
condition: {
|
|
field: 'operation',
|
|
value: 'notion_write',
|
|
},
|
|
required: true,
|
|
},
|
|
// Create operation fields
|
|
{
|
|
id: 'parentId',
|
|
title: 'Parent Page ID',
|
|
type: 'short-input',
|
|
placeholder: 'ID of parent page',
|
|
condition: { field: 'operation', value: 'notion_create_page' },
|
|
required: true,
|
|
},
|
|
{
|
|
id: 'title',
|
|
title: 'Page Title',
|
|
type: 'short-input',
|
|
placeholder: 'Title for the new page',
|
|
condition: {
|
|
field: 'operation',
|
|
value: 'notion_create_page',
|
|
},
|
|
wandConfig: {
|
|
enabled: true,
|
|
prompt:
|
|
"Generate a concise, descriptive title for a Notion page based on the user's description. The title should be clear and professional. Return ONLY the title text - no explanations, no quotes.",
|
|
placeholder: 'Describe what the page is about...',
|
|
},
|
|
},
|
|
// Content input for write/create operations
|
|
{
|
|
id: 'content',
|
|
title: 'Content',
|
|
type: 'long-input',
|
|
placeholder: 'Enter content to add to the page',
|
|
condition: {
|
|
field: 'operation',
|
|
value: 'notion_write',
|
|
},
|
|
required: true,
|
|
wandConfig: {
|
|
enabled: true,
|
|
prompt:
|
|
"Generate content to append to a Notion page based on the user's description. The content can include paragraphs, lists, headings, and other text elements. Format it appropriately for Notion. Return ONLY the content - no explanations.",
|
|
placeholder: 'Describe the content you want to add...',
|
|
},
|
|
},
|
|
{
|
|
id: 'content',
|
|
title: 'Content',
|
|
type: 'long-input',
|
|
placeholder: 'Enter content to add to the page',
|
|
condition: {
|
|
field: 'operation',
|
|
value: 'notion_create_page',
|
|
},
|
|
required: true,
|
|
wandConfig: {
|
|
enabled: true,
|
|
prompt:
|
|
"Generate content for a new Notion page based on the user's description. The content can include paragraphs, lists, headings, and other text elements. Format it appropriately for Notion. Return ONLY the content - no explanations.",
|
|
placeholder: 'Describe the content you want to create...',
|
|
},
|
|
},
|
|
// Query Database Fields
|
|
{
|
|
id: 'databaseId',
|
|
title: 'Database ID',
|
|
type: 'short-input',
|
|
placeholder: 'Enter Notion database ID',
|
|
condition: { field: 'operation', value: 'notion_query_database' },
|
|
required: true,
|
|
},
|
|
{
|
|
id: 'filter',
|
|
title: 'Filter',
|
|
type: 'code',
|
|
placeholder: 'Enter filter conditions as JSON (optional)',
|
|
condition: { field: 'operation', value: 'notion_query_database' },
|
|
wandConfig: {
|
|
enabled: true,
|
|
prompt:
|
|
'Generate a Notion database filter object in JSON format based on the user\'s description. Notion filters use properties like "property", "equals", "contains", "checkbox", "date", etc. Example: {"property": "Status", "select": {"equals": "Done"}}. For compound filters use "and" or "or" arrays. Return ONLY valid JSON - no explanations.',
|
|
placeholder:
|
|
'Describe what you want to filter (e.g., "status is done", "created after last week")...',
|
|
generationType: 'json-object',
|
|
},
|
|
},
|
|
{
|
|
id: 'sorts',
|
|
title: 'Sort Criteria',
|
|
type: 'code',
|
|
placeholder: 'Enter sort criteria as JSON array (optional)',
|
|
condition: { field: 'operation', value: 'notion_query_database' },
|
|
wandConfig: {
|
|
enabled: true,
|
|
prompt:
|
|
'Generate a Notion database sort criteria array in JSON format based on the user\'s description. Each sort object has "property" (property name) or "timestamp" ("created_time" or "last_edited_time") and "direction" ("ascending" or "descending"). Example: [{"property": "Name", "direction": "ascending"}]. Return ONLY a valid JSON array - no explanations.',
|
|
placeholder: 'Describe how to sort (e.g., "by name ascending", "newest first")...',
|
|
generationType: 'json-object',
|
|
},
|
|
},
|
|
{
|
|
id: 'pageSize',
|
|
title: 'Page Size',
|
|
type: 'short-input',
|
|
placeholder: 'Number of results (default: 100, max: 100)',
|
|
condition: { field: 'operation', value: 'notion_query_database' },
|
|
},
|
|
// Search Fields
|
|
{
|
|
id: 'query',
|
|
title: 'Search Query',
|
|
type: 'short-input',
|
|
placeholder: 'Enter search terms (leave empty for all pages)',
|
|
condition: { field: 'operation', value: 'notion_search' },
|
|
wandConfig: {
|
|
enabled: true,
|
|
prompt:
|
|
"Generate a search query string for searching a Notion workspace based on the user's description. The query should be concise and use relevant keywords. Return ONLY the search query text - no explanations, no quotes.",
|
|
placeholder: 'Describe what you want to search for...',
|
|
},
|
|
},
|
|
{
|
|
id: 'filterType',
|
|
title: 'Filter Type',
|
|
type: 'dropdown',
|
|
options: [
|
|
{ label: 'All', id: 'all' },
|
|
{ label: 'Pages Only', id: 'page' },
|
|
{ label: 'Databases Only', id: 'database' },
|
|
],
|
|
condition: { field: 'operation', value: 'notion_search' },
|
|
},
|
|
// Create Database Fields
|
|
{
|
|
id: 'parentId',
|
|
title: 'Parent Page ID',
|
|
type: 'short-input',
|
|
placeholder: 'ID of parent page where database will be created',
|
|
condition: { field: 'operation', value: 'notion_create_database' },
|
|
required: true,
|
|
},
|
|
{
|
|
id: 'title',
|
|
title: 'Database Title',
|
|
type: 'short-input',
|
|
placeholder: 'Title for the new database',
|
|
condition: { field: 'operation', value: 'notion_create_database' },
|
|
required: true,
|
|
wandConfig: {
|
|
enabled: true,
|
|
prompt:
|
|
"Generate a concise, descriptive title for a Notion database based on the user's description. The title should clearly indicate what data the database will contain. Return ONLY the title text - no explanations, no quotes.",
|
|
placeholder: 'Describe what the database will track...',
|
|
},
|
|
},
|
|
{
|
|
id: 'properties',
|
|
title: 'Database Properties',
|
|
type: 'code',
|
|
placeholder: 'Enter database properties as JSON object',
|
|
condition: { field: 'operation', value: 'notion_create_database' },
|
|
wandConfig: {
|
|
enabled: true,
|
|
prompt:
|
|
'Generate Notion database properties in JSON format based on the user\'s description. Only provide the json, no escaping required. Properties define the schema of the database. Common types: "title" (required), "rich_text", "number", "select" (with options), "multi_select", "date", "checkbox", "url", "email", "phone_number". Example: {"Name": {"title": {}}, "Status": {"select": {"options": [{"name": "To Do"}, {"name": "Done"}]}}, "Priority": {"number": {}}}. Return ONLY valid JSON - no explanations.',
|
|
placeholder:
|
|
'Describe the columns/properties you want (e.g., "name, status dropdown, due date, priority number")...',
|
|
generationType: 'json-object',
|
|
},
|
|
},
|
|
// Add Database Row Fields
|
|
{
|
|
id: 'databaseId',
|
|
title: 'Database ID',
|
|
type: 'short-input',
|
|
placeholder: 'Enter Notion database ID',
|
|
condition: { field: 'operation', value: 'notion_add_database_row' },
|
|
required: true,
|
|
},
|
|
{
|
|
id: 'properties',
|
|
title: 'Row Properties',
|
|
type: 'code',
|
|
placeholder: 'Enter row properties as JSON object',
|
|
condition: { field: 'operation', value: 'notion_add_database_row' },
|
|
required: true,
|
|
wandConfig: {
|
|
enabled: true,
|
|
prompt:
|
|
'Generate Notion page/row properties in JSON format based on the user\'s description. Properties must match the database schema. Common formats: Title: {"Name": {"title": [{"text": {"content": "Value"}}]}}, Text: {"Description": {"rich_text": [{"text": {"content": "Value"}}]}}, Number: {"Price": {"number": 10}}, Select: {"Status": {"select": {"name": "Done"}}}, Multi-select: {"Tags": {"multi_select": [{"name": "Tag1"}, {"name": "Tag2"}]}}, Date: {"Due": {"date": {"start": "2024-01-01"}}}, Checkbox: {"Done": {"checkbox": true}}, URL: {"Link": {"url": "https://..."}}, Email: {"Contact": {"email": "test@example.com"}}. Return ONLY valid JSON - no explanations.',
|
|
placeholder:
|
|
'Describe the row data (e.g., "name is Task 1, status is Done, priority is High")...',
|
|
generationType: 'json-object',
|
|
},
|
|
},
|
|
],
|
|
tools: {
|
|
access: [
|
|
'notion_read',
|
|
'notion_read_database',
|
|
'notion_write',
|
|
'notion_create_page',
|
|
'notion_query_database',
|
|
'notion_search',
|
|
'notion_create_database',
|
|
],
|
|
config: {
|
|
tool: (params) => {
|
|
switch (params.operation) {
|
|
case 'notion_read':
|
|
return 'notion_read'
|
|
case 'notion_read_database':
|
|
return 'notion_read_database'
|
|
case 'notion_write':
|
|
return 'notion_write'
|
|
case 'notion_create_page':
|
|
return 'notion_create_page'
|
|
case 'notion_query_database':
|
|
return 'notion_query_database'
|
|
case 'notion_search':
|
|
return 'notion_search'
|
|
case 'notion_create_database':
|
|
return 'notion_create_database'
|
|
default:
|
|
return 'notion_read'
|
|
}
|
|
},
|
|
params: (params) => {
|
|
const { oauthCredential, operation, properties, filter, sorts, ...rest } = params
|
|
|
|
// Parse properties from JSON string for create/add operations
|
|
let parsedProperties
|
|
if (
|
|
(operation === 'notion_create_page' ||
|
|
operation === 'notion_create_database' ||
|
|
operation === 'notion_add_database_row') &&
|
|
properties
|
|
) {
|
|
if (typeof properties === 'string') {
|
|
try {
|
|
parsedProperties = JSON.parse(properties)
|
|
} catch (error) {
|
|
throw new Error(
|
|
`Invalid JSON for properties: ${error instanceof Error ? error.message : String(error)}`
|
|
)
|
|
}
|
|
} else {
|
|
parsedProperties = properties
|
|
}
|
|
}
|
|
|
|
// Parse filter for query database operations
|
|
let parsedFilter
|
|
if (operation === 'notion_query_database' && filter) {
|
|
try {
|
|
parsedFilter = JSON.parse(filter)
|
|
} catch (error) {
|
|
throw new Error(
|
|
`Invalid JSON for filter: ${error instanceof Error ? error.message : String(error)}`
|
|
)
|
|
}
|
|
}
|
|
|
|
// Parse sorts for query database operations
|
|
let parsedSorts
|
|
if (operation === 'notion_query_database' && sorts) {
|
|
try {
|
|
parsedSorts = JSON.parse(sorts)
|
|
} catch (error) {
|
|
throw new Error(
|
|
`Invalid JSON for sorts: ${error instanceof Error ? error.message : String(error)}`
|
|
)
|
|
}
|
|
}
|
|
|
|
return {
|
|
...rest,
|
|
oauthCredential,
|
|
...(parsedProperties ? { properties: parsedProperties } : {}),
|
|
...(parsedFilter ? { filter: JSON.stringify(parsedFilter) } : {}),
|
|
...(parsedSorts ? { sorts: JSON.stringify(parsedSorts) } : {}),
|
|
}
|
|
},
|
|
},
|
|
},
|
|
inputs: {
|
|
operation: { type: 'string', description: 'Operation to perform' },
|
|
oauthCredential: { type: 'string', description: 'Notion access token' },
|
|
pageId: { type: 'string', description: 'Page identifier' },
|
|
content: { type: 'string', description: 'Page content' },
|
|
// Create page inputs
|
|
parentId: { type: 'string', description: 'Parent page identifier' },
|
|
title: { type: 'string', description: 'Page title' },
|
|
// Query database inputs
|
|
databaseId: { type: 'string', description: 'Database identifier' },
|
|
filter: { type: 'string', description: 'Filter criteria' },
|
|
sorts: { type: 'string', description: 'Sort criteria' },
|
|
pageSize: { type: 'number', description: 'Page size limit' },
|
|
// Search inputs
|
|
query: { type: 'string', description: 'Search query' },
|
|
filterType: { type: 'string', description: 'Filter type' },
|
|
},
|
|
outputs: {
|
|
// Common outputs across all Notion operations
|
|
content: {
|
|
type: 'string',
|
|
description: 'Page content, search results, or confirmation messages',
|
|
},
|
|
|
|
// Metadata object containing operation-specific information
|
|
metadata: {
|
|
type: 'json',
|
|
description:
|
|
'Metadata containing operation-specific details including page/database info, results, and pagination data',
|
|
},
|
|
},
|
|
}
|
|
|
|
// V2 Block with API-aligned outputs
|
|
export const NotionV2Block: BlockConfig<any> = {
|
|
type: 'notion_v2',
|
|
name: 'Notion',
|
|
description: 'Manage Notion pages',
|
|
authMode: AuthMode.OAuth,
|
|
longDescription:
|
|
'Integrate with Notion into the workflow. Can read page, read database, create page, create database, append content, query database, and search workspace.',
|
|
docsLink: 'https://docs.sim.ai/tools/notion',
|
|
category: 'tools',
|
|
bgColor: '#181C1E',
|
|
icon: NotionIcon,
|
|
hideFromToolbar: false,
|
|
subBlocks: NotionBlock.subBlocks,
|
|
tools: {
|
|
access: [
|
|
'notion_read_v2',
|
|
'notion_read_database_v2',
|
|
'notion_write_v2',
|
|
'notion_create_page_v2',
|
|
'notion_update_page_v2',
|
|
'notion_query_database_v2',
|
|
'notion_search_v2',
|
|
'notion_create_database_v2',
|
|
'notion_add_database_row_v2',
|
|
],
|
|
config: {
|
|
tool: createVersionedToolSelector({
|
|
baseToolSelector: (params) => params.operation || 'notion_read',
|
|
suffix: '_v2',
|
|
fallbackToolId: 'notion_read_v2',
|
|
}),
|
|
params: NotionBlock.tools?.config?.params,
|
|
},
|
|
},
|
|
inputs: NotionBlock.inputs,
|
|
outputs: {
|
|
// Read page outputs
|
|
content: {
|
|
type: 'string',
|
|
description: 'Page content in markdown format',
|
|
condition: { field: 'operation', value: 'notion_read' },
|
|
},
|
|
title: {
|
|
type: 'string',
|
|
description: 'Page or database title',
|
|
},
|
|
url: {
|
|
type: 'string',
|
|
description: 'Notion URL',
|
|
},
|
|
id: {
|
|
type: 'string',
|
|
description: 'Page or database ID',
|
|
condition: {
|
|
field: 'operation',
|
|
value: [
|
|
'notion_create_page',
|
|
'notion_create_database',
|
|
'notion_add_database_row',
|
|
'notion_read_database',
|
|
'notion_update_page',
|
|
],
|
|
},
|
|
},
|
|
created_time: {
|
|
type: 'string',
|
|
description: 'Creation timestamp',
|
|
},
|
|
last_edited_time: {
|
|
type: 'string',
|
|
description: 'Last edit timestamp',
|
|
},
|
|
// Database query/search outputs
|
|
results: {
|
|
type: 'array',
|
|
description: 'Array of results from query or search',
|
|
condition: { field: 'operation', value: ['notion_query_database', 'notion_search'] },
|
|
},
|
|
has_more: {
|
|
type: 'boolean',
|
|
description: 'Whether more results are available',
|
|
condition: { field: 'operation', value: ['notion_query_database', 'notion_search'] },
|
|
},
|
|
next_cursor: {
|
|
type: 'string',
|
|
description: 'Cursor for pagination',
|
|
condition: { field: 'operation', value: ['notion_query_database', 'notion_search'] },
|
|
},
|
|
total_results: {
|
|
type: 'number',
|
|
description: 'Number of results returned',
|
|
condition: { field: 'operation', value: ['notion_query_database', 'notion_search'] },
|
|
},
|
|
// Database schema
|
|
properties: {
|
|
type: 'json',
|
|
description: 'Database properties schema',
|
|
condition: { field: 'operation', value: ['notion_read_database', 'notion_create_database'] },
|
|
},
|
|
// Write output
|
|
appended: {
|
|
type: 'boolean',
|
|
description: 'Whether content was successfully appended',
|
|
condition: { field: 'operation', value: 'notion_write' },
|
|
},
|
|
},
|
|
}
|