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,146 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Matimo + LangChain Agent - Proper ReAct Agent Pattern
4
+ *
5
+ * This demonstrates a complete agent loop:
6
+ * 1. LLM decides which tool to use based on goal
7
+ * 2. Tool is executed via Matimo
8
+ * 3. Result is fed back to LLM
9
+ * 4. Process repeats until agent reaches conclusion
10
+ *
11
+ * Key advantages:
12
+ * - Shows real agent reasoning loop
13
+ * - Single source of truth (Matimo YAML definitions)
14
+ * - How to integrate Matimo with any LangChain setup
15
+ * - Demonstrates tool selection and execution
16
+ *
17
+ * Run: npm run agent:langchain
18
+ */
19
+
20
+ import 'dotenv/config';
21
+ import path from 'path';
22
+ import { fileURLToPath } from 'url';
23
+ import { ChatOpenAI } from '@langchain/openai';
24
+ import { BaseMessage, HumanMessage, ToolMessage } from '@langchain/core/messages';
25
+ import { MatimoInstance, convertToolsToLangChain, ToolDefinition } from 'matimo';
26
+
27
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
28
+
29
+ /**
30
+ * Run LangChain ReAct Agent with Matimo Tools
31
+ */
32
+ async function runLangChainAgent() {
33
+ console.info('\n╔════════════════════════════════════════════════════════╗');
34
+ console.info('║ Matimo + LangChain Agent (ReAct Pattern) ║');
35
+ console.info('║ Demonstrates real agent reasoning loop ║');
36
+ console.info('╚════════════════════════════════════════════════════════╝\n');
37
+
38
+ try {
39
+ // Initialize Matimo
40
+ console.info('🚀 Initializing Matimo...');
41
+ const matimo = await MatimoInstance.init({ autoDiscover: true });
42
+
43
+ const matimoTools = matimo.listTools();
44
+ console.info(`📦 Loaded ${matimoTools.length} tools:\n`);
45
+ matimoTools.forEach((t) => {
46
+ console.info(` • ${t.name}`);
47
+ console.info(` ${t.description}\n`);
48
+ });
49
+
50
+ // ✅ Convert Matimo tools to LangChain tools
51
+ console.info('🔧 Converting Matimo tools to LangChain format...\n');
52
+ const langchainTools = await convertToolsToLangChain(matimoTools as ToolDefinition[], matimo);
53
+
54
+ console.info(`✅ Successfully converted ${langchainTools.length} tools!\n`);
55
+
56
+ // 🤖 Create GPT-4o-mini LLM with tool binding
57
+ console.info('🧠 Creating GPT-4o-mini LLM with tool binding...\n');
58
+ const llm = new ChatOpenAI({
59
+ model: 'gpt-4o-mini',
60
+ temperature: 0,
61
+ });
62
+
63
+ const llmWithTools = llm.bindTools(langchainTools as any);
64
+
65
+ // 🎯 Agent Loop - ReAct Pattern
66
+ console.info('🧪 Starting Agent Loop (ReAct Pattern)\n');
67
+ console.info('═'.repeat(60));
68
+
69
+ const userQuery = 'What is 42 plus 58?';
70
+ console.info(`\n❓ User Query: "${userQuery}"\n`);
71
+
72
+ const messages: BaseMessage[] = [new HumanMessage(userQuery)];
73
+
74
+ let iterationCount = 0;
75
+ const maxIterations = 10;
76
+ let continueLoop = true;
77
+
78
+ while (continueLoop && iterationCount < maxIterations) {
79
+ iterationCount++;
80
+ console.info(`\n[Iteration ${iterationCount}]`);
81
+ console.info('─'.repeat(60));
82
+
83
+ // Step 1: Call LLM with tools
84
+ console.info('🤔 LLM Thinking...');
85
+ const response = await llmWithTools.invoke(messages);
86
+ console.info(`LLM Response Content: ${response.content || '(no text content)'}`);
87
+
88
+ // Step 2: Check if LLM wants to use tools
89
+ if (response.tool_calls && response.tool_calls.length > 0) {
90
+ // Add assistant message to conversation
91
+ messages.push(response);
92
+
93
+ // Step 3: Execute each tool call
94
+ for (const toolCall of response.tool_calls) {
95
+ console.info(`\n🔧 Executing Tool: ${toolCall.name}`);
96
+ console.info(` Input: ${JSON.stringify(toolCall.args)}`);
97
+
98
+ try {
99
+ // Execute via Matimo
100
+ const result = await matimo.execute(toolCall.name, toolCall.args);
101
+ console.info(` ✅ Result: ${JSON.stringify(result)}`);
102
+
103
+ // Add tool result to conversation
104
+ messages.push(
105
+ new ToolMessage({
106
+ tool_call_id: toolCall.id,
107
+ content: JSON.stringify(result),
108
+ name: toolCall.name,
109
+ })
110
+ );
111
+ } catch (toolError) {
112
+ const msg = toolError instanceof Error ? toolError.message : String(toolError);
113
+ console.info(` ❌ Error: ${msg}`);
114
+
115
+ // Add error to conversation
116
+ messages.push(
117
+ new ToolMessage({
118
+ tool_call_id: toolCall.id,
119
+ content: `Error: ${msg}`,
120
+ name: toolCall.name,
121
+ })
122
+ );
123
+ }
124
+ }
125
+ } else {
126
+ // Step 4: No more tools - agent reached conclusion
127
+ console.info('\n✅ Agent Reached Conclusion');
128
+ console.info(`\n📝 Final Response:\n${response.content || '(no response)'}`);
129
+ continueLoop = false;
130
+ }
131
+ }
132
+
133
+ if (iterationCount >= maxIterations) {
134
+ console.info('\n⚠️ Max iterations reached');
135
+ }
136
+
137
+ console.info('\n' + '═'.repeat(60));
138
+ console.info(`\n✨ Agent Loop Complete (${iterationCount} iterations)\n`);
139
+ } catch (error) {
140
+ console.error('❌ Agent failed:', error instanceof Error ? error.message : String(error));
141
+ process.exit(1);
142
+ }
143
+ }
144
+
145
+ // Run the agent
146
+ runLangChainAgent().catch(console.error);
@@ -0,0 +1,345 @@
1
+ # Gmail Tools - LangChain Integration Examples
2
+
3
+ Complete guide for using Matimo Gmail tools with LangChain and OpenAI for email automation and AI-driven agent workflows.
4
+
5
+ ## 📋 Overview
6
+
7
+ This directory contains three patterns for integrating Gmail tools with LangChain:
8
+
9
+ 1. **Factory Pattern** (`gmail-factory.ts`) - Direct tool execution with explicit parameters
10
+ 2. **Decorator Pattern** (`gmail-decorator.ts`) - TypeScript decorators with automatic auth injection
11
+ 3. **AI Agent** (`gmail-langchain.ts`) - OpenAI-powered agent that decides which tools to use
12
+
13
+ All patterns use **Matimo's YAML-based tool definitions** and **automatic authentication token injection**.
14
+
15
+ ## 🔐 Step 1: Get OAuth2 Access Token
16
+
17
+ ### Using Google OAuth Playground (Easiest)
18
+
19
+ 1. **Visit** [Google OAuth Playground](https://developers.google.com/oauthplayground)
20
+
21
+ 2. **Configure OAuth Credentials** (top-right ⚙️ settings):
22
+ - ☑️ Check "Use your own OAuth credentials"
23
+ - Enter your OAuth **Client ID** (from [Google Cloud Console](https://console.cloud.google.com))
24
+ - Enter your OAuth **Client Secret**
25
+
26
+ > **Don't have credentials?** [Create them here](https://console.cloud.google.com/apis/credentials)
27
+
28
+ 3. **Select Gmail API Scopes** (left panel):
29
+
30
+ Select based on what you need:
31
+ ```
32
+ ✅ https://www.googleapis.com/auth/gmail.readonly
33
+ (Read emails - needed for list-messages)
34
+
35
+ ✅ https://www.googleapis.com/auth/gmail.send
36
+ (Send emails - needed for send-email)
37
+
38
+ ✅ https://www.googleapis.com/auth/gmail.compose
39
+ (Create drafts - needed for create-draft)
40
+ ```
41
+
42
+ 4. **Authorize**:
43
+ - Click "Authorize APIs"
44
+ - Grant permission in the popup
45
+ - Copy the generated **Access Token** (long string starting with `ya29.a0...`)
46
+
47
+ ### Example Token
48
+ ```
49
+ ya29.a0AfH6SMBx1234567890abcdefghijklmnopqrstuvwxyz...
50
+ ```
51
+
52
+ ## 🔑 Step 2: Set Environment Variables
53
+
54
+ ### Option A: Using `.env` file (Recommended)
55
+
56
+ 1. **Create `.env` file** in this directory:
57
+ ```bash
58
+ cd examples/tools/gmail
59
+ cat > .env << EOF
60
+ GMAIL_ACCESS_TOKEN=ya29.a0AfH6SMBx...your-token-here...
61
+ OPENAI_API_KEY=sk-...your-openai-key...
62
+ EOF
63
+ ```
64
+
65
+ 2. **Verify the file** exists:
66
+ ```bash
67
+ cat .env
68
+ ```
69
+
70
+ ### Option B: Using Environment Variables Directly
71
+
72
+ ```bash
73
+ export GMAIL_ACCESS_TOKEN="ya29.a0AfH6SMBx...your-token-here..."
74
+ export OPENAI_API_KEY="sk-...your-openai-key..."
75
+ ```
76
+
77
+ ### Option C: Using `.env.example` Template
78
+
79
+ Copy the template and add your values:
80
+ ```bash
81
+ cp .env.example .env
82
+ # Then edit .env with your actual tokens
83
+ ```
84
+
85
+ ## 🧪 Step 3: Test the Examples
86
+
87
+ ### Prerequisites
88
+ ```bash
89
+ # Install dependencies (if not already done)
90
+ cd /Users/sajesh/My\ Work\ Directory/matimo/examples/tools
91
+ pnpm install
92
+ ```
93
+
94
+ ### Run Factory Pattern
95
+ Tests direct tool execution with factory initialization:
96
+ ```bash
97
+ pnpm run gmail:factory --email:youremail@gmail.com
98
+ ```
99
+
100
+ **What it does:**
101
+ - ✅ Lists recent emails (5 most recent)
102
+ - ✅ Sends test email to your address
103
+ - ✅ Creates a draft email
104
+
105
+ **Expected Output:**
106
+ ```
107
+ 📬 Example 1: List Your Recent Messages
108
+ ✅ Found 5 recent messages:
109
+ 1. From: Alice <alice@example.com>
110
+ 2. From: Bob <bob@example.com>
111
+ ...
112
+
113
+ 📧 Example 2: Send Email
114
+ ✅ Email sent successfully!
115
+
116
+ ✏️ Example 3: Create Draft
117
+ ✅ Draft created successfully!
118
+ ```
119
+
120
+ ### Run Decorator Pattern
121
+ Tests TypeScript decorator-based tool calling:
122
+ ```bash
123
+ pnpm run gmail:decorator --email:youremail@gmail.com
124
+ ```
125
+
126
+ **What it does:**
127
+ - ✅ Lists messages via `@tool` decorator
128
+ - ✅ Sends email using decorated method
129
+ - ✅ Creates draft via decorator
130
+
131
+ **Key Feature:** Auto-injects `GMAIL_ACCESS_TOKEN` from environment
132
+
133
+ ### Run AI Agent (Recommended)
134
+ Tests OpenAI-powered agent that decides which tools to use:
135
+ ```bash
136
+ pnpm run gmail:langchain --email:youremail@gmail.com
137
+ ```
138
+
139
+ **What it does:**
140
+ - ✅ **Example 1:** Agent analyzes your email count
141
+ - ✅ **Example 2:** Agent sends email autonomously
142
+ - ✅ **Example 3:** Agent creates professionally-written draft
143
+
144
+ **Key Features:**
145
+ - 🤖 OpenAI GPT-4o-mini decides which tool to call
146
+ - 📝 Natural language requests (not API calls)
147
+ - 💭 LLM generates appropriate parameters
148
+ - 🔄 Multi-step agentic reasoning
149
+
150
+ **Example Interaction:**
151
+ ```
152
+ Example 2: Send a test email
153
+ ────────────────────────────────────
154
+ 👤 User: "Please send a test email to vsajeshnair@gmail.com
155
+ with subject 'Hello from AI Agent' and body '...'"
156
+
157
+ 🤖 Agent: The test email has been successfully sent to
158
+ **vsajeshnair@gmail.com** with the subject "Hello
159
+ from AI Agent"...
160
+ ```
161
+
162
+ ## 🛠️ Troubleshooting
163
+
164
+ ### Error: `GMAIL_ACCESS_TOKEN not set`
165
+ **Solution:** Set the environment variable:
166
+ ```bash
167
+ export GMAIL_ACCESS_TOKEN="ya29.a0AfH6SMBx..."
168
+ ```
169
+
170
+ ### Error: `401 Unauthorized` or `403 Forbidden`
171
+ **Solution:** Your token may be expired or have insufficient scopes
172
+ - Get a new token from [OAuth Playground](https://developers.google.com/oauthplayground)
173
+ - Ensure you selected all required scopes: `gmail.readonly`, `gmail.send`, `gmail.compose`
174
+
175
+ ### Error: `400 Bad Request` with empty query params
176
+ **Solution:** This is fixed by Matimo's parameter encoding system - update if needed:
177
+ ```bash
178
+ cd /Users/sajesh/My\ Work\ Directory/matimo
179
+ pnpm build
180
+ ```
181
+
182
+ ### Error: `Email not actually sent/drafted`
183
+ **Solution:** Verify the OAuth token has been refreshed and scopes are correct. The email should appear in:
184
+ - **Sent folder** for `gmail-send-email`
185
+ - **Drafts folder** for `gmail-create-draft`
186
+
187
+ ## 📚 Understanding the Patterns
188
+
189
+ ### 1. Factory Pattern (`gmail-factory.ts`)
190
+ Direct SDK usage with explicit parameter passing:
191
+ ```typescript
192
+ await matimo.execute('gmail-send-email', {
193
+ to: userEmail,
194
+ subject: 'Hello',
195
+ body: 'Message',
196
+ // GMAIL_ACCESS_TOKEN auto-injected from env
197
+ });
198
+ ```
199
+
200
+ **Use when:** You know exactly what parameters to pass
201
+
202
+ ### 2. Decorator Pattern (`gmail-decorator.ts`)
203
+ TypeScript decorators for clean syntax:
204
+ ```typescript
205
+ @tool('gmail-send-email')
206
+ async sendEmail(to: string, subject: string, body: string) {
207
+ // Matimo intercepts, auto-injects token
208
+ return undefined;
209
+ }
210
+
211
+ await agent.sendEmail(userEmail, 'Hello', 'Message');
212
+ ```
213
+
214
+ **Use when:** Building decorator-based agents or frameworks
215
+
216
+ ### 3. AI Agent Pattern (`gmail-langchain.ts`)
217
+ OpenAI agent that reasons about tools:
218
+ ```typescript
219
+ const agent = await createAgent({
220
+ model: new ChatOpenAI({ modelName: 'gpt-4o-mini' }),
221
+ tools: langchainTools,
222
+ });
223
+
224
+ await agent.invoke({
225
+ messages: [{
226
+ role: 'user',
227
+ content: 'Send me a test email'
228
+ }]
229
+ });
230
+ // Agent decides which tool to use and calls it!
231
+ ```
232
+
233
+ **Use when:** Building autonomous AI agents with natural language
234
+
235
+ ## 🔄 How Authentication Works
236
+
237
+ All three patterns use **Matimo's automatic auth injection**:
238
+
239
+ 1. **Tool Definition** declares auth requirement in YAML:
240
+ ```yaml
241
+ authentication:
242
+ type: oauth2
243
+ provider: google
244
+ ```
245
+
246
+ 2. **Execution Config** references auth parameter:
247
+ ```yaml
248
+ execution:
249
+ headers:
250
+ Authorization: "Bearer {GMAIL_ACCESS_TOKEN}"
251
+ ```
252
+
253
+ 3. **Matimo auto-injects** from environment:
254
+ ```typescript
255
+ // No explicit token passing needed!
256
+ await matimo.execute('gmail-send-email', {
257
+ to: 'user@example.com',
258
+ subject: 'Hello',
259
+ body: 'Message'
260
+ // GMAIL_ACCESS_TOKEN auto-added from process.env
261
+ });
262
+ ```
263
+
264
+ This keeps your code clean and secure - no tokens in source code!
265
+
266
+ ## 📦 What Gets Created
267
+
268
+ ### Emails Sent
269
+ - Appear in your **Gmail Sent folder** immediately
270
+ - Subject: Varies per example
271
+ - From: Your configured Gmail account
272
+
273
+ ### Drafts Created
274
+ - Appear in your **Gmail Drafts folder**
275
+ - Ready to edit and send manually
276
+ - Useful for AI-generated content review
277
+
278
+ ### Messages Listed
279
+ - Shows your 5 most recent emails
280
+ - Displays sender, subject, and snippet
281
+ - No modifications to existing emails
282
+
283
+ ## 🔗 Related Resources
284
+
285
+ - **[Matimo Documentation](https://tallclub.github.io/matimo/api-reference/SDK.html)** - Complete SDK reference
286
+ - **[Gmail API Docs](https://developers.google.com/gmail/api)** - Official Gmail API
287
+ - **[OAuth Playground](https://developers.google.com/oauthplayground)** - Get tokens
288
+ - **[Google Cloud Console](https://console.cloud.google.com)** - Manage credentials
289
+ - **[LangChain Docs](https://js.langchain.com/)** - LangChain reference
290
+
291
+ ## 💡 Tips & Tricks
292
+
293
+ ### Refresh Tokens
294
+ Tokens expire after 1 hour. Get a new one from OAuth Playground:
295
+ ```bash
296
+ # Get fresh token
297
+ export GMAIL_ACCESS_TOKEN="ya29.a0AfH6SMBx...new-token..."
298
+
299
+ # Re-run example
300
+ pnpm run gmail:langchain --email:youremail@gmail.com
301
+ ```
302
+
303
+ ### Test with Different Emails
304
+ ```bash
305
+ # Send to a different recipient
306
+ pnpm run gmail:factory --email:different@example.com
307
+ ```
308
+
309
+ ### Run All Three Patterns
310
+ ```bash
311
+ echo "Factory Pattern:"
312
+ pnpm run gmail:factory --email:youremail@gmail.com
313
+
314
+ echo -e "\nDecorator Pattern:"
315
+ pnpm run gmail:decorator --email:youremail@gmail.com
316
+
317
+ echo -e "\nAI Agent Pattern:"
318
+ pnpm run gmail:langchain --email:youremail@gmail.com
319
+ ```
320
+
321
+ ### View Generated Emails
322
+ 1. Open Gmail: https://gmail.com
323
+ 2. Check **Sent folder** for sent emails
324
+ 3. Check **Drafts folder** for created drafts
325
+ 4. Check **Inbox** for received emails
326
+
327
+ ## ✨ Key Principles
328
+
329
+ ✅ **All tools defined in YAML** - No code changes needed to modify tools
330
+ ✅ **Auth tokens auto-injected** - Matimo reads from environment
331
+ ✅ **Framework-agnostic** - Works with LangChain, CrewAI, custom agents
332
+ ✅ **Stateless** - Matimo doesn't store tokens or state
333
+ ✅ **Scalable** - Same pattern works for 10,000+ tools
334
+
335
+ ## ❓ Questions or Issues?
336
+
337
+ 1. Check the error message carefully
338
+ 2. Verify your OAuth token is valid (less than 1 hour old)
339
+ 3. Ensure all Gmail scopes are selected
340
+ 4. Check that `GMAIL_ACCESS_TOKEN` is set correctly
341
+ 5. Review the [main README](https://github.com/tallclub/matimo) for general setup
342
+
343
+ ---
344
+
345
+ **Happy emailing! 📧** Use these patterns to build powerful, autonomous email agents with Matimo and OpenAI.
@@ -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);