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,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);
|