matimo-examples 0.1.0-alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +49 -0
- package/LICENSE +21 -0
- package/README.md +525 -0
- package/agents/decorator-pattern-agent.ts +368 -0
- package/agents/factory-pattern-agent.ts +253 -0
- package/agents/langchain-agent.ts +146 -0
- package/edit/edit-decorator.ts +178 -0
- package/edit/edit-factory.ts +138 -0
- package/edit/edit-langchain.ts +292 -0
- package/execute/execute-decorator.ts +49 -0
- package/execute/execute-factory.ts +46 -0
- package/execute/execute-langchain.ts +232 -0
- package/github/github-decorator.ts +326 -0
- package/github/github-factory.ts +355 -0
- package/github/github-langchain.ts +206 -0
- package/github/github-with-approval.ts +228 -0
- package/gmail/README.md +345 -0
- package/gmail/gmail-decorator.ts +216 -0
- package/gmail/gmail-factory.ts +231 -0
- package/gmail/gmail-langchain.ts +201 -0
- package/hubspot/README.md +316 -0
- package/hubspot/hubspot-decorator.ts +180 -0
- package/hubspot/hubspot-factory.ts +188 -0
- package/hubspot/hubspot-langchain.ts +222 -0
- package/logger-example.ts +40 -0
- package/mailchimp/README.md +321 -0
- package/mailchimp/mailchimp-decorator.ts +277 -0
- package/mailchimp/mailchimp-factory.ts +187 -0
- package/mailchimp/mailchimp-langchain.ts +155 -0
- package/notion/README.md +293 -0
- package/notion/notion-decorator.ts +275 -0
- package/notion/notion-factory.ts +256 -0
- package/notion/notion-langchain.ts +237 -0
- package/package.json +79 -0
- package/postgres/README.md +188 -0
- package/postgres/postgres-decorator.ts +198 -0
- package/postgres/postgres-factory.ts +180 -0
- package/postgres/postgres-langchain.ts +213 -0
- package/postgres/postgres-with-approval.ts +344 -0
- package/read/read-decorator.ts +154 -0
- package/read/read-factory.ts +121 -0
- package/read/read-langchain.ts +273 -0
- package/search/search-decorator.ts +206 -0
- package/search/search-factory.ts +146 -0
- package/search/search-langchain.ts +255 -0
- package/slack/README.md +339 -0
- package/slack/slack-decorator.ts +245 -0
- package/slack/slack-factory.ts +226 -0
- package/slack/slack-langchain.ts +242 -0
- package/tsconfig.json +20 -0
- package/twilio/README.md +309 -0
- package/twilio/twilio-decorator.ts +288 -0
- package/twilio/twilio-factory.ts +238 -0
- package/twilio/twilio-langchain.ts +218 -0
- package/web/web-decorator.ts +52 -0
- package/web/web-factory.ts +70 -0
- package/web/web-langchain.ts +163 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ============================================================================
|
|
4
|
+
* NOTION TOOLS - FACTORY PATTERN EXAMPLE (REAL OPERATIONS)
|
|
5
|
+
* ============================================================================
|
|
6
|
+
*
|
|
7
|
+
* This example demonstrates REAL Notion API operations:
|
|
8
|
+
* 1. Search the workspace to discover databases
|
|
9
|
+
* 2. Query actual databases for real data
|
|
10
|
+
* 3. Create new pages with real data
|
|
11
|
+
* 4. Update existing pages
|
|
12
|
+
* 5. Show actual results from your Notion workspace
|
|
13
|
+
*
|
|
14
|
+
* ============================================================================
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import 'dotenv/config';
|
|
18
|
+
import { MatimoInstance } from '@matimo/core';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Run factory pattern examples with REAL Notion operations
|
|
22
|
+
*/
|
|
23
|
+
async function runFactoryPatternExamples() {
|
|
24
|
+
console.info('\n╔════════════════════════════════════════════════════════╗');
|
|
25
|
+
console.info('║ NOTION - Factory Pattern (REAL OPERATIONS) ║');
|
|
26
|
+
console.info('║ Discovering & querying your workspace ║');
|
|
27
|
+
console.info('╚════════════════════════════════════════════════════════╝\n');
|
|
28
|
+
|
|
29
|
+
const apiKey = process.env.NOTION_API_KEY;
|
|
30
|
+
if (!apiKey) {
|
|
31
|
+
console.error('❌ Error: NOTION_API_KEY not set in .env');
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const matimo = await MatimoInstance.init({ autoDiscover: true });
|
|
36
|
+
const allTools = matimo.listTools();
|
|
37
|
+
const notionTools = allTools.filter((t) => t.name.startsWith('notion_'));
|
|
38
|
+
|
|
39
|
+
console.info(`✅ Found ${notionTools.length} Notion tools\n`);
|
|
40
|
+
console.info('DEBUG: Notion tools discovered:');
|
|
41
|
+
notionTools.forEach((tool) => {
|
|
42
|
+
console.info(` • ${tool.name}`);
|
|
43
|
+
});
|
|
44
|
+
console.info('Debug: All available tools:');
|
|
45
|
+
allTools.forEach((tool) => {
|
|
46
|
+
console.info(` • ${tool.name}`);
|
|
47
|
+
});
|
|
48
|
+
console.info('');
|
|
49
|
+
console.info('════════════════════════════════════════════════════════════\n');
|
|
50
|
+
console.info('REAL NOTION OPERATIONS:');
|
|
51
|
+
console.info('════════════════════════════════════════════════════════════\n');
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
// STEP 1: List all databases in workspace
|
|
55
|
+
console.info('1️⃣ DISCOVERING YOUR WORKSPACE...\n');
|
|
56
|
+
const listResult = (await matimo.execute('notion_list_databases', {
|
|
57
|
+
page_size: 10,
|
|
58
|
+
})) as any;
|
|
59
|
+
|
|
60
|
+
const databases = listResult.data?.results || [];
|
|
61
|
+
if (databases.length === 0) {
|
|
62
|
+
console.info(' ℹ️ No databases found. Create and share one first.\n');
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
console.info(`✅ Found ${databases.length} database(s) in workspace\n`);
|
|
67
|
+
|
|
68
|
+
const foundDatabase = databases[0];
|
|
69
|
+
const dbTitle = foundDatabase.title?.[0]?.plain_text || 'Untitled';
|
|
70
|
+
console.info(` 📊 Using database: "${dbTitle}"`);
|
|
71
|
+
console.info(` 🔑 ID: ${foundDatabase.id}\n`);
|
|
72
|
+
|
|
73
|
+
// STEP 2: Query database
|
|
74
|
+
console.info('2️⃣ QUERYING DATABASE...\n');
|
|
75
|
+
const queryResult = (await matimo.execute('notion_query_database', {
|
|
76
|
+
database_id: foundDatabase.id,
|
|
77
|
+
page_size: 5,
|
|
78
|
+
})) as any;
|
|
79
|
+
|
|
80
|
+
const queryData = queryResult.data;
|
|
81
|
+
if (queryData?.results && Array.isArray(queryData.results) && queryData.results.length > 0) {
|
|
82
|
+
console.info(`✅ Retrieved ${queryData.results.length} page(s)\n`);
|
|
83
|
+
queryData.results.slice(0, 3).forEach((page: any, idx: number) => {
|
|
84
|
+
const title =
|
|
85
|
+
(page.properties as any)?.[Object.keys(page.properties || {})[0]]?.[0]?.plain_text ??
|
|
86
|
+
'Untitled';
|
|
87
|
+
const url = page.url;
|
|
88
|
+
console.info(` ${idx + 1}. ${title}`);
|
|
89
|
+
console.info(` 🔗 ${url}\n`);
|
|
90
|
+
});
|
|
91
|
+
if (queryData.results.length > 3) {
|
|
92
|
+
console.info(` ... and ${queryData.results.length - 3} more\n`);
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
console.info(' ℹ️ Database is empty\n');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// STEP 3: Create page with markdown (simple, works with any database)
|
|
99
|
+
console.info('3️⃣ CREATING NEW PAGE...\n');
|
|
100
|
+
const pageTitle = `Matimo Test ${new Date().toLocaleTimeString()}`;
|
|
101
|
+
|
|
102
|
+
// Prefer the database_id from the query results (page parent) if available,
|
|
103
|
+
// otherwise fall back to the discovered database id from notion_list_databases.
|
|
104
|
+
const fallbackDbId = foundDatabase.id;
|
|
105
|
+
const pageParentDbId = queryData?.results?.[0]?.parent?.database_id;
|
|
106
|
+
const resolvedDatabaseId = pageParentDbId || fallbackDbId;
|
|
107
|
+
|
|
108
|
+
const createParams = {
|
|
109
|
+
parent: { database_id: resolvedDatabaseId },
|
|
110
|
+
markdown: `# ${pageTitle}\n\nCreated by Matimo at ${new Date().toLocaleString()}`,
|
|
111
|
+
icon: {
|
|
112
|
+
type: 'emoji',
|
|
113
|
+
emoji: '✅',
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
console.info(
|
|
118
|
+
`DEBUG: Using database id for creation: ${resolvedDatabaseId} (from ${pageParentDbId ? 'query result' : 'discovery'})`
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
console.info('DEBUG: Creating page with params:', JSON.stringify(createParams, null, 2));
|
|
122
|
+
const createResult = (await matimo.execute('notion_create_page', createParams)) as any;
|
|
123
|
+
console.info('DEBUG: Create result:', JSON.stringify(createResult, null, 2).substring(0, 500));
|
|
124
|
+
|
|
125
|
+
const createData = createResult.data || createResult;
|
|
126
|
+
if (createData && createData.id) {
|
|
127
|
+
console.info(`✅ Page created!\n`);
|
|
128
|
+
console.info(` 📄 Title: "${pageTitle}"`);
|
|
129
|
+
console.info(` 🔑 ID: ${createData.id}`);
|
|
130
|
+
console.info(` 🔗 URL: ${createData.url}\n`);
|
|
131
|
+
|
|
132
|
+
// STEP 4: Update page with emoji icon
|
|
133
|
+
console.info('4️⃣ UPDATING PAGE WITH ICON...\n');
|
|
134
|
+
try {
|
|
135
|
+
await matimo.execute('notion_update_page', {
|
|
136
|
+
page_id: createData.id,
|
|
137
|
+
icon: {
|
|
138
|
+
type: 'emoji',
|
|
139
|
+
emoji: '🚀',
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
console.info(`✅ Page updated with icon!\n`);
|
|
143
|
+
} catch (err) {
|
|
144
|
+
console.info(
|
|
145
|
+
` ⚠️ Could not update: ${err instanceof Error ? err.message : String(err)}\n`
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// STEP 5: Add comment
|
|
150
|
+
console.info('5️⃣ ADDING COMMENT...\n');
|
|
151
|
+
try {
|
|
152
|
+
const commentResult = (await matimo.execute('notion_create_comment', {
|
|
153
|
+
parent: { page_id: createData.id },
|
|
154
|
+
rich_text: [
|
|
155
|
+
{
|
|
156
|
+
type: 'text',
|
|
157
|
+
text: {
|
|
158
|
+
content: `Created by Matimo at ${new Date().toLocaleString()}. Real test! 🚀`,
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
})) as any;
|
|
163
|
+
|
|
164
|
+
console.info('DEBUG: Comment result:', JSON.stringify(commentResult).substring(0, 500));
|
|
165
|
+
|
|
166
|
+
const cr = commentResult.data || commentResult;
|
|
167
|
+
if (cr && cr.id) {
|
|
168
|
+
console.info(`✅ Comment added!\n`);
|
|
169
|
+
} else if (commentResult && (commentResult.success === false || commentResult.statusCode)) {
|
|
170
|
+
console.info(
|
|
171
|
+
` ⚠️ Comment failed: ${JSON.stringify(commentResult).substring(0, 200)}\n`
|
|
172
|
+
);
|
|
173
|
+
} else {
|
|
174
|
+
console.info(`✅ Comment added (no id returned)\n`);
|
|
175
|
+
}
|
|
176
|
+
} catch (err) {
|
|
177
|
+
try {
|
|
178
|
+
console.info(' ⚠️ Could not add comment. Error payload:', JSON.stringify(err));
|
|
179
|
+
} catch (_) {
|
|
180
|
+
console.info(
|
|
181
|
+
` ⚠️ Could not add comment: ${err instanceof Error ? err.message : String(err)}\n`
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
} else {
|
|
186
|
+
console.info(
|
|
187
|
+
` ⚠️ Failed to create page. Response: ${JSON.stringify(createData).substring(0, 200)}\n`
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
// If the database wasn't found or not shared, attempt a fallback:
|
|
191
|
+
// create a child page under an existing page returned by the query above.
|
|
192
|
+
const errCode =
|
|
193
|
+
(createData && (createData as any).error && (createData as any).error.code) || '';
|
|
194
|
+
if (errCode === 'object_not_found') {
|
|
195
|
+
console.info(
|
|
196
|
+
' ℹ️ Notion reports the database object was not found or not shared with the integration.'
|
|
197
|
+
);
|
|
198
|
+
const firstPage = queryData?.results?.[0];
|
|
199
|
+
if (firstPage && firstPage.id) {
|
|
200
|
+
console.info(` ℹ️ Falling back to creating a sub-page under page id ${firstPage.id}`);
|
|
201
|
+
try {
|
|
202
|
+
const fallbackResult = await matimo.execute('notion_create_page', {
|
|
203
|
+
parent: { page_id: firstPage.id },
|
|
204
|
+
properties: {
|
|
205
|
+
Name: { title: [{ text: { content: pageTitle } }] },
|
|
206
|
+
},
|
|
207
|
+
icon: {
|
|
208
|
+
type: 'emoji',
|
|
209
|
+
emoji: '✅',
|
|
210
|
+
},
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
const fr = (fallbackResult as any).data || fallbackResult;
|
|
214
|
+
if (fr && fr.id) {
|
|
215
|
+
console.info(' ✅ Fallback page created as child page!');
|
|
216
|
+
console.info(` 🔑 ID: ${fr.id}`);
|
|
217
|
+
console.info(` 🔗 URL: ${fr.url}\n`);
|
|
218
|
+
} else {
|
|
219
|
+
console.info(
|
|
220
|
+
' ⚠️ Fallback creation also failed. Check integration permissions and that the target page is shared.'
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
} catch (fbErr) {
|
|
224
|
+
console.info(
|
|
225
|
+
' ⚠️ Fallback create threw an error:',
|
|
226
|
+
fbErr instanceof Error ? fbErr.message : String(fbErr)
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
} else {
|
|
230
|
+
console.info(
|
|
231
|
+
' ℹ️ No pages available to fall back to. Ensure your integration is shared with the target database.'
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
} else {
|
|
235
|
+
console.info(
|
|
236
|
+
' ℹ️ Creation failed for other reasons; inspect the response above for details.'
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
console.info('════════════════════════════════════════════════════════════\n');
|
|
242
|
+
console.info('✨ COMPLETE!\n');
|
|
243
|
+
console.info('📝 Check your Notion workspace to see the created page!\n');
|
|
244
|
+
} catch (error) {
|
|
245
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
246
|
+
console.error(`❌ Error: ${msg}`);
|
|
247
|
+
if (msg.includes('401') || msg.includes('permission')) {
|
|
248
|
+
console.error(' • Check your NOTION_API_KEY is valid');
|
|
249
|
+
console.error(' • Ensure your integration has read/write capabilities');
|
|
250
|
+
console.error(' • Share your Notion database with the integration');
|
|
251
|
+
}
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
runFactoryPatternExamples().catch(console.error);
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ============================================================================
|
|
4
|
+
* NOTION TOOLS - LANGCHAIN AI AGENT EXAMPLE
|
|
5
|
+
* ============================================================================
|
|
6
|
+
*
|
|
7
|
+
* PATTERN: True AI Agent with OpenAI + LangChain
|
|
8
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
9
|
+
* This is a REAL AI agent that:
|
|
10
|
+
* 1. Takes natural language user requests
|
|
11
|
+
* 2. Uses OpenAI LLM (GPT-4o-mini) to decide which Notion tools to use
|
|
12
|
+
* 3. Generates appropriate parameters based on context
|
|
13
|
+
* 4. Executes tools autonomously
|
|
14
|
+
* 5. Processes results and responds naturally
|
|
15
|
+
*
|
|
16
|
+
* Use this pattern when:
|
|
17
|
+
* ✅ Building true autonomous AI agents
|
|
18
|
+
* ✅ LLM should decide which tools to use
|
|
19
|
+
* ✅ Complex workflows with LLM reasoning
|
|
20
|
+
* ✅ Multi-step agentic processes
|
|
21
|
+
* ✅ User gives high-level instructions (not low-level API calls)
|
|
22
|
+
*
|
|
23
|
+
* SETUP:
|
|
24
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
25
|
+
* 1. Create .env file:
|
|
26
|
+
* NOTION_API_KEY=secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
27
|
+
* OPENAI_API_KEY=sk-xxxxxxxxxxxxx
|
|
28
|
+
*
|
|
29
|
+
* 2. Install dependencies:
|
|
30
|
+
* npm install
|
|
31
|
+
*
|
|
32
|
+
* USAGE:
|
|
33
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
34
|
+
* export NOTION_API_KEY=secret_xxxx
|
|
35
|
+
* export OPENAI_API_KEY=sk-xxxx
|
|
36
|
+
* npm run notion:langchain
|
|
37
|
+
*
|
|
38
|
+
* WHAT IT DOES:
|
|
39
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
40
|
+
* This example shows an AI agent that can:
|
|
41
|
+
* 1. Search Notion workspace
|
|
42
|
+
* 2. Query databases
|
|
43
|
+
* 3. Create pages
|
|
44
|
+
* 4. Update pages
|
|
45
|
+
* 5. Add comments
|
|
46
|
+
* 6. Respond naturally in conversation style
|
|
47
|
+
*
|
|
48
|
+
* Example conversation:
|
|
49
|
+
* User: "Search my Notion workspace for important items"
|
|
50
|
+
* AI Agent: "I'll search your Notion workspace..."
|
|
51
|
+
* [AI Agent calls notion_search tool]
|
|
52
|
+
* AI Agent: "I found 5 items. Here's what I discovered..."
|
|
53
|
+
*
|
|
54
|
+
* ============================================================================
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
import 'dotenv/config';
|
|
58
|
+
import { createAgent } from 'langchain';
|
|
59
|
+
import { ChatOpenAI } from '@langchain/openai';
|
|
60
|
+
import { MatimoInstance, convertToolsToLangChain, ToolDefinition } from '@matimo/core';
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Notion AI Agent - Autonomous agent with LangChain
|
|
64
|
+
*/
|
|
65
|
+
async function runNotionAIAgent() {
|
|
66
|
+
console.info('\n╔════════════════════════════════════════════════════════╗');
|
|
67
|
+
console.info('║ NOTION AI AGENT - LangChain Agentic Loop ║');
|
|
68
|
+
console.info('║ Autonomous Notion workspace management ║');
|
|
69
|
+
console.info('╚════════════════════════════════════════════════════════╝\n');
|
|
70
|
+
|
|
71
|
+
// Validate credentials
|
|
72
|
+
const notionKey = process.env.NOTION_API_KEY;
|
|
73
|
+
const openaiKey = process.env.OPENAI_API_KEY;
|
|
74
|
+
|
|
75
|
+
if (!notionKey) {
|
|
76
|
+
console.error('❌ Error: NOTION_API_KEY not set in .env');
|
|
77
|
+
console.info(' Get one from: https://www.notion.so/my-integrations');
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!openaiKey) {
|
|
82
|
+
console.error('❌ Error: OPENAI_API_KEY not set in .env');
|
|
83
|
+
console.info(' Get one from: https://platform.openai.com/api-keys');
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.info(`🤖 Using OpenAI (GPT-4o-mini) as the AI agent\n`);
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
// Initialize Matimo with auto-discovery
|
|
91
|
+
console.info('🚀 Initializing Matimo...');
|
|
92
|
+
const matimo = await MatimoInstance.init({ autoDiscover: true });
|
|
93
|
+
|
|
94
|
+
// Get Notion tools and convert to LangChain format
|
|
95
|
+
console.info('💬 Loading Notion tools...');
|
|
96
|
+
const matimoTools = matimo.listTools();
|
|
97
|
+
const notionTools = matimoTools.filter((t) => t.name.startsWith('notion_'));
|
|
98
|
+
console.info(`✅ Loaded ${notionTools.length} Notion tools\n`);
|
|
99
|
+
|
|
100
|
+
// Select key Notion tools for agent (in order of typical workflow)
|
|
101
|
+
const keyNotionTools = notionTools.filter((t) =>
|
|
102
|
+
[
|
|
103
|
+
'notion_list_databases',
|
|
104
|
+
'notion_query_database',
|
|
105
|
+
'notion_create_page',
|
|
106
|
+
'notion_update_page',
|
|
107
|
+
].includes(t.name)
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
// ✅ Discover a database first (required for notion_create_page parent parameter)
|
|
111
|
+
// This mirrors the factory example that queries databases before creating pages
|
|
112
|
+
console.info('🧪 Discovering accessible databases...');
|
|
113
|
+
let selectedDatabaseId: string | null = null;
|
|
114
|
+
let selectedDatabaseTitle: string | null = null;
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
const listResult = (await matimo.execute('notion_list_databases', { page_size: 5 })) as any;
|
|
118
|
+
const databases = listResult.data?.results || listResult.results || [];
|
|
119
|
+
console.info(` ✅ Direct tool call succeeded`);
|
|
120
|
+
console.info(` 📊 Found ${databases.length} accessible database(s)\n`);
|
|
121
|
+
|
|
122
|
+
if (databases && databases.length > 0) {
|
|
123
|
+
selectedDatabaseId = databases[0].id;
|
|
124
|
+
selectedDatabaseTitle = databases[0].title?.[0]?.plain_text || 'Untitled';
|
|
125
|
+
console.info(
|
|
126
|
+
` 📍 Selected database: "${selectedDatabaseTitle}" (${selectedDatabaseId})\n`
|
|
127
|
+
);
|
|
128
|
+
} else {
|
|
129
|
+
console.info(' ℹ️ No databases accessible - notion_create_page will fail\n');
|
|
130
|
+
console.info(
|
|
131
|
+
' 📌 Share a Notion database with your integration to enable full functionality\n'
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
} catch (testError) {
|
|
135
|
+
console.info(` ⚠️ Direct tool test failed: ${testError}\n`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ✅ Convert Matimo tools to LangChain format
|
|
139
|
+
console.info('🔄 Converting tools to LangChain format...');
|
|
140
|
+
const langchainTools = await convertToolsToLangChain(
|
|
141
|
+
keyNotionTools as ToolDefinition[],
|
|
142
|
+
matimo,
|
|
143
|
+
{
|
|
144
|
+
NOTION_API_KEY: notionKey,
|
|
145
|
+
...(selectedDatabaseId ? { parent: { database_id: selectedDatabaseId } } : {}),
|
|
146
|
+
} as any
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
console.info(`✅ Converted ${langchainTools.length} tools for LangChain\n`);
|
|
150
|
+
|
|
151
|
+
// Initialize OpenAI LLM
|
|
152
|
+
console.info('🤖 Initializing OpenAI (GPT-4o-mini) LLM...');
|
|
153
|
+
const model = new ChatOpenAI({
|
|
154
|
+
modelName: 'gpt-4o-mini',
|
|
155
|
+
temperature: 0.7,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Create agent
|
|
159
|
+
console.info('🔧 Creating agent...\n');
|
|
160
|
+
const agent = await createAgent({
|
|
161
|
+
model,
|
|
162
|
+
tools: langchainTools as any[], // Type casting for LangChain tools
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// Define agent tasks (natural language requests that require real API usage)
|
|
166
|
+
const userRequests = [
|
|
167
|
+
{
|
|
168
|
+
title: 'Example 1: Explore Workspace',
|
|
169
|
+
request:
|
|
170
|
+
'Explore my Notion workspace and tell me what databases you find. List them by name.',
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
title: 'Example 2: Query and Analyze',
|
|
174
|
+
request:
|
|
175
|
+
'Find a database in my workspace and query it. Tell me how many pages it contains and what you discover.',
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
title: 'Example 3: Create Page',
|
|
179
|
+
request: `Create a new page with the title "AI Agent Report - ${new Date().toLocaleTimeString()}" in the available database`,
|
|
180
|
+
},
|
|
181
|
+
];
|
|
182
|
+
|
|
183
|
+
console.info('🧪 Running AI Agent Tasks');
|
|
184
|
+
console.info('═'.repeat(60));
|
|
185
|
+
console.info('📌 IMPORTANT: Each task shows:');
|
|
186
|
+
console.info(' 1. Natural language user request');
|
|
187
|
+
console.info(' 2. AI agent decision (which tools to call)');
|
|
188
|
+
console.info(' 3. Actual tool execution results\n');
|
|
189
|
+
|
|
190
|
+
// Run each task through the agent
|
|
191
|
+
for (const task of userRequests) {
|
|
192
|
+
console.info(`\n${task.title}`);
|
|
193
|
+
console.info('─'.repeat(60));
|
|
194
|
+
console.info(`👤 User: "${task.request}"\n`);
|
|
195
|
+
|
|
196
|
+
try {
|
|
197
|
+
// Use the same invoke shape as the Slack example: supply `messages` array
|
|
198
|
+
const response = (await (agent as any).invoke({
|
|
199
|
+
messages: [
|
|
200
|
+
{
|
|
201
|
+
role: 'user',
|
|
202
|
+
content: task.request,
|
|
203
|
+
},
|
|
204
|
+
],
|
|
205
|
+
})) as any;
|
|
206
|
+
|
|
207
|
+
// Get the output from the agent
|
|
208
|
+
const output = response.output;
|
|
209
|
+
if (output) {
|
|
210
|
+
console.info(`🤖 Agent Response:\n${output}\n`);
|
|
211
|
+
}
|
|
212
|
+
} catch (error) {
|
|
213
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
214
|
+
console.info(`⚠️ Agent error: ${errorMsg}\n`);
|
|
215
|
+
console.info('📌 Note: This is expected if you lack API permissions or database access');
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
console.info('═'.repeat(60));
|
|
220
|
+
console.info('✨ AI Agent Examples Complete!\n');
|
|
221
|
+
console.info('Key Features:');
|
|
222
|
+
console.info(' ✅ Real LLM (OpenAI) decides which tools to use');
|
|
223
|
+
console.info(' ✅ Natural language requests (not API calls)');
|
|
224
|
+
console.info(' ✅ LLM generates parameters based on context');
|
|
225
|
+
console.info(' ✅ Actual tools executed in your Notion workspace');
|
|
226
|
+
console.info(' ✅ Results processed through LLM for natural response\n');
|
|
227
|
+
} catch (error) {
|
|
228
|
+
console.error('❌ Error:', error instanceof Error ? error.message : String(error));
|
|
229
|
+
if (error instanceof Error && error.stack) {
|
|
230
|
+
console.error('Stack:', error.stack);
|
|
231
|
+
}
|
|
232
|
+
process.exit(1);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Run the AI agent
|
|
237
|
+
runNotionAIAgent().catch(console.error);
|
package/package.json
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "matimo-examples",
|
|
3
|
+
"version": "0.1.0-alpha.11",
|
|
4
|
+
"description": "Matimo SDK examples - Factory Pattern, Decorator Pattern, and LangChain integration with Slack and Gmail",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"@langchain/core": "^1.1.18",
|
|
8
|
+
"@langchain/openai": "^1.2.4",
|
|
9
|
+
"langchain": "^1.2.16",
|
|
10
|
+
"dotenv": "^17.2.3",
|
|
11
|
+
"zod": "^4.3.6",
|
|
12
|
+
"matimo": "0.1.0-alpha.11",
|
|
13
|
+
"@matimo/slack": "0.1.0-alpha.11",
|
|
14
|
+
"@matimo/postgres": "0.1.0-alpha.11",
|
|
15
|
+
"@matimo/github": "0.1.0-alpha.11",
|
|
16
|
+
"@matimo/gmail": "0.1.0-alpha.11",
|
|
17
|
+
"@matimo/hubspot": "0.1.0-alpha.11",
|
|
18
|
+
"@matimo/notion": "0.1.0-alpha.11",
|
|
19
|
+
"@matimo/mailchimp": "0.1.0-alpha.11",
|
|
20
|
+
"@matimo/twilio": "0.1.0-alpha.11"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^25.1.0",
|
|
24
|
+
"better-sqlite3": "^12.6.2",
|
|
25
|
+
"typescript": "^5.9.3",
|
|
26
|
+
"tsx": "^4.21.0"
|
|
27
|
+
},
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=18.0.0"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"agent:decorator": "tsx agents/decorator-pattern-agent.ts",
|
|
33
|
+
"agent:factory": "tsx agents/factory-pattern-agent.ts",
|
|
34
|
+
"agent:langchain": "tsx agents/langchain-agent.ts",
|
|
35
|
+
"gmail:factory": "tsx gmail/gmail-factory.ts",
|
|
36
|
+
"gmail:decorator": "tsx gmail/gmail-decorator.ts",
|
|
37
|
+
"gmail:langchain": "tsx gmail/gmail-langchain.ts",
|
|
38
|
+
"slack:factory": "tsx slack/slack-factory.ts",
|
|
39
|
+
"slack:decorator": "tsx slack/slack-decorator.ts",
|
|
40
|
+
"slack:langchain": "tsx slack/slack-langchain.ts",
|
|
41
|
+
"postgres:factory": "tsx postgres/postgres-factory.ts",
|
|
42
|
+
"postgres:decorator": "tsx postgres/postgres-decorator.ts",
|
|
43
|
+
"postgres:langchain": "tsx postgres/postgres-langchain.ts",
|
|
44
|
+
"postgres:approval": "tsx postgres/postgres-with-approval.ts",
|
|
45
|
+
"execute:factory": "tsx execute/execute-factory.ts",
|
|
46
|
+
"execute:decorator": "tsx execute/execute-decorator.ts",
|
|
47
|
+
"execute:langchain": "tsx execute/execute-langchain.ts",
|
|
48
|
+
"read:factory": "tsx read/read-factory.ts",
|
|
49
|
+
"read:decorator": "tsx read/read-decorator.ts",
|
|
50
|
+
"read:langchain": "tsx read/read-langchain.ts",
|
|
51
|
+
"edit:factory": "tsx edit/edit-factory.ts",
|
|
52
|
+
"edit:decorator": "tsx edit/edit-decorator.ts",
|
|
53
|
+
"edit:langchain": "tsx edit/edit-langchain.ts",
|
|
54
|
+
"search:factory": "tsx search/search-factory.ts",
|
|
55
|
+
"search:decorator": "tsx search/search-decorator.ts",
|
|
56
|
+
"search:langchain": "tsx search/search-langchain.ts",
|
|
57
|
+
"web:factory": "tsx web/web-factory.ts",
|
|
58
|
+
"web:decorator": "tsx web/web-decorator.ts",
|
|
59
|
+
"web:langchain": "tsx web/web-langchain.ts",
|
|
60
|
+
"github:factory": "tsx github/github-factory.ts",
|
|
61
|
+
"github:decorator": "tsx github/github-decorator.ts",
|
|
62
|
+
"github:langchain": "tsx github/github-langchain.ts",
|
|
63
|
+
"github:approval": "tsx github/github-with-approval.ts",
|
|
64
|
+
"hubspot:factory": "tsx hubspot/hubspot-factory.ts",
|
|
65
|
+
"hubspot:decorator": "tsx hubspot/hubspot-decorator.ts",
|
|
66
|
+
"hubspot:langchain": "tsx hubspot/hubspot-langchain.ts",
|
|
67
|
+
"notion:factory": "tsx notion/notion-factory.ts",
|
|
68
|
+
"notion:decorator": "tsx notion/notion-decorator.ts",
|
|
69
|
+
"notion:langchain": "tsx notion/notion-langchain.ts",
|
|
70
|
+
"mailchimp:factory": "tsx mailchimp/mailchimp-factory.ts",
|
|
71
|
+
"mailchimp:decorator": "tsx mailchimp/mailchimp-decorator.ts",
|
|
72
|
+
"mailchimp:langchain": "tsx mailchimp/mailchimp-langchain.ts",
|
|
73
|
+
"twilio:factory": "tsx twilio/twilio-factory.ts",
|
|
74
|
+
"twilio:decorator": "tsx twilio/twilio-decorator.ts",
|
|
75
|
+
"twilio:langchain": "tsx twilio/twilio-langchain.ts",
|
|
76
|
+
"build": "tsc",
|
|
77
|
+
"clean": "rm -rf dist"
|
|
78
|
+
}
|
|
79
|
+
}
|