kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: add @agentic/notion
rodzic
72c77fe155
commit
cb5be23e19
|
@ -73,6 +73,7 @@
|
|||
"tools/leadmagic",
|
||||
"tools/midjourney",
|
||||
"tools/mcp",
|
||||
"tools/notion",
|
||||
"tools/novu",
|
||||
"tools/people-data-labs",
|
||||
"tools/perigon",
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
title: Notion
|
||||
description: Notion API client.
|
||||
---
|
||||
|
||||
The [Notion API](https://developers.notion.com/docs) provides a router for accessing pages, databases, and content.
|
||||
|
||||
- package: `@agentic/notion`
|
||||
- exports: `class NotionClient`, `namespace notion`
|
||||
- env vars: `NOTION_API_KEY`
|
||||
- [source](https://github.com/transitive-bullshit/agentic/blob/main/packages/notion/src/notion-client.ts)
|
||||
- [notion api docs](https://developers.notion.com/docs)
|
||||
|
||||
## Install
|
||||
|
||||
<CodeGroup>
|
||||
```bash npm
|
||||
npm install @agentic/notion
|
||||
```
|
||||
|
||||
```bash yarn
|
||||
yarn add @agentic/notion
|
||||
```
|
||||
|
||||
```bash pnpm
|
||||
pnpm add @agentic/notion
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { NotionClient } from '@agentic/notion'
|
||||
|
||||
const notion = new NotionClient()
|
||||
const authenticatedUser = await notion.getSelf()
|
||||
```
|
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"name": "@agentic/notion",
|
||||
"version": "0.1.0",
|
||||
"description": "Agentic SDK for Notion.",
|
||||
"author": "Travis Fischer <travis@transitivebullsh.it>",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/transitive-bullshit/agentic.git",
|
||||
"directory": "packages/notion"
|
||||
},
|
||||
"type": "module",
|
||||
"source": "./src/index.ts",
|
||||
"types": "./dist/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js",
|
||||
"default": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsup",
|
||||
"dev": "tsup --watch",
|
||||
"clean": "del dist",
|
||||
"test": "run-s test:*",
|
||||
"test:lint": "eslint .",
|
||||
"test:typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agentic/core": "workspace:*",
|
||||
"ky": "catalog:"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"zod": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@agentic/tsconfig": "workspace:*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<p align="center">
|
||||
<a href="https://agentic.so">
|
||||
<img alt="Agentic" src="https://raw.githubusercontent.com/transitive-bullshit/agentic/main/docs/media/agentic-header.jpg" width="308">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<em>AI agent stdlib that works with any LLM and TypeScript AI SDK.</em>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/transitive-bullshit/agentic/actions/workflows/main.yml"><img alt="Build Status" src="https://github.com/transitive-bullshit/agentic/actions/workflows/main.yml/badge.svg" /></a>
|
||||
<a href="https://www.npmjs.com/package/@agentic/stdlib"><img alt="NPM" src="https://img.shields.io/npm/v/@agentic/stdlib.svg" /></a>
|
||||
<a href="https://github.com/transitive-bullshit/agentic/blob/main/license"><img alt="MIT License" src="https://img.shields.io/badge/license-MIT-blue" /></a>
|
||||
<a href="https://prettier.io"><img alt="Prettier Code Formatting" src="https://img.shields.io/badge/code_style-prettier-brightgreen.svg" /></a>
|
||||
</p>
|
||||
|
||||
# Agentic
|
||||
|
||||
**See the [github repo](https://github.com/transitive-bullshit/agentic) or [docs](https://agentic.so) for more info.**
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Travis Fischer](https://x.com/transitive_bs)
|
|
@ -0,0 +1,2 @@
|
|||
export * from './notion'
|
||||
export * from './notion-client'
|
|
@ -0,0 +1,483 @@
|
|||
import {
|
||||
aiFunction,
|
||||
AIFunctionsProvider,
|
||||
assert,
|
||||
getEnv,
|
||||
pick,
|
||||
sanitizeSearchParams
|
||||
} from '@agentic/core'
|
||||
import defaultKy, { type KyInstance } from 'ky'
|
||||
|
||||
import { notion } from './notion'
|
||||
|
||||
/**
|
||||
* Agentic Notion client.
|
||||
*/
|
||||
export class NotionClient extends AIFunctionsProvider {
|
||||
protected readonly ky: KyInstance
|
||||
protected readonly apiKey: string
|
||||
protected readonly apiBaseUrl: string
|
||||
|
||||
constructor({
|
||||
apiKey = getEnv('NOTION_API_KEY'),
|
||||
apiBaseUrl = notion.apiBaseUrl,
|
||||
ky = defaultKy
|
||||
}: {
|
||||
apiKey?: string
|
||||
apiBaseUrl?: string
|
||||
ky?: KyInstance
|
||||
} = {}) {
|
||||
assert(
|
||||
apiKey,
|
||||
'NotionClient missing required "apiKey" (defaults to "NOTION_API_KEY")'
|
||||
)
|
||||
super()
|
||||
|
||||
this.apiKey = apiKey
|
||||
this.apiBaseUrl = apiBaseUrl
|
||||
|
||||
this.ky = ky.extend({
|
||||
prefixUrl: apiBaseUrl,
|
||||
headers: {
|
||||
Authorization: `Bearer ${apiKey}`
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current user.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_get_self',
|
||||
description: `Get current user.`,
|
||||
inputSchema: notion.GetSelfParamsSchema
|
||||
})
|
||||
async getSelf(
|
||||
_params: notion.GetSelfParams
|
||||
): Promise<notion.GetSelfResponse> {
|
||||
return this.ky.get('/users/me').json<notion.GetSelfResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_get_user',
|
||||
description: `Get user.`,
|
||||
inputSchema: notion.GetUserParamsSchema
|
||||
})
|
||||
async getUser(params: notion.GetUserParams): Promise<notion.GetUserResponse> {
|
||||
return this.ky
|
||||
.get(`/users/${params.user_id}`)
|
||||
.json<notion.GetUserResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* List users.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_list_users',
|
||||
description: `List users.`,
|
||||
inputSchema: notion.ListUsersParamsSchema
|
||||
})
|
||||
async listUsers(
|
||||
params: notion.ListUsersParams
|
||||
): Promise<notion.ListUsersResponse> {
|
||||
return this.ky
|
||||
.get('/users', {
|
||||
searchParams: sanitizeSearchParams(
|
||||
pick(params, 'start_cursor', 'page_size')
|
||||
)
|
||||
})
|
||||
.json<notion.ListUsersResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Create page.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_create_page',
|
||||
description: `Create page.`,
|
||||
inputSchema: notion.CreatePageParamsSchema
|
||||
})
|
||||
async createPage(
|
||||
params: notion.CreatePageParams
|
||||
): Promise<notion.CreatePageResponse> {
|
||||
return this.ky
|
||||
.post('/pages', {
|
||||
json: pick(params, 'parent', 'properties')
|
||||
})
|
||||
.json<notion.CreatePageResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get page.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_get_page',
|
||||
description: `Get page.`,
|
||||
inputSchema: notion.GetPageParamsSchema
|
||||
})
|
||||
async getPage(params: notion.GetPageParams): Promise<notion.GetPageResponse> {
|
||||
return this.ky
|
||||
.get(`/pages/${params.page_id}`, {
|
||||
searchParams: sanitizeSearchParams(pick(params, 'filter_properties'))
|
||||
})
|
||||
.json<notion.GetPageResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Update page.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_update_page',
|
||||
description: `Update page.`,
|
||||
inputSchema: notion.UpdatePageParamsSchema
|
||||
})
|
||||
async updatePage(
|
||||
params: notion.UpdatePageParams
|
||||
): Promise<notion.UpdatePageResponse> {
|
||||
return this.ky
|
||||
.patch(`/pages/${params.page_id}`, {
|
||||
json: pick(params, 'properties', 'archived')
|
||||
})
|
||||
.json<notion.UpdatePageResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get page property.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_get_page_property',
|
||||
description: `Get page property.`,
|
||||
inputSchema: notion.GetPagePropertyParamsSchema
|
||||
})
|
||||
async getPageProperty(
|
||||
params: notion.GetPagePropertyParams
|
||||
): Promise<notion.GetPagePropertyResponse> {
|
||||
return this.ky
|
||||
.get(`/pages/${params.page_id}/properties/${params.property_id}`, {
|
||||
searchParams: sanitizeSearchParams(
|
||||
pick(params, 'start_cursor', 'page_size')
|
||||
)
|
||||
})
|
||||
.json<notion.GetPagePropertyResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get block.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_get_block',
|
||||
description: `Get block.`,
|
||||
inputSchema: notion.GetBlockParamsSchema
|
||||
})
|
||||
async getBlock(
|
||||
params: notion.GetBlockParams
|
||||
): Promise<notion.GetBlockResponse> {
|
||||
return this.ky
|
||||
.get(`/blocks/${params.block_id}`)
|
||||
.json<notion.GetBlockResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete block.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_delete_block',
|
||||
description: `Delete block.`,
|
||||
inputSchema: notion.DeleteBlockParamsSchema
|
||||
})
|
||||
async deleteBlock(
|
||||
params: notion.DeleteBlockParams
|
||||
): Promise<notion.DeleteBlockResponse> {
|
||||
return this.ky
|
||||
.delete(`/blocks/${params.block_id}`)
|
||||
.json<notion.DeleteBlockResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Update block.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_update_block',
|
||||
description: `Update block.`,
|
||||
inputSchema: notion.UpdateBlockParamsSchema
|
||||
})
|
||||
async updateBlock(
|
||||
params: notion.UpdateBlockParams
|
||||
): Promise<notion.UpdateBlockResponse> {
|
||||
return this.ky
|
||||
.patch(`/blocks/${params.block_id}`, {
|
||||
json: pick(
|
||||
params,
|
||||
'paragraph',
|
||||
'heading_1',
|
||||
'heading_2',
|
||||
'heading_3',
|
||||
'bulleted_list_item',
|
||||
'numbered_list_item',
|
||||
'quote',
|
||||
'to_do',
|
||||
'toggle',
|
||||
'code',
|
||||
'embed',
|
||||
'image',
|
||||
'video',
|
||||
'file',
|
||||
'pdf',
|
||||
'bookmark',
|
||||
'equation',
|
||||
'divider',
|
||||
'table_of_contents',
|
||||
'breadcrumb',
|
||||
'column_list',
|
||||
'column',
|
||||
'link_to_page',
|
||||
'table_row',
|
||||
'archived'
|
||||
)
|
||||
})
|
||||
.json<notion.UpdateBlockResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* List block children.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_list_block_children',
|
||||
description: `List block children.`,
|
||||
inputSchema: notion.ListBlockChildrenParamsSchema
|
||||
})
|
||||
async listBlockChildren(
|
||||
params: notion.ListBlockChildrenParams
|
||||
): Promise<notion.ListBlockChildrenResponse> {
|
||||
return this.ky
|
||||
.get(`/blocks/${params.block_id}/children`, {
|
||||
searchParams: sanitizeSearchParams(
|
||||
pick(params, 'start_cursor', 'page_size')
|
||||
)
|
||||
})
|
||||
.json<notion.ListBlockChildrenResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Append block children.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_append_block_children',
|
||||
description: `Append block children.`,
|
||||
inputSchema: notion.AppendBlockChildrenParamsSchema
|
||||
})
|
||||
async appendBlockChildren(
|
||||
params: notion.AppendBlockChildrenParams
|
||||
): Promise<notion.AppendBlockChildrenResponse> {
|
||||
return this.ky
|
||||
.patch(`/blocks/${params.block_id}/children`, {
|
||||
json: pick(params, 'children')
|
||||
})
|
||||
.json<notion.AppendBlockChildrenResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get database.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_get_database',
|
||||
description: `Get database.`,
|
||||
inputSchema: notion.GetDatabaseParamsSchema
|
||||
})
|
||||
async getDatabase(
|
||||
params: notion.GetDatabaseParams
|
||||
): Promise<notion.GetDatabaseResponse> {
|
||||
return this.ky
|
||||
.get(`/databases/${params.database_id}`)
|
||||
.json<notion.GetDatabaseResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Update database.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_update_database',
|
||||
description: `Update database.`,
|
||||
inputSchema: notion.UpdateDatabaseParamsSchema
|
||||
})
|
||||
async updateDatabase(
|
||||
params: notion.UpdateDatabaseParams
|
||||
): Promise<notion.UpdateDatabaseResponse> {
|
||||
return this.ky
|
||||
.patch(`/databases/${params.database_id}`, {
|
||||
json: pick(
|
||||
params,
|
||||
'title',
|
||||
'description',
|
||||
'icon',
|
||||
'cover',
|
||||
'properties',
|
||||
'is_inline',
|
||||
'archived'
|
||||
)
|
||||
})
|
||||
.json<notion.UpdateDatabaseResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Query database.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_query_database',
|
||||
description: `Query database.`,
|
||||
inputSchema: notion.QueryDatabaseParamsSchema
|
||||
})
|
||||
async queryDatabase(
|
||||
params: notion.QueryDatabaseParams
|
||||
): Promise<notion.QueryDatabaseResponse> {
|
||||
return this.ky
|
||||
.post(`/databases/${params.database_id}/query`, {
|
||||
searchParams: sanitizeSearchParams(pick(params, 'filter_properties')),
|
||||
json: pick(
|
||||
params,
|
||||
'sorts',
|
||||
'filter',
|
||||
'start_cursor',
|
||||
'page_size',
|
||||
'archived'
|
||||
)
|
||||
})
|
||||
.json<notion.QueryDatabaseResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* List databases.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_list_databases',
|
||||
description: `List databases.`,
|
||||
inputSchema: notion.ListDatabasesParamsSchema
|
||||
})
|
||||
async listDatabases(
|
||||
params: notion.ListDatabasesParams
|
||||
): Promise<notion.ListDatabasesResponse> {
|
||||
return this.ky
|
||||
.get('/databases', {
|
||||
searchParams: sanitizeSearchParams(
|
||||
pick(params, 'start_cursor', 'page_size')
|
||||
)
|
||||
})
|
||||
.json<notion.ListDatabasesResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Create database.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_create_database',
|
||||
description: `Create database.`,
|
||||
inputSchema: notion.CreateDatabaseParamsSchema
|
||||
})
|
||||
async createDatabase(
|
||||
params: notion.CreateDatabaseParams
|
||||
): Promise<notion.CreateDatabaseResponse> {
|
||||
return this.ky
|
||||
.post('/databases', {
|
||||
json: pick(
|
||||
params,
|
||||
'parent',
|
||||
'properties',
|
||||
'icon',
|
||||
'cover',
|
||||
'title',
|
||||
'description',
|
||||
'is_inline'
|
||||
)
|
||||
})
|
||||
.json<notion.CreateDatabaseResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Search.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_search',
|
||||
description: `Search.`,
|
||||
inputSchema: notion.SearchParamsSchema
|
||||
})
|
||||
async search(params: notion.SearchParams): Promise<notion.SearchResponse> {
|
||||
return this.ky
|
||||
.post('/search', {
|
||||
json: pick(
|
||||
params,
|
||||
'query',
|
||||
'sort',
|
||||
'filter',
|
||||
'start_cursor',
|
||||
'page_size'
|
||||
)
|
||||
})
|
||||
.json<notion.SearchResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* List comments.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_list_comments',
|
||||
description: `List comments.`,
|
||||
inputSchema: notion.ListCommentsParamsSchema
|
||||
})
|
||||
async listComments(
|
||||
params: notion.ListCommentsParams
|
||||
): Promise<notion.ListCommentsResponse> {
|
||||
return this.ky
|
||||
.get('/comments', {
|
||||
searchParams: sanitizeSearchParams(
|
||||
pick(params, 'block_id', 'start_cursor', 'page_size')
|
||||
)
|
||||
})
|
||||
.json<notion.ListCommentsResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Create comment.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_create_comment',
|
||||
description: `Create comment.`,
|
||||
// TODO: Improve handling of union params
|
||||
inputSchema: notion.CreateCommentParamsSchema as any
|
||||
})
|
||||
async createComment(
|
||||
params: notion.CreateCommentParams
|
||||
): Promise<notion.CreateCommentResponse> {
|
||||
return this.ky
|
||||
.post('/comments', {
|
||||
json: params
|
||||
})
|
||||
.json<notion.CreateCommentResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* OAuth token.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'notion_oauth_token',
|
||||
description: `OAuth token.`,
|
||||
inputSchema: notion.OauthTokenParamsSchema
|
||||
})
|
||||
async oauthToken(
|
||||
params: notion.OauthTokenParams
|
||||
): Promise<notion.OauthTokenResponse> {
|
||||
return this.ky
|
||||
.post('/oauth/token', {
|
||||
json: pick(
|
||||
params,
|
||||
'grant_type',
|
||||
'code',
|
||||
'redirect_uri',
|
||||
'external_account'
|
||||
)
|
||||
})
|
||||
.json<notion.OauthTokenResponse>()
|
||||
}
|
||||
}
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"extends": "@agentic/tsconfig/base.json",
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
|
@ -198,6 +198,7 @@ Full docs are available at [agentic.so](https://agentic.so).
|
|||
| [LeadMagic](https://leadmagic.io) | `@agentic/leadmagic` | [docs](https://agentic.so/tools/leadmagic) | B2B person, company, and email enrichment API. |
|
||||
| [Midjourney](https://www.imagineapi.dev) | `@agentic/midjourney` | [docs](https://agentic.so/tools/midjourney) | Unofficial Midjourney client for generative images. |
|
||||
| [McpTools](https://modelcontextprotocol.io) | `@agentic/mcp` | [docs](https://agentic.so/tools/mcp) | Model Context Protocol (MCP) client, supporting any MCP server. Use [createMcpTools](https://agentic.so/tools/mcp) to spawn or connect to an MCP server. |
|
||||
| [Notion](https://developers.notion.com/docs) | `@agentic/notion` | [docs](https://agentic.so/tools/notion) | Official Notion API for accessing pages, databases, and content. |
|
||||
| [Novu](https://novu.co) | `@agentic/novu` | [docs](https://agentic.so/tools/novu) | Sending notifications (email, SMS, in-app, push, etc). |
|
||||
| [People Data Labs](https://www.peopledatalabs.com) | `@agentic/people-data-labs` | [docs](https://agentic.so/tools/people-data-labs) | People & company data (WIP). |
|
||||
| [Perigon](https://www.goperigon.com/products/news-api) | `@agentic/perigon` | [docs](https://agentic.so/tools/perigon) | Real-time news API and web content data from 140,000+ sources. Structured and enriched by AI, primed for LLMs. |
|
||||
|
|
Ładowanie…
Reference in New Issue