Added notion tool/block

This commit is contained in:
Waleed Latif
2025-02-10 00:58:35 -08:00
parent da1d2adf5d
commit 46a4a305e3
5 changed files with 242 additions and 10 deletions

69
blocks/blocks/notion.ts Normal file
View File

@@ -0,0 +1,69 @@
import { NotionIcon } from '@/components/icons'
import { NotionResponse } from '@/tools/notion/read'
import { BlockConfig } from '../types'
export const NotionBlock: BlockConfig<NotionResponse> = {
type: 'notion_reader',
toolbar: {
title: 'Notion',
description: 'Read and write to Notion pages and databases',
bgColor: '#000000',
icon: NotionIcon,
category: 'tools',
},
tools: {
access: ['notion_read', 'notion_write'],
config: {
tool: (params) => {
return params.operation === 'write' ? 'notion_write' : 'notion_read'
},
},
},
workflow: {
inputs: {
pageId: { type: 'string', required: true },
operation: { type: 'string', required: true },
content: { type: 'string', required: false },
apiKey: { type: 'string', required: true },
},
outputs: {
response: {
type: {
content: 'string',
metadata: 'any',
},
},
},
subBlocks: [
{
id: 'operation',
title: 'Operation',
type: 'dropdown',
layout: 'full',
options: ['read', 'write'],
},
{
id: 'pageId',
title: 'Page ID',
type: 'short-input',
layout: 'full',
placeholder: 'Enter Notion page ID',
},
{
id: 'content',
title: 'Content',
type: 'long-input',
layout: 'full',
placeholder: 'Enter content to write (for write operation)',
},
{
id: 'apiKey',
title: 'API Key',
type: 'short-input',
layout: 'full',
placeholder: 'Enter your Notion API key',
password: true,
},
],
},
}

View File

@@ -7,6 +7,7 @@ import { FirecrawlScrapeBlock } from './blocks/firecrawl'
import { FunctionBlock } from './blocks/function'
import { GitHubBlock } from './blocks/github'
import { JinaBlock } from './blocks/jina'
import { NotionBlock } from './blocks/notion'
import { RouterBlock } from './blocks/router'
import { SerperBlock } from './blocks/serper'
import { SlackMessageBlock } from './blocks/slack'
@@ -32,6 +33,7 @@ export {
TavilyExtractBlock,
RouterBlock,
YouTubeSearchBlock,
NotionBlock,
}
// Registry of all block configurations
@@ -51,6 +53,7 @@ const blocks: Record<string, BlockConfig> = {
tavily_search: TavilySearchBlock,
tavily_extract: TavilyExtractBlock,
youtube_search: YouTubeSearchBlock,
notion_reader: NotionBlock,
}
// Build a reverse mapping of tools to block types

View File

@@ -9,6 +9,8 @@ import { chatTool as googleChat } from './google/chat'
import { requestTool as httpRequest } from './http/request'
import { contactsTool as hubspotContacts } from './hubspot/contacts'
import { readUrlTool } from './jina/reader'
import { notionReadTool } from './notion/read'
import { notionWriteTool } from './notion/write'
import { chatTool as openAIChat } from './openai/chat'
import { opportunitiesTool as salesforceOpportunities } from './salesforce/opportunities'
import { searchTool as serperSearch } from './serper/search'
@@ -21,35 +23,27 @@ import { youtubeSearchTool } from './youtube/search'
// Registry of all available tools
export const tools: Record<string, ToolConfig> = {
// AI Models
openai_chat: openAIChat,
anthropic_chat: anthropicChat,
google_chat: googleChat,
xai_chat: xaiChat,
deepseek_chat: deepseekChat,
deepseek_reasoner: deepseekReasoner,
// HTTP
http_request: httpRequest,
// CRM Tools
hubspot_contacts: hubspotContacts,
salesforce_opportunities: salesforceOpportunities,
// Function Tools
function_execute: functionExecute,
// CrewAI Tools
crewai_vision: crewAIVision,
// Firecrawl Tools
firecrawl_scrape: scrapeTool,
// Jina Tools
jina_readurl: readUrlTool,
// Slack Tools
slack_message: slackMessageTool,
// GitHub Tools
github_repoinfo: repoInfoTool,
// Search Tools
serper_search: serperSearch,
tavily_search: tavilySearch,
tavily_extract: tavilyExtract,
youtube_search: youtubeSearchTool,
notion_read: notionReadTool,
notion_write: notionWriteTool,
}
// Get a tool by its ID

