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,309 @@
1
+ # Twilio Tools Examples
2
+
3
+ Example directory contains **3 example patterns** showing different ways to use Matimo's Twilio tools:
4
+
5
+ 1. **Factory Pattern** - Direct SDK execution (simplest)
6
+ 2. **Decorator Pattern** - Class-based with `@tool` decorators
7
+ 3. **LangChain Pattern** - AI-driven with OpenAI agent
8
+
9
+ All examples demonstrate real Twilio Messaging API operations (send SMS, send MMS, retrieve messages, list history).
10
+
11
+ ---
12
+
13
+ ## ๐Ÿš€ Quick Start
14
+
15
+ ### 1. Create a Twilio Account
16
+
17
+ 1. Go to [twilio.com/try-twilio](https://www.twilio.com/try-twilio) and sign up for a free account
18
+ 2. After verifying your email and phone number, you'll land on the **Twilio Console** dashboard
19
+
20
+ ### 2. Find Your Account SID and Auth Token
21
+
22
+ On the [Twilio Console dashboard](https://console.twilio.com), look for the **Account Info** section:
23
+
24
+ - **Account SID** โ€” a 34-character identifier starting with `AC`. Acts as your username for every API call.
25
+ - **Auth Token** โ€” a 32-character secret key. Click the **eye (๐Ÿ‘) icon** to reveal it.
26
+
27
+ > โš ๏ธ **Keep both values secret.** Do not commit them to version control.
28
+
29
+ ### 3. Get a Phone Number
30
+
31
+ 1. In the Console sidebar, go to **Phone Numbers โ†’ Manage โ†’ Buy a Number**
32
+ 2. Choose a number with SMS capability
33
+ 3. Click **Buy** (free trial credit covers this)
34
+ 4. This will be your `TWILIO_FROM_NUMBER`
35
+
36
+ > **Trial accounts**: You can also use the number auto-assigned to your trial account, shown on the Console dashboard.
37
+
38
+ ### 4. Verify Your "To" Number (Trial Accounts Only)
39
+
40
+ Free trial accounts can only send messages to **Verified Caller IDs**:
41
+
42
+ 1. Go to **Phone Numbers โ†’ Manage โ†’ Verified Caller IDs**
43
+ 2. Click **Add a new Caller ID**
44
+ 3. Enter the phone number you want to send messages to
45
+ 4. Complete the verification call or SMS
46
+
47
+ ### 5. Set Up Environment Variables
48
+
49
+ Create or update `.env` in `examples/tools/`:
50
+
51
+ ```env
52
+ TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
53
+ TWILIO_AUTH_TOKEN=your_auth_token_here
54
+ TWILIO_FROM_NUMBER=+15557122661
55
+ TWILIO_TO_NUMBER=+15558675310
56
+ OPENAI_API_KEY=sk-your-openai-key-here # Required for LangChain example only
57
+ ```
58
+
59
+ > **Note:** All phone numbers must be in **E.164 format** (e.g. `+15551234567`).
60
+ > Matimo automatically handles Basic Auth encoding โ€” no manual base64 encoding required.
61
+
62
+ ### 6. Run Examples
63
+
64
+ ```bash
65
+ # From examples/tools/ directory
66
+
67
+ # Factory Pattern (simplest, direct API calls)
68
+ pnpm twilio:factory
69
+
70
+ # Decorator Pattern (class-based OOP approach)
71
+ pnpm twilio:decorator
72
+
73
+ # LangChain Pattern (AI-driven agent with OpenAI)
74
+ pnpm twilio:langchain
75
+ ```
76
+
77
+ ---
78
+
79
+ ## ๐Ÿ“š Examples Overview
80
+
81
+ ### 1. Factory Pattern (`twilio-factory.ts`)
82
+
83
+ **Best for:** Scripts, quick tests, CLI tools
84
+
85
+ **What it does:**
86
+ - โœ… Direct tool execution with `matimo.execute()`
87
+ - โœ… Validates environment variables before running
88
+ - โœ… Sends an SMS via `twilio-send-sms`
89
+ - โœ… Retrieves the sent message via `twilio-get-message`
90
+ - โœ… Lists recent messages via `twilio-list-messages`
91
+ - โœ… Simplest implementation
92
+
93
+ **Run it:**
94
+ ```bash
95
+ pnpm twilio:factory
96
+ ```
97
+
98
+ **Key Code:**
99
+ ```typescript
100
+ const matimo = await MatimoInstance.init('./tools');
101
+
102
+ // Send SMS
103
+ await matimo.execute('twilio-send-sms', {
104
+ account_sid: process.env.TWILIO_ACCOUNT_SID,
105
+ to: '+15558675310',
106
+ from: '+15557122661',
107
+ body: 'Hello from Matimo!'
108
+ });
109
+
110
+ // List recent messages
111
+ await matimo.execute('twilio-list-messages', {
112
+ account_sid: process.env.TWILIO_ACCOUNT_SID,
113
+ page_size: 5
114
+ });
115
+ ```
116
+
117
+ **File:** [twilio-factory.ts](twilio-factory.ts)
118
+
119
+ ---
120
+
121
+ ### 2. Decorator Pattern (`twilio-decorator.ts`)
122
+
123
+ **Best for:** Object-oriented design, class-based applications, service wrappers
124
+
125
+ **What it does:**
126
+ - โœ… Class methods decorated with `@tool`
127
+ - โœ… Automatic tool execution via decorators
128
+ - โœ… Account SID bound at construction time and reused
129
+ - โœ… Sends SMS, retrieves messages, lists history
130
+ - โœ… OOP-friendly approach
131
+
132
+ **Run it:**
133
+ ```bash
134
+ pnpm twilio:decorator
135
+ ```
136
+
137
+ **Key Code:**
138
+ ```typescript
139
+ class TwilioDecoratorAgent {
140
+ constructor(private readonly accountSid: string) {}
141
+
142
+ @tool('twilio-send-sms')
143
+ async sendSms(account_sid: string, to: string, from: string, body: string) {
144
+ // @tool decorator auto-executes via matimo.execute()
145
+ return undefined;
146
+ }
147
+
148
+ @tool('twilio-list-messages')
149
+ async listMessages(account_sid: string, page_size?: number) {
150
+ return undefined;
151
+ }
152
+ }
153
+
154
+ const agent = new TwilioDecoratorAgent(process.env.TWILIO_ACCOUNT_SID!);
155
+ await agent.sendSms(accountSid, '+15558675310', '+15557122661', 'Hello!');
156
+ ```
157
+
158
+ **File:** [twilio-decorator.ts](twilio-decorator.ts)
159
+
160
+ ---
161
+
162
+ ### 3. LangChain AI Agent (`twilio-langchain.ts`)
163
+
164
+ **Best for:** True autonomous agents with AI reasoning
165
+
166
+ **What it does:**
167
+ - โœ… AI agent (OpenAI GPT-4o-mini) decides which Twilio tools to use
168
+ - โœ… Takes natural language instructions
169
+ - โœ… Autonomously executes Twilio operations
170
+ - โœ… Processes results and responds naturally
171
+ - โœ… Multi-step reasoning (e.g. send then verify delivery status)
172
+
173
+ **Run it:**
174
+ ```bash
175
+ pnpm twilio:langchain
176
+ ```
177
+
178
+ **Example Conversation:**
179
+ ```
180
+ User: "Send a test SMS to my verified number and check its delivery status"
181
+ AI Agent: I'll send the SMS first using twilio-send-sms...
182
+ [AI calls twilio-send-sms tool]
183
+ AI Agent: Message sent with SID SM1234... Now checking delivery status...
184
+ [AI calls twilio-get-message tool]
185
+ AI Agent: The message was delivered successfully. Status: delivered.
186
+ ```
187
+
188
+ **Key Code:**
189
+ ```typescript
190
+ const agent = await createAgent({
191
+ model: new ChatOpenAI({ modelName: 'gpt-4o-mini' }),
192
+ tools: langchainTools // AI picks which Twilio tools to use
193
+ });
194
+
195
+ const response = await agent.invoke({
196
+ messages: [{ role: 'user', content: 'Send a test SMS to my number' }]
197
+ });
198
+ ```
199
+
200
+ **File:** [twilio-langchain.ts](twilio-langchain.ts)
201
+
202
+ ---
203
+
204
+ ## ๐Ÿ› ๏ธ Available Twilio Tools (4 Total)
205
+
206
+ All patterns have access to these 4 Twilio tools:
207
+
208
+ | Tool | Method | Description |
209
+ |------|--------|-------------|
210
+ | `twilio-send-sms` | POST | Send an SMS message |
211
+ | `twilio-send-mms` | POST | Send an MMS message with media |
212
+ | `twilio-get-message` | GET | Retrieve a message by SID |
213
+ | `twilio-list-messages` | GET | List messages with optional filters |
214
+
215
+ ### Tool Parameters
216
+
217
+ #### `twilio-send-sms`
218
+ | Parameter | Type | Required | Description |
219
+ |-----------|------|----------|-------------|
220
+ | `account_sid` | string | โœ… | Your Twilio Account SID (`AC...`) |
221
+ | `to` | string | โœ… | Recipient phone number (E.164) |
222
+ | `from` | string | โœ… | Twilio phone number (E.164) |
223
+ | `body` | string | โœ… | SMS message text |
224
+ | `status_callback` | string | โŒ | URL for delivery status webhooks |
225
+
226
+ #### `twilio-send-mms`
227
+ | Parameter | Type | Required | Description |
228
+ |-----------|------|----------|-------------|
229
+ | `account_sid` | string | โœ… | Your Twilio Account SID (`AC...`) |
230
+ | `to` | string | โœ… | Recipient phone number (E.164) |
231
+ | `from` | string | โœ… | Twilio phone number (E.164) |
232
+ | `media_url` | string | โœ… | Publicly accessible URL of the media file |
233
+ | `body` | string | โŒ | Optional text caption |
234
+ | `status_callback` | string | โŒ | URL for delivery status webhooks |
235
+
236
+ #### `twilio-get-message`
237
+ | Parameter | Type | Required | Description |
238
+ |-----------|------|----------|-------------|
239
+ | `account_sid` | string | โœ… | Your Twilio Account SID (`AC...`) |
240
+ | `message_sid` | string | โœ… | Message SID (`SM...`) to retrieve |
241
+
242
+ #### `twilio-list-messages`
243
+ | Parameter | Type | Required | Description |
244
+ |-----------|------|----------|-------------|
245
+ | `account_sid` | string | โœ… | Your Twilio Account SID (`AC...`) |
246
+ | `to` | string | โŒ | Filter by recipient number |
247
+ | `from` | string | โŒ | Filter by sender number |
248
+ | `date_sent` | string | โŒ | Filter by date (YYYY-MM-DD) |
249
+ | `page_size` | number | โŒ | Results per page (default 50, max 1000) |
250
+
251
+ ---
252
+
253
+ ## ๐Ÿงช Trial Account Limitations
254
+
255
+ | Limitation | Details |
256
+ |-----------|---------|
257
+ | **Daily message limit** | 50 messages/day |
258
+ | **Recipients** | Must be Verified Caller IDs only |
259
+ | **Trial prefix** | All outgoing messages include `"Sent from your Twilio trial account -"` |
260
+ | **Geographic reach** | Sending to some international numbers may be restricted |
261
+ | **Phone numbers** | 1 trial number provided free |
262
+ | **WhatsApp** | Not available on trial |
263
+
264
+ To remove these limitations, [upgrade to a paid account](https://console.twilio.com/us1/billing/upgrade).
265
+
266
+ ---
267
+
268
+ ## ๐Ÿ”ง Troubleshooting
269
+
270
+ ### `โŒ Error 21659: From number is not a valid, SMS-capable Twilio number`
271
+ Your `TWILIO_FROM_NUMBER` is not a Twilio number on your account, or it doesn't have SMS capability.
272
+ **Fix:** Go to [Phone Numbers โ†’ Manage โ†’ Active Numbers](https://console.twilio.com/us1/develop/phone-numbers/manage/active) and confirm the number is SMS-capable.
273
+
274
+ ### `โŒ Error 21211: Invalid To phone number`
275
+ The `to` number is not in E.164 format or is not a valid phone number.
276
+ **Fix:** Use format `+15551234567` (country code + number, no dashes or spaces).
277
+
278
+ ### `โŒ Error 21408: Permission to send to this region is not enabled`
279
+ Your account doesn't have permission to send to that country.
280
+ **Fix:** Go to [Messaging โ†’ Settings โ†’ Geo Permissions](https://console.twilio.com/us1/develop/sms/settings/geo-permissions) and enable the target region.
281
+
282
+ ### `โŒ Error 21266: Unverified phone number in To field during trial`
283
+ You're on a trial account and the recipient number is not a Verified Caller ID.
284
+ **Fix:** Add the number at [Phone Numbers โ†’ Manage โ†’ Verified Caller IDs](https://console.twilio.com/us1/develop/phone-numbers/manage/verified).
285
+
286
+ ### `โŒ 401 Unauthorized / Error 20003: Authentication Failed`
287
+ Your `TWILIO_ACCOUNT_SID` or `TWILIO_AUTH_TOKEN` is incorrect.
288
+ **Fix:** Copy both values directly from the [Console dashboard](https://console.twilio.com). Matimo handles Basic Auth encoding automatically.
289
+
290
+ ### `TWILIO_ACCOUNT_SID not set in .env`
291
+ The `account_sid` parameter is required for all Twilio tools.
292
+ **Fix:** Add `TWILIO_ACCOUNT_SID=ACxxxxxxxx` to `examples/tools/.env`.
293
+
294
+ ### Messages have an unexpected prefix
295
+ Trial accounts automatically prepend `"Sent from your Twilio trial account - "` to all messages. This is removed when you upgrade to a paid account.
296
+
297
+ ### `OPENAI_API_KEY not set` (LangChain example only)
298
+ The LangChain agent requires an OpenAI API key.
299
+ **Fix:** Get one at [platform.openai.com/api-keys](https://platform.openai.com/api-keys) and add `OPENAI_API_KEY=sk-...` to your `.env`.
300
+
301
+ ---
302
+
303
+ ## ๐Ÿ”— Related Documentation
304
+
305
+ - [Matimo Twilio Package](../../../packages/twilio/README.md)
306
+ - [Twilio Messages API Reference](https://www.twilio.com/docs/messaging/api/message-resource)
307
+ - [Twilio Console](https://console.twilio.com)
308
+ - [Twilio Free Trial Guide](https://www.twilio.com/docs/messaging/guides/how-to-use-your-free-trial-account)
309
+ - [Matimo SDK Docs](../../../packages/core/README.md)
@@ -0,0 +1,288 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ============================================================================
4
+ * TWILIO TOOLS - DECORATOR PATTERN EXAMPLE
5
+ * ============================================================================
6
+ *
7
+ * PATTERN: Decorator Pattern with @tool
8
+ * โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
9
+ * Uses TypeScript @tool decorators to wrap Twilio 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
+ * TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
22
+ * TWILIO_AUTH_TOKEN=your_auth_token_here
23
+ * TWILIO_FROM_NUMBER=+15557122661
24
+ * TWILIO_TO_NUMBER=+15558675310
25
+ *
26
+ * Matimo automatically handles base64 Basic Auth encoding โ€” no extra steps!
27
+ *
28
+ * USAGE:
29
+ * โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
30
+ * pnpm twilio:decorator
31
+ *
32
+ * ============================================================================
33
+ */
34
+
35
+ import 'dotenv/config';
36
+ import { MatimoInstance, tool, setGlobalMatimoInstance } from 'matimo';
37
+
38
+ /**
39
+ * Decorator Pattern Agent - Uses @tool decorators for Twilio messaging operations.
40
+ * The account_sid is bound at construction time and reused in all tool calls.
41
+ */
42
+ class TwilioDecoratorAgent {
43
+ constructor(private readonly accountSid: string) {}
44
+
45
+ /**
46
+ * Send an SMS message - automatically executes via @tool decorator
47
+ */
48
+ @tool('twilio-send-sms')
49
+ async sendSms(
50
+ account_sid: string,
51
+ to: string,
52
+ from: string,
53
+ body: string,
54
+ status_callback?: string
55
+ ): Promise<unknown> {
56
+ // Decorator automatically calls: matimo.execute('twilio-send-sms', { account_sid, to, from, body, status_callback })
57
+ return undefined;
58
+ }
59
+
60
+ /**
61
+ * Send an MMS message with media - automatically executes via @tool decorator
62
+ */
63
+ @tool('twilio-send-mms')
64
+ async sendMms(
65
+ account_sid: string,
66
+ to: string,
67
+ from: string,
68
+ media_url: string,
69
+ body?: string
70
+ ): Promise<unknown> {
71
+ // Decorator automatically calls: matimo.execute('twilio-send-mms', { account_sid, to, from, media_url, body })
72
+ return undefined;
73
+ }
74
+
75
+ /**
76
+ * Fetch a message by SID - automatically executes via @tool decorator
77
+ */
78
+ @tool('twilio-get-message')
79
+ async getMessage(account_sid: string, message_sid: string): Promise<unknown> {
80
+ // Decorator automatically calls: matimo.execute('twilio-get-message', { account_sid, message_sid })
81
+ return undefined;
82
+ }
83
+
84
+ /**
85
+ * List messages with optional filters - automatically executes via @tool decorator
86
+ */
87
+ @tool('twilio-list-messages')
88
+ async listMessages(
89
+ account_sid: string,
90
+ to?: string,
91
+ from?: string,
92
+ date_sent?: string,
93
+ page_size?: number
94
+ ): Promise<unknown> {
95
+ // Decorator automatically calls: matimo.execute('twilio-list-messages', { account_sid, to, from, date_sent, page_size })
96
+ return undefined;
97
+ }
98
+
99
+ // โ”€โ”€ Convenience helpers that bind account_sid automatically โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
100
+
101
+ /** Send SMS using the bound account SID */
102
+ async sms(to: string, from: string, body: string): Promise<unknown> {
103
+ return this.sendSms(this.accountSid, to, from, body);
104
+ }
105
+
106
+ /** Send MMS using the bound account SID */
107
+ async mms(to: string, from: string, mediaUrl: string, body?: string): Promise<unknown> {
108
+ return this.sendMms(this.accountSid, to, from, mediaUrl, body);
109
+ }
110
+
111
+ /** Fetch a message using the bound account SID */
112
+ async fetch(messageSid: string): Promise<unknown> {
113
+ return this.getMessage(this.accountSid, messageSid);
114
+ }
115
+
116
+ /** List recent messages using the bound account SID */
117
+ async list(
118
+ options: { to?: string; from?: string; dateSent?: string; pageSize?: number } = {}
119
+ ): Promise<unknown> {
120
+ return this.listMessages(
121
+ this.accountSid,
122
+ options.to,
123
+ options.from,
124
+ options.dateSent,
125
+ options.pageSize
126
+ );
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Run decorator pattern examples
132
+ */
133
+ async function runTwilioDecoratorExamples() {
134
+ console.info('โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—');
135
+ console.info('โ•‘ Twilio Tools - Decorator Pattern โ•‘');
136
+ console.info('โ•‘ (Uses @tool decorators for automatic execution) โ•‘');
137
+ console.info('โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•\n');
138
+
139
+ // Validate required environment variables
140
+ const accountSid = process.env.TWILIO_ACCOUNT_SID;
141
+ const authToken = process.env.TWILIO_AUTH_TOKEN;
142
+ const fromNumber = process.env.TWILIO_FROM_NUMBER;
143
+ const toNumber = process.env.TWILIO_TO_NUMBER;
144
+
145
+ if (!accountSid) {
146
+ console.info('๐Ÿ” Warning: TWILIO_ACCOUNT_SID not set in environment');
147
+ console.info(' Set it: export TWILIO_ACCOUNT_SID="ACxxxxxxxxxx"');
148
+ console.info(' Get it from: https://console.twilio.com\n');
149
+ }
150
+
151
+ if (!authToken) {
152
+ console.info('๐Ÿ” Warning: TWILIO_AUTH_TOKEN not set');
153
+ console.info(' Set it: export TWILIO_AUTH_TOKEN="your_auth_token"\n');
154
+ }
155
+
156
+ if (!fromNumber || !toNumber) {
157
+ console.info('๐Ÿ“ฑ Warning: TWILIO_FROM_NUMBER or TWILIO_TO_NUMBER not set\n');
158
+ }
159
+
160
+ if (!accountSid || !authToken || !fromNumber || !toNumber) {
161
+ console.info('โš ๏ธ Missing credentials โ€” skipping live API calls.\n');
162
+ }
163
+
164
+ console.info(`๐Ÿ”‘ Account SID: ${accountSid ? 'Configured' : '(not set)'}`);
165
+ console.info(`๐Ÿ“ค From: ${fromNumber || '(not set)'}`);
166
+ console.info(`๐Ÿ“ฅ To: ${toNumber || '(not set)'}\n`);
167
+
168
+ try {
169
+ // Initialize Matimo with auto-discovery
170
+ console.info('๐Ÿš€ Initializing Matimo...');
171
+ const matimo = await MatimoInstance.init({ autoDiscover: true });
172
+ setGlobalMatimoInstance(matimo);
173
+
174
+ const allTools = matimo.listTools();
175
+ const twilioTools = allTools.filter((t) => t.name.startsWith('twilio-'));
176
+ console.info(`๐Ÿ“ฆ Loaded ${allTools.length} total tools, ${twilioTools.length} Twilio tools\n`);
177
+
178
+ // Create agent with bound account SID
179
+ const agent = new TwilioDecoratorAgent(accountSid || 'ACxxxxxxxx');
180
+
181
+ console.info('๐Ÿงช Testing Twilio Tools with Decorator Pattern');
182
+ console.info('โ•'.repeat(60) + '\n');
183
+
184
+ // โ”€โ”€ Example 1: List recent messages โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
185
+ console.info('๐Ÿ“‹ Example 1: List Recent Messages');
186
+ console.info('โ”€'.repeat(60));
187
+ try {
188
+ const listResult = await agent.list({ pageSize: 5 });
189
+ const listData = (listResult as any).data || listResult;
190
+
191
+ if (listData.messages && Array.isArray(listData.messages)) {
192
+ console.info(`โœ… Found ${listData.messages.length} recent message(s):`);
193
+ listData.messages.slice(0, 3).forEach((msg: any, idx: number) => {
194
+ console.info(
195
+ ` ${idx + 1}. ${msg.sid} โ€” ${msg.status} โ€” "${msg.body?.substring(0, 40)}"`
196
+ );
197
+ });
198
+ } else {
199
+ console.info(`โ„น๏ธ Response: ${JSON.stringify(listData).substring(0, 100)}`);
200
+ }
201
+ } catch (error) {
202
+ console.info(`โŒ Error: ${error instanceof Error ? error.message : String(error)}`);
203
+ }
204
+ console.info();
205
+
206
+ // โ”€โ”€ Example 2: Send SMS โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
207
+ console.info('๐Ÿ’ฌ Example 2: Send SMS Message');
208
+ console.info('โ”€'.repeat(60));
209
+
210
+ if (!accountSid || !fromNumber || !toNumber) {
211
+ console.info('โญ๏ธ Skipping โ€” credentials not set');
212
+ } else {
213
+ try {
214
+ const smsResult = await agent.sms(
215
+ toNumber,
216
+ fromNumber,
217
+ `๐Ÿ‘‹ Hello from Matimo! Decorator pattern test at ${new Date().toISOString()}`
218
+ );
219
+ const smsData = (smsResult as any).data || smsResult;
220
+
221
+ if (smsData.sid) {
222
+ console.info(`โœ… SMS queued successfully!`);
223
+ console.info(` SID: ${smsData.sid}`);
224
+ console.info(` Status: ${smsData.status}`);
225
+ console.info(` To: ${smsData.to}`);
226
+
227
+ // โ”€โ”€ Example 3: Fetch the sent message โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
228
+ console.info();
229
+ console.info('๐Ÿ” Example 3: Fetch the Sent Message');
230
+ console.info('โ”€'.repeat(60));
231
+ const fetchResult = await agent.fetch(smsData.sid);
232
+ const fetchData = (fetchResult as any).data || fetchResult;
233
+
234
+ if (fetchData.sid) {
235
+ console.info(`โœ… Message fetched!`);
236
+ console.info(` Status: ${fetchData.status}`);
237
+ console.info(` Direction: ${fetchData.direction}`);
238
+ console.info(` Num Segments: ${fetchData.num_segments}`);
239
+ } else {
240
+ console.info(`โŒ Failed: ${JSON.stringify(fetchData).substring(0, 100)}`);
241
+ }
242
+ } else {
243
+ console.info(`โŒ SMS failed: ${JSON.stringify(smsData).substring(0, 100)}`);
244
+ }
245
+ } catch (error) {
246
+ console.info(`โŒ Error: ${error instanceof Error ? error.message : String(error)}`);
247
+ }
248
+ }
249
+ console.info();
250
+
251
+ // โ”€โ”€ Example 4: List messages filtered by sender โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
252
+ console.info('๐Ÿ“Š Example 4: List Messages Filtered by Sender');
253
+ console.info('โ”€'.repeat(60));
254
+
255
+ if (!accountSid || !fromNumber) {
256
+ console.info('โญ๏ธ Skipping โ€” credentials not set');
257
+ } else {
258
+ try {
259
+ const fromResult = await agent.list({ from: fromNumber, pageSize: 5 });
260
+ const fromData = (fromResult as any).data || fromResult;
261
+
262
+ if (fromData.messages && Array.isArray(fromData.messages)) {
263
+ console.info(`โœ… Found ${fromData.messages.length} message(s) from ${fromNumber}`);
264
+ fromData.messages.slice(0, 3).forEach((msg: any, idx: number) => {
265
+ console.info(` ${idx + 1}. ${msg.sid} โ€” ${msg.status}`);
266
+ });
267
+ } else {
268
+ console.info(`โ„น๏ธ Response: ${JSON.stringify(fromData).substring(0, 100)}`);
269
+ }
270
+ } catch (error) {
271
+ console.info(`โŒ Error: ${error instanceof Error ? error.message : String(error)}`);
272
+ }
273
+ }
274
+
275
+ console.info('\n' + 'โ•'.repeat(60));
276
+ console.info('โœจ Decorator Pattern Example Complete!');
277
+ console.info('โ•'.repeat(60) + '\n');
278
+ } catch (error) {
279
+ console.error('โŒ Fatal error:', error instanceof Error ? error.message : String(error));
280
+ process.exit(1);
281
+ }
282
+ }
283
+
284
+ // Run the example
285
+ runTwilioDecoratorExamples().catch((error) => {
286
+ console.error('โŒ Unhandled error:', error);
287
+ process.exit(1);
288
+ });