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,49 @@
1
+ import { MatimoInstance, setGlobalMatimoInstance, tool } from '@matimo/core';
2
+
3
+ /**
4
+ * Example: Execute tool using @tool decorator pattern
5
+ * Demonstrates class-based tool execution with automatic decoration
6
+ */
7
+ class CommandExecutor {
8
+ @tool('execute')
9
+ async runCommand(command: string, timeout?: number): Promise<unknown> {
10
+ // Decorator automatically intercepts and executes via Matimo
11
+ return undefined;
12
+ }
13
+
14
+ @tool('execute')
15
+ async listDirectory(): Promise<unknown> {
16
+ // Decorator automatically intercepts and executes via Matimo
17
+ return undefined;
18
+ }
19
+ }
20
+
21
+ async function decoratorExample() {
22
+ // Set up decorator support with autoDiscover
23
+ const matimo = await MatimoInstance.init({ autoDiscover: true });
24
+ setGlobalMatimoInstance(matimo);
25
+
26
+ console.info('=== Execute Tool - Decorator Pattern ===\n');
27
+
28
+ const executor = new CommandExecutor();
29
+
30
+ try {
31
+ // Example 1: Run command through decorated method
32
+ console.info('1. Running command: echo "Hello from decorator"\n');
33
+ const result1 = await executor.runCommand('echo "Hello from decorator"');
34
+ console.info('Success:', (result1 as any).success);
35
+ console.info('Output:', (result1 as any).stdout);
36
+ console.info('---\n');
37
+
38
+ // Example 2: List directory
39
+ console.info('2. Running command: pwd\n');
40
+ const result2 = await executor.listDirectory();
41
+ console.info('Success:', (result2 as any).success);
42
+ console.info('Output:', (result2 as any).stdout);
43
+ console.info('---\n');
44
+ } catch (error: any) {
45
+ console.error('Error:', error.message);
46
+ }
47
+ }
48
+
49
+ decoratorExample();
@@ -0,0 +1,46 @@
1
+ import { MatimoInstance } from '@matimo/core';
2
+
3
+ /**
4
+ * Example: Execute tool using factory pattern
5
+ * Demonstrates running shell commands and capturing output
6
+ */
7
+ async function executeExample() {
8
+ // Initialize Matimo with autoDiscover to find all tools (core + providers)
9
+ const matimo = await MatimoInstance.init({ autoDiscover: true });
10
+
11
+ console.info('=== Execute Tool - Factory Pattern ===\n');
12
+
13
+ try {
14
+ // Example 1: List files in current directory
15
+ console.info('1. Running: ls\n');
16
+ const lsResult = await matimo.execute('execute', {
17
+ command: 'ls',
18
+ timeout: 10000,
19
+ });
20
+ console.info('Success:', (lsResult as any).success);
21
+ console.info('Output:', (lsResult as any).stdout?.substring(0, 200));
22
+ console.info('---\n');
23
+
24
+ // Example 2: Get current working directory
25
+ console.info('2. Running: pwd\n');
26
+ const pwdResult = await matimo.execute('execute', {
27
+ command: 'pwd',
28
+ });
29
+ console.info('Success:', (pwdResult as any).success);
30
+ console.info('Output:', (pwdResult as any).stdout);
31
+ console.info('---\n');
32
+
33
+ // Example 3: Echo command
34
+ console.info('3. Running: echo "Hello from Matimo"\n');
35
+ const echoResult = await matimo.execute('execute', {
36
+ command: 'echo "Hello from Matimo"',
37
+ });
38
+ console.info('Success:', (echoResult as any).success);
39
+ console.info('Output:', (echoResult as any).stdout);
40
+ console.info('---\n');
41
+ } catch (error: any) {
42
+ console.error('Error executing command:', error.message);
43
+ }
44
+ }
45
+
46
+ executeExample();
@@ -0,0 +1,163 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ============================================================================
4
+ * EXECUTE TOOL - 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 when to execute commands
12
+ * 3. Generates appropriate command parameters based on context
13
+ * 4. Executes tools autonomously
14
+ * 5. Processes results and responds naturally
15
+ *
16
+ * SETUP:
17
+ * ─────────────────────────────────────────────────────────────────────────
18
+ * 1. Create .env file:
19
+ * OPENAI_API_KEY=sk-xxxxxxxxxxxxx
20
+ *
21
+ * 2. Install dependencies:
22
+ * npm install
23
+ *
24
+ * USAGE:
25
+ * ─────────────────────────────────────────────────────────────────────────
26
+ * export OPENAI_API_KEY=sk-xxxx
27
+ * npm run execute:langchain
28
+ *
29
+ * ============================================================================
30
+ */
31
+
32
+ import 'dotenv/config';
33
+ import { createAgent } from 'langchain';
34
+ import { ChatOpenAI } from '@langchain/openai';
35
+ import { MatimoInstance, convertToolsToLangChain, ToolDefinition } from '@matimo/core';
36
+
37
+ /**
38
+ * Run AI Agent with Execute tool
39
+ * The agent receives natural language requests and decides which commands to execute
40
+ */
41
+ async function runExecuteAIAgent() {
42
+ console.info('\n╔════════════════════════════════════════════════════════╗');
43
+ console.info('║ Execute Tool AI Agent - LangChain + OpenAI ║');
44
+ console.info('║ True autonomous agent with LLM reasoning ║');
45
+ console.info('╚════════════════════════════════════════════════════════╝\n');
46
+
47
+ // Check required environment variables
48
+ const openaiKey = process.env.OPENAI_API_KEY;
49
+ if (!openaiKey) {
50
+ console.error('❌ Error: OPENAI_API_KEY not set in .env');
51
+ console.info(' Set it: export OPENAI_API_KEY="sk-..."');
52
+ console.info(' Get one from: https://platform.openai.com/api-keys');
53
+ process.exit(1);
54
+ }
55
+
56
+ console.info('🤖 Using OpenAI (GPT-4o-mini) as the AI agent\n');
57
+
58
+ try {
59
+ // Initialize Matimo with auto-discovery
60
+ console.info('🚀 Initializing Matimo...');
61
+ const matimo = await MatimoInstance.init({ autoDiscover: true });
62
+
63
+ // Get execute tool
64
+ console.info('💬 Loading execute tool...');
65
+ const matimoTools = matimo.listTools();
66
+ const executeTools = matimoTools.filter((t) => t.name === 'execute');
67
+ console.info(`✅ Loaded ${executeTools.length} execute tool(s)\n`);
68
+
69
+ if (executeTools.length === 0) {
70
+ console.error('❌ Execute tool not found');
71
+ process.exit(1);
72
+ }
73
+
74
+ // Convert to LangChain tools using the built-in converter
75
+ const langchainTools = await convertToolsToLangChain(executeTools as ToolDefinition[], matimo);
76
+
77
+ // Initialize OpenAI LLM
78
+ console.info('🤖 Initializing OpenAI (GPT-4o-mini) LLM...');
79
+ const model = new ChatOpenAI({
80
+ modelName: 'gpt-4o-mini',
81
+ temperature: 0.7,
82
+ });
83
+
84
+ // Create agent
85
+ console.info('🔧 Creating agent...\n');
86
+ const agent = await createAgent({
87
+ model,
88
+ tools: langchainTools as any,
89
+ });
90
+
91
+ // Define agent tasks (natural language requests)
92
+ const userRequests = [
93
+ {
94
+ title: 'Example 1: Get system information',
95
+ request: 'Show me the current working directory using pwd command',
96
+ },
97
+ {
98
+ title: 'Example 2: List files',
99
+ request: 'List files and directories in the current folder (use ls -la)',
100
+ },
101
+ {
102
+ title: 'Example 3: Create a test file',
103
+ request: 'Create a simple test file named test.txt in /tmp with content "Hello from Agent"',
104
+ },
105
+ ];
106
+
107
+ console.info('🧪 Running AI Agent Tasks');
108
+ console.info('═'.repeat(60) + '\n');
109
+
110
+ // Run each task through the agent
111
+ for (const task of userRequests) {
112
+ console.info(`${task.title}`);
113
+ console.info('─'.repeat(60));
114
+ console.info(`👤 User: "${task.request}"\n`);
115
+
116
+ try {
117
+ const response = await agent.invoke({
118
+ messages: [
119
+ {
120
+ role: 'user',
121
+ content: task.request,
122
+ },
123
+ ],
124
+ });
125
+
126
+ // Get the last message from the agent
127
+ const lastMessage = response.messages[response.messages.length - 1];
128
+ if (lastMessage) {
129
+ const content =
130
+ typeof lastMessage.content === 'string'
131
+ ? lastMessage.content
132
+ : String(lastMessage.content);
133
+
134
+ if (content && content.trim()) {
135
+ console.info(`🤖 Agent: ${content}\n`);
136
+ } else {
137
+ console.info('🤖 Agent: (Command executed successfully)\n');
138
+ }
139
+ }
140
+ } catch (error) {
141
+ const errorMsg = error instanceof Error ? error.message : String(error);
142
+ console.info(`⚠️ Agent error: ${errorMsg}\n`);
143
+ }
144
+ }
145
+
146
+ console.info('═'.repeat(60));
147
+ console.info('\n✨ AI Agent Examples Complete!\n');
148
+ console.info('Key Features:');
149
+ console.info(' ✅ Real LLM (OpenAI) decides which tools to use');
150
+ console.info(' ✅ Natural language requests, not API calls');
151
+ console.info(' ✅ LLM generates command parameters based on context');
152
+ console.info(' ✅ Agentic reasoning and decision-making\n');
153
+ } catch (error) {
154
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
155
+ if (error instanceof Error && error.stack) {
156
+ console.error('Stack:', error.stack);
157
+ }
158
+ process.exit(1);
159
+ }
160
+ }
161
+
162
+ // Run the AI agent
163
+ runExecuteAIAgent().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.