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,238 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ============================================================================
|
|
4
|
+
* TWILIO 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
|
+
* TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
21
|
+
* TWILIO_AUTH_TOKEN=your_auth_token_here
|
|
22
|
+
* TWILIO_FROM_NUMBER=+15557122661
|
|
23
|
+
* TWILIO_TO_NUMBER=+15558675310
|
|
24
|
+
*
|
|
25
|
+
* 2. Get Twilio credentials:
|
|
26
|
+
* - Go to: https://console.twilio.com
|
|
27
|
+
* - Account SID and Auth Token are on the dashboard
|
|
28
|
+
* - Buy a phone number or use your trial number as TWILIO_FROM_NUMBER
|
|
29
|
+
* - In trial mode, TWILIO_TO_NUMBER must be a verified caller ID
|
|
30
|
+
* - Matimo automatically handles base64 encoding — no extra steps required!
|
|
31
|
+
*
|
|
32
|
+
* USAGE:
|
|
33
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
34
|
+
* pnpm twilio:factory
|
|
35
|
+
*
|
|
36
|
+
* AVAILABLE TOOLS:
|
|
37
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
38
|
+
* 1. twilio-send-sms
|
|
39
|
+
* Parameters: account_sid (required), to (required), from (required), body (required)
|
|
40
|
+
* Optional: status_callback
|
|
41
|
+
* Returns: Message resource with sid and status: queued
|
|
42
|
+
*
|
|
43
|
+
* 2. twilio-send-mms
|
|
44
|
+
* Parameters: account_sid (required), to (required), from (required), media_url (required)
|
|
45
|
+
* Optional: body, status_callback
|
|
46
|
+
* Returns: Message resource with sid and num_media: "1"
|
|
47
|
+
*
|
|
48
|
+
* 3. twilio-get-message
|
|
49
|
+
* Parameters: account_sid (required), message_sid (required)
|
|
50
|
+
* Returns: Full Message resource with current status
|
|
51
|
+
*
|
|
52
|
+
* 4. twilio-list-messages
|
|
53
|
+
* Parameters: account_sid (required)
|
|
54
|
+
* Optional: to, from, date_sent, page_size
|
|
55
|
+
* Returns: Paginated list of Message resources
|
|
56
|
+
*
|
|
57
|
+
* ============================================================================
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
import 'dotenv/config';
|
|
61
|
+
import { MatimoInstance } from 'matimo';
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Run factory pattern examples for Twilio messaging tools
|
|
65
|
+
*/
|
|
66
|
+
async function runTwilioFactoryExamples() {
|
|
67
|
+
console.info('\n╔════════════════════════════════════════════════════════╗');
|
|
68
|
+
console.info('║ Twilio Tools - Factory Pattern ║');
|
|
69
|
+
console.info('║ (Direct execution - simplest approach) ║');
|
|
70
|
+
console.info('╚════════════════════════════════════════════════════════╝\n');
|
|
71
|
+
|
|
72
|
+
// Validate required environment variables
|
|
73
|
+
const accountSid = process.env.TWILIO_ACCOUNT_SID;
|
|
74
|
+
if (!accountSid) {
|
|
75
|
+
console.error('❌ Error: TWILIO_ACCOUNT_SID not set in .env');
|
|
76
|
+
console.info(' Set it: export TWILIO_ACCOUNT_SID="ACxxxxxxxxxx"');
|
|
77
|
+
console.info(' Get it from: https://console.twilio.com');
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const authToken = process.env.TWILIO_AUTH_TOKEN;
|
|
82
|
+
if (!authToken) {
|
|
83
|
+
console.error('❌ Error: TWILIO_AUTH_TOKEN not set in .env');
|
|
84
|
+
console.info(' Set it: export TWILIO_AUTH_TOKEN="your_auth_token"');
|
|
85
|
+
console.info(' Get it from: https://console.twilio.com');
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const fromNumber = process.env.TWILIO_FROM_NUMBER;
|
|
90
|
+
if (!fromNumber) {
|
|
91
|
+
console.error('❌ Error: TWILIO_FROM_NUMBER not set in .env');
|
|
92
|
+
console.info(' Set it: export TWILIO_FROM_NUMBER="+15557122661"');
|
|
93
|
+
console.info(' (Your Twilio phone number in E.164 format)');
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const toNumber = process.env.TWILIO_TO_NUMBER;
|
|
98
|
+
if (!toNumber) {
|
|
99
|
+
console.error('❌ Error: TWILIO_TO_NUMBER not set in .env');
|
|
100
|
+
console.info(' Set it: export TWILIO_TO_NUMBER="+15558675310"');
|
|
101
|
+
console.info(' (In trial mode, must be a verified caller ID)');
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
console.info(`🔑 Account SID: Configured.`);
|
|
106
|
+
console.info(`📤 From: ${fromNumber}`);
|
|
107
|
+
console.info(`📥 To: ${toNumber}\n`);
|
|
108
|
+
|
|
109
|
+
// Initialize Matimo with auto-discovery to find all @matimo/* packages
|
|
110
|
+
console.info('🚀 Initializing Matimo...');
|
|
111
|
+
const matimo = await MatimoInstance.init({ autoDiscover: true });
|
|
112
|
+
|
|
113
|
+
const allTools = matimo.listTools();
|
|
114
|
+
const twilioTools = allTools.filter((t) => t.name.startsWith('twilio-'));
|
|
115
|
+
console.info(`✅ Loaded ${allTools.length} tools total`);
|
|
116
|
+
console.info(
|
|
117
|
+
`🔧 Found ${twilioTools.length} Twilio tools: ${twilioTools.map((t) => t.name).join(', ')}\n`
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
console.info('════════════════════════════════════════════════════════════\n');
|
|
121
|
+
console.info('Running Examples:');
|
|
122
|
+
console.info('════════════════════════════════════════════════════════════\n');
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
// ── EXAMPLE 1: List recent messages ──────────────────────────────────
|
|
126
|
+
console.info('1️⃣ Listing recent messages...');
|
|
127
|
+
const listResult = await matimo.execute('twilio-list-messages', {
|
|
128
|
+
account_sid: accountSid,
|
|
129
|
+
page_size: 5,
|
|
130
|
+
});
|
|
131
|
+
const listData = (listResult as any).data || listResult;
|
|
132
|
+
|
|
133
|
+
if (listData.messages && Array.isArray(listData.messages)) {
|
|
134
|
+
const messages = listData.messages;
|
|
135
|
+
console.info(` ✅ Found ${messages.length} recent message(s)`);
|
|
136
|
+
messages.slice(0, 3).forEach((msg: any, idx: number) => {
|
|
137
|
+
console.info(
|
|
138
|
+
` ${idx + 1}. ${msg.sid} — ${msg.direction} — ${msg.status} — "${msg.body?.substring(0, 40)}"`
|
|
139
|
+
);
|
|
140
|
+
});
|
|
141
|
+
} else {
|
|
142
|
+
console.info(
|
|
143
|
+
` ℹ️ No messages found or unexpected response: ${JSON.stringify(listData).substring(0, 100)}`
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
console.info();
|
|
147
|
+
|
|
148
|
+
// ── EXAMPLE 2: Send SMS ───────────────────────────────────────────────
|
|
149
|
+
console.info('2️⃣ Sending SMS message...');
|
|
150
|
+
let sentMessageSid: string | undefined;
|
|
151
|
+
try {
|
|
152
|
+
const smsResult = await matimo.execute('twilio-send-sms', {
|
|
153
|
+
account_sid: accountSid,
|
|
154
|
+
to: toNumber,
|
|
155
|
+
from: fromNumber,
|
|
156
|
+
body: `Hello from Matimo! Factory pattern test at ${new Date().toISOString()}`,
|
|
157
|
+
});
|
|
158
|
+
const smsData = (smsResult as any).data || smsResult;
|
|
159
|
+
|
|
160
|
+
if (smsData.sid) {
|
|
161
|
+
sentMessageSid = smsData.sid;
|
|
162
|
+
console.info(` ✅ SMS queued successfully!`);
|
|
163
|
+
console.info(` SID: ${smsData.sid}`);
|
|
164
|
+
console.info(` Status: ${smsData.status}`);
|
|
165
|
+
console.info(` To: ${smsData.to}`);
|
|
166
|
+
console.info(` From: ${smsData.from}`);
|
|
167
|
+
} else {
|
|
168
|
+
console.info(` ❌ SMS failed: ${JSON.stringify(smsData).substring(0, 100)}`);
|
|
169
|
+
}
|
|
170
|
+
} catch (smsErr: any) {
|
|
171
|
+
const msg = smsErr?.message || String(smsErr);
|
|
172
|
+
console.info(` ⚠️ SMS skipped: ${msg}`);
|
|
173
|
+
if (fromNumber === toNumber) {
|
|
174
|
+
console.info(
|
|
175
|
+
` ℹ️ Tip: TWILIO_FROM_NUMBER and TWILIO_TO_NUMBER must be different numbers.`
|
|
176
|
+
);
|
|
177
|
+
console.info(` In trial mode, TWILIO_TO_NUMBER must be a verified caller ID.`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
console.info();
|
|
181
|
+
|
|
182
|
+
// ── EXAMPLE 3: Fetch the sent message ──────────────────────────────────
|
|
183
|
+
if (sentMessageSid) {
|
|
184
|
+
console.info('3️⃣ Fetching the sent message...');
|
|
185
|
+
try {
|
|
186
|
+
const fetchResult = await matimo.execute('twilio-get-message', {
|
|
187
|
+
account_sid: accountSid,
|
|
188
|
+
message_sid: sentMessageSid,
|
|
189
|
+
});
|
|
190
|
+
const fetchData = (fetchResult as any).data || fetchResult;
|
|
191
|
+
|
|
192
|
+
if (fetchData.sid) {
|
|
193
|
+
console.info(` ✅ Message fetched!`);
|
|
194
|
+
console.info(` SID: ${fetchData.sid}`);
|
|
195
|
+
console.info(` Status: ${fetchData.status}`);
|
|
196
|
+
console.info(` Direction: ${fetchData.direction}`);
|
|
197
|
+
console.info(` Num Segments: ${fetchData.num_segments}`);
|
|
198
|
+
console.info(` Date Created: ${fetchData.date_created}`);
|
|
199
|
+
} else {
|
|
200
|
+
console.info(
|
|
201
|
+
` ❌ Failed to fetch message: ${JSON.stringify(fetchData).substring(0, 100)}`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
} catch (fetchErr: any) {
|
|
205
|
+
console.info(` ⚠️ Fetch skipped: ${fetchErr?.message || fetchErr}`);
|
|
206
|
+
}
|
|
207
|
+
console.info();
|
|
208
|
+
} else {
|
|
209
|
+
console.info('3️⃣ Fetching sent message — skipped (no SMS was queued)');
|
|
210
|
+
console.info();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// ── EXAMPLE 4: List messages filtered by recipient ────────────────────
|
|
214
|
+
console.info('4️⃣ Listing messages filtered by recipient...');
|
|
215
|
+
const filteredResult = await matimo.execute('twilio-list-messages', {
|
|
216
|
+
account_sid: accountSid,
|
|
217
|
+
to: toNumber,
|
|
218
|
+
page_size: 5,
|
|
219
|
+
});
|
|
220
|
+
const filteredData = (filteredResult as any).data || filteredResult;
|
|
221
|
+
|
|
222
|
+
if (filteredData.messages && Array.isArray(filteredData.messages)) {
|
|
223
|
+
console.info(` ✅ Found ${filteredData.messages.length} message(s) sent to ${toNumber}`);
|
|
224
|
+
} else {
|
|
225
|
+
console.info(` ℹ️ Response: ${JSON.stringify(filteredData).substring(0, 100)}`);
|
|
226
|
+
}
|
|
227
|
+
console.info();
|
|
228
|
+
} catch (error) {
|
|
229
|
+
console.error('❌ Error:', error instanceof Error ? error.message : String(error));
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
console.info('════════════════════════════════════════════════════════════');
|
|
234
|
+
console.info('✨ Factory Pattern Example Complete!');
|
|
235
|
+
console.info('════════════════════════════════════════════════════════════\n');
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
runTwilioFactoryExamples().catch(console.error);
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ============================================================================
|
|
4
|
+
* TWILIO 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 Twilio 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
|
+
* TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
27
|
+
* TWILIO_AUTH_TOKEN=your_auth_token_here
|
|
28
|
+
* TWILIO_FROM_NUMBER=+15557122661
|
|
29
|
+
* TWILIO_TO_NUMBER=+15558675310
|
|
30
|
+
* OPENAI_API_KEY=sk-xxxxxxxxxxxxx
|
|
31
|
+
*
|
|
32
|
+
* Matimo automatically handles base64 Basic Auth encoding — no extra steps!
|
|
33
|
+
*
|
|
34
|
+
* USAGE:
|
|
35
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
36
|
+
* pnpm twilio:langchain
|
|
37
|
+
*
|
|
38
|
+
* WHAT IT DOES:
|
|
39
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
40
|
+
* This example shows an AI agent that can:
|
|
41
|
+
* 1. Check recent message history
|
|
42
|
+
* 2. Send SMS messages based on instructions
|
|
43
|
+
* 3. Retrieve message delivery status
|
|
44
|
+
* 4. Filter and search messages
|
|
45
|
+
*
|
|
46
|
+
* Example conversation:
|
|
47
|
+
* User: "Send a test SMS to my phone number"
|
|
48
|
+
* AI Agent: "I'll send a test SMS using twilio-send-sms..."
|
|
49
|
+
* [AI Agent calls twilio-send-sms tool]
|
|
50
|
+
* AI Agent: "Done! SMS sent successfully with SID: SM..."
|
|
51
|
+
*
|
|
52
|
+
* ============================================================================
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
import 'dotenv/config';
|
|
56
|
+
import { createAgent } from 'langchain';
|
|
57
|
+
import { ChatOpenAI } from '@langchain/openai';
|
|
58
|
+
import { MatimoInstance, convertToolsToLangChain, ToolDefinition } from 'matimo';
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Run Twilio AI Agent with LangChain
|
|
62
|
+
* The agent receives natural language requests and decides which Twilio tools to use
|
|
63
|
+
*/
|
|
64
|
+
async function runTwilioAIAgent() {
|
|
65
|
+
console.info('\n╔════════════════════════════════════════════════════════╗');
|
|
66
|
+
console.info('║ Twilio AI Agent - LangChain + OpenAI ║');
|
|
67
|
+
console.info('║ True autonomous agent with LLM reasoning ║');
|
|
68
|
+
console.info('╚════════════════════════════════════════════════════════╝\n');
|
|
69
|
+
|
|
70
|
+
// Check required environment variables
|
|
71
|
+
const accountSid = process.env.TWILIO_ACCOUNT_SID;
|
|
72
|
+
if (!accountSid) {
|
|
73
|
+
console.error('❌ Error: TWILIO_ACCOUNT_SID not set in .env');
|
|
74
|
+
console.info(' Set it: export TWILIO_ACCOUNT_SID="ACxxxxxxxxxx"');
|
|
75
|
+
console.info(' Get it from: https://console.twilio.com');
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const authToken = process.env.TWILIO_AUTH_TOKEN;
|
|
80
|
+
if (!authToken) {
|
|
81
|
+
console.error('❌ Error: TWILIO_AUTH_TOKEN not set in .env');
|
|
82
|
+
console.info(' Set it: export TWILIO_AUTH_TOKEN="your_auth_token"');
|
|
83
|
+
console.info(' Get it from: https://console.twilio.com');
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const fromNumber = process.env.TWILIO_FROM_NUMBER;
|
|
88
|
+
if (!fromNumber) {
|
|
89
|
+
console.error('❌ Error: TWILIO_FROM_NUMBER not set in .env');
|
|
90
|
+
console.info(' Set it: export TWILIO_FROM_NUMBER="+15557122661"');
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const toNumber = process.env.TWILIO_TO_NUMBER;
|
|
95
|
+
if (!toNumber) {
|
|
96
|
+
console.error('❌ Error: TWILIO_TO_NUMBER not set in .env');
|
|
97
|
+
console.info(' Set it: export TWILIO_TO_NUMBER="+15558675310"');
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const openaiKey = process.env.OPENAI_API_KEY;
|
|
102
|
+
if (!openaiKey) {
|
|
103
|
+
console.error('❌ Error: OPENAI_API_KEY not set in .env');
|
|
104
|
+
console.info(' Set it: export OPENAI_API_KEY="sk-..."');
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
console.info(`🔑 Account SID: Configured`);
|
|
109
|
+
console.info(`📤 From Number: ${fromNumber}`);
|
|
110
|
+
console.info(`📥 To Number: ${toNumber}`);
|
|
111
|
+
console.info(`🤖 Using OpenAI (GPT-4o-mini) as the AI agent\n`);
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
// Initialize Matimo with auto-discovery
|
|
115
|
+
console.info('🚀 Initializing Matimo...');
|
|
116
|
+
const matimo = await MatimoInstance.init({ autoDiscover: true });
|
|
117
|
+
|
|
118
|
+
// Get Twilio tools and convert to LangChain format
|
|
119
|
+
console.info('📱 Loading Twilio tools...');
|
|
120
|
+
const allTools = matimo.listTools();
|
|
121
|
+
const twilioTools = allTools.filter((t) => t.name.startsWith('twilio-'));
|
|
122
|
+
console.info(`✅ Loaded ${twilioTools.length} Twilio tools\n`);
|
|
123
|
+
|
|
124
|
+
// List recent messages first to give agent context
|
|
125
|
+
console.info('📋 Fetching recent messages for agent context...');
|
|
126
|
+
const listResult = await matimo.execute('twilio-list-messages', {
|
|
127
|
+
account_sid: accountSid,
|
|
128
|
+
page_size: 5,
|
|
129
|
+
});
|
|
130
|
+
const listData = (listResult as any).data || listResult;
|
|
131
|
+
const recentCount = listData.messages?.length ?? 0;
|
|
132
|
+
console.info(` ${recentCount} recent message(s) in account\n`);
|
|
133
|
+
|
|
134
|
+
// Convert Twilio tools to LangChain format using the Matimo integration
|
|
135
|
+
const langchainTools = await convertToolsToLangChain(twilioTools as ToolDefinition[], matimo);
|
|
136
|
+
|
|
137
|
+
// Initialize OpenAI LLM
|
|
138
|
+
console.info('🤖 Initializing OpenAI (GPT-4o-mini) LLM...');
|
|
139
|
+
const model = new ChatOpenAI({
|
|
140
|
+
modelName: 'gpt-4o-mini',
|
|
141
|
+
temperature: 0.7,
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Create agent
|
|
145
|
+
console.info('🔧 Creating agent...\n');
|
|
146
|
+
const agent = await createAgent({
|
|
147
|
+
model,
|
|
148
|
+
tools: langchainTools as any[], // Type casting for LangChain tools
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// Define agent tasks (natural language requests)
|
|
152
|
+
const userRequests = [
|
|
153
|
+
{
|
|
154
|
+
title: 'Example 1: Check message history',
|
|
155
|
+
request: `Check my recent Twilio message history. How many messages are there and what are their statuses?`,
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
title: 'Example 2: Send a test SMS',
|
|
159
|
+
request: `Send a test SMS from ${fromNumber} to ${toNumber} saying "Hello from the Matimo AI Agent! LangChain integration test." Use account SID .`,
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
title: 'Example 3: Check sent message status',
|
|
163
|
+
request: `List the 3 most recent messages sent from ${fromNumber} on my account and describe their delivery status.`,
|
|
164
|
+
},
|
|
165
|
+
];
|
|
166
|
+
|
|
167
|
+
console.info('🧪 Running AI Agent Tasks');
|
|
168
|
+
console.info('═'.repeat(60));
|
|
169
|
+
|
|
170
|
+
// Run each task through the agent
|
|
171
|
+
for (const task of userRequests) {
|
|
172
|
+
console.info(`\n${task.title}`);
|
|
173
|
+
console.info('─'.repeat(60));
|
|
174
|
+
console.info(`👤 User: "${task.request}"\n`);
|
|
175
|
+
|
|
176
|
+
try {
|
|
177
|
+
const response = await agent.invoke({
|
|
178
|
+
messages: [
|
|
179
|
+
{
|
|
180
|
+
role: 'user',
|
|
181
|
+
content: task.request,
|
|
182
|
+
},
|
|
183
|
+
],
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Get the last message from the agent
|
|
187
|
+
const lastMessage = response.messages[response.messages.length - 1];
|
|
188
|
+
if (lastMessage) {
|
|
189
|
+
if (typeof lastMessage.content === 'string') {
|
|
190
|
+
console.info(`🤖 Agent: ${lastMessage.content}\n`);
|
|
191
|
+
} else {
|
|
192
|
+
console.info(`🤖 Agent:`, lastMessage.content, '\n');
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
} catch (error) {
|
|
196
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
197
|
+
console.info(`⚠️ Agent error: ${errorMsg}\n`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
console.info('═'.repeat(60));
|
|
202
|
+
console.info('✨ AI Agent Examples Complete!\n');
|
|
203
|
+
console.info('Key Features:');
|
|
204
|
+
console.info(' ✅ Real LLM (OpenAI) decides which tools to use');
|
|
205
|
+
console.info(' ✅ Natural language requests, not API calls');
|
|
206
|
+
console.info(' ✅ LLM generates tool parameters based on context');
|
|
207
|
+
console.info(' ✅ Agentic reasoning and decision-making\n');
|
|
208
|
+
} catch (error) {
|
|
209
|
+
console.error('❌ Error:', error instanceof Error ? error.message : String(error));
|
|
210
|
+
if (error instanceof Error && error.stack) {
|
|
211
|
+
console.error('Stack:', error.stack);
|
|
212
|
+
}
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Run the AI agent
|
|
218
|
+
runTwilioAIAgent().catch(console.error);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { MatimoInstance, setGlobalMatimoInstance, tool } from '@matimo/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Example: Web tool using @tool decorator pattern
|
|
5
|
+
* Demonstrates class-based HTTP requests with automatic decoration
|
|
6
|
+
*/
|
|
7
|
+
class WebClient {
|
|
8
|
+
@tool('web')
|
|
9
|
+
async fetchUrl(url: string, timeout?: number): Promise<unknown> {
|
|
10
|
+
// Decorator automatically intercepts and executes via Matimo
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@tool('web')
|
|
15
|
+
async postData(url: string, body: string, headers?: Record<string, string>): 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('=== Web Tool - Decorator Pattern ===\n');
|
|
27
|
+
|
|
28
|
+
const client = new WebClient();
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
// Example 1: Fetch through decorated method
|
|
32
|
+
console.info('1. Fetching content via decorator\n');
|
|
33
|
+
const result1 = await client.fetchUrl('https://api.github.com/repos/tallclub/matimo');
|
|
34
|
+
console.info('Status:', (result1 as any).statusCode);
|
|
35
|
+
console.info('Size:', (result1 as any).contentLength);
|
|
36
|
+
console.info('---\n');
|
|
37
|
+
|
|
38
|
+
// Example 2: POST through decorated method
|
|
39
|
+
console.info('2. Posting data via decorator\n');
|
|
40
|
+
const result2 = await client.postData(
|
|
41
|
+
'https://httpbin.org/post',
|
|
42
|
+
JSON.stringify({ test: 'data' }),
|
|
43
|
+
{ 'Content-Type': 'application/json' }
|
|
44
|
+
);
|
|
45
|
+
console.info('Status:', (result2 as any).statusCode);
|
|
46
|
+
console.info('---\n');
|
|
47
|
+
} catch (error: any) {
|
|
48
|
+
console.error('Error:', error.message);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
decoratorExample();
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { MatimoInstance } from '@matimo/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Example: Web tool using factory pattern
|
|
5
|
+
* Demonstrates making HTTP requests and fetching web content
|
|
6
|
+
*/
|
|
7
|
+
async function webExample() {
|
|
8
|
+
// Initialize Matimo with autoDiscover to find all tools (core + providers)
|
|
9
|
+
const matimo = await MatimoInstance.init({ autoDiscover: true });
|
|
10
|
+
|
|
11
|
+
console.info('=== Web Tool - Factory Pattern ===\n');
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
// Example 1: Fetch GitHub API
|
|
15
|
+
console.info('1. Fetching GitHub API (public endpoint)\n');
|
|
16
|
+
const github = await matimo.execute('web', {
|
|
17
|
+
url: 'https://api.github.com/repos/tallclub/matimo',
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
console.info('Status Code:', (github as any).statusCode);
|
|
21
|
+
console.info('Content size:', (github as any).size);
|
|
22
|
+
// Content is already parsed as an object
|
|
23
|
+
const githubData =
|
|
24
|
+
typeof (github as any).content === 'string'
|
|
25
|
+
? JSON.parse((github as any).content)
|
|
26
|
+
: (github as any).content;
|
|
27
|
+
console.info('Repository:', githubData.full_name);
|
|
28
|
+
console.info('Description:', githubData.description);
|
|
29
|
+
console.info('---\n');
|
|
30
|
+
|
|
31
|
+
// Example 2: Fetch HTML content
|
|
32
|
+
console.info('2. Fetching HTML content\n');
|
|
33
|
+
const html = await matimo.execute('web', {
|
|
34
|
+
url: 'https://www.example.com',
|
|
35
|
+
timeout: 15000,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
console.info('Status Code:', (html as any).statusCode);
|
|
39
|
+
console.info('Content type:', (html as any).contentType);
|
|
40
|
+
console.info('Content size:', (html as any).size);
|
|
41
|
+
const htmlContent =
|
|
42
|
+
typeof (html as any).content === 'string'
|
|
43
|
+
? (html as any).content
|
|
44
|
+
: JSON.stringify((html as any).content);
|
|
45
|
+
console.info('Content preview:');
|
|
46
|
+
console.info(htmlContent.substring(0, 200));
|
|
47
|
+
console.info('---\n');
|
|
48
|
+
|
|
49
|
+
// Example 3: POST request
|
|
50
|
+
console.info('3. POST request (echo service)\n');
|
|
51
|
+
const post = await matimo.execute('web', {
|
|
52
|
+
url: 'https://httpbin.org/post',
|
|
53
|
+
method: 'POST',
|
|
54
|
+
body: JSON.stringify({ message: 'Hello from Matimo' }),
|
|
55
|
+
headers: { 'Content-Type': 'application/json' },
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
console.info('Status Code:', (post as any).statusCode);
|
|
59
|
+
const postContent =
|
|
60
|
+
typeof (post as any).content === 'string'
|
|
61
|
+
? (post as any).content
|
|
62
|
+
: JSON.stringify((post as any).content);
|
|
63
|
+
console.info('Response:', postContent.substring(0, 200));
|
|
64
|
+
console.info('---\n');
|
|
65
|
+
} catch (error: any) {
|
|
66
|
+
console.error('Error fetching web content:', error.message);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
webExample();
|