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,154 @@
1
+ import {
2
+ MatimoInstance,
3
+ setGlobalMatimoInstance,
4
+ tool,
5
+ getGlobalApprovalHandler,
6
+ type ApprovalRequest,
7
+ } from '@matimo/core';
8
+ import path from 'path';
9
+ import { fileURLToPath } from 'url';
10
+ import * as readline from 'readline';
11
+
12
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
13
+
14
+ /**
15
+ * Create an interactive approval callback
16
+ */
17
+ function createApprovalCallback() {
18
+ return async (request: ApprovalRequest): Promise<boolean> => {
19
+ const isInteractive = process.stdin.isTTY;
20
+
21
+ console.info('\n' + '='.repeat(70));
22
+ console.info('๐Ÿ”’ APPROVAL REQUIRED FOR FILE OPERATION');
23
+ console.info('='.repeat(70));
24
+ console.info(`\n๐Ÿ“‹ Tool: ${request.toolName}`);
25
+ console.info(`๐Ÿ“ Description: ${request.description || '(no description provided)'}`);
26
+ console.info(`\n๐Ÿ“„ File Operation:`);
27
+ console.info(` Path: ${request.params.filePath}`);
28
+ if (request.params.startLine) {
29
+ console.info(` Start Line: ${request.params.startLine}`);
30
+ }
31
+ if (request.params.endLine) {
32
+ console.info(` End Line: ${request.params.endLine}`);
33
+ }
34
+
35
+ if (!isInteractive) {
36
+ console.info('\nโŒ REJECTED - Non-interactive environment (no terminal)');
37
+ console.info('\n๐Ÿ’ก To enable auto-approval in CI/scripts:');
38
+ console.info(' export MATIMO_AUTO_APPROVE=true');
39
+ console.info('\n๐Ÿ’ก Or approve specific patterns:');
40
+ console.info(' export MATIMO_APPROVED_PATTERNS="read"');
41
+ console.info('\n' + '='.repeat(70) + '\n');
42
+ return false;
43
+ }
44
+
45
+ // Interactive mode: prompt user
46
+ const rl = readline.createInterface({
47
+ input: process.stdin,
48
+ output: process.stdout,
49
+ });
50
+
51
+ return new Promise((resolve) => {
52
+ console.info('\nโ“ User Action Required');
53
+ const question = ' Type "yes" to approve or "no" to reject: ';
54
+
55
+ rl.question(question, (answer) => {
56
+ const approved = answer.toLowerCase() === 'yes' || answer.toLowerCase() === 'y';
57
+
58
+ if (approved) {
59
+ console.info(' โœ… Operation APPROVED by user');
60
+ } else {
61
+ console.info(' โŒ Operation REJECTED by user');
62
+ }
63
+ console.info('='.repeat(70) + '\n');
64
+
65
+ rl.close();
66
+ resolve(approved);
67
+ });
68
+ });
69
+ };
70
+ }
71
+
72
+ /**
73
+ * Example: Read tool using @tool decorator pattern
74
+ * Demonstrates class-based file reading with automatic decoration
75
+ */
76
+ class FileReader {
77
+ @tool('read')
78
+ async readFile(filePath: string, startLine: number, endLine: number): Promise<unknown> {
79
+ // Decorator automatically intercepts and executes via Matimo
80
+ return undefined;
81
+ }
82
+
83
+ @tool('read')
84
+ async getFileMetadata(filePath: string): Promise<unknown> {
85
+ // Decorator automatically intercepts and executes via Matimo
86
+ return undefined;
87
+ }
88
+ }
89
+
90
+ async function decoratorExample() {
91
+ // Set up decorator support with autoDiscover
92
+ const matimo = await MatimoInstance.init({ autoDiscover: true });
93
+ setGlobalMatimoInstance(matimo);
94
+
95
+ // Configure centralized approval handler
96
+ const approvalHandler = getGlobalApprovalHandler();
97
+ approvalHandler.setApprovalCallback(createApprovalCallback());
98
+
99
+ console.info('\n' + '='.repeat(70));
100
+ console.info('๐Ÿš€ Read Tool - Decorator Pattern Example');
101
+ console.info('='.repeat(70));
102
+
103
+ // Show current approval mode
104
+ const autoApproveEnabled = process.env.MATIMO_AUTO_APPROVE === 'true';
105
+ const approvedPatterns = process.env.MATIMO_APPROVED_PATTERNS;
106
+
107
+ console.info('\n๐Ÿ” APPROVAL CONFIGURATION:');
108
+ if (autoApproveEnabled) {
109
+ console.info(' โœ… MATIMO_AUTO_APPROVE=true');
110
+ console.info(' โ†’ All file read operations will be AUTO-APPROVED');
111
+ } else if (approvedPatterns) {
112
+ console.info(` โœ… MATIMO_APPROVED_PATTERNS="${approvedPatterns}"`);
113
+ console.info(' โ†’ Matching operations will be auto-approved');
114
+ } else {
115
+ console.info(' โš ๏ธ INTERACTIVE MODE ENABLED');
116
+ console.info(' โ†’ You will be prompted to approve file operations');
117
+ }
118
+
119
+ const reader = new FileReader();
120
+
121
+ try {
122
+ // Example 1: Read file through decorated method
123
+ console.info('\n1๏ธโƒฃ READING FILE WITH LINE RANGE');
124
+ console.info('-'.repeat(70));
125
+ console.info('Reading read-factory.ts (lines 1-15)\n');
126
+ const result1 = await reader.readFile(path.join(__dirname, './read-factory.ts'), 1, 15);
127
+ if (result1) {
128
+ console.info('โœ… File:', (result1 as any).filePath);
129
+ console.info('๐Ÿ“Š Lines read:', (result1 as any).readLines);
130
+ console.info('๐Ÿ“ Content preview:');
131
+ console.info((result1 as any).content?.substring(0, 150) + '...');
132
+ }
133
+ console.info('---\n');
134
+
135
+ // Example 2: Read another file
136
+ console.info('2๏ธโƒฃ READING ENTIRE FILE');
137
+ console.info('-'.repeat(70));
138
+ console.info('Reading package.json (all lines)\n');
139
+ const result2 = await reader.getFileMetadata(path.join(__dirname, '../../../package.json'));
140
+ if (result2) {
141
+ console.info('โœ… File:', (result2 as any).filePath);
142
+ console.info('๐Ÿ“Š Lines read:', (result2 as any).readLines);
143
+ console.info('๐Ÿ“ Content preview:');
144
+ console.info((result2 as any).content?.substring(0, 150) + '...');
145
+ }
146
+ console.info('---\n');
147
+
148
+ console.info('โœ… Decorator example completed successfully');
149
+ } catch (error: any) {
150
+ console.error('โŒ Error:', error.message);
151
+ }
152
+ }
153
+
154
+ decoratorExample();
@@ -0,0 +1,121 @@
1
+ import { MatimoInstance, getGlobalApprovalHandler, type ApprovalRequest } from '@matimo/core';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import * as readline from 'readline';
5
+
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
+
8
+ /**
9
+ * Create an interactive approval callback for file operations
10
+ */
11
+ function createApprovalCallback() {
12
+ return async (request: ApprovalRequest): Promise<boolean> => {
13
+ const isInteractive = process.stdin.isTTY;
14
+
15
+ console.info('\n' + '='.repeat(70));
16
+ console.info('๐Ÿ”’ APPROVAL REQUIRED FOR FILE OPERATION');
17
+ console.info('='.repeat(70));
18
+ console.info(`\n๐Ÿ“‹ Tool: ${request.toolName}`);
19
+ console.info(`๐Ÿ“ Description: ${request.description || '(no description provided)'}`);
20
+ console.info(`\n๐Ÿ“„ File Operation:`);
21
+ console.info(` Path: ${request.params.filePath}`);
22
+ if (request.params.startLine) {
23
+ console.info(` Start Line: ${request.params.startLine}`);
24
+ }
25
+ if (request.params.endLine) {
26
+ console.info(` End Line: ${request.params.endLine}`);
27
+ }
28
+
29
+ if (!isInteractive) {
30
+ console.info('\nโŒ REJECTED - Non-interactive environment (no terminal)');
31
+ console.info('\n๐Ÿ’ก To enable auto-approval in CI/scripts:');
32
+ console.info(' export MATIMO_AUTO_APPROVE=true');
33
+ console.info('\n๐Ÿ’ก Or approve specific patterns:');
34
+ console.info(' export MATIMO_APPROVED_PATTERNS="read"');
35
+ console.info('\n' + '='.repeat(70) + '\n');
36
+ return false;
37
+ }
38
+
39
+ // Interactive mode: prompt user
40
+ const rl = readline.createInterface({
41
+ input: process.stdin,
42
+ output: process.stdout,
43
+ });
44
+
45
+ return new Promise((resolve) => {
46
+ console.info('\nโ“ User Action Required');
47
+ const question = ' Type "yes" to approve or "no" to reject: ';
48
+
49
+ rl.question(question, (answer) => {
50
+ const approved = answer.toLowerCase() === 'yes' || answer.toLowerCase() === 'y';
51
+
52
+ if (approved) {
53
+ console.info(' โœ… Operation APPROVED by user');
54
+ } else {
55
+ console.info(' โŒ Operation REJECTED by user');
56
+ }
57
+ console.info('='.repeat(70) + '\n');
58
+
59
+ rl.close();
60
+ resolve(approved);
61
+ });
62
+ });
63
+ };
64
+ }
65
+
66
+ /**
67
+ * Example: Read tool using factory pattern
68
+ * Demonstrates reading file contents and metadata with interactive approval
69
+ */
70
+ async function readExample() {
71
+ // Initialize Matimo with autoDiscover to find all tools (core + providers)
72
+ const matimo = await MatimoInstance.init({ autoDiscover: true });
73
+
74
+ // Configure centralized approval handler
75
+ const approvalHandler = getGlobalApprovalHandler();
76
+ approvalHandler.setApprovalCallback(createApprovalCallback());
77
+
78
+ console.info('=== Read Tool - Factory Pattern (Interactive Approval) ===\n');
79
+
80
+ try {
81
+ // Example 1: Read this example file
82
+ console.info('1. Reading read-factory.ts\n');
83
+ const result1 = await matimo.execute('read', {
84
+ filePath: path.join(__dirname, './read-factory.ts'),
85
+ startLine: 1,
86
+ endLine: 20,
87
+ });
88
+
89
+ if ((result1 as any).success) {
90
+ console.info('File:', (result1 as any).filePath);
91
+ console.info('Lines read:', (result1 as any).readLines);
92
+ console.info('Content preview:');
93
+ console.info((result1 as any).content?.substring(0, 300));
94
+ } else {
95
+ console.info('Access denied:', (result1 as any).error);
96
+ }
97
+ console.info('---\n');
98
+
99
+ // Example 2: Read package.json
100
+ console.info('2. Reading package.json\n');
101
+ const result2 = await matimo.execute('read', {
102
+ filePath: path.join(__dirname, '../../../package.json'),
103
+ startLine: 1,
104
+ endLine: 15,
105
+ });
106
+
107
+ if ((result2 as any).success) {
108
+ console.info('File:', (result2 as any).filePath);
109
+ console.info('Lines read:', (result2 as any).readLines);
110
+ console.info('Content preview:');
111
+ console.info((result2 as any).content?.substring(0, 200));
112
+ } else {
113
+ console.info('Access denied:', (result2 as any).error);
114
+ }
115
+ console.info('---\n');
116
+ } catch (error: any) {
117
+ console.error('Error reading file:', error.message, error.code, error.details);
118
+ }
119
+ }
120
+
121
+ readExample();
@@ -0,0 +1,273 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ============================================================================
4
+ * READ 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 read files
12
+ * 3. Generates appropriate file paths and line ranges based on context
13
+ * 4. Executes tools autonomously
14
+ * 5. Processes results and responds naturally
15
+ *
16
+ * SETUP:
17
+ * โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
18
+ * 1. Create .env file in examples/tools/:
19
+ * OPENAI_API_KEY=sk-xxxxxxxxxxxxx
20
+ *
21
+ * 2. Install dependencies:
22
+ * cd examples/tools && npm install
23
+ *
24
+ * USAGE:
25
+ * โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
26
+ * # From root directory:
27
+ * pnpm read:langchain
28
+ *
29
+ * # Or from examples/tools directory:
30
+ * npm run read:langchain
31
+ *
32
+ * ============================================================================
33
+ */
34
+
35
+ import 'dotenv/config';
36
+ import fs from 'fs';
37
+ import path from 'path';
38
+ import { fileURLToPath } from 'url';
39
+ import * as readline from 'readline';
40
+ import { createAgent } from 'langchain';
41
+ import { ChatOpenAI } from '@langchain/openai';
42
+ import {
43
+ MatimoInstance,
44
+ convertToolsToLangChain,
45
+ type ToolDefinition,
46
+ getGlobalApprovalHandler,
47
+ type ApprovalRequest,
48
+ } from '@matimo/core';
49
+
50
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
51
+
52
+ /**
53
+ * Create an interactive approval callback for file operations
54
+ */
55
+ function createApprovalCallback() {
56
+ return async (request: ApprovalRequest): Promise<boolean> => {
57
+ const isInteractive = process.stdin.isTTY;
58
+
59
+ console.info('\n' + '='.repeat(70));
60
+ console.info('๐Ÿ”’ APPROVAL REQUIRED FOR FILE OPERATION');
61
+ console.info('='.repeat(70));
62
+ console.info(`\n๐Ÿ“‹ Tool: ${request.toolName}`);
63
+ console.info(`๐Ÿ“ Description: ${request.description || '(no description provided)'}`);
64
+ console.info(`\n๐Ÿ“„ File Operation:`);
65
+ console.info(` Path: ${request.params.filePath}`);
66
+ if (request.params.startLine) {
67
+ console.info(` Start Line: ${request.params.startLine}`);
68
+ }
69
+ if (request.params.endLine) {
70
+ console.info(` End Line: ${request.params.endLine}`);
71
+ }
72
+
73
+ if (!isInteractive) {
74
+ console.info('\nโŒ REJECTED - Non-interactive environment (no terminal)');
75
+ console.info('\n๐Ÿ’ก To enable auto-approval in CI/scripts:');
76
+ console.info(' export MATIMO_AUTO_APPROVE=true');
77
+ console.info('\n๐Ÿ’ก Or approve specific patterns:');
78
+ console.info(' export MATIMO_APPROVED_PATTERNS="read"');
79
+ console.info('\n' + '='.repeat(70) + '\n');
80
+ return false;
81
+ }
82
+
83
+ // Interactive mode: prompt user
84
+ const rl = readline.createInterface({
85
+ input: process.stdin,
86
+ output: process.stdout,
87
+ });
88
+
89
+ return new Promise((resolve) => {
90
+ console.info('\nโ“ User Action Required');
91
+ const question = ' Type "yes" to approve or "no" to reject: ';
92
+
93
+ rl.question(question, (answer) => {
94
+ const approved = answer.toLowerCase() === 'yes' || answer.toLowerCase() === 'y';
95
+
96
+ if (approved) {
97
+ console.info(' โœ… Operation APPROVED by user');
98
+ } else {
99
+ console.info(' โŒ Operation REJECTED by user');
100
+ }
101
+ console.info('='.repeat(70) + '\n');
102
+
103
+ rl.close();
104
+ resolve(approved);
105
+ });
106
+ });
107
+ };
108
+ }
109
+
110
+ /**
111
+ * Run AI Agent with Read tool
112
+ * The agent receives natural language requests and decides which files to read
113
+ */
114
+ async function runReadAIAgent() {
115
+ console.info('\nโ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—');
116
+ console.info('โ•‘ Read Tool AI Agent - LangChain + OpenAI โ•‘');
117
+ console.info('โ•‘ True autonomous agent with LLM reasoning โ•‘');
118
+ console.info('โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•\n');
119
+
120
+ // Check required environment variables
121
+ const openaiKey = process.env.OPENAI_API_KEY;
122
+ if (!openaiKey) {
123
+ console.error('โŒ Error: OPENAI_API_KEY not set in .env');
124
+ console.info(' Set it: export OPENAI_API_KEY="sk-..."');
125
+ process.exit(1);
126
+ }
127
+
128
+ console.info('๐Ÿค– Using OpenAI (GPT-4o-mini) as the AI agent\n');
129
+
130
+ // Create a sample file for the agent to read
131
+ const sampleFile = path.join(__dirname, 'sample-code.ts');
132
+ fs.writeFileSync(
133
+ sampleFile,
134
+ `// Sample TypeScript file
135
+ interface User {
136
+ id: string;
137
+ name: string;
138
+ email: string;
139
+ }
140
+
141
+ function getUserInfo(userId: string): User {
142
+ // Fetch user from database
143
+ return {
144
+ id: userId,
145
+ name: 'John Doe',
146
+ email: 'john@example.com',
147
+ };
148
+ }
149
+
150
+ function validateEmail(email: string): boolean {
151
+ const pattern = /^[^@]+@[^@]+\\.[^@]+$/;
152
+ return pattern.test(email);
153
+ }
154
+
155
+ export { getUserInfo, validateEmail };
156
+ `
157
+ );
158
+
159
+ try {
160
+ // Initialize Matimo with auto-discovery
161
+ console.info('๐Ÿš€ Initializing Matimo...');
162
+ const matimo = await MatimoInstance.init({ autoDiscover: true });
163
+
164
+ // Configure centralized approval handler
165
+ const approvalHandler = getGlobalApprovalHandler();
166
+ approvalHandler.setApprovalCallback(createApprovalCallback());
167
+
168
+ // Get read tool
169
+ console.info('๐Ÿ’ฌ Loading read tool...');
170
+ const matimoTools = matimo.listTools();
171
+ const readTools = matimoTools.filter((t) => t.name === 'read') as ToolDefinition[];
172
+ console.info(`โœ… Loaded ${readTools.length} read tool(s)\n`);
173
+
174
+ if (readTools.length === 0) {
175
+ console.error('โŒ Read tool not found');
176
+ process.exit(1);
177
+ }
178
+
179
+ // Convert to LangChain tools using the built-in converter
180
+ const langchainTools = await convertToolsToLangChain(readTools, matimo);
181
+
182
+ // Initialize OpenAI LLM
183
+ console.info('๐Ÿค– Initializing OpenAI (GPT-4o-mini) LLM...');
184
+ const model = new ChatOpenAI({
185
+ modelName: 'gpt-4o-mini',
186
+ temperature: 0.7,
187
+ });
188
+
189
+ // Create agent
190
+ console.info('๐Ÿ”ง Creating agent...\n');
191
+ const agent = await createAgent({
192
+ model,
193
+ tools: langchainTools as any,
194
+ });
195
+
196
+ // Define agent tasks (natural language requests)
197
+ const userRequests = [
198
+ {
199
+ title: 'Example 1: Read function definition',
200
+ request: `Read the getUserInfo function from file ${sampleFile}`,
201
+ },
202
+ {
203
+ title: 'Example 2: Read specific lines',
204
+ request: `Read lines 1-10 from file ${sampleFile} and tell me what interfaces are defined`,
205
+ },
206
+ {
207
+ title: 'Example 3: Read entire file',
208
+ request: `Show me the complete content of file ${sampleFile}`,
209
+ },
210
+ ];
211
+
212
+ console.info('๐Ÿงช Running AI Agent Tasks');
213
+ console.info('โ•'.repeat(60) + '\n');
214
+
215
+ // Run each task through the agent
216
+ for (const task of userRequests) {
217
+ console.info(`${task.title}`);
218
+ console.info('โ”€'.repeat(60));
219
+ console.info(`๐Ÿ‘ค User: "${task.request}"\n`);
220
+
221
+ try {
222
+ const response = await agent.invoke({
223
+ messages: [
224
+ {
225
+ role: 'user',
226
+ content: task.request,
227
+ },
228
+ ],
229
+ });
230
+
231
+ // Get the last message from the agent
232
+ const lastMessage = response.messages[response.messages.length - 1];
233
+ if (lastMessage) {
234
+ const content =
235
+ typeof lastMessage.content === 'string'
236
+ ? lastMessage.content
237
+ : String(lastMessage.content);
238
+
239
+ if (content && content.trim()) {
240
+ console.info(`๐Ÿค– Agent: ${content}\n`);
241
+ } else {
242
+ console.info('๐Ÿค– Agent: (File read successfully)\n');
243
+ }
244
+ }
245
+ } catch (error) {
246
+ const errorMsg = error instanceof Error ? error.message : String(error);
247
+ console.info(`โš ๏ธ Agent error: ${errorMsg}\n`);
248
+ }
249
+ }
250
+
251
+ console.info('โ•'.repeat(60));
252
+ console.info('\nโœจ AI Agent Examples Complete!\n');
253
+ console.info('Key Features:');
254
+ console.info(' โœ… Real LLM (OpenAI) decides which tools to use');
255
+ console.info(' โœ… Natural language requests, not API calls');
256
+ console.info(' โœ… LLM determines file paths and line ranges');
257
+ console.info(' โœ… Agentic reasoning and decision-making\n');
258
+ } catch (error) {
259
+ console.error('โŒ Error:', error instanceof Error ? error.message : String(error));
260
+ if (error instanceof Error && error.stack) {
261
+ console.error('Stack:', error.stack);
262
+ }
263
+ process.exit(1);
264
+ } finally {
265
+ // Clean up
266
+ if (fs.existsSync(sampleFile)) {
267
+ fs.unlinkSync(sampleFile);
268
+ }
269
+ }
270
+ }
271
+
272
+ // Run the AI agent
273
+ runReadAIAgent().catch(console.error);