@loxia-labs/loxia-autopilot-one 1.0.1 → 1.0.3
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/README.md +44 -54
- package/bin/cli.js +1 -115
- package/bin/loxia-terminal-v2.js +3 -0
- package/bin/loxia-terminal.js +3 -0
- package/bin/start-with-terminal.js +3 -0
- package/package.json +14 -15
- package/scripts/install-scanners.js +1 -235
- package/src/analyzers/CSSAnalyzer.js +1 -297
- package/src/analyzers/ConfigValidator.js +1 -690
- package/src/analyzers/ESLintAnalyzer.js +1 -320
- package/src/analyzers/JavaScriptAnalyzer.js +1 -261
- package/src/analyzers/PrettierFormatter.js +1 -247
- package/src/analyzers/PythonAnalyzer.js +1 -266
- package/src/analyzers/SecurityAnalyzer.js +1 -729
- package/src/analyzers/TypeScriptAnalyzer.js +1 -247
- package/src/analyzers/codeCloneDetector/analyzer.js +1 -344
- package/src/analyzers/codeCloneDetector/detector.js +1 -203
- package/src/analyzers/codeCloneDetector/index.js +1 -160
- package/src/analyzers/codeCloneDetector/parser.js +1 -199
- package/src/analyzers/codeCloneDetector/reporter.js +1 -148
- package/src/analyzers/codeCloneDetector/scanner.js +1 -59
- package/src/core/agentPool.js +1 -1474
- package/src/core/agentScheduler.js +1 -2147
- package/src/core/contextManager.js +1 -709
- package/src/core/messageProcessor.js +1 -732
- package/src/core/orchestrator.js +1 -548
- package/src/core/stateManager.js +1 -877
- package/src/index.js +1 -631
- package/src/interfaces/cli.js +1 -549
- package/src/interfaces/terminal/__tests__/smoke/advancedFeatures.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/agentControl.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/agents.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/components.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/connection.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/enhancements.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/imports.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/messages.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/tools.test.js +1 -0
- package/src/interfaces/terminal/api/apiClient.js +1 -0
- package/src/interfaces/terminal/api/messageRouter.js +1 -0
- package/src/interfaces/terminal/api/session.js +1 -0
- package/src/interfaces/terminal/api/websocket.js +1 -0
- package/src/interfaces/terminal/components/AgentCreator.js +1 -0
- package/src/interfaces/terminal/components/AgentEditor.js +1 -0
- package/src/interfaces/terminal/components/AgentSwitcher.js +1 -0
- package/src/interfaces/terminal/components/ErrorBoundary.js +1 -0
- package/src/interfaces/terminal/components/ErrorPanel.js +1 -0
- package/src/interfaces/terminal/components/Header.js +1 -0
- package/src/interfaces/terminal/components/HelpPanel.js +1 -0
- package/src/interfaces/terminal/components/InputBox.js +1 -0
- package/src/interfaces/terminal/components/Layout.js +1 -0
- package/src/interfaces/terminal/components/LoadingSpinner.js +1 -0
- package/src/interfaces/terminal/components/MessageList.js +1 -0
- package/src/interfaces/terminal/components/MultilineTextInput.js +1 -0
- package/src/interfaces/terminal/components/SearchPanel.js +1 -0
- package/src/interfaces/terminal/components/SettingsPanel.js +1 -0
- package/src/interfaces/terminal/components/StatusBar.js +1 -0
- package/src/interfaces/terminal/components/TextInput.js +1 -0
- package/src/interfaces/terminal/config/agentEditorConstants.js +1 -0
- package/src/interfaces/terminal/config/constants.js +1 -0
- package/src/interfaces/terminal/index.js +1 -0
- package/src/interfaces/terminal/state/useAgentControl.js +1 -0
- package/src/interfaces/terminal/state/useAgents.js +1 -0
- package/src/interfaces/terminal/state/useConnection.js +1 -0
- package/src/interfaces/terminal/state/useMessages.js +1 -0
- package/src/interfaces/terminal/state/useTools.js +1 -0
- package/src/interfaces/terminal/utils/debugLogger.js +1 -0
- package/src/interfaces/terminal/utils/settingsStorage.js +1 -0
- package/src/interfaces/terminal/utils/theme.js +1 -0
- package/src/interfaces/webServer.js +1 -2162
- package/src/modules/fileExplorer/controller.js +1 -280
- package/src/modules/fileExplorer/index.js +1 -37
- package/src/modules/fileExplorer/middleware.js +1 -92
- package/src/modules/fileExplorer/routes.js +1 -125
- package/src/modules/fileExplorer/types.js +1 -44
- package/src/services/aiService.js +1 -1232
- package/src/services/apiKeyManager.js +1 -164
- package/src/services/benchmarkService.js +1 -366
- package/src/services/budgetService.js +1 -539
- package/src/services/contextInjectionService.js +1 -247
- package/src/services/conversationCompactionService.js +1 -637
- package/src/services/errorHandler.js +1 -810
- package/src/services/fileAttachmentService.js +1 -544
- package/src/services/modelRouterService.js +1 -366
- package/src/services/modelsService.js +1 -322
- package/src/services/qualityInspector.js +1 -796
- package/src/services/tokenCountingService.js +1 -536
- package/src/tools/agentCommunicationTool.js +1 -1344
- package/src/tools/agentDelayTool.js +1 -485
- package/src/tools/asyncToolManager.js +1 -604
- package/src/tools/baseTool.js +1 -800
- package/src/tools/browserTool.js +1 -920
- package/src/tools/cloneDetectionTool.js +1 -621
- package/src/tools/dependencyResolverTool.js +1 -1215
- package/src/tools/fileContentReplaceTool.js +1 -875
- package/src/tools/fileSystemTool.js +1 -1107
- package/src/tools/fileTreeTool.js +1 -853
- package/src/tools/imageTool.js +1 -901
- package/src/tools/importAnalyzerTool.js +1 -1060
- package/src/tools/jobDoneTool.js +1 -248
- package/src/tools/seekTool.js +1 -956
- package/src/tools/staticAnalysisTool.js +1 -1778
- package/src/tools/taskManagerTool.js +1 -2873
- package/src/tools/terminalTool.js +1 -2304
- package/src/tools/webTool.js +1 -1430
- package/src/types/agent.js +1 -519
- package/src/types/contextReference.js +1 -972
- package/src/types/conversation.js +1 -730
- package/src/types/toolCommand.js +1 -747
- package/src/utilities/attachmentValidator.js +1 -292
- package/src/utilities/configManager.js +1 -582
- package/src/utilities/constants.js +1 -722
- package/src/utilities/directoryAccessManager.js +1 -535
- package/src/utilities/fileProcessor.js +1 -307
- package/src/utilities/logger.js +1 -436
- package/src/utilities/tagParser.js +1 -1246
- package/src/utilities/toolConstants.js +1 -317
- package/web-ui/build/index.html +2 -2
- package/web-ui/build/static/{index-Dy2bYbOa.css → index-CClD1090.css} +1 -1
- package/web-ui/build/static/{index-CjkkcnFA.js → index-lCBai6dX.js} +66 -67
package/src/tools/seekTool.js
CHANGED
|
@@ -1,956 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SeekTool - Search for content within project files
|
|
3
|
-
*
|
|
4
|
-
* Purpose:
|
|
5
|
-
* - Search for specific content/patterns within files
|
|
6
|
-
* - Support glob patterns for file paths
|
|
7
|
-
* - Verify imports, function usage, and variable references
|
|
8
|
-
* - Provide detailed match information with line numbers
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { BaseTool } from './baseTool.js';
|
|
12
|
-
import TagParser from '../utilities/tagParser.js';
|
|
13
|
-
import { promises as fs } from 'fs';
|
|
14
|
-
import path from 'path';
|
|
15
|
-
|
|
16
|
-
// Configuration constants
|
|
17
|
-
const SEEK_CONFIG = {
|
|
18
|
-
// File size limits
|
|
19
|
-
MAX_FILE_SIZE: 10 * 1024 * 1024, // 10MB - don't search files larger than this
|
|
20
|
-
|
|
21
|
-
// Search limits
|
|
22
|
-
MAX_FILES_PER_SEARCH: 1000, // Maximum files to search in one operation
|
|
23
|
-
MAX_MATCHES_PER_FILE: 100, // Maximum matches to return per file
|
|
24
|
-
MAX_TOTAL_MATCHES: 500, // Maximum total matches to return
|
|
25
|
-
|
|
26
|
-
// Performance limits
|
|
27
|
-
MAX_SEARCH_TERMS: 50, // Maximum number of search terms
|
|
28
|
-
MAX_FILE_PATHS: 100, // Maximum number of file path patterns
|
|
29
|
-
|
|
30
|
-
// Recursion limits
|
|
31
|
-
MAX_DIRECTORY_DEPTH: 20, // Maximum directory recursion depth
|
|
32
|
-
|
|
33
|
-
// Result formatting
|
|
34
|
-
MAX_LINE_CONTENT_LENGTH: 200, // Maximum line content to show in results
|
|
35
|
-
CONTEXT_LINES_BEFORE: 0, // Lines of context before match
|
|
36
|
-
CONTEXT_LINES_AFTER: 0, // Lines of context after match
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
// File encoding
|
|
40
|
-
const FILE_ENCODING = 'utf-8';
|
|
41
|
-
|
|
42
|
-
// Common binary file extensions to skip
|
|
43
|
-
const BINARY_EXTENSIONS = new Set([
|
|
44
|
-
'.png', '.jpg', '.jpeg', '.gif', '.bmp', '.ico', '.svg',
|
|
45
|
-
'.pdf', '.zip', '.tar', '.gz', '.rar', '.7z',
|
|
46
|
-
'.exe', '.dll', '.so', '.dylib',
|
|
47
|
-
'.mp3', '.mp4', '.avi', '.mov', '.wmv',
|
|
48
|
-
'.woff', '.woff2', '.ttf', '.eot',
|
|
49
|
-
'.bin', '.dat', '.db', '.sqlite'
|
|
50
|
-
]);
|
|
51
|
-
|
|
52
|
-
class SeekTool extends BaseTool {
|
|
53
|
-
constructor(config = {}, logger = null) {
|
|
54
|
-
super(config, logger);
|
|
55
|
-
|
|
56
|
-
// Tool metadata
|
|
57
|
-
this.requiresProject = true; // Requires project directory
|
|
58
|
-
this.isAsync = true; // File operations are async
|
|
59
|
-
this.timeout = config.timeout || 120000; // 2 minutes default
|
|
60
|
-
|
|
61
|
-
// Merge config with defaults
|
|
62
|
-
this.seekConfig = {
|
|
63
|
-
...SEEK_CONFIG,
|
|
64
|
-
...config.seekConfig
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Get tool description for LLM consumption
|
|
70
|
-
* @returns {string} Tool description
|
|
71
|
-
*/
|
|
72
|
-
getDescription() {
|
|
73
|
-
return `
|
|
74
|
-
Seek Tool: Search for specific content within project files. Highly recommended for verifying imports, function usage, and variable references.
|
|
75
|
-
|
|
76
|
-
XML USAGE:
|
|
77
|
-
<seek>
|
|
78
|
-
<in-files>
|
|
79
|
-
file/path/one.js
|
|
80
|
-
file/path/two.js
|
|
81
|
-
src/**/*.js
|
|
82
|
-
</in-files>
|
|
83
|
-
<search-terms>
|
|
84
|
-
<term>search phrase one</term>
|
|
85
|
-
<term>search phrase two</term>
|
|
86
|
-
<term>search phrase three</term>
|
|
87
|
-
</search-terms>
|
|
88
|
-
</seek>
|
|
89
|
-
|
|
90
|
-
JSON USAGE:
|
|
91
|
-
\`\`\`json
|
|
92
|
-
{
|
|
93
|
-
"toolId": "seek",
|
|
94
|
-
"filePaths": [
|
|
95
|
-
"src/components/Header.js",
|
|
96
|
-
"src/utils/*.js",
|
|
97
|
-
"src/**/*.jsx"
|
|
98
|
-
],
|
|
99
|
-
"searchTerms": [
|
|
100
|
-
"import React",
|
|
101
|
-
"useState",
|
|
102
|
-
"function handleSubmit"
|
|
103
|
-
]
|
|
104
|
-
}
|
|
105
|
-
\`\`\`
|
|
106
|
-
|
|
107
|
-
SUPPORTED GLOB PATTERNS:
|
|
108
|
-
- *.js - All .js files in a directory
|
|
109
|
-
- **/*.js - All .js files recursively
|
|
110
|
-
- src/**/*.jsx - All .jsx files under src/ recursively
|
|
111
|
-
- components/*.* - All files in components/
|
|
112
|
-
|
|
113
|
-
EXAMPLES:
|
|
114
|
-
|
|
115
|
-
Example 1 - Find function usage:
|
|
116
|
-
<seek>
|
|
117
|
-
<in-files>
|
|
118
|
-
src/components/*.js
|
|
119
|
-
src/utils/helpers.js
|
|
120
|
-
</in-files>
|
|
121
|
-
<search-terms>
|
|
122
|
-
<term>function handleSubmit</term>
|
|
123
|
-
<term>useState(</term>
|
|
124
|
-
</search-terms>
|
|
125
|
-
</seek>
|
|
126
|
-
|
|
127
|
-
Example 2 - Verify imports:
|
|
128
|
-
<seek>
|
|
129
|
-
<in-files>
|
|
130
|
-
src/components/Header.js
|
|
131
|
-
src/components/Footer.js
|
|
132
|
-
</in-files>
|
|
133
|
-
<search-terms>
|
|
134
|
-
<term>import React</term>
|
|
135
|
-
<term>import { useState }</term>
|
|
136
|
-
<term>from 'react'</term>
|
|
137
|
-
</search-terms>
|
|
138
|
-
</seek>
|
|
139
|
-
|
|
140
|
-
Example 3 - Find variable references:
|
|
141
|
-
<seek>
|
|
142
|
-
<in-files>
|
|
143
|
-
src/**/*.js
|
|
144
|
-
</in-files>
|
|
145
|
-
<search-terms>
|
|
146
|
-
<term>apiClient</term>
|
|
147
|
-
<term>config.apiUrl</term>
|
|
148
|
-
</search-terms>
|
|
149
|
-
</seek>
|
|
150
|
-
|
|
151
|
-
Example 4 - Search specific files only:
|
|
152
|
-
<seek>
|
|
153
|
-
<in-files>
|
|
154
|
-
package.json
|
|
155
|
-
tsconfig.json
|
|
156
|
-
.gitignore
|
|
157
|
-
</in-files>
|
|
158
|
-
<search-terms>
|
|
159
|
-
<term>react</term>
|
|
160
|
-
<term>typescript</term>
|
|
161
|
-
</search-terms>
|
|
162
|
-
</seek>
|
|
163
|
-
|
|
164
|
-
FEATURES:
|
|
165
|
-
- Searches for exact string matches (case-sensitive)
|
|
166
|
-
- Returns file path, line number, and line content for each match
|
|
167
|
-
- Supports glob patterns for flexible file selection
|
|
168
|
-
- Skips binary files automatically
|
|
169
|
-
- Reports files not found and files with errors
|
|
170
|
-
- Limited to ${SEEK_CONFIG.MAX_FILE_SIZE / (1024 * 1024)}MB per file
|
|
171
|
-
- Returns up to ${SEEK_CONFIG.MAX_TOTAL_MATCHES} matches total
|
|
172
|
-
|
|
173
|
-
RESULT FORMAT:
|
|
174
|
-
The tool returns:
|
|
175
|
-
- List of files that were not found
|
|
176
|
-
- List of files that had errors during search
|
|
177
|
-
- For each search term:
|
|
178
|
-
- File path where found
|
|
179
|
-
- Line number
|
|
180
|
-
- Line content (trimmed)
|
|
181
|
-
|
|
182
|
-
MULTI-DIRECTORY SUPPORT:
|
|
183
|
-
When an agent has multiple directories configured, the SeekTool can search across all of them:
|
|
184
|
-
- Relative paths are resolved from the working directory
|
|
185
|
-
- Absolute paths can reference any accessible directory
|
|
186
|
-
- Automatic validation ensures paths are within allowed directories
|
|
187
|
-
|
|
188
|
-
Example with multiple directories:
|
|
189
|
-
If agent has access to:
|
|
190
|
-
- /home/user/project1 (working directory)
|
|
191
|
-
- /home/user/project2 (read-only)
|
|
192
|
-
- /home/user/shared (read-only)
|
|
193
|
-
|
|
194
|
-
You can search:
|
|
195
|
-
src/**/*.js → Searches in /home/user/project1/src/**/*.js
|
|
196
|
-
/home/user/project2/config.json → Searches in project2 (absolute path)
|
|
197
|
-
/home/user/shared/docs/*.md → Searches in shared directory
|
|
198
|
-
|
|
199
|
-
LIMITATIONS:
|
|
200
|
-
- Maximum ${SEEK_CONFIG.MAX_FILES_PER_SEARCH} files per search
|
|
201
|
-
- Maximum ${SEEK_CONFIG.MAX_SEARCH_TERMS} search terms
|
|
202
|
-
- Maximum ${SEEK_CONFIG.MAX_FILE_SIZE / (1024 * 1024)}MB per file
|
|
203
|
-
- Case-sensitive search only
|
|
204
|
-
- Exact string matching (not regex)
|
|
205
|
-
- Paths outside accessible directories will be reported as "not found"
|
|
206
|
-
`;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Parse parameters from tool command content
|
|
211
|
-
* @param {string} content - Raw tool command content
|
|
212
|
-
* @returns {Object} Parsed parameters
|
|
213
|
-
*/
|
|
214
|
-
parseParameters(content) {
|
|
215
|
-
try {
|
|
216
|
-
// Try JSON first
|
|
217
|
-
if (content.trim().startsWith('{')) {
|
|
218
|
-
const parsed = JSON.parse(content);
|
|
219
|
-
|
|
220
|
-
return {
|
|
221
|
-
filePaths: parsed.filePaths || [],
|
|
222
|
-
searchTerms: parsed.searchTerms || []
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// XML parsing
|
|
227
|
-
const params = {
|
|
228
|
-
filePaths: [],
|
|
229
|
-
searchTerms: []
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
// Extract in-files content
|
|
233
|
-
const inFilesPattern = /<in-files>([\s\S]*?)<\/in-files>/i;
|
|
234
|
-
const inFilesMatch = inFilesPattern.exec(content);
|
|
235
|
-
|
|
236
|
-
if (inFilesMatch) {
|
|
237
|
-
const filesContent = inFilesMatch[1];
|
|
238
|
-
params.filePaths = filesContent
|
|
239
|
-
.split('\n')
|
|
240
|
-
.map(line => line.trim())
|
|
241
|
-
.filter(line => line.length > 0);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// Extract search-terms content
|
|
245
|
-
const searchTermsPattern = /<search-terms>([\s\S]*?)<\/search-terms>/i;
|
|
246
|
-
const searchTermsMatch = searchTermsPattern.exec(content);
|
|
247
|
-
|
|
248
|
-
if (searchTermsMatch) {
|
|
249
|
-
const termsContent = searchTermsMatch[1];
|
|
250
|
-
|
|
251
|
-
// Extract individual <term> tags
|
|
252
|
-
const termPattern = /<term>(.*?)<\/term>/gi;
|
|
253
|
-
let termMatch;
|
|
254
|
-
|
|
255
|
-
while ((termMatch = termPattern.exec(termsContent)) !== null) {
|
|
256
|
-
const term = termMatch[1].trim();
|
|
257
|
-
if (term.length > 0) {
|
|
258
|
-
params.searchTerms.push(term);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
return params;
|
|
264
|
-
|
|
265
|
-
} catch (error) {
|
|
266
|
-
this.logger?.error('Failed to parse seek parameters', { error: error.message });
|
|
267
|
-
return {
|
|
268
|
-
filePaths: [],
|
|
269
|
-
searchTerms: [],
|
|
270
|
-
parseError: error.message
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Get required parameters
|
|
277
|
-
* @returns {Array<string>} Array of required parameter names
|
|
278
|
-
*/
|
|
279
|
-
getRequiredParameters() {
|
|
280
|
-
return ['filePaths', 'searchTerms'];
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Custom parameter validation
|
|
285
|
-
* @param {Object} params - Parameters to validate
|
|
286
|
-
* @returns {Object} Validation result
|
|
287
|
-
*/
|
|
288
|
-
customValidateParameters(params) {
|
|
289
|
-
const errors = [];
|
|
290
|
-
|
|
291
|
-
// Validate filePaths
|
|
292
|
-
if (!params.filePaths || !Array.isArray(params.filePaths) || params.filePaths.length === 0) {
|
|
293
|
-
errors.push('At least one file path is required');
|
|
294
|
-
} else if (params.filePaths.length > this.seekConfig.MAX_FILE_PATHS) {
|
|
295
|
-
errors.push(`Too many file paths (max ${this.seekConfig.MAX_FILE_PATHS})`);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// Validate searchTerms
|
|
299
|
-
if (!params.searchTerms || !Array.isArray(params.searchTerms) || params.searchTerms.length === 0) {
|
|
300
|
-
errors.push('At least one search term is required');
|
|
301
|
-
} else if (params.searchTerms.length > this.seekConfig.MAX_SEARCH_TERMS) {
|
|
302
|
-
errors.push(`Too many search terms (max ${this.seekConfig.MAX_SEARCH_TERMS})`);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
// Validate search terms are non-empty strings
|
|
306
|
-
if (params.searchTerms && Array.isArray(params.searchTerms)) {
|
|
307
|
-
for (const [index, term] of params.searchTerms.entries()) {
|
|
308
|
-
if (typeof term !== 'string' || term.trim().length === 0) {
|
|
309
|
-
errors.push(`Search term ${index + 1}: must be a non-empty string`);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// Validate file paths are non-empty strings
|
|
315
|
-
if (params.filePaths && Array.isArray(params.filePaths)) {
|
|
316
|
-
for (const [index, filePath] of params.filePaths.entries()) {
|
|
317
|
-
if (typeof filePath !== 'string' || filePath.trim().length === 0) {
|
|
318
|
-
errors.push(`File path ${index + 1}: must be a non-empty string`);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// Check for path traversal attempts
|
|
322
|
-
if (filePath.includes('..')) {
|
|
323
|
-
errors.push(`File path ${index + 1}: path traversal (..) not allowed for security`);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
return {
|
|
329
|
-
valid: errors.length === 0,
|
|
330
|
-
errors
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* Execute tool with parsed parameters
|
|
336
|
-
* @param {Object} params - Parsed parameters
|
|
337
|
-
* @param {Object} context - Execution context
|
|
338
|
-
* @returns {Promise<Object>} Execution result
|
|
339
|
-
*/
|
|
340
|
-
async execute(params, context) {
|
|
341
|
-
const { filePaths, searchTerms } = params;
|
|
342
|
-
const { projectDir, agentId, directoryAccess } = context;
|
|
343
|
-
|
|
344
|
-
// IMPORTANT: Get all accessible directories for the agent
|
|
345
|
-
// This includes workingDirectory, readOnlyDirectories, and writeEnabledDirectories
|
|
346
|
-
let workingDirectory = projectDir || process.cwd();
|
|
347
|
-
let accessibleDirectories = [workingDirectory];
|
|
348
|
-
|
|
349
|
-
if (directoryAccess && directoryAccess.workingDirectory) {
|
|
350
|
-
workingDirectory = directoryAccess.workingDirectory;
|
|
351
|
-
|
|
352
|
-
// Collect all accessible directories (for read operations)
|
|
353
|
-
accessibleDirectories = this.getAllAccessibleDirectories(directoryAccess);
|
|
354
|
-
|
|
355
|
-
this.logger?.info('Using agent configured directory access', {
|
|
356
|
-
workingDirectory: directoryAccess.workingDirectory,
|
|
357
|
-
totalAccessibleDirs: accessibleDirectories.length,
|
|
358
|
-
readOnlyDirs: directoryAccess.readOnlyDirectories?.length || 0,
|
|
359
|
-
writeEnabledDirs: directoryAccess.writeEnabledDirectories?.length || 0,
|
|
360
|
-
agentId
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
if (!workingDirectory) {
|
|
365
|
-
throw new Error('Project directory is required for seek tool');
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
this.logger?.info('Executing seek tool', {
|
|
369
|
-
filePathCount: filePaths.length,
|
|
370
|
-
searchTermCount: searchTerms.length,
|
|
371
|
-
workingDirectory,
|
|
372
|
-
accessibleDirectories: accessibleDirectories.length,
|
|
373
|
-
agentId
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
try {
|
|
377
|
-
// Resolve file paths (expand globs)
|
|
378
|
-
// Pass accessible directories for validation (if agent has directoryAccess configured)
|
|
379
|
-
const resolveResult = await this.resolveFilePaths(
|
|
380
|
-
filePaths,
|
|
381
|
-
workingDirectory,
|
|
382
|
-
directoryAccess ? accessibleDirectories : null
|
|
383
|
-
);
|
|
384
|
-
|
|
385
|
-
const resolvedFiles = resolveResult.found;
|
|
386
|
-
const notFoundFiles = resolveResult.notFound;
|
|
387
|
-
|
|
388
|
-
// Check file count limit
|
|
389
|
-
if (resolvedFiles.length > this.seekConfig.MAX_FILES_PER_SEARCH) {
|
|
390
|
-
return {
|
|
391
|
-
success: false,
|
|
392
|
-
error: `Too many files to search (${resolvedFiles.length}). Maximum is ${this.seekConfig.MAX_FILES_PER_SEARCH}. Use more specific file patterns.`,
|
|
393
|
-
filesResolved: resolvedFiles.length,
|
|
394
|
-
filesNotFound: notFoundFiles.length
|
|
395
|
-
};
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// Search in files
|
|
399
|
-
const searchResult = await this.searchFiles(resolvedFiles, searchTerms, workingDirectory);
|
|
400
|
-
|
|
401
|
-
// Format results
|
|
402
|
-
const formattedResults = this.formatResults(
|
|
403
|
-
searchResult.matches,
|
|
404
|
-
searchResult.errorFiles,
|
|
405
|
-
notFoundFiles,
|
|
406
|
-
resolvedFiles.length
|
|
407
|
-
);
|
|
408
|
-
|
|
409
|
-
return {
|
|
410
|
-
success: true,
|
|
411
|
-
filesSearched: resolvedFiles.length,
|
|
412
|
-
filesNotFound: notFoundFiles.length,
|
|
413
|
-
filesWithErrors: searchResult.errorFiles.length,
|
|
414
|
-
totalMatches: searchResult.matches.length,
|
|
415
|
-
matchesByTerm: searchResult.matchesByTerm,
|
|
416
|
-
formattedResults,
|
|
417
|
-
toolUsed: 'seek'
|
|
418
|
-
};
|
|
419
|
-
|
|
420
|
-
} catch (error) {
|
|
421
|
-
this.logger?.error('Seek tool execution failed', { error: error.message });
|
|
422
|
-
throw error;
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
/**
|
|
427
|
-
* Get all accessible directories for read operations
|
|
428
|
-
* @param {Object} directoryAccess - Directory access configuration
|
|
429
|
-
* @returns {Array<string>} Array of accessible directory paths
|
|
430
|
-
* @private
|
|
431
|
-
*/
|
|
432
|
-
getAllAccessibleDirectories(directoryAccess) {
|
|
433
|
-
const directories = new Set();
|
|
434
|
-
|
|
435
|
-
// Add working directory
|
|
436
|
-
if (directoryAccess.workingDirectory) {
|
|
437
|
-
directories.add(directoryAccess.workingDirectory);
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
// Add read-only directories
|
|
441
|
-
if (directoryAccess.readOnlyDirectories && Array.isArray(directoryAccess.readOnlyDirectories)) {
|
|
442
|
-
for (const dir of directoryAccess.readOnlyDirectories) {
|
|
443
|
-
directories.add(dir);
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// Add write-enabled directories (if you can write, you can read)
|
|
448
|
-
if (directoryAccess.writeEnabledDirectories && Array.isArray(directoryAccess.writeEnabledDirectories)) {
|
|
449
|
-
for (const dir of directoryAccess.writeEnabledDirectories) {
|
|
450
|
-
directories.add(dir);
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
return Array.from(directories);
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
/**
|
|
458
|
-
* Check if a path is within any accessible directory
|
|
459
|
-
* @param {string} targetPath - Path to check
|
|
460
|
-
* @param {Array<string>} accessibleDirs - Array of accessible directories
|
|
461
|
-
* @returns {boolean} True if path is accessible
|
|
462
|
-
* @private
|
|
463
|
-
*/
|
|
464
|
-
isPathAccessible(targetPath, accessibleDirs) {
|
|
465
|
-
for (const dir of accessibleDirs) {
|
|
466
|
-
const relative = path.relative(dir, targetPath);
|
|
467
|
-
const isWithin = !relative.startsWith('..') && !path.isAbsolute(relative);
|
|
468
|
-
if (isWithin) {
|
|
469
|
-
return true;
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
return false;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
/**
|
|
476
|
-
* Resolve file paths, expanding glob patterns
|
|
477
|
-
* @param {Array<string>} filePaths - File paths with possible glob patterns
|
|
478
|
-
* @param {string} projectDir - Project directory
|
|
479
|
-
* @param {Array<string>} accessibleDirs - Optional array of accessible directories
|
|
480
|
-
* @returns {Promise<Object>} Object with found and notFound arrays
|
|
481
|
-
* @private
|
|
482
|
-
*/
|
|
483
|
-
async resolveFilePaths(filePaths, projectDir, accessibleDirs = null) {
|
|
484
|
-
const result = {
|
|
485
|
-
found: [],
|
|
486
|
-
notFound: []
|
|
487
|
-
};
|
|
488
|
-
|
|
489
|
-
for (const filePath of filePaths) {
|
|
490
|
-
const normalizedPath = filePath.trim();
|
|
491
|
-
|
|
492
|
-
if (normalizedPath.includes('*')) {
|
|
493
|
-
// Handle glob patterns
|
|
494
|
-
const globResult = await this.expandGlobPattern(normalizedPath, projectDir);
|
|
495
|
-
|
|
496
|
-
if (globResult.found.length > 0) {
|
|
497
|
-
result.found.push(...globResult.found);
|
|
498
|
-
} else {
|
|
499
|
-
result.notFound.push(`${normalizedPath} (no matching files)`);
|
|
500
|
-
}
|
|
501
|
-
} else {
|
|
502
|
-
// Handle direct file reference
|
|
503
|
-
const absolutePath = path.isAbsolute(normalizedPath)
|
|
504
|
-
? normalizedPath
|
|
505
|
-
: path.resolve(projectDir, normalizedPath);
|
|
506
|
-
|
|
507
|
-
// Check if path is within accessible directories (if configured)
|
|
508
|
-
if (accessibleDirs && accessibleDirs.length > 0) {
|
|
509
|
-
if (!this.isPathAccessible(absolutePath, accessibleDirs)) {
|
|
510
|
-
result.notFound.push(`${normalizedPath} (not in accessible directories)`);
|
|
511
|
-
continue;
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
try {
|
|
516
|
-
const stats = await fs.stat(absolutePath);
|
|
517
|
-
|
|
518
|
-
if (stats.isFile()) {
|
|
519
|
-
result.found.push(absolutePath);
|
|
520
|
-
} else if (stats.isDirectory()) {
|
|
521
|
-
result.notFound.push(`${normalizedPath} (is a directory, not a file)`);
|
|
522
|
-
} else {
|
|
523
|
-
result.notFound.push(`${normalizedPath} (not a regular file)`);
|
|
524
|
-
}
|
|
525
|
-
} catch (error) {
|
|
526
|
-
result.notFound.push(`${normalizedPath} (${error.code || error.message})`);
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
return result;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
/**
|
|
535
|
-
* Expand glob pattern to matching file paths
|
|
536
|
-
* @param {string} pattern - Glob pattern
|
|
537
|
-
* @param {string} projectDir - Project directory
|
|
538
|
-
* @returns {Promise<Object>} Object with found files
|
|
539
|
-
* @private
|
|
540
|
-
*/
|
|
541
|
-
async expandGlobPattern(pattern, projectDir) {
|
|
542
|
-
const result = { found: [] };
|
|
543
|
-
|
|
544
|
-
// Handle recursive pattern: src/**/*.js
|
|
545
|
-
if (pattern.includes('**/')) {
|
|
546
|
-
const [baseDir, filePattern] = pattern.split('**/');
|
|
547
|
-
const basePath = path.resolve(projectDir, baseDir);
|
|
548
|
-
|
|
549
|
-
try {
|
|
550
|
-
const stats = await fs.stat(basePath);
|
|
551
|
-
|
|
552
|
-
if (stats.isDirectory()) {
|
|
553
|
-
await this.findFilesRecursively(
|
|
554
|
-
basePath,
|
|
555
|
-
filePattern,
|
|
556
|
-
result.found,
|
|
557
|
-
0,
|
|
558
|
-
this.seekConfig.MAX_DIRECTORY_DEPTH
|
|
559
|
-
);
|
|
560
|
-
}
|
|
561
|
-
} catch (error) {
|
|
562
|
-
// Directory doesn't exist
|
|
563
|
-
this.logger?.warn('Base directory not found for glob pattern', { basePath, error: error.message });
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
// Handle simple pattern: src/*.js
|
|
567
|
-
else if (pattern.includes('*')) {
|
|
568
|
-
const dirPath = path.dirname(path.resolve(projectDir, pattern));
|
|
569
|
-
const filePattern = path.basename(pattern);
|
|
570
|
-
|
|
571
|
-
try {
|
|
572
|
-
const stats = await fs.stat(dirPath);
|
|
573
|
-
|
|
574
|
-
if (stats.isDirectory()) {
|
|
575
|
-
const files = await fs.readdir(dirPath);
|
|
576
|
-
|
|
577
|
-
for (const file of files) {
|
|
578
|
-
const filePath = path.join(dirPath, file);
|
|
579
|
-
|
|
580
|
-
try {
|
|
581
|
-
const fileStats = await fs.stat(filePath);
|
|
582
|
-
|
|
583
|
-
if (fileStats.isFile() && this.matchesPattern(file, filePattern)) {
|
|
584
|
-
result.found.push(filePath);
|
|
585
|
-
}
|
|
586
|
-
} catch (error) {
|
|
587
|
-
// Skip files we can't stat
|
|
588
|
-
continue;
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
} catch (error) {
|
|
593
|
-
// Directory doesn't exist
|
|
594
|
-
this.logger?.warn('Directory not found for glob pattern', { dirPath, error: error.message });
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
return result;
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
/**
|
|
602
|
-
* Find files recursively matching a pattern
|
|
603
|
-
* @param {string} dir - Directory to search
|
|
604
|
-
* @param {string} filePattern - File pattern to match
|
|
605
|
-
* @param {Array<string>} results - Results array
|
|
606
|
-
* @param {number} currentDepth - Current recursion depth
|
|
607
|
-
* @param {number} maxDepth - Maximum recursion depth
|
|
608
|
-
* @returns {Promise<void>}
|
|
609
|
-
* @private
|
|
610
|
-
*/
|
|
611
|
-
async findFilesRecursively(dir, filePattern, results, currentDepth, maxDepth) {
|
|
612
|
-
// Prevent infinite recursion
|
|
613
|
-
if (currentDepth >= maxDepth) {
|
|
614
|
-
this.logger?.warn('Maximum directory depth reached', { dir, currentDepth });
|
|
615
|
-
return;
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
try {
|
|
619
|
-
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
620
|
-
|
|
621
|
-
for (const entry of entries) {
|
|
622
|
-
// Skip hidden files and directories
|
|
623
|
-
if (entry.name.startsWith('.')) {
|
|
624
|
-
continue;
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
const fullPath = path.join(dir, entry.name);
|
|
628
|
-
|
|
629
|
-
try {
|
|
630
|
-
if (entry.isDirectory()) {
|
|
631
|
-
// Skip common large directories
|
|
632
|
-
if (this.shouldSkipDirectory(entry.name)) {
|
|
633
|
-
continue;
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
await this.findFilesRecursively(
|
|
637
|
-
fullPath,
|
|
638
|
-
filePattern,
|
|
639
|
-
results,
|
|
640
|
-
currentDepth + 1,
|
|
641
|
-
maxDepth
|
|
642
|
-
);
|
|
643
|
-
} else if (entry.isFile()) {
|
|
644
|
-
if (this.matchesPattern(entry.name, filePattern)) {
|
|
645
|
-
results.push(fullPath);
|
|
646
|
-
|
|
647
|
-
// Stop if we've found too many files
|
|
648
|
-
if (results.length >= this.seekConfig.MAX_FILES_PER_SEARCH) {
|
|
649
|
-
return;
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
} catch (error) {
|
|
654
|
-
// Skip entries we can't access
|
|
655
|
-
continue;
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
} catch (error) {
|
|
659
|
-
this.logger?.warn('Error reading directory', { dir, error: error.message });
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
/**
|
|
664
|
-
* Check if filename matches a wildcard pattern
|
|
665
|
-
* @param {string} filename - Filename to check
|
|
666
|
-
* @param {string} pattern - Wildcard pattern
|
|
667
|
-
* @returns {boolean} True if matches
|
|
668
|
-
* @private
|
|
669
|
-
*/
|
|
670
|
-
matchesPattern(filename, pattern) {
|
|
671
|
-
// Simple wildcard matching
|
|
672
|
-
const regexPattern = pattern
|
|
673
|
-
.split('*')
|
|
674
|
-
.map(part => this.escapeRegExp(part))
|
|
675
|
-
.join('.*');
|
|
676
|
-
|
|
677
|
-
const regex = new RegExp(`^${regexPattern}$`, 'i');
|
|
678
|
-
return regex.test(filename);
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
/**
|
|
682
|
-
* Escape special regex characters
|
|
683
|
-
* @param {string} string - String to escape
|
|
684
|
-
* @returns {string} Escaped string
|
|
685
|
-
* @private
|
|
686
|
-
*/
|
|
687
|
-
escapeRegExp(string) {
|
|
688
|
-
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
/**
|
|
692
|
-
* Check if directory should be skipped during recursive search
|
|
693
|
-
* @param {string} dirName - Directory name
|
|
694
|
-
* @returns {boolean} True if should skip
|
|
695
|
-
* @private
|
|
696
|
-
*/
|
|
697
|
-
shouldSkipDirectory(dirName) {
|
|
698
|
-
const skipDirs = new Set([
|
|
699
|
-
'node_modules',
|
|
700
|
-
'.git',
|
|
701
|
-
'dist',
|
|
702
|
-
'build',
|
|
703
|
-
'coverage',
|
|
704
|
-
'.next',
|
|
705
|
-
'.nuxt',
|
|
706
|
-
'out',
|
|
707
|
-
'target',
|
|
708
|
-
'vendor',
|
|
709
|
-
'__pycache__',
|
|
710
|
-
'.cache',
|
|
711
|
-
'tmp',
|
|
712
|
-
'temp'
|
|
713
|
-
]);
|
|
714
|
-
|
|
715
|
-
return skipDirs.has(dirName.toLowerCase());
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
/**
|
|
719
|
-
* Check if file should be skipped (binary files)
|
|
720
|
-
* @param {string} filePath - File path
|
|
721
|
-
* @returns {boolean} True if should skip
|
|
722
|
-
* @private
|
|
723
|
-
*/
|
|
724
|
-
shouldSkipFile(filePath) {
|
|
725
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
726
|
-
return BINARY_EXTENSIONS.has(ext);
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
/**
|
|
730
|
-
* Search for terms in multiple files
|
|
731
|
-
* @param {Array<string>} filePaths - File paths to search
|
|
732
|
-
* @param {Array<string>} searchTerms - Search terms
|
|
733
|
-
* @param {string} projectDir - Project directory for relative paths
|
|
734
|
-
* @returns {Promise<Object>} Search results
|
|
735
|
-
* @private
|
|
736
|
-
*/
|
|
737
|
-
async searchFiles(filePaths, searchTerms, projectDir) {
|
|
738
|
-
const allMatches = [];
|
|
739
|
-
const errorFiles = [];
|
|
740
|
-
let totalMatches = 0;
|
|
741
|
-
|
|
742
|
-
for (const filePath of filePaths) {
|
|
743
|
-
// Skip binary files
|
|
744
|
-
if (this.shouldSkipFile(filePath)) {
|
|
745
|
-
continue;
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
try {
|
|
749
|
-
// Check file size
|
|
750
|
-
const stats = await fs.stat(filePath);
|
|
751
|
-
|
|
752
|
-
if (stats.size > this.seekConfig.MAX_FILE_SIZE) {
|
|
753
|
-
errorFiles.push({
|
|
754
|
-
filePath: path.relative(projectDir, filePath),
|
|
755
|
-
error: `File too large (${Math.round(stats.size / (1024 * 1024))}MB, max ${Math.round(this.seekConfig.MAX_FILE_SIZE / (1024 * 1024))}MB)`
|
|
756
|
-
});
|
|
757
|
-
continue;
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
// Search in file
|
|
761
|
-
const matches = await this.searchInFile(filePath, searchTerms, projectDir);
|
|
762
|
-
|
|
763
|
-
allMatches.push(...matches);
|
|
764
|
-
totalMatches += matches.length;
|
|
765
|
-
|
|
766
|
-
// Stop if we've exceeded max total matches
|
|
767
|
-
if (totalMatches >= this.seekConfig.MAX_TOTAL_MATCHES) {
|
|
768
|
-
this.logger?.warn('Maximum total matches reached', { totalMatches });
|
|
769
|
-
break;
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
} catch (error) {
|
|
773
|
-
errorFiles.push({
|
|
774
|
-
filePath: path.relative(projectDir, filePath),
|
|
775
|
-
error: error.message
|
|
776
|
-
});
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
// Group matches by search term
|
|
781
|
-
const matchesByTerm = {};
|
|
782
|
-
|
|
783
|
-
for (const match of allMatches) {
|
|
784
|
-
if (!matchesByTerm[match.term]) {
|
|
785
|
-
matchesByTerm[match.term] = [];
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
matchesByTerm[match.term].push({
|
|
789
|
-
filePath: match.filePath,
|
|
790
|
-
lineNumber: match.lineNumber,
|
|
791
|
-
lineContent: match.lineContent
|
|
792
|
-
});
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
return {
|
|
796
|
-
matches: allMatches,
|
|
797
|
-
matchesByTerm,
|
|
798
|
-
errorFiles
|
|
799
|
-
};
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
/**
|
|
803
|
-
* Search for terms in a single file
|
|
804
|
-
* @param {string} filePath - File path
|
|
805
|
-
* @param {Array<string>} searchTerms - Search terms
|
|
806
|
-
* @param {string} projectDir - Project directory for relative paths
|
|
807
|
-
* @returns {Promise<Array<Object>>} Matches found
|
|
808
|
-
* @private
|
|
809
|
-
*/
|
|
810
|
-
async searchInFile(filePath, searchTerms, projectDir) {
|
|
811
|
-
const matches = [];
|
|
812
|
-
let matchesInFile = 0;
|
|
813
|
-
|
|
814
|
-
try {
|
|
815
|
-
// Read file content
|
|
816
|
-
const content = await fs.readFile(filePath, FILE_ENCODING);
|
|
817
|
-
|
|
818
|
-
// Split into lines
|
|
819
|
-
const lines = content.split('\n');
|
|
820
|
-
const relativePath = path.relative(projectDir, filePath);
|
|
821
|
-
|
|
822
|
-
// Search each line
|
|
823
|
-
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
|
|
824
|
-
const line = lines[lineIndex];
|
|
825
|
-
const lineNumber = lineIndex + 1; // 1-based line numbers
|
|
826
|
-
|
|
827
|
-
// Check each search term
|
|
828
|
-
for (const term of searchTerms) {
|
|
829
|
-
if (line.includes(term)) {
|
|
830
|
-
// Truncate line content if too long
|
|
831
|
-
let lineContent = line;
|
|
832
|
-
if (lineContent.length > this.seekConfig.MAX_LINE_CONTENT_LENGTH) {
|
|
833
|
-
const termIndex = lineContent.indexOf(term);
|
|
834
|
-
const start = Math.max(0, termIndex - 50);
|
|
835
|
-
const end = Math.min(lineContent.length, termIndex + term.length + 50);
|
|
836
|
-
lineContent = (start > 0 ? '...' : '') +
|
|
837
|
-
lineContent.substring(start, end) +
|
|
838
|
-
(end < lineContent.length ? '...' : '');
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
matches.push({
|
|
842
|
-
term,
|
|
843
|
-
filePath: relativePath,
|
|
844
|
-
lineNumber,
|
|
845
|
-
lineContent: lineContent.trim()
|
|
846
|
-
});
|
|
847
|
-
|
|
848
|
-
matchesInFile++;
|
|
849
|
-
|
|
850
|
-
// Limit matches per file
|
|
851
|
-
if (matchesInFile >= this.seekConfig.MAX_MATCHES_PER_FILE) {
|
|
852
|
-
this.logger?.warn('Maximum matches per file reached', { filePath: relativePath });
|
|
853
|
-
return matches;
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
} catch (error) {
|
|
860
|
-
throw new Error(`Failed to read file: ${error.message}`);
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
return matches;
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
/**
|
|
867
|
-
* Format search results for display
|
|
868
|
-
* @param {Array<Object>} matches - Search matches
|
|
869
|
-
* @param {Array<Object>} errorFiles - Files with errors
|
|
870
|
-
* @param {Array<string>} notFoundFiles - Files not found
|
|
871
|
-
* @param {number} filesSearched - Number of files searched
|
|
872
|
-
* @returns {string} Formatted results
|
|
873
|
-
* @private
|
|
874
|
-
*/
|
|
875
|
-
formatResults(matches, errorFiles, notFoundFiles, filesSearched) {
|
|
876
|
-
let output = '';
|
|
877
|
-
|
|
878
|
-
// Report files not found
|
|
879
|
-
if (notFoundFiles.length > 0) {
|
|
880
|
-
output += 'FILES NOT FOUND:\n';
|
|
881
|
-
for (const file of notFoundFiles) {
|
|
882
|
-
output += ` - ${file}\n`;
|
|
883
|
-
}
|
|
884
|
-
output += '\n';
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
// Report files with errors
|
|
888
|
-
if (errorFiles.length > 0) {
|
|
889
|
-
output += 'FILES WITH ERRORS:\n';
|
|
890
|
-
for (const file of errorFiles) {
|
|
891
|
-
output += ` - ${file.filePath}: ${file.error}\n`;
|
|
892
|
-
}
|
|
893
|
-
output += '\n';
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
// Report search results
|
|
897
|
-
if (matches.length === 0) {
|
|
898
|
-
output += `No matches found for the specified search terms in ${filesSearched} file(s).\n`;
|
|
899
|
-
} else {
|
|
900
|
-
// Group by term
|
|
901
|
-
const matchesByTerm = {};
|
|
902
|
-
for (const match of matches) {
|
|
903
|
-
if (!matchesByTerm[match.term]) {
|
|
904
|
-
matchesByTerm[match.term] = [];
|
|
905
|
-
}
|
|
906
|
-
matchesByTerm[match.term].push(match);
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
output += `SEARCH RESULTS (${matches.length} total matches in ${filesSearched} file(s)):\n\n`;
|
|
910
|
-
|
|
911
|
-
for (const [term, termMatches] of Object.entries(matchesByTerm)) {
|
|
912
|
-
output += `Search term: "${term}" (${termMatches.length} matches)\n`;
|
|
913
|
-
|
|
914
|
-
for (const match of termMatches) {
|
|
915
|
-
output += ` ${match.filePath}:${match.lineNumber} - ${match.lineContent}\n`;
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
output += '\n';
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
// Add warning if max matches reached
|
|
922
|
-
if (matches.length >= this.seekConfig.MAX_TOTAL_MATCHES) {
|
|
923
|
-
output += `⚠️ Maximum matches limit reached (${this.seekConfig.MAX_TOTAL_MATCHES}). Some matches may not be shown.\n`;
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
return output.trim();
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
/**
|
|
931
|
-
* Get supported file extensions
|
|
932
|
-
* @returns {Array<string>} Array of supported extensions
|
|
933
|
-
*/
|
|
934
|
-
getSupportedExtensions() {
|
|
935
|
-
return [
|
|
936
|
-
'.js', '.jsx', '.ts', '.tsx',
|
|
937
|
-
'.json', '.xml', '.html', '.css', '.scss', '.sass', '.less',
|
|
938
|
-
'.md', '.txt', '.log',
|
|
939
|
-
'.py', '.rb', '.java', '.go', '.rs',
|
|
940
|
-
'.c', '.cpp', '.h', '.hpp',
|
|
941
|
-
'.sh', '.bash', '.zsh',
|
|
942
|
-
'.yml', '.yaml', '.toml', '.ini', '.conf'
|
|
943
|
-
];
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
/**
|
|
947
|
-
* Resource cleanup
|
|
948
|
-
* @param {string} operationId - Operation identifier
|
|
949
|
-
*/
|
|
950
|
-
async cleanup(operationId) {
|
|
951
|
-
// No persistent resources to clean up
|
|
952
|
-
this.logger?.info('Seek tool cleanup completed', { operationId });
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
export default SeekTool;
|
|
1
|
+
const a0_0x3a250c=a0_0x29c1;(function(_0x254de9,_0x160ced){const _0x7aaeb6=a0_0x29c1,_0x367bcc=_0x254de9();while(!![]){try{const _0x13d145=parseInt(_0x7aaeb6(0xe0))/0x1*(-parseInt(_0x7aaeb6(0x88))/0x2)+-parseInt(_0x7aaeb6(0xd3))/0x3*(-parseInt(_0x7aaeb6(0xc8))/0x4)+-parseInt(_0x7aaeb6(0x11b))/0x5*(-parseInt(_0x7aaeb6(0x8f))/0x6)+-parseInt(_0x7aaeb6(0xe5))/0x7*(-parseInt(_0x7aaeb6(0xae))/0x8)+parseInt(_0x7aaeb6(0x11a))/0x9*(-parseInt(_0x7aaeb6(0x9d))/0xa)+parseInt(_0x7aaeb6(0xb8))/0xb+-parseInt(_0x7aaeb6(0xeb))/0xc;if(_0x13d145===_0x160ced)break;else _0x367bcc['push'](_0x367bcc['shift']());}catch(_0x13c27a){_0x367bcc['push'](_0x367bcc['shift']());}}}(a0_0x2f90,0x21209));function a0_0x29c1(_0x2bf797,_0x43681f){_0x2bf797=_0x2bf797-0x88;const _0x2f90f4=a0_0x2f90();let _0x29c1a4=_0x2f90f4[_0x2bf797];if(a0_0x29c1['ioUHrO']===undefined){var _0x4a7341=function(_0x28345d){const _0x3f5a4e='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0xf5f143='',_0x464161='';for(let _0x4d8b1f=0x0,_0x10872e,_0x3faf32,_0x30c016=0x0;_0x3faf32=_0x28345d['charAt'](_0x30c016++);~_0x3faf32&&(_0x10872e=_0x4d8b1f%0x4?_0x10872e*0x40+_0x3faf32:_0x3faf32,_0x4d8b1f++%0x4)?_0xf5f143+=String['fromCharCode'](0xff&_0x10872e>>(-0x2*_0x4d8b1f&0x6)):0x0){_0x3faf32=_0x3f5a4e['indexOf'](_0x3faf32);}for(let _0x3a21f0=0x0,_0x52efc3=_0xf5f143['length'];_0x3a21f0<_0x52efc3;_0x3a21f0++){_0x464161+='%'+('00'+_0xf5f143['charCodeAt'](_0x3a21f0)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x464161);};a0_0x29c1['rqXPTi']=_0x4a7341,a0_0x29c1['XWdRHZ']={},a0_0x29c1['ioUHrO']=!![];}const _0x38f937=_0x2f90f4[0x0],_0x453615=_0x2bf797+_0x38f937,_0x37d3c0=a0_0x29c1['XWdRHZ'][_0x453615];return!_0x37d3c0?(_0x29c1a4=a0_0x29c1['rqXPTi'](_0x29c1a4),a0_0x29c1['XWdRHZ'][_0x453615]=_0x29c1a4):_0x29c1a4=_0x37d3c0,_0x29c1a4;}import{BaseTool}from'./baseTool.js';function a0_0x2f90(){const _0x2636e3=['lNnV','rMLSzsb0B28GBgfYz2uGka','u2vLAYb0B29Sigv4zwn1DgLVBIbMywLSzwq','lNjZ','rgLYzwn0B3j5ig5VDcbMB3vUzcbMB3iGz2XVyIbWyxr0zxjU','tuiGCgvYigzPBguklsbdyxnLlxnLBNnPDgL2zsbZzwfYy2GGB25SEqOTiev4ywn0ihn0CMLUzYbTyxrJAgLUzYaOBM90ihjLz2v4kqOTifbHDgHZig91DhnPzguGywnJzxnZAwjSzsbKAxjLy3rVCMLLCYb3AwXSigjLihjLCg9YDgvKigfZicjUB3qGzM91BMqIcIaGica','lNPZAa','mZGYmJiWDw1ItM9T','z2v0rgvZy3jPChrPB24','lI4U','lNnXBgL0zq','C2HVDwXKu2TPCerPCMvJDg9YEq','lMjHC2G','oIbTDxn0igjLigeGBM9UlwvTChr5ihn0CMLUzW','tufyx0zjtevFu0LArq','lMjTCa','lNDTDG','tufyx0zjtevFuefusfm','lMv4zq','C3rHCNrZv2L0Aa','C2vLA0nVBMzPzW','AxngAwXL','lMDPzG','C2HVDwXKu2TPCezPBgu','mJy4mZyWB2rwEfnc','lMHWCa','tuiSig1HEca','yNvPBgq','D2fYBG','C3vIC3rYAw5N','Bwf0y2HLC0j5vgvYBq','tufyx01bvenirvnFuevsx0zjteu','ig1HDgnOzxmPcG','CM91BMq','mtG3mJKWnfLhBM1LrW','AxneAxjLy3rVCNK','zxHWyw5Kr2XVyLbHDhrLCM4','tufyx0XjtKvFq09ovevovf9mru5hveG','zxHLy3v0zq','DhjPBq','C3rHDa','kIOV','icHUB3qGAw4GywnJzxnZAwjSzsbKAxjLy3rVCMLLCYK','zxnJyxbLuMvNrxHW','tufyx0zjtevtx1bfuL9trufsq0G','lM1K','lNrVBwW','lMrI','tuiGCgvYigzPBguklsbszxr1CM5ZihvWihrVia','lMr5BgLI','mZeWntG4uKTwuK9w','B3v0','Bwf0y2HLC1bHDhrLCM4','lNnHC3m','CMvXDwLYzxnqCM9Qzwn0','tufyx1rpvefmx01bvenirvm','y3DK','zw50CMLLCW','CMvHze9UBhLeAxjLy3rVCMLLCW','AxnbCNjHEq','DgvZDa','ovjzEK56sG','zMLSzvbHDgG','BwvZC2fNzq','lMLJBW','igzPBguOCYKUcG','lMnZCW','zM91BMq','BgLUzu51BwjLCG','lNDVzMyY','lMf2Aq','lMH0BwW','x19WEwnHy2HLx18','lNnJC3m','mJq4mJC5CerTBMHh','CMvZB2X2zuzPBgvqyxrOCW','CMvWBgfJzq','AM9PBG','D3jPDgvfBMfIBgvKrgLYzwn0B3jPzxm','mtrICvnfze0','CMvZB2X2zq','Bwf0y2HLCW','BM90rM91BMq','zMLSzvbHDgHZ','z2v0uMvXDwLYzwrqyxjHBwv0zxjZ','mtaYmJuYywvdsgX1','tuiP','AxnqyxrOqwnJzxnZAwjSzq','Aw5KzxHpzG','lMnVBMy','rxHLy3v0Aw5NihnLzwSGDg9VBa','twf4Aw11BsbKAxjLy3rVCNKGzgvWDgGGCMvHy2HLza','BMfTzq','ks4Gu29TzsbTyxrJAgvZig1HEsbUB3qGyMuGC2HVD24UcG','qMfZzsbKAxjLy3rVCNKGBM90igzVDw5KigzVCIbNBg9IihbHDhrLCM4','rKLmrvmGv0LuscbfuLjpuLm6cG','C2vHCMnOrMLSzxm','lMDPDa','BgvUz3rO','ChvZAa','lMrHDa','zxjYB3jgAwXLCW','igzPBguOCYKPoGOk','DgvYBq','icaTia','lMPWzW','lNrHCG','lMDV','icHUB3qGysbYzwD1BgfYigzPBguP','rMLSzsbWyxrOia','lNb5','icHPCYbHigrPCMvJDg9YEsWGBM90igeGzMLSzsK','D29YA2LUz0rPCMvJDg9YEq','lNnO','C3rYAw5N','zxHLyW','ic0G','Bg9Nz2vY','lMnHy2HL','twf4Aw11BsbTyxrJAgvZihbLCIbMAwXLihjLywnOzwq','vg9Vig1HBNKGC2vHCMnOihrLCM1ZicHTyxGG','iIaO','BwfW','lMPZB24','DMvUzg9Y','ks4Gtwf4Aw11BsbPCYa','CgfYC2vqyxjHBwv0zxjZ','z2v0u3vWCg9YDgvKrxH0zw5ZAw9UCW','CMvHzezPBgu','lNbUzW','lMvVDa','u2vLAYb0B29SignSzwfUDxaGy29TCgXLDgvK','nJnRzvbrAvO','mJy2nwjctxrwyW','C3bSAxq','Aw5JBhvKzxm','zMLUzezPBgvZuMvJDxjZAxzLBhK','zxjYB3i','Dg9mB3DLCKnHC2u','C2vHCMnOvgvYBxm','mKzmt0zwCa','lJD6','rKLmrvmGtK9uiezpvu5eoGO','vg9Vig1HBNKGzMLSzxmGDg8GC2vHCMnOicG','lM1VDG','lNr0zG','CMvSyxrPDMu','mJeZnK9rwMrIra','y2XLyw51Ca','lNLTBa','lMPWzwC','lNPPCa','DgLTzw91Da','lMLUAq'];a0_0x2f90=function(){return _0x2636e3;};return a0_0x2f90();}import a0_0xf5f143 from'../utilities/tagParser.js';import{promises as a0_0x464161}from'fs';import a0_0x4d8b1f from'path';const SEEK_CONFIG={'MAX_FILE_SIZE':0xa*0x400*0x400,'MAX_FILES_PER_SEARCH':0x3e8,'MAX_MATCHES_PER_FILE':0x64,'MAX_TOTAL_MATCHES':0x1f4,'MAX_SEARCH_TERMS':0x32,'MAX_FILE_PATHS':0x64,'MAX_DIRECTORY_DEPTH':0x14,'MAX_LINE_CONTENT_LENGTH':0xc8,'CONTEXT_LINES_BEFORE':0x0,'CONTEXT_LINES_AFTER':0x0},FILE_ENCODING='utf-8',BINARY_EXTENSIONS=new Set([a0_0x3a250c(0x117),a0_0x3a250c(0xff),a0_0x3a250c(0x92),a0_0x3a250c(0xac),a0_0x3a250c(0xa5),a0_0x3a250c(0xd6),'.svg','.pdf',a0_0x3a250c(0x93),a0_0x3a250c(0x100),'.gz','.rar',a0_0x3a250c(0x89),a0_0x3a250c(0xa8),'.dll',a0_0x3a250c(0x96),a0_0x3a250c(0xc7),'.mp3','.mp4',a0_0x3a250c(0xdc),a0_0x3a250c(0x8c),a0_0x3a250c(0xa6),'.woff',a0_0x3a250c(0xdb),a0_0x3a250c(0x8d),a0_0x3a250c(0x118),'.bin',a0_0x3a250c(0xfa),a0_0x3a250c(0xc5),a0_0x3a250c(0xa0)]);class SeekTool extends BaseTool{constructor(_0x10872e={},_0x3faf32=null){const _0x5d78a7=a0_0x3a250c;super(_0x10872e,_0x3faf32),this[_0x5d78a7(0xcc)]=!![],this['isAsync']=!![],this[_0x5d78a7(0x94)]=_0x10872e['timeout']||0x1d4c0,this['seekConfig']={...SEEK_CONFIG,..._0x10872e[_0x5d78a7(0xaa)]};}[a0_0x3a250c(0x9e)](){const _0x564f0b=a0_0x3a250c;return'\x0aSeek\x20Tool:\x20Search\x20for\x20specific\x20content\x20within\x20project\x20files.\x20Highly\x20recommended\x20for\x20verifying\x20imports,\x20function\x20usage,\x20and\x20variable\x20references.\x0a\x0aXML\x20USAGE:\x0a<seek>\x0a\x20\x20<in-files>\x0a\x20\x20\x20\x20file/path/one.js\x0a\x20\x20\x20\x20file/path/two.js\x0a\x20\x20\x20\x20src/**/*.js\x0a\x20\x20</in-files>\x0a\x20\x20<search-terms>\x0a\x20\x20\x20\x20<term>search\x20phrase\x20one</term>\x0a\x20\x20\x20\x20<term>search\x20phrase\x20two</term>\x0a\x20\x20\x20\x20<term>search\x20phrase\x20three</term>\x0a\x20\x20</search-terms>\x0a</seek>\x0a\x0aJSON\x20USAGE:\x0a```json\x0a{\x0a\x20\x20\x22toolId\x22:\x20\x22seek\x22,\x0a\x20\x20\x22filePaths\x22:\x20[\x0a\x20\x20\x20\x20\x22src/components/Header.js\x22,\x0a\x20\x20\x20\x20\x22src/utils/*.js\x22,\x0a\x20\x20\x20\x20\x22src/**/*.jsx\x22\x0a\x20\x20],\x0a\x20\x20\x22searchTerms\x22:\x20[\x0a\x20\x20\x20\x20\x22import\x20React\x22,\x0a\x20\x20\x20\x20\x22useState\x22,\x0a\x20\x20\x20\x20\x22function\x20handleSubmit\x22\x0a\x20\x20]\x0a}\x0a```\x0a\x0aSUPPORTED\x20GLOB\x20PATTERNS:\x0a-\x20*.js\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20-\x20All\x20.js\x20files\x20in\x20a\x20directory\x0a-\x20**/*.js\x20\x20\x20\x20\x20\x20\x20\x20-\x20All\x20.js\x20files\x20recursively\x0a-\x20src/**/*.jsx\x20\x20\x20-\x20All\x20.jsx\x20files\x20under\x20src/\x20recursively\x0a-\x20components/*.*\x20-\x20All\x20files\x20in\x20components/\x0a\x0aEXAMPLES:\x0a\x0aExample\x201\x20-\x20Find\x20function\x20usage:\x0a<seek>\x0a\x20\x20<in-files>\x0a\x20\x20\x20\x20src/components/*.js\x0a\x20\x20\x20\x20src/utils/helpers.js\x0a\x20\x20</in-files>\x0a\x20\x20<search-terms>\x0a\x20\x20\x20\x20<term>function\x20handleSubmit</term>\x0a\x20\x20\x20\x20<term>useState(</term>\x0a\x20\x20</search-terms>\x0a</seek>\x0a\x0aExample\x202\x20-\x20Verify\x20imports:\x0a<seek>\x0a\x20\x20<in-files>\x0a\x20\x20\x20\x20src/components/Header.js\x0a\x20\x20\x20\x20src/components/Footer.js\x0a\x20\x20</in-files>\x0a\x20\x20<search-terms>\x0a\x20\x20\x20\x20<term>import\x20React</term>\x0a\x20\x20\x20\x20<term>import\x20{\x20useState\x20}</term>\x0a\x20\x20\x20\x20<term>from\x20\x27react\x27</term>\x0a\x20\x20</search-terms>\x0a</seek>\x0a\x0aExample\x203\x20-\x20Find\x20variable\x20references:\x0a<seek>\x0a\x20\x20<in-files>\x0a\x20\x20\x20\x20src/**/*.js\x0a\x20\x20</in-files>\x0a\x20\x20<search-terms>\x0a\x20\x20\x20\x20<term>apiClient</term>\x0a\x20\x20\x20\x20<term>config.apiUrl</term>\x0a\x20\x20</search-terms>\x0a</seek>\x0a\x0aExample\x204\x20-\x20Search\x20specific\x20files\x20only:\x0a<seek>\x0a\x20\x20<in-files>\x0a\x20\x20\x20\x20package.json\x0a\x20\x20\x20\x20tsconfig.json\x0a\x20\x20\x20\x20.gitignore\x0a\x20\x20</in-files>\x0a\x20\x20<search-terms>\x0a\x20\x20\x20\x20<term>react</term>\x0a\x20\x20\x20\x20<term>typescript</term>\x0a\x20\x20</search-terms>\x0a</seek>\x0a\x0aFEATURES:\x0a-\x20Searches\x20for\x20exact\x20string\x20matches\x20(case-sensitive)\x0a-\x20Returns\x20file\x20path,\x20line\x20number,\x20and\x20line\x20content\x20for\x20each\x20match\x0a-\x20Supports\x20glob\x20patterns\x20for\x20flexible\x20file\x20selection\x0a-\x20Skips\x20binary\x20files\x20automatically\x0a-\x20Reports\x20files\x20not\x20found\x20and\x20files\x20with\x20errors\x0a-\x20Limited\x20to\x20'+SEEK_CONFIG['MAX_FILE_SIZE']/(0x400*0x400)+_0x564f0b(0xc6)+SEEK_CONFIG['MAX_TOTAL_MATCHES']+'\x20matches\x20total\x0a\x0aRESULT\x20FORMAT:\x0aThe\x20tool\x20returns:\x0a-\x20List\x20of\x20files\x20that\x20were\x20not\x20found\x0a-\x20List\x20of\x20files\x20that\x20had\x20errors\x20during\x20search\x0a-\x20For\x20each\x20search\x20term:\x0a\x20\x20-\x20File\x20path\x20where\x20found\x0a\x20\x20-\x20Line\x20number\x0a\x20\x20-\x20Line\x20content\x20(trimmed)\x0a\x0aMULTI-DIRECTORY\x20SUPPORT:\x0aWhen\x20an\x20agent\x20has\x20multiple\x20directories\x20configured,\x20the\x20SeekTool\x20can\x20search\x20across\x20all\x20of\x20them:\x0a-\x20Relative\x20paths\x20are\x20resolved\x20from\x20the\x20working\x20directory\x0a-\x20Absolute\x20paths\x20can\x20reference\x20any\x20accessible\x20directory\x0a-\x20Automatic\x20validation\x20ensures\x20paths\x20are\x20within\x20allowed\x20directories\x0a\x0aExample\x20with\x20multiple\x20directories:\x0aIf\x20agent\x20has\x20access\x20to:\x0a\x20\x20-\x20/home/user/project1\x20(working\x20directory)\x0a\x20\x20-\x20/home/user/project2\x20(read-only)\x0a\x20\x20-\x20/home/user/shared\x20(read-only)\x0a\x0aYou\x20can\x20search:\x0a\x20\x20src/**/*.js\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20→\x20Searches\x20in\x20/home/user/project1/src/**/*.js\x0a\x20\x20/home/user/project2/config.json\x20\x20\x20\x20\x20\x20\x20→\x20Searches\x20in\x20project2\x20(absolute\x20path)\x0a\x20\x20/home/user/shared/docs/*.md\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20→\x20Searches\x20in\x20shared\x20directory\x0a\x0aLIMITATIONS:\x0a-\x20Maximum\x20'+SEEK_CONFIG[_0x564f0b(0xc2)]+'\x20files\x20per\x20search\x0a-\x20Maximum\x20'+SEEK_CONFIG['MAX_SEARCH_TERMS']+'\x20search\x20terms\x0a-\x20Maximum\x20'+SEEK_CONFIG[_0x564f0b(0xa4)]/(0x400*0x400)+_0x564f0b(0x9b);}[a0_0x3a250c(0x114)](_0x30c016){const _0x1147d3=a0_0x3a250c;try{if(_0x30c016['trim']()[_0x1147d3(0xa9)]('{')){const _0x3129af=JSON['parse'](_0x30c016);return{'filePaths':_0x3129af[_0x1147d3(0xe9)]||[],'searchTerms':_0x3129af['searchTerms']||[]};}const _0x3a21f0={'filePaths':[],'searchTerms':[]},_0x52efc3=/<in-files>([\s\S]*?)<\/in-files>/i,_0x6e152e=_0x52efc3[_0x1147d3(0x109)](_0x30c016);if(_0x6e152e){const _0x87cb09=_0x6e152e[0x1];_0x3a21f0[_0x1147d3(0xe9)]=_0x87cb09[_0x1147d3(0x11c)]('\x0a')[_0x1147d3(0x110)](_0x5e88a7=>_0x5e88a7['trim']())['filter'](_0x3db61b=>_0x3db61b['length']>0x0);}const _0x10a9ca=/<search-terms>([\s\S]*?)<\/search-terms>/i,_0x1df2f6=_0x10a9ca['exec'](_0x30c016);if(_0x1df2f6){const _0x15ff1f=_0x1df2f6[0x1],_0x42abb1=/<term>(.*?)<\/term>/gi;let _0x36104d;while((_0x36104d=_0x42abb1['exec'](_0x15ff1f))!==null){const _0x533b15=_0x36104d[0x1][_0x1147d3(0xbd)]();_0x533b15[_0x1147d3(0xf8)]>0x0&&_0x3a21f0[_0x1147d3(0x121)]['push'](_0x533b15);}}return _0x3a21f0;}catch(_0x50c134){return this['logger']?.[_0x1147d3(0x11f)]('Failed\x20to\x20parse\x20seek\x20parameters',{'error':_0x50c134['message']}),{'filePaths':[],'searchTerms':[],'parseError':_0x50c134[_0x1147d3(0xd5)]};}}[a0_0x3a250c(0xea)](){const _0x613e20=a0_0x3a250c;return[_0x613e20(0xe9),_0x613e20(0x121)];}['customValidateParameters'](_0x13b5e3){const _0x5c8ddc=a0_0x3a250c,_0x4014a6=[];if(!_0x13b5e3['filePaths']||!Array[_0x5c8ddc(0xd1)](_0x13b5e3[_0x5c8ddc(0xe9)])||_0x13b5e3['filePaths']['length']===0x0)_0x4014a6[_0x5c8ddc(0xf9)]('At\x20least\x20one\x20file\x20path\x20is\x20required');else _0x13b5e3['filePaths'][_0x5c8ddc(0xf8)]>this['seekConfig'][_0x5c8ddc(0xa7)]&&_0x4014a6[_0x5c8ddc(0xf9)]('Too\x20many\x20file\x20paths\x20(max\x20'+this['seekConfig']['MAX_FILE_PATHS']+')');if(!_0x13b5e3['searchTerms']||!Array['isArray'](_0x13b5e3['searchTerms'])||_0x13b5e3['searchTerms']['length']===0x0)_0x4014a6[_0x5c8ddc(0xf9)]('At\x20least\x20one\x20search\x20term\x20is\x20required');else _0x13b5e3['searchTerms']['length']>this[_0x5c8ddc(0xaa)]['MAX_SEARCH_TERMS']&&_0x4014a6[_0x5c8ddc(0xf9)](_0x5c8ddc(0x10e)+this['seekConfig']['MAX_SEARCH_TERMS']+')');if(_0x13b5e3[_0x5c8ddc(0x121)]&&Array['isArray'](_0x13b5e3['searchTerms']))for(const [_0x3df2f9,_0x86cf26]of _0x13b5e3['searchTerms'][_0x5c8ddc(0xcf)]()){(typeof _0x86cf26!==_0x5c8ddc(0x108)||_0x86cf26[_0x5c8ddc(0xbd)]()['length']===0x0)&&_0x4014a6[_0x5c8ddc(0xf9)]('Search\x20term\x20'+(_0x3df2f9+0x1)+':\x20must\x20be\x20a\x20non-empty\x20string');}if(_0x13b5e3[_0x5c8ddc(0xe9)]&&Array[_0x5c8ddc(0xd1)](_0x13b5e3[_0x5c8ddc(0xe9)]))for(const [_0x1724f8,_0x3fa833]of _0x13b5e3['filePaths']['entries']()){(typeof _0x3fa833!==_0x5c8ddc(0x108)||_0x3fa833[_0x5c8ddc(0xbd)]()[_0x5c8ddc(0xf8)]===0x0)&&_0x4014a6['push']('File\x20path\x20'+(_0x1724f8+0x1)+_0x5c8ddc(0xa3)),_0x3fa833['includes']('..')&&_0x4014a6['push'](_0x5c8ddc(0x103)+(_0x1724f8+0x1)+':\x20path\x20traversal\x20(..)\x20not\x20allowed\x20for\x20security');}return{'valid':_0x4014a6['length']===0x0,'errors':_0x4014a6};}async[a0_0x3a250c(0xbc)](_0x4a2efd,_0xbee323){const _0x4814fa=a0_0x3a250c,{filePaths:_0x151c6f,searchTerms:_0x2bc3ba}=_0x4a2efd,{projectDir:_0x27b2fd,agentId:_0xa3900,directoryAccess:_0x237255}=_0xbee323;let _0x267730=_0x27b2fd||process[_0x4814fa(0xce)](),_0x333e4d=[_0x267730];_0x237255&&_0x237255[_0x4814fa(0x106)]&&(_0x267730=_0x237255[_0x4814fa(0x106)],_0x333e4d=this['getAllAccessibleDirectories'](_0x237255),this[_0x4814fa(0x10b)]?.['info']('Using\x20agent\x20configured\x20directory\x20access',{'workingDirectory':_0x237255[_0x4814fa(0x106)],'totalAccessibleDirs':_0x333e4d['length'],'readOnlyDirs':_0x237255['readOnlyDirectories']?.[_0x4814fa(0xf8)]||0x0,'writeEnabledDirs':_0x237255['writeEnabledDirectories']?.['length']||0x0,'agentId':_0xa3900}));if(!_0x267730)throw new Error('Project\x20directory\x20is\x20required\x20for\x20seek\x20tool');this['logger']?.['info'](_0x4814fa(0xf0),{'filePathCount':_0x151c6f[_0x4814fa(0xf8)],'searchTermCount':_0x2bc3ba['length'],'workingDirectory':_0x267730,'accessibleDirectories':_0x333e4d['length'],'agentId':_0xa3900});try{const _0x5dc34e=await this['resolveFilePaths'](_0x151c6f,_0x267730,_0x237255?_0x333e4d:null),_0x4da0e0=_0x5dc34e['found'],_0x459a61=_0x5dc34e['notFound'];if(_0x4da0e0['length']>this['seekConfig'][_0x4814fa(0xc2)])return{'success':![],'error':_0x4814fa(0x8b)+_0x4da0e0['length']+_0x4814fa(0x113)+this['seekConfig']['MAX_FILES_PER_SEARCH']+'.\x20Use\x20more\x20specific\x20file\x20patterns.','filesResolved':_0x4da0e0['length'],'filesNotFound':_0x459a61['length']};const _0x337442=await this[_0x4814fa(0xf6)](_0x4da0e0,_0x2bc3ba,_0x267730),_0x3bb5bd=this['formatResults'](_0x337442[_0x4814fa(0xe7)],_0x337442['errorFiles'],_0x459a61,_0x4da0e0[_0x4814fa(0xf8)]);return{'success':!![],'filesSearched':_0x4da0e0['length'],'filesNotFound':_0x459a61[_0x4814fa(0xf8)],'filesWithErrors':_0x337442[_0x4814fa(0xfb)][_0x4814fa(0xf8)],'totalMatches':_0x337442[_0x4814fa(0xe7)][_0x4814fa(0xf8)],'matchesByTerm':_0x337442[_0x4814fa(0xb4)],'formattedResults':_0x3bb5bd,'toolUsed':'seek'};}catch(_0x50e58c){this[_0x4814fa(0x10b)]?.['error'](_0x4814fa(0x98),{'error':_0x50e58c[_0x4814fa(0xd5)]});throw _0x50e58c;}}['getAllAccessibleDirectories'](_0x4ca1a1){const _0x294658=a0_0x3a250c,_0x2ec64b=new Set();_0x4ca1a1[_0x294658(0x106)]&&_0x2ec64b['add'](_0x4ca1a1['workingDirectory']);if(_0x4ca1a1[_0x294658(0xd0)]&&Array['isArray'](_0x4ca1a1['readOnlyDirectories']))for(const _0x179e59 of _0x4ca1a1[_0x294658(0xd0)]){_0x2ec64b['add'](_0x179e59);}if(_0x4ca1a1[_0x294658(0xe4)]&&Array['isArray'](_0x4ca1a1['writeEnabledDirectories']))for(const _0x1f3fa0 of _0x4ca1a1['writeEnabledDirectories']){_0x2ec64b['add'](_0x1f3fa0);}return Array['from'](_0x2ec64b);}[a0_0x3a250c(0xed)](_0x244d3b,_0x28b6a2){for(const _0x4a07be of _0x28b6a2){const _0x5bdaab=a0_0x4d8b1f['relative'](_0x4a07be,_0x244d3b),_0x2f3b50=!_0x5bdaab['startsWith']('..')&&!a0_0x4d8b1f['isAbsolute'](_0x5bdaab);if(_0x2f3b50)return!![];}return![];}async[a0_0x3a250c(0xe1)](_0x78c55b,_0x91a8a4,_0x36c652=null){const _0xb4e743=a0_0x3a250c,_0x4c04bc={'found':[],'notFound':[]};for(const _0x42c1f4 of _0x78c55b){const _0x802c=_0x42c1f4['trim']();if(_0x802c['includes']('*')){const _0x14dc25=await this['expandGlobPattern'](_0x802c,_0x91a8a4);_0x14dc25[_0xb4e743(0xd9)][_0xb4e743(0xf8)]>0x0?_0x4c04bc[_0xb4e743(0xd9)]['push'](..._0x14dc25[_0xb4e743(0xd9)]):_0x4c04bc[_0xb4e743(0xe8)][_0xb4e743(0xf9)](_0x802c+'\x20(no\x20matching\x20files)');}else{const _0xb014f9=a0_0x4d8b1f['isAbsolute'](_0x802c)?_0x802c:a0_0x4d8b1f[_0xb4e743(0xe6)](_0x91a8a4,_0x802c);if(_0x36c652&&_0x36c652[_0xb4e743(0xf8)]>0x0){if(!this[_0xb4e743(0xed)](_0xb014f9,_0x36c652)){_0x4c04bc['notFound'][_0xb4e743(0xf9)](_0x802c+_0xb4e743(0xc0));continue;}}try{const _0x56d6fd=await a0_0x464161[_0xb4e743(0xbe)](_0xb014f9);if(_0x56d6fd[_0xb4e743(0xab)]())_0x4c04bc[_0xb4e743(0xd9)]['push'](_0xb014f9);else _0x56d6fd[_0xb4e743(0xb9)]()?_0x4c04bc['notFound']['push'](_0x802c+_0xb4e743(0x105)):_0x4c04bc[_0xb4e743(0xe8)][_0xb4e743(0xf9)](_0x802c+_0xb4e743(0x102));}catch(_0x23b212){_0x4c04bc[_0xb4e743(0xe8)]['push'](_0x802c+'\x20('+(_0x23b212['code']||_0x23b212['message'])+')');}}}return _0x4c04bc;}async[a0_0x3a250c(0xba)](_0x3cbabb,_0x23dc82){const _0x3bac28=a0_0x3a250c,_0x1b0fda={'found':[]};if(_0x3cbabb[_0x3bac28(0x11d)]('**/')){const [_0x2a73e4,_0x68c670]=_0x3cbabb[_0x3bac28(0x11c)](_0x3bac28(0xbf)),_0x5d4532=a0_0x4d8b1f['resolve'](_0x23dc82,_0x2a73e4);try{const _0x433173=await a0_0x464161['stat'](_0x5d4532);_0x433173[_0x3bac28(0xb9)]()&&await this['findFilesRecursively'](_0x5d4532,_0x68c670,_0x1b0fda[_0x3bac28(0xd9)],0x0,this[_0x3bac28(0xaa)]['MAX_DIRECTORY_DEPTH']);}catch(_0x5ded8b){this[_0x3bac28(0x10b)]?.[_0x3bac28(0xb2)](_0x3bac28(0xf4),{'basePath':_0x5d4532,'error':_0x5ded8b[_0x3bac28(0xd5)]});}}else{if(_0x3cbabb['includes']('*')){const _0x1dd374=a0_0x4d8b1f['dirname'](a0_0x4d8b1f[_0x3bac28(0xe6)](_0x23dc82,_0x3cbabb)),_0x560432=a0_0x4d8b1f['basename'](_0x3cbabb);try{const _0x233cf1=await a0_0x464161['stat'](_0x1dd374);if(_0x233cf1[_0x3bac28(0xb9)]()){const _0x4ebc02=await a0_0x464161['readdir'](_0x1dd374);for(const _0x17ec0b of _0x4ebc02){const _0x3ff3fb=a0_0x4d8b1f[_0x3bac28(0xe3)](_0x1dd374,_0x17ec0b);try{const _0x5c7822=await a0_0x464161['stat'](_0x3ff3fb);_0x5c7822[_0x3bac28(0xab)]()&&this[_0x3bac28(0xca)](_0x17ec0b,_0x560432)&&_0x1b0fda[_0x3bac28(0xd9)]['push'](_0x3ff3fb);}catch(_0x595e4c){continue;}}}}catch(_0x1cc63b){this['logger']?.[_0x3bac28(0xb2)](_0x3bac28(0x9a),{'dirPath':_0x1dd374,'error':_0x1cc63b[_0x3bac28(0xd5)]});}}}return _0x1b0fda;}async['findFilesRecursively'](_0x2bdd01,_0x5c7d0e,_0x247972,_0x2f0587,_0x3e9025){const _0x59a57a=a0_0x3a250c;if(_0x2f0587>=_0x3e9025){this['logger']?.['warn'](_0x59a57a(0xf1),{'dir':_0x2bdd01,'currentDepth':_0x2f0587});return;}try{const _0x579f5b=await a0_0x464161['readdir'](_0x2bdd01,{'withFileTypes':!![]});for(const _0x353f14 of _0x579f5b){if(_0x353f14['name']['startsWith']('.'))continue;const _0x33f6a0=a0_0x4d8b1f[_0x59a57a(0xe3)](_0x2bdd01,_0x353f14['name']);try{if(_0x353f14[_0x59a57a(0xb9)]()){if(this[_0x59a57a(0xa1)](_0x353f14[_0x59a57a(0xf2)]))continue;await this[_0x59a57a(0x11e)](_0x33f6a0,_0x5c7d0e,_0x247972,_0x2f0587+0x1,_0x3e9025);}else{if(_0x353f14['isFile']()){if(this['matchesPattern'](_0x353f14[_0x59a57a(0xf2)],_0x5c7d0e)){_0x247972[_0x59a57a(0xf9)](_0x33f6a0);if(_0x247972[_0x59a57a(0xf8)]>=this[_0x59a57a(0xaa)][_0x59a57a(0xc2)])return;}}}}catch(_0x2ed0e3){continue;}}}catch(_0x46ffcb){this['logger']?.[_0x59a57a(0xb2)]('Error\x20reading\x20directory',{'dir':_0x2bdd01,'error':_0x46ffcb[_0x59a57a(0xd5)]});}}['matchesPattern'](_0x120b83,_0x260d57){const _0x41b31c=a0_0x3a250c,_0x3705a0=_0x260d57['split']('*')['map'](_0x508c57=>this[_0x41b31c(0xc1)](_0x508c57))['join']('.*'),_0xaea6bd=new RegExp('^'+_0x3705a0+'$','i');return _0xaea6bd[_0x41b31c(0xd2)](_0x120b83);}['escapeRegExp'](_0x2be1c3){const _0x284c62=a0_0x3a250c;return _0x2be1c3[_0x284c62(0xe2)](/[.*+?^${}()|[\]\\]/g,'\x5c$&');}[a0_0x3a250c(0xa1)](_0x23addb){const _0x2d48f3=a0_0x3a250c,_0xacb523=new Set(['node_modules',_0x2d48f3(0xf7),'dist',_0x2d48f3(0xb1),'coverage','.next','.nuxt',_0x2d48f3(0xc9),'target',_0x2d48f3(0x112),_0x2d48f3(0xde),_0x2d48f3(0x10c),'tmp','temp']);return _0xacb523['has'](_0x23addb[_0x2d48f3(0x120)]());}[a0_0x3a250c(0xad)](_0xa1306){const _0x48b916=a0_0x3a250c,_0xfaacb4=a0_0x4d8b1f['extname'](_0xa1306)[_0x48b916(0x120)]();return BINARY_EXTENSIONS['has'](_0xfaacb4);}async['searchFiles'](_0xa68b29,_0x2da80c,_0x1ae18f){const _0x3bcffd=a0_0x3a250c,_0x19abf0=[],_0x5cd4a9=[];let _0x2288b0=0x0;for(const _0x4cacb4 of _0xa68b29){if(this['shouldSkipFile'](_0x4cacb4))continue;try{const _0x3f6107=await a0_0x464161[_0x3bcffd(0xbe)](_0x4cacb4);if(_0x3f6107['size']>this['seekConfig']['MAX_FILE_SIZE']){_0x5cd4a9[_0x3bcffd(0xf9)]({'filePath':a0_0x4d8b1f['relative'](_0x1ae18f,_0x4cacb4),'error':_0x3bcffd(0x97)+Math['round'](_0x3f6107['size']/(0x400*0x400))+_0x3bcffd(0xb0)+Math[_0x3bcffd(0xb7)](this['seekConfig'][_0x3bcffd(0xa4)]/(0x400*0x400))+_0x3bcffd(0xec)});continue;}const _0x29b5a9=await this['searchInFile'](_0x4cacb4,_0x2da80c,_0x1ae18f);_0x19abf0[_0x3bcffd(0xf9)](..._0x29b5a9),_0x2288b0+=_0x29b5a9[_0x3bcffd(0xf8)];if(_0x2288b0>=this[_0x3bcffd(0xaa)][_0x3bcffd(0xcd)]){this[_0x3bcffd(0x10b)]?.[_0x3bcffd(0xb2)]('Maximum\x20total\x20matches\x20reached',{'totalMatches':_0x2288b0});break;}}catch(_0x434449){_0x5cd4a9[_0x3bcffd(0xf9)]({'filePath':a0_0x4d8b1f[_0x3bcffd(0x8e)](_0x1ae18f,_0x4cacb4),'error':_0x434449[_0x3bcffd(0xd5)]});}}const _0xfe174a={};for(const _0x1c5b87 of _0x19abf0){!_0xfe174a[_0x1c5b87[_0x3bcffd(0xfd)]]&&(_0xfe174a[_0x1c5b87[_0x3bcffd(0xfd)]]=[]),_0xfe174a[_0x1c5b87['term']][_0x3bcffd(0xf9)]({'filePath':_0x1c5b87['filePath'],'lineNumber':_0x1c5b87['lineNumber'],'lineContent':_0x1c5b87['lineContent']});}return{'matches':_0x19abf0,'matchesByTerm':_0xfe174a,'errorFiles':_0x5cd4a9};}async['searchInFile'](_0x3198cc,_0x4a117b,_0x1cee46){const _0x56f03c=a0_0x3a250c,_0x58b871=[];let _0x314432=0x0;try{const _0x342085=await a0_0x464161[_0x56f03c(0x116)](_0x3198cc,FILE_ENCODING),_0x3beb38=_0x342085[_0x56f03c(0x11c)]('\x0a'),_0x4d9e86=a0_0x4d8b1f['relative'](_0x1cee46,_0x3198cc);for(let _0x2fc57f=0x0;_0x2fc57f<_0x3beb38['length'];_0x2fc57f++){const _0x20e04a=_0x3beb38[_0x2fc57f],_0x2bc6ed=_0x2fc57f+0x1;for(const _0x53cc4f of _0x4a117b){if(_0x20e04a[_0x56f03c(0x11d)](_0x53cc4f)){let _0x5bc2c0=_0x20e04a;if(_0x5bc2c0[_0x56f03c(0xf8)]>this[_0x56f03c(0xaa)][_0x56f03c(0xbb)]){const _0x201c92=_0x5bc2c0[_0x56f03c(0xee)](_0x53cc4f),_0x30b4da=Math['max'](0x0,_0x201c92-0x32),_0x47c8fc=Math['min'](_0x5bc2c0[_0x56f03c(0xf8)],_0x201c92+_0x53cc4f['length']+0x32);_0x5bc2c0=(_0x30b4da>0x0?_0x56f03c(0x9f):'')+_0x5bc2c0[_0x56f03c(0xb3)](_0x30b4da,_0x47c8fc)+(_0x47c8fc<_0x5bc2c0['length']?_0x56f03c(0x9f):'');}_0x58b871[_0x56f03c(0xf9)]({'term':_0x53cc4f,'filePath':_0x4d9e86,'lineNumber':_0x2bc6ed,'lineContent':_0x5bc2c0[_0x56f03c(0xbd)]()}),_0x314432++;if(_0x314432>=this[_0x56f03c(0xaa)][_0x56f03c(0xb5)])return this['logger']?.['warn'](_0x56f03c(0x10d),{'filePath':_0x4d9e86}),_0x58b871;}}}}catch(_0x5b4ee6){throw new Error('Failed\x20to\x20read\x20file:\x20'+_0x5b4ee6['message']);}return _0x58b871;}['formatResults'](_0x176267,_0x489db4,_0x415bfe,_0x2e3177){const _0xabd97d=a0_0x3a250c;let _0x32830e='';if(_0x415bfe['length']>0x0){_0x32830e+=_0xabd97d(0x8a);for(const _0x4f5457 of _0x415bfe){_0x32830e+=_0xabd97d(0xfe)+_0x4f5457+'\x0a';}_0x32830e+='\x0a';}if(_0x489db4[_0xabd97d(0xf8)]>0x0){_0x32830e+=_0xabd97d(0xf5);for(const _0x4c8c35 of _0x489db4){_0x32830e+=_0xabd97d(0xfe)+_0x4c8c35[_0xabd97d(0xd4)]+':\x20'+_0x4c8c35[_0xabd97d(0x11f)]+'\x0a';}_0x32830e+='\x0a';}if(_0x176267['length']===0x0)_0x32830e+='No\x20matches\x20found\x20for\x20the\x20specified\x20search\x20terms\x20in\x20'+_0x2e3177+_0xabd97d(0xd7);else{const _0x587a1e={};for(const _0x2f9a1f of _0x176267){!_0x587a1e[_0x2f9a1f['term']]&&(_0x587a1e[_0x2f9a1f[_0xabd97d(0xfd)]]=[]),_0x587a1e[_0x2f9a1f[_0xabd97d(0xfd)]]['push'](_0x2f9a1f);}_0x32830e+='SEARCH\x20RESULTS\x20('+_0x176267['length']+'\x20total\x20matches\x20in\x20'+_0x2e3177+_0xabd97d(0xfc);for(const [_0x5a6d1b,_0x430287]of Object[_0xabd97d(0xcf)](_0x587a1e)){_0x32830e+='Search\x20term:\x20\x22'+_0x5a6d1b+_0xabd97d(0x10f)+_0x430287[_0xabd97d(0xf8)]+_0xabd97d(0xb6);for(const _0x2a8572 of _0x430287){_0x32830e+='\x20\x20'+_0x2a8572['filePath']+':'+_0x2a8572[_0xabd97d(0xda)]+_0xabd97d(0x10a)+_0x2a8572['lineContent']+'\x0a';}_0x32830e+='\x0a';}_0x176267[_0xabd97d(0xf8)]>=this['seekConfig'][_0xabd97d(0xcd)]&&(_0x32830e+='⚠️\x20\x20Maximum\x20matches\x20limit\x20reached\x20('+this['seekConfig']['MAX_TOTAL_MATCHES']+_0xabd97d(0xf3));}return _0x32830e['trim']();}[a0_0x3a250c(0x115)](){const _0x8c2cb8=a0_0x3a250c;return['.js','.jsx','.ts','.tsx',_0x8c2cb8(0x111),'.xml',_0x8c2cb8(0xdd),_0x8c2cb8(0xd8),_0x8c2cb8(0xdf),_0x8c2cb8(0xcb),'.less',_0x8c2cb8(0xc3),'.txt','.log',_0x8c2cb8(0x104),'.rb','.java',_0x8c2cb8(0x101),_0x8c2cb8(0x99),'.c','.cpp','.h',_0x8c2cb8(0xaf),_0x8c2cb8(0x107),_0x8c2cb8(0xa2),_0x8c2cb8(0x9c),_0x8c2cb8(0x91),'.yaml',_0x8c2cb8(0xc4),_0x8c2cb8(0x95),_0x8c2cb8(0xef)];}async[a0_0x3a250c(0x90)](_0x1b74b6){const _0x21d323=a0_0x3a250c;this[_0x21d323(0x10b)]?.['info'](_0x21d323(0x119),{'operationId':_0x1b74b6});}}export default SeekTool;
|