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.
Files changed (57) hide show
  1. package/.env.example +49 -0
  2. package/LICENSE +21 -0
  3. package/README.md +525 -0
  4. package/agents/decorator-pattern-agent.ts +368 -0
  5. package/agents/factory-pattern-agent.ts +253 -0
  6. package/agents/langchain-agent.ts +146 -0
  7. package/edit/edit-decorator.ts +178 -0
  8. package/edit/edit-factory.ts +138 -0
  9. package/edit/edit-langchain.ts +292 -0
  10. package/execute/execute-decorator.ts +49 -0
  11. package/execute/execute-factory.ts +46 -0
  12. package/execute/execute-langchain.ts +232 -0
  13. package/github/github-decorator.ts +326 -0
  14. package/github/github-factory.ts +355 -0
  15. package/github/github-langchain.ts +206 -0
  16. package/github/github-with-approval.ts +228 -0
  17. package/gmail/README.md +345 -0
  18. package/gmail/gmail-decorator.ts +216 -0
  19. package/gmail/gmail-factory.ts +231 -0
  20. package/gmail/gmail-langchain.ts +201 -0
  21. package/hubspot/README.md +316 -0
  22. package/hubspot/hubspot-decorator.ts +180 -0
  23. package/hubspot/hubspot-factory.ts +188 -0
  24. package/hubspot/hubspot-langchain.ts +222 -0
  25. package/logger-example.ts +40 -0
  26. package/mailchimp/README.md +321 -0
  27. package/mailchimp/mailchimp-decorator.ts +277 -0
  28. package/mailchimp/mailchimp-factory.ts +187 -0
  29. package/mailchimp/mailchimp-langchain.ts +155 -0
  30. package/notion/README.md +293 -0
  31. package/notion/notion-decorator.ts +275 -0
  32. package/notion/notion-factory.ts +256 -0
  33. package/notion/notion-langchain.ts +237 -0
  34. package/package.json +79 -0
  35. package/postgres/README.md +188 -0
  36. package/postgres/postgres-decorator.ts +198 -0
  37. package/postgres/postgres-factory.ts +180 -0
  38. package/postgres/postgres-langchain.ts +213 -0
  39. package/postgres/postgres-with-approval.ts +344 -0
  40. package/read/read-decorator.ts +154 -0
  41. package/read/read-factory.ts +121 -0
  42. package/read/read-langchain.ts +273 -0
  43. package/search/search-decorator.ts +206 -0
  44. package/search/search-factory.ts +146 -0
  45. package/search/search-langchain.ts +255 -0
  46. package/slack/README.md +339 -0
  47. package/slack/slack-decorator.ts +245 -0
  48. package/slack/slack-factory.ts +226 -0
  49. package/slack/slack-langchain.ts +242 -0
  50. package/tsconfig.json +20 -0
  51. package/twilio/README.md +309 -0
  52. package/twilio/twilio-decorator.ts +288 -0
  53. package/twilio/twilio-factory.ts +238 -0
  54. package/twilio/twilio-langchain.ts +218 -0
  55. package/web/web-decorator.ts +52 -0
  56. package/web/web-factory.ts +70 -0
  57. 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();