Skip to content
This repository was archived by the owner on Aug 22, 2025. It is now read-only.

Commit e84f7f4

Browse files
author
Michael Liebmann
committed
Removed openAI, added instructions, updated readme
1 parent 78e1038 commit e84f7f4

File tree

4 files changed

+37
-112
lines changed

4 files changed

+37
-112
lines changed

.env.example

Lines changed: 0 additions & 4 deletions
This file was deleted.

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,8 @@
22
/dist
33
.env
44
.vercel
5+
.cursorrules
6+
# Ignore all .DS_Store files
7+
.DS_Store
8+
**/.DS_Store
9+

README.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
# Notion
22

3-
This plugin enables interaction with Notion-based knowledge repositories,
4-
allowing users to query and retrieve answers from both public and private Notion pages.
5-
The plugin integrates with OpenAI to provide high-certainty answers based on the content
6-
available in Notion and suggests follow-ups in case of missing content.
3+
Connery plugin for retrieving content from Notion pages.
4+
5+
The Plugin currently contains only one action: `Get Notion Page Content`.
6+
7+
- Allows you to chat with the content of a Notion page. Can be used for FAQ, Knowledge Base, etc.
8+
- The action extracts all content elements including text, media, and toggles, and returns the page content as a single string. It does not extract content form inline DBs.
9+
- Allows you to provide additional instructions for the Connery assistant on how to handle the content.
10+
- This can be useful if the table contains additional information that should not be used for answering the question.
11+
- It can also be used to provide more context or output formatting instructions.
712

813
## Repository structure
914

src/actions/askNotionPage.ts

Lines changed: 23 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
import { ActionDefinition, ActionContext, OutputObject } from 'connery';
22
import { Client, iteratePaginatedAPI, isFullBlock } from '@notionhq/client'; // Import Client and types from Notion
3-
import OpenAI from 'openai';
43

