matimo-examples 1.0.0

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.
@@ -0,0 +1,231 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ============================================================================
4
+ * GMAIL TOOLS - FACTORY PATTERN EXAMPLE
5
+ * ============================================================================
6
+ *
7
+ * PATTERN: SDK Factory Pattern
8
+ * ─────────────────────────────────────────────────────────────────────────
9
+ * Direct tool execution via MatimoInstance - the simplest way to use tools.
10
+ *
11
+ * Use this pattern when:
12
+ * ✅ Building simple scripts or CLI tools
13
+ * ✅ Direct API calls without abstraction
14
+ * ✅ Quick prototyping
15
+ * ✅ One-off tool execution
16
+ *
17
+ * SETUP:
18
+ * ─────────────────────────────────────────────────────────────────────────
19
+ * 1. Create .env file in project root:
20
+ * GMAIL_ACCESS_TOKEN=ya29.xxxxxxxxxxxxx
21
+ *
22
+ * 2. Get a Gmail access token:
23
+ * - Use OAuth2Handler to authenticate with Google
24
+ * - Request these scopes:
25
+ * • https://www.googleapis.com/auth/gmail.send (send emails)
26
+ * • https://www.googleapis.com/auth/gmail.readonly (read emails)
27
+ * • https://www.googleapis.com/auth/gmail.modify (drafts, delete)
28
+ *
29
+ * USAGE:
30
+ * ─────────────────────────────────────────────────────────────────────────
31
+ * export GMAIL_ACCESS_TOKEN=your_token_here
32
+ * npm run gmail:factory
33
+ *
34
+ * AVAILABLE TOOLS:
35
+ * ─────────────────────────────────────────────────────────────────────────
36
+ * 1. gmail-send-email
37
+ * Parameters: to (required), subject (required), body (required), [cc], [bcc]
38
+ * Returns: { id, threadId, labelIds }
39
+ * Example: Send an email to someone@example.com
40
+ *
41
+ * 2. gmail-list-messages
42
+ * Parameters: [query], [maxResults], [pageToken]
43
+ * Returns: { messages[], nextPageToken }
44
+ * Example queries: "is:unread", "from:someone@example.com", "has:attachment"
45
+ *
46
+ * 3. gmail-get-message
47
+ * Parameters: message_id, [format]
48
+ * Format options: "minimal" (lightweight), "full" (complete with headers)
49
+ * Returns: { payload { headers, body }, snippet }
50
+ *
51
+ * 4. gmail-create-draft
52
+ * Parameters: to, subject, body, [cc], [bcc]
53
+ * Returns: { id, message { id, threadId } }
54
+ * Note: Draft is created but not sent - user edits then sends manually
55
+ *
56
+ * 5. gmail-delete-message
57
+ * Parameters: message_id
58
+ * Returns: { success }
59
+ * Note: Permanently deletes the message
60
+ *
61
+ * ============================================================================
62
+ */
63
+
64
+ import 'dotenv/config';
65
+ import path from 'path';
66
+ import { fileURLToPath } from 'url';
67
+ import { MatimoInstance } from 'matimo';
68
+
69
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
70
+
71
+ /**
72
+ * Run factory pattern examples
73
+ */
74
+ async function runFactoryPatternExamples() {
75
+ // Parse CLI arguments
76
+ const args = process.argv.slice(2);
77
+ let userEmail = process.env.TEST_EMAIL || 'test@example.com';
78
+
79
+ for (const arg of args) {
80
+ if (arg.startsWith('--email:')) {
81
+ userEmail = arg.split(':')[1];
82
+ } else if (arg.startsWith('--email=')) {
83
+ userEmail = arg.split('=')[1];
84
+ }
85
+ }
86
+
87
+ console.info('\n╔════════════════════════════════════════════════════════╗');
88
+ console.info('║ Gmail Tools - Factory Pattern ║');
89
+ console.info('║ (Direct execution - simplest approach) ║');
90
+ console.info('╚════════════════════════════════════════════════════════╝\n');
91
+
92
+ const accessToken = process.env.GMAIL_ACCESS_TOKEN;
93
+ if (!accessToken) {
94
+ console.error('❌ Error: GMAIL_ACCESS_TOKEN not set in .env');
95
+ console.info(' Set it: export GMAIL_ACCESS_TOKEN="ya29...."');
96
+ console.info(' Or get a token from: https://developers.google.com/oauthplayground');
97
+ process.exit(1);
98
+ }
99
+
100
+ console.info(`📧 User Email: ${userEmail}\n`);
101
+
102
+ try {
103
+ // Initialize Matimo
104
+ console.info('🚀 Initializing Matimo...');
105
+ const matimo = await MatimoInstance.init({ autoDiscover: true });
106
+
107
+ const matimoTools = matimo.listTools();
108
+ console.info(`📦 Loaded ${matimoTools.length} tools:\n`);
109
+ matimoTools.forEach((t) => {
110
+ console.info(` • ${t.name}`);
111
+ console.info(` ${t.description}\n`);
112
+ });
113
+
114
+ // Filter to Gmail tools
115
+ const gmailTools = matimoTools.filter((t) => t.name.startsWith('gmail-'));
116
+ console.info(`📧 Found ${gmailTools.length} Gmail tools\n`);
117
+
118
+ console.info('🧪 Testing Gmail Tools with Factory Pattern');
119
+ console.info('═'.repeat(60));
120
+
121
+ // Example 1: List Messages (GET emails)
122
+ console.info('\n📬 Example 1: List Your Recent Messages');
123
+ console.info('─'.repeat(60));
124
+ try {
125
+ const listResult = await matimo.execute('gmail-list-messages', {
126
+ maxResults: 5,
127
+ GMAIL_ACCESS_TOKEN: accessToken,
128
+ });
129
+ console.info('📤 Raw Result:', JSON.stringify(listResult, null, 2));
130
+
131
+ if (typeof listResult === 'object' && listResult !== null) {
132
+ const data = listResult as any;
133
+ if (data.data?.messages && Array.isArray(data.data.messages)) {
134
+ console.info(`✅ Found ${data.data.messages.length} recent messages:`);
135
+ data.data.messages.slice(0, 3).forEach((msg: any, idx: number) => {
136
+ console.info(` ${idx + 1}. ID: ${msg.id}`);
137
+ console.info(` Thread: ${msg.threadId}`);
138
+ });
139
+ } else if (data.messages && Array.isArray(data.messages)) {
140
+ console.info(`✅ Found ${data.messages.length} recent messages:`);
141
+ data.messages.slice(0, 3).forEach((msg: any, idx: number) => {
142
+ console.info(` ${idx + 1}. ID: ${msg.id}`);
143
+ console.info(` Thread: ${msg.threadId}`);
144
+ });
145
+ } else {
146
+ console.info('❌ Unexpected response format');
147
+ }
148
+ }
149
+ } catch (error) {
150
+ console.info(`❌ List failed: ${error instanceof Error ? error.message : String(error)}`);
151
+ console.info(JSON.stringify(error, null, 2));
152
+ }
153
+
154
+ // Example 2: Send Email
155
+ console.info('\n📧 Example 2: Send Email');
156
+ console.info('─'.repeat(60));
157
+ try {
158
+ // Simple API - just pass to, subject, body
159
+ // Matimo automatically converts to MIME format (defined in YAML)
160
+ const sendResult = await matimo.execute('gmail-send-email', {
161
+ to: userEmail,
162
+ subject: 'Hello from Matimo Factory Pattern',
163
+ body: 'This is a test email from the Factory pattern',
164
+ GMAIL_ACCESS_TOKEN: accessToken,
165
+ });
166
+ console.info('📤 Raw Result:', JSON.stringify(sendResult, null, 2));
167
+
168
+ if (typeof sendResult === 'object' && sendResult !== null) {
169
+ const data = sendResult as any;
170
+ if (data.data?.id) {
171
+ console.info(`✅ Email sent successfully!`);
172
+ console.info(` Message ID: ${data.data.id}`);
173
+ console.info(` Thread ID: ${data.data.threadId || 'N/A'}`);
174
+ } else if (data.id) {
175
+ console.info(`✅ Email sent successfully!`);
176
+ console.info(` Message ID: ${data.id}`);
177
+ console.info(` Thread ID: ${data.threadId || 'N/A'}`);
178
+ } else {
179
+ console.info('❌ Unexpected response format');
180
+ }
181
+ }
182
+ } catch (error) {
183
+ console.info(`❌ Send failed: ${error instanceof Error ? error.message : String(error)}`);
184
+ console.info(JSON.stringify(error, null, 2));
185
+ }
186
+
187
+ // Example 3: Create Draft
188
+ console.info('\n✏️ Example 3: Create Draft');
189
+ console.info('─'.repeat(60));
190
+ try {
191
+ // Simple API - just pass to, subject, body
192
+ // Matimo automatically converts to MIME format (defined in YAML)
193
+ const draftResult = await matimo.execute('gmail-create-draft', {
194
+ to: userEmail,
195
+ subject: 'Factory Pattern Draft',
196
+ body: 'This is a draft created by the Factory pattern',
197
+ GMAIL_ACCESS_TOKEN: accessToken,
198
+ });
199
+ console.info('📤 Raw Result:', JSON.stringify(draftResult, null, 2));
200
+
201
+ if (typeof draftResult === 'object' && draftResult !== null) {
202
+ const data = draftResult as any;
203
+ if (data.data?.id) {
204
+ console.info(`✅ Draft created successfully!`);
205
+ console.info(` Draft ID: ${data.data.id}`);
206
+ console.info(` Message ID: ${data.data.message?.id || 'N/A'}`);
207
+ } else if (data.id) {
208
+ console.info(`✅ Draft created successfully!`);
209
+ console.info(` Draft ID: ${data.id}`);
210
+ } else {
211
+ console.info('❌ Unexpected response format');
212
+ }
213
+ }
214
+ } catch (error) {
215
+ console.info(`❌ Draft failed: ${error instanceof Error ? error.message : String(error)}`);
216
+ console.info(JSON.stringify(error, null, 2));
217
+ }
218
+
219
+ console.info('\n' + '═'.repeat(60));
220
+ console.info('✨ Factory Pattern Examples Complete!\n');
221
+ console.info('Usage:');
222
+ console.info(' npm run gmail:factory');
223
+ console.info(' npm run gmail:factory -- --email:your-email@gmail.com\n');
224
+ } catch (error) {
225
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
226
+ process.exit(1);
227
+ }
228
+ }
229
+
230
+ // Run the examples
231
+ runFactoryPatternExamples().catch(console.error);
@@ -0,0 +1,201 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ============================================================================
4
+ * GMAIL 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 Gmail 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
+ * GMAIL_ACCESS_TOKEN=ya29.xxxxxxxxxxxxx
27
+ * OPENAI_API_KEY=sk-xxxxxxxxxxxxx
28
+ *
29
+ * 2. Install dependencies:
30
+ * npm install
31
+ *
32
+ * USAGE:
33
+ * ─────────────────────────────────────────────────────────────────────────
34
+ * export GMAIL_ACCESS_TOKEN=your_token_here
35
+ * export OPENAI_API_KEY=your_openai_key_here
36
+ * npm run gmail:langchain
37
+ *
38
+ * WHAT IT DOES:
39
+ * ─────────────────────────────────────────────────────────────────────────
40
+ * This example shows an AI agent that can:
41
+ * 1. Check your recent emails
42
+ * 2. Send emails to you based on LLM reasoning
43
+ * 3. Create draft emails with AI-generated content
44
+ * 4. Respond naturally in conversation style
45
+ *
46
+ * Example conversation:
47
+ * User: "Send me a test email"
48
+ * Claude: "I'll send you a test email now..."
49
+ * [Claude calls gmail-send-email tool]
50
+ * Claude: "Done! Email sent to your address."
51
+ *
52
+ * ============================================================================
53
+ */
54
+
55
+ import 'dotenv/config';
56
+ import path from 'path';
57
+ import { fileURLToPath } from 'url';
58
+ import { createAgent } from 'langchain';
59
+ import { ChatOpenAI } from '@langchain/openai';
60
+ import { MatimoInstance, convertToolsToLangChain } from 'matimo';
61
+
62
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
63
+
64
+ /**
65
+ * Run AI Agent with Gmail tools
66
+ * The agent receives natural language requests and decides which Gmail tools to use
67
+ */
68
+ async function runGmailAIAgent() {
69
+ // Parse CLI arguments
70
+ const args = process.argv.slice(2);
71
+ let userEmail = process.env.TEST_EMAIL || 'test@example.com';
72
+
73
+ for (const arg of args) {
74
+ if (arg.startsWith('--email:')) {
75
+ userEmail = arg.split(':')[1];
76
+ } else if (arg.startsWith('--email=')) {
77
+ userEmail = arg.split('=')[1];
78
+ }
79
+ }
80
+
81
+ console.info('\n╔════════════════════════════════════════════════════════╗');
82
+ console.info('║ Gmail AI Agent - LangChain + OpenAI ║');
83
+ console.info('║ True autonomous agent with LLM reasoning ║');
84
+ console.info('╚════════════════════════════════════════════════════════╝\n');
85
+
86
+ // Check required environment variables
87
+ const accessToken = process.env.GMAIL_ACCESS_TOKEN;
88
+ if (!accessToken) {
89
+ console.error('❌ Error: GMAIL_ACCESS_TOKEN not set in .env');
90
+ console.info(' Set it: export GMAIL_ACCESS_TOKEN="ya29...."');
91
+ process.exit(1);
92
+ }
93
+
94
+ const openaiKey = process.env.OPENAI_API_KEY;
95
+ if (!openaiKey) {
96
+ console.error('❌ Error: OPENAI_API_KEY not set in .env');
97
+ console.info(' Set it: export OPENAI_API_KEY="sk-..."');
98
+ process.exit(1);
99
+ }
100
+
101
+ console.info(`📧 User Email: ${userEmail}`);
102
+ console.info(`🤖 Using OpenAI (GPT-4o-mini) as the AI agent\n`);
103
+
104
+ try {
105
+ // Initialize Matimo
106
+ console.info('🚀 Initializing Matimo...');
107
+ const matimo = await MatimoInstance.init({ autoDiscover: true });
108
+
109
+ // Get Gmail tools and convert to LangChain format
110
+ console.info('📬 Loading Gmail tools...');
111
+ const matimoTools = matimo.listTools();
112
+ const gmailTools = matimoTools.filter((t) => t.name.startsWith('gmail-'));
113
+ console.info(`✅ Loaded ${gmailTools.length} Gmail tools\n`);
114
+
115
+ // Convert to LangChain tools
116
+ const langchainTools = await convertToolsToLangChain(gmailTools, matimo, {
117
+ GMAIL_ACCESS_TOKEN: accessToken,
118
+ });
119
+
120
+ // Initialize OpenAI LLM
121
+ console.info('🤖 Initializing OpenAI (GPT-4o-mini) LLM...');
122
+ const model = new ChatOpenAI({
123
+ modelName: 'gpt-4o-mini',
124
+ temperature: 0.7,
125
+ });
126
+
127
+ // Create agent
128
+ console.info('🔧 Creating agent...\n');
129
+ const agent = await createAgent({
130
+ model,
131
+ tools: langchainTools,
132
+ });
133
+
134
+ // Define agent tasks (natural language requests)
135
+ const userRequests = [
136
+ {
137
+ title: 'Example 1: Check recent emails',
138
+ request: 'How many recent emails do I have? List the first 3.',
139
+ },
140
+ {
141
+ title: 'Example 2: Send a test email',
142
+ request: `Please send a test email to ${userEmail} with subject "Hello from AI Agent" and body "This email was sent by an AI agent using Matimo tools."`,
143
+ },
144
+ {
145
+ title: 'Example 3: Create an automated draft',
146
+ request: `Create a draft email to ${userEmail} about "Weekly Summary" with a professional greeting and a summary of what this example demonstrated.`,
147
+ },
148
+ ];
149
+
150
+ console.info('🧪 Running AI Agent Tasks');
151
+ console.info('═'.repeat(60));
152
+
153
+ // Run each task through the agent
154
+ for (const task of userRequests) {
155
+ console.info(`\n${task.title}`);
156
+ console.info('─'.repeat(60));
157
+ console.info(`👤 User: "${task.request}"\n`);
158
+
159
+ try {
160
+ const response = await agent.invoke({
161
+ messages: [
162
+ {
163
+ role: 'user',
164
+ content: task.request,
165
+ },
166
+ ],
167
+ });
168
+
169
+ // Get the last message from the agent
170
+ const lastMessage = response.messages[response.messages.length - 1];
171
+ if (lastMessage) {
172
+ if (typeof lastMessage.content === 'string') {
173
+ console.info(`🤖 Agent: ${lastMessage.content}\n`);
174
+ } else {
175
+ console.info(`🤖 Agent:`, lastMessage.content, '\n');
176
+ }
177
+ }
178
+ } catch (error) {
179
+ const errorMsg = error instanceof Error ? error.message : String(error);
180
+ console.info(`⚠️ Agent error: ${errorMsg}\n`);
181
+ }
182
+ }
183
+
184
+ console.info('═'.repeat(60));
185
+ console.info('✨ AI Agent Examples Complete!\n');
186
+ console.info('Key Features:');
187
+ console.info(' ✅ Real LLM (OpenAI) decides which tools to use');
188
+ console.info(' ✅ Natural language requests, not API calls');
189
+ console.info(' ✅ LLM generates tool parameters based on context');
190
+ console.info(' ✅ Agentic reasoning and decision-making\n');
191
+ } catch (error) {
192
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
193
+ if (error instanceof Error && error.stack) {
194
+ console.error('Stack:', error.stack);
195
+ }
196
+ process.exit(1);
197
+ }
198
+ }
199
+
200
+ // Run the AI agent
201
+ runGmailAIAgent().catch(console.error);
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "matimo-examples",
3
+ "version": "1.0.0",
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.4",
13
+ "@matimo/gmail": "0.1.0-alpha.4",
14
+ "@matimo/slack": "0.1.0-alpha.4"
15
+ },
16
+ "devDependencies": {
17
+ "@types/node": "^25.1.0",
18
+ "better-sqlite3": "^12.6.2",
19
+ "typescript": "^5.9.3",
20
+ "tsx": "^4.21.0"
21
+ },
22
+ "engines": {
23
+ "node": ">=18.0.0"
24
+ },
25
+ "scripts": {
26
+ "agent:decorator": "tsx agents/decorator-pattern-agent.ts",
27
+ "agent:factory": "tsx agents/factory-pattern-agent.ts",
28
+ "agent:langchain": "tsx agents/langchain-agent.ts",
29
+ "gmail:factory": "tsx gmail/gmail-factory.ts",
30
+ "gmail:decorator": "tsx gmail/gmail-decorator.ts",
31
+ "gmail:langchain": "tsx gmail/gmail-langchain.ts",
32
+ "slack:factory": "tsx slack/slack-factory.ts",
33
+ "slack:decorator": "tsx slack/slack-decorator.ts",
34
+ "slack:langchain": "tsx slack/slack-langchain.ts",
35
+ "build": "tsc",
36
+ "clean": "rm -rf dist"
37
+ }
38
+ }