@matimo/core 0.1.0-alpha.10
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/LICENSE +21 -0
- package/README.md +252 -0
- package/destructive-keywords.yaml +70 -0
- package/dist/approval/approval-handler.d.ts +74 -0
- package/dist/approval/approval-handler.d.ts.map +1 -0
- package/dist/approval/approval-handler.js +210 -0
- package/dist/approval/approval-handler.js.map +1 -0
- package/dist/auth/oauth2-config.d.ts +104 -0
- package/dist/auth/oauth2-config.d.ts.map +1 -0
- package/dist/auth/oauth2-config.js +38 -0
- package/dist/auth/oauth2-config.js.map +1 -0
- package/dist/auth/oauth2-handler.d.ts +130 -0
- package/dist/auth/oauth2-handler.d.ts.map +1 -0
- package/dist/auth/oauth2-handler.js +265 -0
- package/dist/auth/oauth2-handler.js.map +1 -0
- package/dist/auth/oauth2-provider-loader.d.ts +68 -0
- package/dist/auth/oauth2-provider-loader.d.ts.map +1 -0
- package/dist/auth/oauth2-provider-loader.js +120 -0
- package/dist/auth/oauth2-provider-loader.js.map +1 -0
- package/dist/core/schema.d.ts +259 -0
- package/dist/core/schema.d.ts.map +1 -0
- package/dist/core/schema.js +187 -0
- package/dist/core/schema.js.map +1 -0
- package/dist/core/tool-loader.d.ts +57 -0
- package/dist/core/tool-loader.d.ts.map +1 -0
- package/dist/core/tool-loader.js +250 -0
- package/dist/core/tool-loader.js.map +1 -0
- package/dist/core/tool-registry.d.ts +48 -0
- package/dist/core/tool-registry.d.ts.map +1 -0
- package/dist/core/tool-registry.js +93 -0
- package/dist/core/tool-registry.js.map +1 -0
- package/dist/core/types.d.ts +162 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +5 -0
- package/dist/core/types.js.map +1 -0
- package/dist/decorators/index.d.ts +2 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +2 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/tool-decorator.d.ts +97 -0
- package/dist/decorators/tool-decorator.d.ts.map +1 -0
- package/dist/decorators/tool-decorator.js +157 -0
- package/dist/decorators/tool-decorator.js.map +1 -0
- package/dist/encodings/parameter-encoding.d.ts +51 -0
- package/dist/encodings/parameter-encoding.d.ts.map +1 -0
- package/dist/encodings/parameter-encoding.js +124 -0
- package/dist/encodings/parameter-encoding.js.map +1 -0
- package/dist/errors/matimo-error.d.ts +41 -0
- package/dist/errors/matimo-error.d.ts.map +1 -0
- package/dist/errors/matimo-error.js +71 -0
- package/dist/errors/matimo-error.js.map +1 -0
- package/dist/executors/command-executor.d.ts +19 -0
- package/dist/executors/command-executor.d.ts.map +1 -0
- package/dist/executors/command-executor.js +98 -0
- package/dist/executors/command-executor.js.map +1 -0
- package/dist/executors/function-executor.d.ts +23 -0
- package/dist/executors/function-executor.d.ts.map +1 -0
- package/dist/executors/function-executor.js +181 -0
- package/dist/executors/function-executor.js.map +1 -0
- package/dist/executors/http-executor.d.ts +78 -0
- package/dist/executors/http-executor.d.ts.map +1 -0
- package/dist/executors/http-executor.js +279 -0
- package/dist/executors/http-executor.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/langchain.d.ts +46 -0
- package/dist/integrations/langchain.d.ts.map +1 -0
- package/dist/integrations/langchain.js +197 -0
- package/dist/integrations/langchain.js.map +1 -0
- package/dist/logging/index.d.ts +3 -0
- package/dist/logging/index.d.ts.map +1 -0
- package/dist/logging/index.js +3 -0
- package/dist/logging/index.js.map +1 -0
- package/dist/logging/logger.d.ts +96 -0
- package/dist/logging/logger.d.ts.map +1 -0
- package/dist/logging/logger.js +53 -0
- package/dist/logging/logger.js.map +1 -0
- package/dist/logging/winston-logger.d.ts +29 -0
- package/dist/logging/winston-logger.d.ts.map +1 -0
- package/dist/logging/winston-logger.js +73 -0
- package/dist/logging/winston-logger.js.map +1 -0
- package/dist/matimo-instance.d.ts +140 -0
- package/dist/matimo-instance.d.ts.map +1 -0
- package/dist/matimo-instance.js +412 -0
- package/dist/matimo-instance.js.map +1 -0
- package/package.json +96 -0
- package/tools/calculator/calculator.ts +145 -0
- package/tools/calculator/definition.yaml +70 -0
- package/tools/edit/definition.yaml +115 -0
- package/tools/edit/edit.ts +187 -0
- package/tools/execute/definition.yaml +90 -0
- package/tools/execute/execute.ts +207 -0
- package/tools/read/definition.yaml +106 -0
- package/tools/read/read.ts +118 -0
- package/tools/search/definition.yaml +148 -0
- package/tools/search/search.ts +192 -0
- package/tools/web/definition.yaml +132 -0
- package/tools/web/web.ts +134 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
name: read
|
|
2
|
+
version: '1.0.0'
|
|
3
|
+
description: Read file contents with support for line ranges, encoding detection, and large file handling.
|
|
4
|
+
requires_approval: true
|
|
5
|
+
|
|
6
|
+
parameters:
|
|
7
|
+
filePath:
|
|
8
|
+
type: string
|
|
9
|
+
description: Absolute or relative path to file to read (supports ~ for home directory)
|
|
10
|
+
required: true
|
|
11
|
+
example: './src/config.ts'
|
|
12
|
+
|
|
13
|
+
startLine:
|
|
14
|
+
type: number
|
|
15
|
+
description: Starting line number (1-based, inclusive). If not provided, reads from beginning.
|
|
16
|
+
required: false
|
|
17
|
+
example: 10
|
|
18
|
+
|
|
19
|
+
endLine:
|
|
20
|
+
type: number
|
|
21
|
+
description: Ending line number (1-based, inclusive). If not provided, reads to end of file.
|
|
22
|
+
required: false
|
|
23
|
+
example: 50
|
|
24
|
+
|
|
25
|
+
encoding:
|
|
26
|
+
type: string
|
|
27
|
+
description: File encoding (utf8, utf16, ascii, latin1). Defaults to utf8.
|
|
28
|
+
required: false
|
|
29
|
+
default: 'utf8'
|
|
30
|
+
example: 'utf8'
|
|
31
|
+
|
|
32
|
+
maxLines:
|
|
33
|
+
type: number
|
|
34
|
+
description: Maximum lines to read (default 10000, useful for large files). Returns error if exceeded.
|
|
35
|
+
required: false
|
|
36
|
+
example: 5000
|
|
37
|
+
|
|
38
|
+
execution:
|
|
39
|
+
type: function
|
|
40
|
+
code: './read.ts'
|
|
41
|
+
|
|
42
|
+
output_schema:
|
|
43
|
+
type: object
|
|
44
|
+
properties:
|
|
45
|
+
success:
|
|
46
|
+
type: boolean
|
|
47
|
+
description: Whether file read was successful
|
|
48
|
+
filePath:
|
|
49
|
+
type: string
|
|
50
|
+
description: Path to the file that was read
|
|
51
|
+
content:
|
|
52
|
+
type: string
|
|
53
|
+
description: File content (or file excerpt if line range specified)
|
|
54
|
+
encoding:
|
|
55
|
+
type: string
|
|
56
|
+
description: Encoding used for file read
|
|
57
|
+
lineCount:
|
|
58
|
+
type: number
|
|
59
|
+
description: Total number of lines in file (if known)
|
|
60
|
+
readLines:
|
|
61
|
+
type: number
|
|
62
|
+
description: Number of lines actually read
|
|
63
|
+
linesRequested:
|
|
64
|
+
type: object
|
|
65
|
+
properties:
|
|
66
|
+
start:
|
|
67
|
+
type: number
|
|
68
|
+
end:
|
|
69
|
+
type: number
|
|
70
|
+
size:
|
|
71
|
+
type: number
|
|
72
|
+
description: File size in bytes
|
|
73
|
+
mtime:
|
|
74
|
+
type: string
|
|
75
|
+
description: Last modified time (ISO format)
|
|
76
|
+
required: [success, filePath, content, encoding, readLines]
|
|
77
|
+
|
|
78
|
+
error_handling:
|
|
79
|
+
retry: 1
|
|
80
|
+
backoff_type: exponential
|
|
81
|
+
initial_delay_ms: 300
|
|
82
|
+
|
|
83
|
+
examples:
|
|
84
|
+
- name: 'Read entire file'
|
|
85
|
+
description: 'Read complete file contents'
|
|
86
|
+
params:
|
|
87
|
+
filePath: './config.json'
|
|
88
|
+
- name: 'Read specific line range'
|
|
89
|
+
description: 'Read lines 10-50 from file'
|
|
90
|
+
params:
|
|
91
|
+
filePath: './src/app.ts'
|
|
92
|
+
startLine: 10
|
|
93
|
+
endLine: 50
|
|
94
|
+
- name: 'Read single line'
|
|
95
|
+
description: 'Read exactly line 42'
|
|
96
|
+
params:
|
|
97
|
+
filePath: './package.json'
|
|
98
|
+
startLine: 42
|
|
99
|
+
endLine: 42
|
|
100
|
+
- name: 'Read with encoding'
|
|
101
|
+
description: 'Read file with specific encoding'
|
|
102
|
+
params:
|
|
103
|
+
filePath: './data/records.csv'
|
|
104
|
+
encoding: 'latin1'
|
|
105
|
+
|
|
106
|
+
tags: [file-io, read, filesystem, text, content]
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Read Tool - Read file contents with line range support
|
|
4
|
+
* Function-type tool: Exports default async function
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import { MatimoError, ErrorCode } from '@matimo/core';
|
|
10
|
+
|
|
11
|
+
interface ReadParams {
|
|
12
|
+
filePath: string;
|
|
13
|
+
startLine?: number;
|
|
14
|
+
endLine?: number;
|
|
15
|
+
encoding?: string;
|
|
16
|
+
maxLines?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface ReadResult {
|
|
20
|
+
success: boolean;
|
|
21
|
+
filePath: string;
|
|
22
|
+
content: string;
|
|
23
|
+
encoding: string;
|
|
24
|
+
readLines: number;
|
|
25
|
+
lineCount?: number;
|
|
26
|
+
linesRequested?: {
|
|
27
|
+
start?: number;
|
|
28
|
+
end?: number;
|
|
29
|
+
};
|
|
30
|
+
size: number;
|
|
31
|
+
mtime: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Read file contents with optional line range
|
|
36
|
+
*/
|
|
37
|
+
export default async function readTool(params: ReadParams): Promise<ReadResult> {
|
|
38
|
+
const { filePath, startLine, endLine, encoding = 'utf8', maxLines = 10000 } = params;
|
|
39
|
+
|
|
40
|
+
// Validate required parameter
|
|
41
|
+
if (!filePath) {
|
|
42
|
+
throw new MatimoError('Missing required parameter', ErrorCode.INVALID_PARAMETER, {
|
|
43
|
+
reason: 'filePath is required',
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Resolve path
|
|
48
|
+
const resolvedPath = filePath.startsWith('~')
|
|
49
|
+
? path.join(process.env.HOME || '/', filePath.slice(1))
|
|
50
|
+
: path.isAbsolute(filePath)
|
|
51
|
+
? filePath
|
|
52
|
+
: path.resolve(process.cwd(), filePath);
|
|
53
|
+
|
|
54
|
+
// Check file exists
|
|
55
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
56
|
+
throw new MatimoError('File not found', ErrorCode.FILE_NOT_FOUND, {
|
|
57
|
+
filePath: resolvedPath,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Get file stats
|
|
62
|
+
const stats = fs.statSync(resolvedPath);
|
|
63
|
+
if (!stats.isFile()) {
|
|
64
|
+
throw new MatimoError('Not a file', ErrorCode.EXECUTION_FAILED, {
|
|
65
|
+
filePath: resolvedPath,
|
|
66
|
+
reason: 'Path exists but is not a file',
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (stats.size > 50 * 1024 * 1024) {
|
|
71
|
+
throw new MatimoError('File too large', ErrorCode.EXECUTION_FAILED, {
|
|
72
|
+
filePath: resolvedPath,
|
|
73
|
+
size: stats.size,
|
|
74
|
+
maxSize: 50 * 1024 * 1024,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Read file
|
|
79
|
+
const content = fs.readFileSync(resolvedPath, encoding as BufferEncoding);
|
|
80
|
+
const lines = content.split('\n');
|
|
81
|
+
|
|
82
|
+
// Check line count
|
|
83
|
+
if (lines.length > maxLines) {
|
|
84
|
+
throw new MatimoError('File exceeds maxLines limit', ErrorCode.EXECUTION_FAILED, {
|
|
85
|
+
filePath: resolvedPath,
|
|
86
|
+
lineCount: lines.length,
|
|
87
|
+
maxLines,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Handle line range request
|
|
92
|
+
let readContent = content;
|
|
93
|
+
let readLines = lines.length;
|
|
94
|
+
const linesRequested: { start?: number; end?: number } = {};
|
|
95
|
+
|
|
96
|
+
if (startLine !== undefined || endLine !== undefined) {
|
|
97
|
+
const start = Math.max(0, (startLine || 1) - 1); // Convert to 0-based
|
|
98
|
+
const end = Math.min(lines.length, (endLine || lines.length)); // Convert to 0-based exclusive
|
|
99
|
+
readContent = lines.slice(start, end).join('\n');
|
|
100
|
+
readLines = end - start;
|
|
101
|
+
linesRequested.start = startLine;
|
|
102
|
+
linesRequested.end = endLine;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const result: ReadResult = {
|
|
106
|
+
success: true,
|
|
107
|
+
filePath: resolvedPath,
|
|
108
|
+
content: readContent,
|
|
109
|
+
encoding,
|
|
110
|
+
readLines,
|
|
111
|
+
lineCount: lines.length,
|
|
112
|
+
linesRequested: Object.keys(linesRequested).length > 0 ? linesRequested : undefined,
|
|
113
|
+
size: stats.size,
|
|
114
|
+
mtime: stats.mtime.toISOString(),
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
name: search
|
|
2
|
+
version: '1.0.0'
|
|
3
|
+
description: Search files by name or content using patterns and regex
|
|
4
|
+
requires_approval: true
|
|
5
|
+
|
|
6
|
+
parameters:
|
|
7
|
+
query:
|
|
8
|
+
type: string
|
|
9
|
+
description: Search query (file pattern or text to find)
|
|
10
|
+
required: true
|
|
11
|
+
example: 'MatimoInstance'
|
|
12
|
+
|
|
13
|
+
directory:
|
|
14
|
+
type: string
|
|
15
|
+
description: Directory to search (default current directory)
|
|
16
|
+
required: false
|
|
17
|
+
example: './src'
|
|
18
|
+
|
|
19
|
+
filePattern:
|
|
20
|
+
type: string
|
|
21
|
+
description: File glob pattern (e.g. '*.ts', '**/*.test.ts')
|
|
22
|
+
required: false
|
|
23
|
+
example: '*.ts'
|
|
24
|
+
|
|
25
|
+
isRegex:
|
|
26
|
+
type: boolean
|
|
27
|
+
description: Treat query as regex (default false)
|
|
28
|
+
required: false
|
|
29
|
+
default: false
|
|
30
|
+
|
|
31
|
+
caseSensitive:
|
|
32
|
+
type: boolean
|
|
33
|
+
description: Case-sensitive search (default false)
|
|
34
|
+
required: false
|
|
35
|
+
default: false
|
|
36
|
+
|
|
37
|
+
excludePatterns:
|
|
38
|
+
type: array
|
|
39
|
+
description: Glob patterns to exclude
|
|
40
|
+
required: false
|
|
41
|
+
example: ['node_modules/**', 'dist/**']
|
|
42
|
+
|
|
43
|
+
maxResults:
|
|
44
|
+
type: number
|
|
45
|
+
description: Maximum results to return (default 50)
|
|
46
|
+
required: false
|
|
47
|
+
default: 50
|
|
48
|
+
|
|
49
|
+
contextLines:
|
|
50
|
+
type: number
|
|
51
|
+
description: Context lines around matches (default 2)
|
|
52
|
+
required: false
|
|
53
|
+
default: 2
|
|
54
|
+
|
|
55
|
+
execution:
|
|
56
|
+
type: function
|
|
57
|
+
code: './search.ts'
|
|
58
|
+
|
|
59
|
+
output_schema:
|
|
60
|
+
type: object
|
|
61
|
+
properties:
|
|
62
|
+
success:
|
|
63
|
+
type: boolean
|
|
64
|
+
description: Whether search completed successfully
|
|
65
|
+
query:
|
|
66
|
+
type: string
|
|
67
|
+
description: Search query that was used
|
|
68
|
+
directory:
|
|
69
|
+
type: string
|
|
70
|
+
description: Directory that was searched
|
|
71
|
+
pattern:
|
|
72
|
+
type: string
|
|
73
|
+
description: File pattern used for filtering
|
|
74
|
+
matches:
|
|
75
|
+
type: array
|
|
76
|
+
description: Array of matching files and content
|
|
77
|
+
items:
|
|
78
|
+
type: object
|
|
79
|
+
properties:
|
|
80
|
+
filePath:
|
|
81
|
+
type: string
|
|
82
|
+
description: Path to file containing match
|
|
83
|
+
lineNumber:
|
|
84
|
+
type: number
|
|
85
|
+
description: Line number of match (1-based)
|
|
86
|
+
lineContent:
|
|
87
|
+
type: string
|
|
88
|
+
description: Content of matched line
|
|
89
|
+
matchIndex:
|
|
90
|
+
type: number
|
|
91
|
+
description: Character position of match in line
|
|
92
|
+
context:
|
|
93
|
+
type: array
|
|
94
|
+
description: Context lines before and after match
|
|
95
|
+
items:
|
|
96
|
+
type: string
|
|
97
|
+
totalMatches:
|
|
98
|
+
type: number
|
|
99
|
+
description: Total number of matches found
|
|
100
|
+
filesSearched:
|
|
101
|
+
type: number
|
|
102
|
+
description: Number of files searched
|
|
103
|
+
duration:
|
|
104
|
+
type: number
|
|
105
|
+
description: Search duration in milliseconds
|
|
106
|
+
truncated:
|
|
107
|
+
type: boolean
|
|
108
|
+
description: Whether results were truncated due to maxResults
|
|
109
|
+
required: [success, query, matches, totalMatches, filesSearched, duration]
|
|
110
|
+
|
|
111
|
+
error_handling:
|
|
112
|
+
retry: 1
|
|
113
|
+
backoff_type: exponential
|
|
114
|
+
initial_delay_ms: 300
|
|
115
|
+
|
|
116
|
+
examples:
|
|
117
|
+
- name: 'Search for function definition'
|
|
118
|
+
description: 'Search for function definitions in TypeScript files'
|
|
119
|
+
params:
|
|
120
|
+
query: 'function'
|
|
121
|
+
directory: './src'
|
|
122
|
+
filePattern: '*.ts'
|
|
123
|
+
maxResults: 20
|
|
124
|
+
- name: 'Regex search in codebase'
|
|
125
|
+
description: 'Search using regex pattern'
|
|
126
|
+
params:
|
|
127
|
+
query: 'const\s+[a-zA-Z_]\w*\s*=\s*{'
|
|
128
|
+
directory: '.'
|
|
129
|
+
filePattern: '**/*.ts'
|
|
130
|
+
isRegex: true
|
|
131
|
+
excludePatterns: ['node_modules/**', 'dist/**']
|
|
132
|
+
- name: 'Case-sensitive search'
|
|
133
|
+
description: 'Find exact case matches'
|
|
134
|
+
params:
|
|
135
|
+
query: 'MatimoInstance'
|
|
136
|
+
directory: './src'
|
|
137
|
+
caseSensitive: true
|
|
138
|
+
maxResults: 100
|
|
139
|
+
- name: 'Search with context'
|
|
140
|
+
description: 'Search with surrounding context lines'
|
|
141
|
+
params:
|
|
142
|
+
query: 'export class'
|
|
143
|
+
directory: './src/core'
|
|
144
|
+
filePattern: '*.ts'
|
|
145
|
+
contextLines: 3
|
|
146
|
+
maxResults: 30
|
|
147
|
+
|
|
148
|
+
tags: [search, filesystem, grep, pattern-matching, text-search]
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Search Tool - Search files with native Node.js fs and regex
|
|
4
|
+
* Function-type tool: Exports default async function
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import { glob } from 'glob';
|
|
10
|
+
import { MatimoError, ErrorCode, getGlobalMatimoLogger } from '@matimo/core';
|
|
11
|
+
|
|
12
|
+
interface SearchMatch {
|
|
13
|
+
filePath: string;
|
|
14
|
+
lineNumber: number;
|
|
15
|
+
lineContent: string;
|
|
16
|
+
matchIndex: number;
|
|
17
|
+
context: string[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface SearchParams {
|
|
21
|
+
query: string;
|
|
22
|
+
directory?: string;
|
|
23
|
+
filePattern?: string;
|
|
24
|
+
isRegex?: boolean;
|
|
25
|
+
caseSensitive?: boolean;
|
|
26
|
+
maxResults?: number;
|
|
27
|
+
contextLines?: number;
|
|
28
|
+
excludePatterns?: string[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface SearchResult {
|
|
32
|
+
success: boolean;
|
|
33
|
+
query: string;
|
|
34
|
+
directory: string;
|
|
35
|
+
pattern: string;
|
|
36
|
+
matches: SearchMatch[];
|
|
37
|
+
totalMatches: number;
|
|
38
|
+
filesSearched: number;
|
|
39
|
+
duration: number;
|
|
40
|
+
truncated: boolean;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Search files for pattern matches
|
|
45
|
+
*/
|
|
46
|
+
export default async function searchTool(params: SearchParams): Promise<SearchResult> {
|
|
47
|
+
const logger = getGlobalMatimoLogger();
|
|
48
|
+
const {
|
|
49
|
+
query,
|
|
50
|
+
directory = '.',
|
|
51
|
+
filePattern = '**/*',
|
|
52
|
+
isRegex = false,
|
|
53
|
+
caseSensitive = false,
|
|
54
|
+
maxResults = 50,
|
|
55
|
+
contextLines = 2,
|
|
56
|
+
excludePatterns = ['**/node_modules/**', '**/.git/**', '**/dist/**', '**/build/**'],
|
|
57
|
+
} = params;
|
|
58
|
+
|
|
59
|
+
const startTime = Date.now();
|
|
60
|
+
|
|
61
|
+
logger.debug('Search tool invoked', {
|
|
62
|
+
query: query.substring(0, 100),
|
|
63
|
+
directory,
|
|
64
|
+
isRegex,
|
|
65
|
+
caseSensitive,
|
|
66
|
+
maxResults,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Validate required parameter
|
|
70
|
+
if (!query) {
|
|
71
|
+
logger.error('Search tool: Missing required parameter', {
|
|
72
|
+
reason: 'query is required',
|
|
73
|
+
});
|
|
74
|
+
throw new MatimoError('Missing required parameter', ErrorCode.INVALID_PARAMETER, {
|
|
75
|
+
reason: 'query is required',
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Resolve directory
|
|
80
|
+
const resolvedDir = directory.startsWith('~')
|
|
81
|
+
? path.join(process.env.HOME || '/', directory.slice(1))
|
|
82
|
+
: path.isAbsolute(directory)
|
|
83
|
+
? directory
|
|
84
|
+
: path.resolve(process.cwd(), directory);
|
|
85
|
+
|
|
86
|
+
if (!fs.existsSync(resolvedDir)) {
|
|
87
|
+
logger.error('Search tool: Directory not found', {
|
|
88
|
+
directory: resolvedDir,
|
|
89
|
+
});
|
|
90
|
+
throw new MatimoError('Directory not found', ErrorCode.FILE_NOT_FOUND, {
|
|
91
|
+
directory: resolvedDir,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Build search pattern
|
|
96
|
+
let searchRegex: RegExp;
|
|
97
|
+
try {
|
|
98
|
+
if (isRegex) {
|
|
99
|
+
searchRegex = new RegExp(query, caseSensitive ? 'g' : 'gi');
|
|
100
|
+
} else {
|
|
101
|
+
const escapedQuery = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
102
|
+
searchRegex = new RegExp(escapedQuery, caseSensitive ? 'g' : 'gi');
|
|
103
|
+
}
|
|
104
|
+
} catch {
|
|
105
|
+
throw new MatimoError('Invalid regex pattern', ErrorCode.INVALID_PARAMETER, {
|
|
106
|
+
pattern: query,
|
|
107
|
+
isRegex,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Enforce max results cap
|
|
112
|
+
const safeMaxResults = Math.min(maxResults, 1000);
|
|
113
|
+
|
|
114
|
+
// Find files matching pattern
|
|
115
|
+
const globPattern = path.join(resolvedDir, filePattern);
|
|
116
|
+
let files: string[] = [];
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
files = await glob(globPattern, {
|
|
120
|
+
nodir: true,
|
|
121
|
+
absolute: true,
|
|
122
|
+
ignore: excludePatterns,
|
|
123
|
+
});
|
|
124
|
+
} catch {
|
|
125
|
+
throw new MatimoError('Invalid glob pattern', ErrorCode.INVALID_PARAMETER, {
|
|
126
|
+
pattern: filePattern,
|
|
127
|
+
baseDirectory: resolvedDir,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const matches: SearchMatch[] = [];
|
|
132
|
+
let filesSearched = 0;
|
|
133
|
+
|
|
134
|
+
// Search each file
|
|
135
|
+
for (const filePath of files) {
|
|
136
|
+
if (matches.length >= safeMaxResults) break;
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
|
|
140
|
+
// Skip binary files
|
|
141
|
+
const stats = fs.statSync(filePath);
|
|
142
|
+
if (stats.size > 5 * 1024 * 1024) continue; // Skip files > 5MB
|
|
143
|
+
|
|
144
|
+
filesSearched++;
|
|
145
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
146
|
+
const lines = content.split('\n');
|
|
147
|
+
|
|
148
|
+
for (let lineNum = 0; lineNum < lines.length; lineNum++) {
|
|
149
|
+
if (matches.length >= safeMaxResults) break;
|
|
150
|
+
|
|
151
|
+
const line = lines[lineNum];
|
|
152
|
+
const lineContent = line.trim();
|
|
153
|
+
const match = searchRegex.exec(line);
|
|
154
|
+
|
|
155
|
+
if (match) {
|
|
156
|
+
// Get context lines
|
|
157
|
+
const contextStart = Math.max(0, lineNum - contextLines);
|
|
158
|
+
const contextEnd = Math.min(lines.length, lineNum + contextLines + 1);
|
|
159
|
+
const context = lines.slice(contextStart, contextEnd);
|
|
160
|
+
|
|
161
|
+
matches.push({
|
|
162
|
+
filePath,
|
|
163
|
+
lineNumber: lineNum + 1,
|
|
164
|
+
lineContent,
|
|
165
|
+
matchIndex: match.index,
|
|
166
|
+
context,
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// Reset regex for next exec
|
|
170
|
+
searchRegex.lastIndex = 0;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
} catch {
|
|
174
|
+
// Skip files that can't be read
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const result: SearchResult = {
|
|
180
|
+
success: true,
|
|
181
|
+
query,
|
|
182
|
+
directory: resolvedDir,
|
|
183
|
+
pattern: filePattern,
|
|
184
|
+
matches,
|
|
185
|
+
totalMatches: matches.length,
|
|
186
|
+
filesSearched,
|
|
187
|
+
duration: Date.now() - startTime,
|
|
188
|
+
truncated: matches.length >= safeMaxResults && files.length > filesSearched,
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
return result;
|
|
192
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
name: web
|
|
2
|
+
version: '1.0.0'
|
|
3
|
+
description: Fetch and parse web content from URLs. Supports redirects, headers, timeouts, and content extraction.
|
|
4
|
+
|
|
5
|
+
parameters:
|
|
6
|
+
url:
|
|
7
|
+
type: string
|
|
8
|
+
description: URL to fetch (http or https)
|
|
9
|
+
required: true
|
|
10
|
+
example: 'https://api.github.com/users/octocat'
|
|
11
|
+
|
|
12
|
+
method:
|
|
13
|
+
type: string
|
|
14
|
+
description: 'HTTP method: GET, POST, PUT, PATCH, DELETE (default GET)'
|
|
15
|
+
required: false
|
|
16
|
+
default: 'GET'
|
|
17
|
+
example: 'GET'
|
|
18
|
+
|
|
19
|
+
headers:
|
|
20
|
+
type: object
|
|
21
|
+
description: Additional HTTP headers as key-value pairs (optional)
|
|
22
|
+
required: false
|
|
23
|
+
example: '{"Authorization": "Bearer token123", "Accept": "application/json"}'
|
|
24
|
+
|
|
25
|
+
body:
|
|
26
|
+
type: string
|
|
27
|
+
description: Request body for POST/PUT/PATCH (JSON string or plain text)
|
|
28
|
+
required: false
|
|
29
|
+
example: '{"key": "value"}'
|
|
30
|
+
|
|
31
|
+
timeout:
|
|
32
|
+
type: number
|
|
33
|
+
description: Request timeout in milliseconds (default 30000)
|
|
34
|
+
required: false
|
|
35
|
+
default: 30000
|
|
36
|
+
example: 60000
|
|
37
|
+
|
|
38
|
+
followRedirects:
|
|
39
|
+
type: boolean
|
|
40
|
+
description: Follow HTTP redirects (default true, max 5 redirects)
|
|
41
|
+
required: false
|
|
42
|
+
default: true
|
|
43
|
+
|
|
44
|
+
parseJson:
|
|
45
|
+
type: boolean
|
|
46
|
+
description: Automatically parse response as JSON if content-type is application/json (default true)
|
|
47
|
+
required: false
|
|
48
|
+
default: true
|
|
49
|
+
|
|
50
|
+
maxSize:
|
|
51
|
+
type: number
|
|
52
|
+
description: Maximum response size in bytes (default 10485760 = 10MB). Prevents memory exhaustion.
|
|
53
|
+
required: false
|
|
54
|
+
default: 10485760
|
|
55
|
+
|
|
56
|
+
execution:
|
|
57
|
+
type: function
|
|
58
|
+
code: './web.ts'
|
|
59
|
+
|
|
60
|
+
output_schema:
|
|
61
|
+
type: object
|
|
62
|
+
properties:
|
|
63
|
+
success:
|
|
64
|
+
type: boolean
|
|
65
|
+
description: Whether request succeeded
|
|
66
|
+
url:
|
|
67
|
+
type: string
|
|
68
|
+
description: URL that was fetched
|
|
69
|
+
statusCode:
|
|
70
|
+
type: number
|
|
71
|
+
description: HTTP status code (200, 404, 500, etc.)
|
|
72
|
+
statusText:
|
|
73
|
+
type: string
|
|
74
|
+
description: HTTP status text
|
|
75
|
+
contentType:
|
|
76
|
+
type: string
|
|
77
|
+
description: Content-Type header from response
|
|
78
|
+
content:
|
|
79
|
+
oneOf:
|
|
80
|
+
- type: object
|
|
81
|
+
description: Parsed JSON object (if parseJson=true and content-type is json)
|
|
82
|
+
- type: string
|
|
83
|
+
description: Response body as string
|
|
84
|
+
headers:
|
|
85
|
+
type: object
|
|
86
|
+
description: Response headers as key-value pairs
|
|
87
|
+
size:
|
|
88
|
+
type: number
|
|
89
|
+
description: Response body size in bytes
|
|
90
|
+
duration:
|
|
91
|
+
type: number
|
|
92
|
+
description: Request duration in milliseconds
|
|
93
|
+
redirects:
|
|
94
|
+
type: array
|
|
95
|
+
description: Array of redirect URLs if followed
|
|
96
|
+
items:
|
|
97
|
+
type: string
|
|
98
|
+
required: [success, url, statusCode, statusText, content, duration]
|
|
99
|
+
|
|
100
|
+
error_handling:
|
|
101
|
+
retry: 2
|
|
102
|
+
backoff_type: exponential
|
|
103
|
+
initial_delay_ms: 1000
|
|
104
|
+
|
|
105
|
+
examples:
|
|
106
|
+
- name: 'Fetch JSON API'
|
|
107
|
+
description: 'Get JSON data from REST API'
|
|
108
|
+
params:
|
|
109
|
+
url: 'https://api.github.com/users/octocat'
|
|
110
|
+
method: 'GET'
|
|
111
|
+
- name: 'Fetch HTML webpage'
|
|
112
|
+
description: 'Get HTML content from website'
|
|
113
|
+
params:
|
|
114
|
+
url: 'https://example.com'
|
|
115
|
+
method: 'GET'
|
|
116
|
+
parseJson: false
|
|
117
|
+
- name: 'POST with JSON body'
|
|
118
|
+
description: 'Send POST request with JSON payload'
|
|
119
|
+
params:
|
|
120
|
+
url: 'https://api.example.com/data'
|
|
121
|
+
method: 'POST'
|
|
122
|
+
headers: '{"Content-Type": "application/json"}'
|
|
123
|
+
body: '{"name": "Matimo", "version": "1.0.0"}'
|
|
124
|
+
- name: 'Fetch with authentication'
|
|
125
|
+
description: 'Request with bearer token'
|
|
126
|
+
params:
|
|
127
|
+
url: 'https://api.github.com/user'
|
|
128
|
+
method: 'GET'
|
|
129
|
+
headers: '{"Authorization": "Bearer ghp_xxxxxxxxxxxx"}'
|
|
130
|
+
timeout: 15000
|
|
131
|
+
|
|
132
|
+
tags: [web, http, fetch, api, network, rest]
|