matimo-examples 0.1.0-alpha.7

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,216 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ============================================================================
4
+ * GMAIL TOOLS - DECORATOR PATTERN EXAMPLE
5
+ * ============================================================================
6
+ *
7
+ * PATTERN: Decorator Pattern with @tool
8
+ * ─────────────────────────────────────────────────────────────────────────
9
+ * Uses TypeScript @tool decorators to wrap Gmail tool calls in a class.
10
+ *
11
+ * Use this pattern when:
12
+ * ✅ Building class-based applications
13
+ * ✅ Encapsulating tool logic in services
14
+ * ✅ Adding custom methods that combine multiple tools
15
+ * ✅ Need reusable tool wrappers
16
+ * ✅ Object-oriented design preferred
17
+ *
18
+ * SETUP:
19
+ * ─────────────────────────────────────────────────────────────────────────
20
+ * 1. Create .env file:
21
+ * GMAIL_ACCESS_TOKEN=ya29.xxxxxxxxxxxxx
22
+ *
23
+ * 2. Same scopes as factory pattern
24
+ *
25
+ * USAGE:
26
+ * ─────────────────────────────────────────────────────────────────────────
27
+ * export GMAIL_ACCESS_TOKEN=your_token_here
28
+ * npm run gmail:decorator
29
+ *
30
+ * ============================================================================
31
+ */
32
+
33
+ import 'dotenv/config';
34
+ import path from 'path';
35
+ import { fileURLToPath } from 'url';
36
+ import { MatimoInstance, tool, setGlobalMatimoInstance } from 'matimo';
37
+
38
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
39
+
40
+ /**
41
+ * Decorator Pattern Agent - Uses @tool decorators for Gmail operations
42
+ */
43
+ class DecoratorPatternAgent {
44
+ constructor(private matimo: MatimoInstance) {}
45
+
46
+ /**
47
+ * Gmail send-email tool - automatically executes via @tool decorator
48
+ */
49
+ @tool('gmail-send-email')
50
+ async sendEmail(to: string, subject: string, body: string): Promise<unknown> {
51
+ // Decorator automatically calls: matimo.execute('gmail-send-email', { to, subject, body })
52
+ // Matimo automatically injects GMAIL_ACCESS_TOKEN from env vars
53
+ return undefined;
54
+ }
55
+
56
+ /**
57
+ * Gmail list-messages tool - automatically executes via @tool decorator
58
+ */
59
+ @tool('gmail-list-messages')
60
+ async listMessages(query?: string, maxResults?: number): Promise<unknown> {
61
+ // Decorator automatically calls: matimo.execute('gmail-list-messages', { query, maxResults })
62
+ // Matimo automatically injects GMAIL_ACCESS_TOKEN from env vars
63
+ return undefined;
64
+ }
65
+
66
+ /**
67
+ * Gmail get-message tool - automatically executes via @tool decorator
68
+ */
69
+ @tool('gmail-get-message')
70
+ async getMessage(message_id: string, format?: string): Promise<unknown> {
71
+ // Decorator automatically calls: matimo.execute('gmail-get-message', { message_id, format })
72
+ // Matimo automatically injects GMAIL_ACCESS_TOKEN from env vars
73
+ return undefined;
74
+ }
75
+
76
+ /**
77
+ * Gmail create-draft tool - automatically executes via @tool decorator
78
+ */
79
+ @tool('gmail-create-draft')
80
+ async createDraft(to: string, subject: string, body: string): Promise<unknown> {
81
+ // Decorator automatically calls: matimo.execute('gmail-create-draft', { to, subject, body })
82
+ // Matimo automatically injects GMAIL_ACCESS_TOKEN from env vars
83
+ return undefined;
84
+ }
85
+
86
+ /**
87
+ * Gmail delete-message tool - automatically executes via @tool decorator
88
+ */
89
+ @tool('gmail-delete-message')
90
+ async deleteMessage(message_id: string): Promise<unknown> {
91
+ // Decorator automatically calls: matimo.execute('gmail-delete-message', { message_id })
92
+ // Matimo automatically injects GMAIL_ACCESS_TOKEN from env vars
93
+ return undefined;
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Run decorator pattern examples
99
+ */
100
+ async function runDecoratorPatternExamples() {
101
+ // Parse CLI arguments
102
+ const args = process.argv.slice(2);
103
+ let userEmail = process.env.TEST_EMAIL || 'test@example.com';
104
+
105
+ for (const arg of args) {
106
+ if (arg.startsWith('--email:')) {
107
+ userEmail = arg.split(':')[1];
108
+ } else if (arg.startsWith('--email=')) {
109
+ userEmail = arg.split('=')[1];
110
+ }
111
+ }
112
+
113
+ console.info('\n╔════════════════════════════════════════════════════════╗');
114
+ console.info('║ Gmail Tools - Decorator Pattern ║');
115
+ console.info('║ (Uses @tool decorators for automatic execution) ║');
116
+ console.info('╚════════════════════════════════════════════════════════╝\n');
117
+
118
+ const accessToken = process.env.GMAIL_ACCESS_TOKEN;
119
+ if (!accessToken) {
120
+ console.error('❌ Error: GMAIL_ACCESS_TOKEN not set in .env');
121
+ console.info(' Set it: export GMAIL_ACCESS_TOKEN="ya29...."');
122
+ console.info(' Or get a token from: https://developers.google.com/oauthplayground');
123
+ process.exit(1);
124
+ }
125
+
126
+ console.info(`📧 User Email: ${userEmail}\n`);
127
+
128
+ try {
129
+ // Initialize Matimo
130
+ console.info('🚀 Initializing Matimo...');
131
+ const matimo = await MatimoInstance.init({ autoDiscover: true });
132
+ setGlobalMatimoInstance(matimo);
133
+
134
+ const matimoTools = matimo.listTools();
135
+ console.info(`📦 Loaded ${matimoTools.length} tools:\n`);
136
+ matimoTools.forEach((t) => {
137
+ console.info(` • ${t.name}`);
138
+ console.info(` ${t.description}\n`);
139
+ });
140
+
141
+ // Create agent
142
+ const agent = new DecoratorPatternAgent(matimo);
143
+
144
+ console.info('🧪 Testing Gmail Tools with Decorator Pattern');
145
+ console.info('═'.repeat(60));
146
+
147
+ // Example 1: List Messages via decorator
148
+ console.info('\n📬 Example 1: List Messages via @tool Decorator');
149
+ console.info('─'.repeat(60));
150
+ try {
151
+ const listResult = await agent.listMessages('', 5);
152
+ console.info('✅ Messages retrieved successfully!');
153
+ if (typeof listResult === 'object' && listResult !== null) {
154
+ const data = listResult as any;
155
+ if (data.messages && Array.isArray(data.messages)) {
156
+ console.info(` Found ${data.messages.length} recent messages:`);
157
+ data.messages.slice(0, 3).forEach((msg: any, idx: number) => {
158
+ console.info(` ${idx + 1}. ID: ${msg.id.substring(0, 15)}...`);
159
+ });
160
+ } else {
161
+ console.info(' No messages or unexpected format');
162
+ }
163
+ }
164
+ } catch (error) {
165
+ console.info(`⚠️ List failed: ${error instanceof Error ? error.message : String(error)}`);
166
+ }
167
+
168
+ // Example 2: Send Email via decorator
169
+ console.info('\n📧 Example 2: Send Email via @tool Decorator');
170
+ console.info('─'.repeat(60));
171
+ try {
172
+ const sendResult = await agent.sendEmail(
173
+ userEmail,
174
+ 'Hello from Decorator Pattern',
175
+ 'This email was sent using the @tool decorator'
176
+ );
177
+ console.info('✅ Email sent successfully!');
178
+ if (typeof sendResult === 'object' && sendResult !== null) {
179
+ const data = sendResult as any;
180
+ if (data.id) console.info(` Message ID: ${data.id}`);
181
+ }
182
+ } catch (error) {
183
+ console.info(`⚠️ Send failed: ${error instanceof Error ? error.message : String(error)}`);
184
+ }
185
+
186
+ // Example 3: Create Draft via decorator
187
+ console.info('\n✏️ Example 3: Create Draft via @tool Decorator');
188
+ console.info('─'.repeat(60));
189
+ try {
190
+ const draftResult = await agent.createDraft(
191
+ userEmail,
192
+ 'Decorator Pattern Draft',
193
+ 'This draft was created using the @tool decorator'
194
+ );
195
+ console.info('✅ Draft created successfully!');
196
+ if (typeof draftResult === 'object' && draftResult !== null) {
197
+ const data = draftResult as any;
198
+ if (data.id) console.info(` Draft ID: ${data.id}`);
199
+ }
200
+ } catch (error) {
201
+ console.info(`⚠️ Draft failed: ${error instanceof Error ? error.message : String(error)}`);
202
+ }
203
+
204
+ console.info('\n' + '═'.repeat(60));
205
+ console.info('✨ Decorator Pattern Examples Complete!\n');
206
+ console.info('Usage:');
207
+ console.info(' npm run gmail:decorator');
208
+ console.info(' npm run gmail:decorator -- --email:your-email@gmail.com\n');
209
+ } catch (error) {
210
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
211
+ process.exit(1);
212
+ }
213
+ }
214
+
215
+ // Run the examples
216
+ runDecoratorPatternExamples().catch(console.error);
@@ -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 from matimo
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
+ * pnpm 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, ToolDefinition } 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 as ToolDefinition[], 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 as any[], // Type casting for LangChain tools
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);