85
tools/notion/read.ts Normal file
View File

@@ -0,0 +1,85 @@
import { ToolConfig, ToolResponse } from '../types'
export interface NotionReadParams {
pageId: string
apiKey: string
}
export interface NotionResponse extends ToolResponse {
output: {
content: string
metadata?: {
title?: string
lastEditedTime?: string
createdTime?: string
url?: string
}
}
}
export const notionReadTool: ToolConfig<NotionReadParams, NotionResponse> = {
id: 'notion_read',
name: 'Notion Reader',
description: 'Read content from a Notion page',
version: '1.0.0',
params: {
pageId: {
type: 'string',
required: true,
requiredForToolCall: true,
description: 'The ID of the Notion page to read',
},
apiKey: {
type: 'string',
required: true,
requiredForToolCall: true,
description: 'Your Notion API key',
},
},
request: {
url: (params: NotionReadParams) => {
// Format page ID with hyphens if needed
const formattedId = params.pageId.replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/, '$1-$2-$3-$4-$5')
return `https://api.notion.com/v1/blocks/${formattedId}/children?page_size=100`
},
method: 'GET',
headers: (params: NotionReadParams) => ({
Authorization: `Bearer ${params.apiKey}`,
'Notion-Version': '2022-06-28',
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
// Extract text content from blocks
const blocks = data.results || []
const content = blocks
.map((block: any) => {
if (block.type === 'paragraph') {
return block.paragraph.rich_text.map((text: any) => text.plain_text).join('')
}
return ''
})
.filter(Boolean)
.join('\n\n')
return {
success: response.ok,
output: {
content: content,
metadata: {
lastEditedTime: blocks[0]?.last_edited_time,
createdTime: blocks[0]?.created_time,
},
},
}
},
transformError: (error) => {
return error instanceof Error ? error.message : 'Failed to read Notion page'
},
}

81
tools/notion/write.ts Normal file
View File

@@ -0,0 +1,81 @@
import { ToolConfig } from '../types'
import { NotionResponse } from './read'
export interface NotionWriteParams {
pageId: string
content: string
apiKey: string
}
export const notionWriteTool: ToolConfig<NotionWriteParams, NotionResponse> = {
id: 'notion_write',
name: 'Notion Writer',
description: 'Write content to a Notion page',
version: '1.0.0',
params: {
pageId: {
type: 'string',
required: true,
requiredForToolCall: true,
description: 'The ID of the Notion page to write to',
},
content: {
type: 'string',
required: true,
description: 'The content to write to the page',
},
apiKey: {
type: 'string',
required: true,
requiredForToolCall: true,
description: 'Your Notion API key',
},
},
request: {
url: (params: NotionWriteParams) => {
// Format page ID with hyphens if needed
const formattedId = params.pageId.replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/, '$1-$2-$3-$4-$5')
return `https://api.notion.com/v1/blocks/${formattedId}/children`
},
method: 'PATCH',
headers: (params: NotionWriteParams) => ({
Authorization: `Bearer ${params.apiKey}`,
'Notion-Version': '2022-06-28',
'Content-Type': 'application/json',
}),
body: (params: NotionWriteParams) => ({
children: [
{
object: 'block',
type: 'paragraph',
paragraph: {
rich_text: [
{
type: 'text',
text: {
content: params.content,
},
},
],
},
},
],
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: response.ok,
output: {
content: 'Successfully appended content to Notion page',
},
}
},
transformError: (error) => {
return error instanceof Error ? error.message : 'Failed to write to Notion page'
},
}