54
const actionDefinition: ActionDefinition = {
65
key: 'askNotionPage',
7-
name: 'Ask Notion Page',
6+
name: 'Get Notion Page Content',
87
description:
9-
'This action enables users to ask questions and receive answers from a knowledge base hosted on a private Notion page. The action accesses the Notion page via its URL using the Notion API and an API key. Users’ questions are processed by OpenAI, which generates answers based on the content retrieved from the page. The action supports all content elements, including toggles.',
8+
'This action retrieves the content of a Notion page using its URL and the Notion API. It can optionally include instructions before the page content. The action required the Notion page URL and Notion API key connected to this URL. It fetches all content elements including text, media, and toggles, and returns the page content as a single string. It does not extract content form inline DBs.',
109
type: 'read',
1110
inputParameters: [
1211
{
1312
key: 'notionPageUrl',
1413
name: 'Notion Page URL',
15-
description: 'The URL of the private Notion page to fetch knowledge content from.',
14+
description: 'The URL of the private Notion page to fetch content from.',
1615
type: 'string',
1716
validation: {
1817
required: true,
@@ -28,30 +27,12 @@ const actionDefinition: ActionDefinition = {
2827
},
2928
},
3029
{
31-
key: 'openaiApiKey',
32-
name: 'OpenAI API Key',
33-
description: 'API key to authenticate with OpenAI',
30+
key: 'instructions',
31+
name: 'Instructions',
32+
description: 'Optional instructions for content processing.',
3433
type: 'string',
3534
validation: {
36-
required: true,
37-
},
38-
},
39-
{
40-
key: 'openaiModel',
41-
name: 'OpenAI Model',
42-
description: 'The model to use for generating the answer (e.g. gpt-4-turbo, gpt-4o-mini, etc.).',
43-
type: 'string',
44-
validation: {
45-
required: true,
46-
},
47-
},
48-
{
49-
key: 'question',
50-
name: 'User Question',
51-
description: 'The question asked by the user about the particular knowledge base.',
52-
type: 'string',
53-
validation: {
54-
required: true,
35+
required: false,
5536
},
5637
},
5738
],
@@ -60,8 +41,8 @@ const actionDefinition: ActionDefinition = {
6041
},
6142
outputParameters: [
6243
{
63-
key: 'textResponse',
64-
name: 'Text response',
44+
key: 'notionContent',
45+
name: 'Notion Content',
6546
type: 'string',
6647
validation: {
6748
required: true,
@@ -93,73 +74,23 @@ export async function handler({ input }: ActionContext): Promise<OutputObject> {
9374
);
9475
}
9576

96-
// Ask OpenAI for an answer
97-
const answer = await askOpenAI(input.openaiApiKey, input.openaiModel, pageContent, input.question);
77+
// Prepare the output based on whether instructions are provided
78+
let output: string;
79+
if (input.instructions) {
80+
output = `Follow these instructions: ${input.instructions}\nContent: ${pageContent}`;
81+
} else {
82+
output = pageContent;
83+
}
9884

99-
// Return the model's answer directly
100-
return { textResponse: answer };
85+
// Return the formatted output
86+
return { notionContent: output };
10187
} catch (error: any) {
10288
console.error('An error occurred:', (error as Error).message);
10389
throw new Error(`Error occurred: ${(error as Error).message}`);
10490
}
10591
}
10692

107-
async function askOpenAI(
108-
openaiApiKey: string,
109-
openaiModel: string,
110-
pageContent: string,
111-
question: string,
112-
): Promise<string> {
113-
// Initialize OpenAI with the provided API key
114-
const openai = new OpenAI({ apiKey: openaiApiKey });
115-
116-
// Create the system message with instructions for the model
117-
const systemMessage = `You are an FAQ expert. When asked a question or given a request related to a specific topic, you provide an accurate and concise answer based strictly on the content provided.
118-
You respond in the same language as the user’s input and adjust your answer to fit the context of the request, whether it’s a direct question or an indirect inquiry.
119-
You never guess or paraphrase — only answer if the explicit content for that request is available.
120-
If there are any disclaimers or indications in the content that it should not be shared with clients or is a work in progress, include that information only if it is explicitly mentioned.
121-
Here is the content you should use to generate your answer:
122-
${pageContent}
123-
`;
124-
125-
// Set the user's question separately
126-
const userQuestion = `Based on this content, please respond to the following request or question with high confidence:
127-
${question}”.
128-
If you are not confident that the content fully addresses the request, respond with:
129-
‘I don’t have enough information to answer your question.’
130-
`;
131-
132-
// Request completion from OpenAI using the specified model
133-
const response = await openai.chat.completions.create({
134-
model: openaiModel,
135-
messages: [
136-
{ role: 'system', content: systemMessage },
137-
{ role: 'user', content: userQuestion },
138-
],
139-
});
140-
141-
// Log and handle the response
142-
if (!response.choices || response.choices.length === 0) {
143-
console.error('Model did not respond with any choices.');
144-
throw new Error('Model did not respond.');
145-
}
146-
147-
const messageContent = response.choices[0].message.content;
148-
149-
if (messageContent === null || messageContent.trim().length === 0) {
150-
console.error("Model's answer length is too short.");
151-
throw new Error("Model's answer is too short.");
152-
}
153-
154-
const answer = messageContent.trim();
155-
156-
return answer;
157-
}
158-
159-
/**
160-
* Helper function to retrieve all blocks from a Notion page using pagination.
161-
* Recursively fetches child blocks if they exist.
162-
*/
93+
// Helper function to retrieve all blocks from a Notion page using pagination. Recursively fetches child blocks if they exist.
16394
async function retrieveBlockChildren(notion: Client, id: string) {
16495
const blocks: Array<any> = [];
16596
for await (const block of iteratePaginatedAPI(notion.blocks.children.list, { block_id: id })) {
@@ -174,18 +105,12 @@ async function retrieveBlockChildren(notion: Client, id: string) {
174105
return blocks;
175106
}
176107

177-
/**
178-
* Helper function to extract plain text from a rich text object in Notion.
179-
* Combines all pieces of text within a block into a single string.
180-
*/
108+
// Helper function to extract plain text from a rich text object in Notion. Combines all pieces of text within a block into a single string.
181109
const getPlainTextFromRichText = (richText: any) => {
182110
return richText.map((t: any) => t.plain_text).join('');
183111
};
184112

185-
/**
186-
* Helper function to convert a Notion block into a string representation.
187-
* Handles various block types, including media, tables, and text blocks.
188-
*/
113+
// Helper function to convert a Notion block into a string representation. Handles various block types, including media, tables, and text blocks.
189114
const getTextFromBlock = (block: any) => {
190115
let text;
191116

@@ -248,10 +173,7 @@ const getTextFromBlock = (block: any) => {
248173
return block.type + ': ' + text;
249174
};
250175

251-
/**
252-
* Helper function to extract the source text of media blocks, such as images or videos,
253-
* including any associated captions.
254-
*/
176+
//Helper function to extract the source text of media blocks, such as images or videos, including any associated captions.
255177
const getMediaSourceText = (block: any) => {
256178
let source, caption;
257179

@@ -273,10 +195,7 @@ const getMediaSourceText = (block: any) => {
273195
return source;
274196
};
275197

276-
/**
277-
* Helper function to extract the Notion page ID from the provided URL.
278-
* The function uses a regular expression to identify and return the page ID.
279-
*/
198+
// Helper function to extract the Notion page ID from the provided URL. The function uses a regular expression to identify and return the page ID.
280199
function extractPageIdFromUrl(url: string): string {
281200
const regex = /([a-f0-9]{32})|([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/;
282201
const match = url.match(regex);

0 commit comments

Comments
 (0)