onbuzz 3.6.1 → 3.6.2
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/package.json +1 -1
- package/src/__test-utils__/fixtures/malformedJson.js +31 -0
- package/src/__test-utils__/globalSetup.js +9 -0
- package/src/__test-utils__/globalTeardown.js +12 -0
- package/src/__test-utils__/mockFactories.js +101 -0
- package/src/analyzers/__tests__/CSSAnalyzer.test.js +41 -0
- package/src/analyzers/__tests__/ConfigValidator.test.js +362 -0
- package/src/analyzers/__tests__/ESLintAnalyzer.test.js +271 -0
- package/src/analyzers/__tests__/JavaScriptAnalyzer.test.js +40 -0
- package/src/analyzers/__tests__/PrettierFormatter.test.js +197 -0
- package/src/analyzers/__tests__/PythonAnalyzer.test.js +208 -0
- package/src/analyzers/__tests__/SecurityAnalyzer.test.js +303 -0
- package/src/analyzers/__tests__/SparrowAnalyzer.test.js +270 -0
- package/src/analyzers/__tests__/TypeScriptAnalyzer.test.js +187 -0
- package/src/core/__tests__/agentPool.test.js +601 -0
- package/src/core/__tests__/agentScheduler.test.js +576 -0
- package/src/core/__tests__/contextManager.test.js +252 -0
- package/src/core/__tests__/flowExecutor.test.js +262 -0
- package/src/core/__tests__/messageProcessor.test.js +627 -0
- package/src/core/__tests__/orchestrator.test.js +257 -0
- package/src/core/__tests__/stateManager.test.js +375 -0
- package/src/core/agentPool.js +11 -1
- package/src/index.js +25 -9
- package/src/interfaces/terminal/__tests__/smoke/imports.test.js +3 -5
- package/src/services/__tests__/agentActivityService.test.js +319 -0
- package/src/services/__tests__/apiKeyManager.test.js +206 -0
- package/src/services/__tests__/benchmarkService.test.js +184 -0
- package/src/services/__tests__/budgetService.test.js +211 -0
- package/src/services/__tests__/contextInjectionService.test.js +205 -0
- package/src/services/__tests__/conversationCompactionService.test.js +280 -0
- package/src/services/__tests__/credentialVault.test.js +469 -0
- package/src/services/__tests__/errorHandler.test.js +314 -0
- package/src/services/__tests__/fileAttachmentService.test.js +278 -0
- package/src/services/__tests__/flowContextService.test.js +199 -0
- package/src/services/__tests__/memoryService.test.js +450 -0
- package/src/services/__tests__/modelRouterService.test.js +388 -0
- package/src/services/__tests__/modelsService.test.js +261 -0
- package/src/services/__tests__/portRegistry.test.js +123 -0
- package/src/services/__tests__/projectDetector.test.js +34 -0
- package/src/services/__tests__/promptService.test.js +242 -0
- package/src/services/__tests__/qualityInspector.test.js +97 -0
- package/src/services/__tests__/scheduleService.test.js +308 -0
- package/src/services/__tests__/serviceRegistry.test.js +74 -0
- package/src/services/__tests__/skillsService.test.js +402 -0
- package/src/services/__tests__/tokenCountingService.test.js +48 -0
- package/src/tools/__tests__/agentCommunicationTool.test.js +500 -0
- package/src/tools/__tests__/agentDelayTool.test.js +342 -0
- package/src/tools/__tests__/asyncToolManager.test.js +344 -0
- package/src/tools/__tests__/baseTool.test.js +420 -0
- package/src/tools/__tests__/codeMapTool.test.js +348 -0
- package/src/tools/__tests__/fileContentReplaceTool.test.js +309 -0
- package/src/tools/__tests__/fileTreeTool.test.js +274 -0
- package/src/tools/__tests__/filesystemTool.test.js +717 -0
- package/src/tools/__tests__/helpTool.test.js +204 -0
- package/src/tools/__tests__/jobDoneTool.test.js +296 -0
- package/src/tools/__tests__/memoryTool.test.js +297 -0
- package/src/tools/__tests__/seekTool.test.js +282 -0
- package/src/tools/__tests__/skillsTool.test.js +226 -0
- package/src/tools/__tests__/staticAnalysisTool.test.js +509 -0
- package/src/tools/__tests__/taskManagerTool.test.js +725 -0
- package/src/tools/__tests__/terminalTool.test.js +384 -0
- package/src/tools/__tests__/userPromptTool.test.js +297 -0
- package/src/tools/__tests__/webTool.e2e.test.js +25 -11
- package/src/tools/webTool.js +6 -12
- package/src/types/__tests__/agent.test.js +499 -0
- package/src/types/__tests__/contextReference.test.js +606 -0
- package/src/types/__tests__/conversation.test.js +555 -0
- package/src/types/__tests__/toolCommand.test.js +584 -0
- package/src/types/contextReference.js +1 -1
- package/src/utilities/__tests__/attachmentValidator.test.js +80 -0
- package/src/utilities/__tests__/configManager.test.js +397 -0
- package/src/utilities/__tests__/constants.test.js +49 -0
- package/src/utilities/__tests__/directoryAccessManager.test.js +388 -0
- package/src/utilities/__tests__/fileProcessor.test.js +104 -0
- package/src/utilities/__tests__/jsonRepair.test.js +104 -0
- package/src/utilities/__tests__/logger.test.js +129 -0
- package/src/utilities/__tests__/platformUtils.test.js +87 -0
- package/src/utilities/__tests__/structuredFileValidator.test.js +263 -0
- package/src/utilities/__tests__/tagParser.test.js +887 -0
- package/src/utilities/__tests__/toolConstants.test.js +94 -0
- package/src/utilities/tagParser.js +2 -2
- package/src/tools/browserTool.js +0 -897
- package/src/utilities/platformUtils.test.js +0 -98
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { jest, describe, test, expect, beforeEach } from '@jest/globals';
|
|
2
|
+
import { createMockLogger, createMockConfig } from '../../__test-utils__/mockFactories.js';
|
|
3
|
+
|
|
4
|
+
// Mock fs/promises before import
|
|
5
|
+
const mockFs = {
|
|
6
|
+
stat: jest.fn(),
|
|
7
|
+
readdir: jest.fn()
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
jest.unstable_mockModule('fs', () => ({
|
|
11
|
+
promises: mockFs,
|
|
12
|
+
default: { promises: mockFs }
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
// Mock constants
|
|
16
|
+
jest.unstable_mockModule('../../utilities/constants.js', () => ({
|
|
17
|
+
TOOL_STATUS: { PENDING: 'pending', EXECUTING: 'executing', COMPLETED: 'completed', FAILED: 'failed' },
|
|
18
|
+
OPERATION_STATUS: { NOT_FOUND: 'not_found' },
|
|
19
|
+
ERROR_TYPES: {},
|
|
20
|
+
SYSTEM_DEFAULTS: { MAX_TOOL_EXECUTION_TIME: 300000 }
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
const { default: FileTreeTool } = await import('../fileTreeTool.js');
|
|
24
|
+
|
|
25
|
+
// Helper to create mock dirent
|
|
26
|
+
function mockDirent(name, isDir = false) {
|
|
27
|
+
return {
|
|
28
|
+
name,
|
|
29
|
+
isDirectory: () => isDir,
|
|
30
|
+
isFile: () => !isDir,
|
|
31
|
+
isSymbolicLink: () => false
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
describe('FileTreeTool', () => {
|
|
36
|
+
let tool;
|
|
37
|
+
let logger;
|
|
38
|
+
const context = { projectDir: '/project', agentId: 'agent-1' };
|
|
39
|
+
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
jest.clearAllMocks();
|
|
42
|
+
logger = createMockLogger();
|
|
43
|
+
tool = new FileTreeTool({}, logger);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('constructor sets metadata correctly', () => {
|
|
47
|
+
expect(tool.id).toBe('file-tree');
|
|
48
|
+
expect(tool.requiresProject).toBe(true);
|
|
49
|
+
expect(tool.isAsync).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('getDescription mentions file tree', () => {
|
|
53
|
+
const desc = tool.getDescription();
|
|
54
|
+
expect(desc).toContain('File Tree Tool');
|
|
55
|
+
expect(desc).toContain('maxDepth');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('getRequiredParameters returns empty array', () => {
|
|
59
|
+
expect(tool.getRequiredParameters()).toEqual([]);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('parseParameters parses JSON content', () => {
|
|
63
|
+
const content = JSON.stringify({
|
|
64
|
+
directory: 'src',
|
|
65
|
+
maxDepth: 5,
|
|
66
|
+
includeExtensions: ['.js'],
|
|
67
|
+
showFiles: true
|
|
68
|
+
});
|
|
69
|
+
const result = tool.parseParameters(content);
|
|
70
|
+
expect(result.directory).toBe('src');
|
|
71
|
+
expect(result.maxDepth).toBe(5);
|
|
72
|
+
expect(result.includeExtensions).toEqual(['.js']);
|
|
73
|
+
expect(result.showFiles).toBe(true);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('parseParameters defaults for missing JSON fields', () => {
|
|
77
|
+
const result = tool.parseParameters('{}');
|
|
78
|
+
expect(result.directory).toBe('.');
|
|
79
|
+
expect(result.maxDepth).toBe(3);
|
|
80
|
+
expect(result.showFiles).toBe(true);
|
|
81
|
+
expect(result.showHidden).toBe(false);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('parseParameters handles XML content', () => {
|
|
85
|
+
const content = '<directory>src</directory><max-depth>4</max-depth><show-files>true</show-files>';
|
|
86
|
+
const result = tool.parseParameters(content);
|
|
87
|
+
expect(result.directory).toBe('src');
|
|
88
|
+
expect(result.maxDepth).toBe(4);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('parseParameters returns defaults on parse error', () => {
|
|
92
|
+
const result = tool.parseParameters('{ broken');
|
|
93
|
+
expect(result.directory).toBe('.');
|
|
94
|
+
expect(result).toHaveProperty('parseError');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test('customValidateParameters rejects maxDepth exceeding limit', () => {
|
|
98
|
+
expect(() => tool.customValidateParameters({ maxDepth: 100 })).toThrow();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test('customValidateParameters rejects maxDepth < 1', () => {
|
|
102
|
+
expect(() => tool.customValidateParameters({ maxDepth: 0 })).toThrow();
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test('customValidateParameters rejects path traversal', () => {
|
|
106
|
+
expect(() => tool.customValidateParameters({ directory: '../etc' })).toThrow('traversal');
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('customValidateParameters rejects non-array includeExtensions', () => {
|
|
110
|
+
expect(() => tool.customValidateParameters({ includeExtensions: '.js' })).toThrow();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test('customValidateParameters rejects extension without dot', () => {
|
|
114
|
+
expect(() => tool.customValidateParameters({ includeExtensions: ['js'] })).toThrow('dot');
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test('customValidateParameters accepts valid params', () => {
|
|
118
|
+
const result = tool.customValidateParameters({
|
|
119
|
+
maxDepth: 3,
|
|
120
|
+
directory: 'src',
|
|
121
|
+
includeExtensions: ['.js'],
|
|
122
|
+
excludeExtensions: ['.test.js'],
|
|
123
|
+
excludeDirectories: ['tests']
|
|
124
|
+
});
|
|
125
|
+
expect(result.valid).toBe(true);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test('execute generates directory tree structure', async () => {
|
|
129
|
+
// Root directory stat
|
|
130
|
+
mockFs.stat.mockResolvedValue({ isDirectory: () => true });
|
|
131
|
+
|
|
132
|
+
// Root readdir
|
|
133
|
+
mockFs.readdir.mockResolvedValueOnce([
|
|
134
|
+
mockDirent('src', true),
|
|
135
|
+
mockDirent('package.json')
|
|
136
|
+
]);
|
|
137
|
+
|
|
138
|
+
// src readdir
|
|
139
|
+
mockFs.readdir.mockResolvedValueOnce([
|
|
140
|
+
mockDirent('index.js'),
|
|
141
|
+
mockDirent('app.js')
|
|
142
|
+
]);
|
|
143
|
+
|
|
144
|
+
const result = await tool.execute(
|
|
145
|
+
{ directory: '.', maxDepth: 3, showFiles: true, showHidden: false },
|
|
146
|
+
context
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
expect(result.success).toBe(true);
|
|
150
|
+
expect(result.tree).toContain('src');
|
|
151
|
+
expect(result.tree).toContain('package.json');
|
|
152
|
+
expect(result.totalFiles).toBeGreaterThanOrEqual(1);
|
|
153
|
+
expect(result.totalDirectories).toBeGreaterThanOrEqual(1);
|
|
154
|
+
expect(result).toHaveProperty('summary');
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test('execute respects depth limit', async () => {
|
|
158
|
+
mockFs.stat.mockResolvedValue({ isDirectory: () => true });
|
|
159
|
+
|
|
160
|
+
// Root readdir with deep nesting
|
|
161
|
+
mockFs.readdir.mockResolvedValueOnce([
|
|
162
|
+
mockDirent('level1', true)
|
|
163
|
+
]);
|
|
164
|
+
|
|
165
|
+
// level1 readdir - at depth 1 with maxDepth 1, files at depth 2 should be excluded
|
|
166
|
+
mockFs.readdir.mockResolvedValueOnce([
|
|
167
|
+
mockDirent('deep.js')
|
|
168
|
+
]);
|
|
169
|
+
|
|
170
|
+
const result = await tool.execute(
|
|
171
|
+
{ directory: '.', maxDepth: 1, showFiles: true, showHidden: false },
|
|
172
|
+
context
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
expect(result.success).toBe(true);
|
|
176
|
+
// Files at depth 2 should not appear when maxDepth is 1
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
test('execute ignores node_modules and .git by default', async () => {
|
|
180
|
+
mockFs.stat.mockResolvedValue({ isDirectory: () => true });
|
|
181
|
+
|
|
182
|
+
mockFs.readdir.mockResolvedValueOnce([
|
|
183
|
+
mockDirent('src', true),
|
|
184
|
+
mockDirent('node_modules', true),
|
|
185
|
+
mockDirent('.git', true)
|
|
186
|
+
]);
|
|
187
|
+
|
|
188
|
+
mockFs.readdir.mockResolvedValueOnce([]); // src is empty
|
|
189
|
+
|
|
190
|
+
const result = await tool.execute(
|
|
191
|
+
{ directory: '.', maxDepth: 3, showFiles: true, showHidden: false },
|
|
192
|
+
context
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
expect(result.success).toBe(true);
|
|
196
|
+
expect(result.skippedCount).toBeGreaterThanOrEqual(2); // node_modules, .git skipped
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test('execute handles empty directory', async () => {
|
|
200
|
+
mockFs.stat.mockResolvedValue({ isDirectory: () => true });
|
|
201
|
+
mockFs.readdir.mockResolvedValueOnce([]);
|
|
202
|
+
|
|
203
|
+
const result = await tool.execute(
|
|
204
|
+
{ directory: '.', maxDepth: 3, showFiles: true, showHidden: false },
|
|
205
|
+
context
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
expect(result.success).toBe(true);
|
|
209
|
+
expect(result.totalFiles).toBe(0);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test('execute throws for non-existent directory', async () => {
|
|
213
|
+
mockFs.stat.mockRejectedValue(new Error('ENOENT'));
|
|
214
|
+
|
|
215
|
+
await expect(tool.execute(
|
|
216
|
+
{ directory: 'nonexistent', maxDepth: 3, showFiles: true, showHidden: false },
|
|
217
|
+
context
|
|
218
|
+
)).rejects.toThrow('does not exist');
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
test('execute with includeExtensions filters files', async () => {
|
|
222
|
+
mockFs.stat.mockResolvedValue({ isDirectory: () => true });
|
|
223
|
+
|
|
224
|
+
mockFs.readdir.mockResolvedValueOnce([
|
|
225
|
+
mockDirent('app.js'),
|
|
226
|
+
mockDirent('style.css'),
|
|
227
|
+
mockDirent('readme.md')
|
|
228
|
+
]);
|
|
229
|
+
|
|
230
|
+
const result = await tool.execute(
|
|
231
|
+
{ directory: '.', maxDepth: 3, showFiles: true, showHidden: false, includeExtensions: ['.js'] },
|
|
232
|
+
context
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
expect(result.success).toBe(true);
|
|
236
|
+
expect(result.tree).toContain('app.js');
|
|
237
|
+
expect(result.tree).not.toContain('style.css');
|
|
238
|
+
expect(result.tree).not.toContain('readme.md');
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
test('formatFileSize formats bytes correctly', () => {
|
|
242
|
+
expect(tool.formatFileSize(500)).toBe('500 B');
|
|
243
|
+
expect(tool.formatFileSize(2048)).toContain('KB');
|
|
244
|
+
expect(tool.formatFileSize(2 * 1024 * 1024)).toContain('MB');
|
|
245
|
+
expect(tool.formatFileSize(2 * 1024 * 1024 * 1024)).toContain('GB');
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
test('generateSummary produces summary text', () => {
|
|
249
|
+
const summary = tool.generateSummary('src', { filesCount: 10, directoriesCount: 3, skippedCount: 2 }, 4);
|
|
250
|
+
expect(summary).toContain('src');
|
|
251
|
+
expect(summary).toContain('10');
|
|
252
|
+
expect(summary).toContain('3');
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
test('formatTree handles null node', () => {
|
|
256
|
+
expect(tool.formatTree(null)).toBe('');
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test('execute uses directoryAccess working directory', async () => {
|
|
260
|
+
mockFs.stat.mockResolvedValue({ isDirectory: () => true });
|
|
261
|
+
mockFs.readdir.mockResolvedValueOnce([]);
|
|
262
|
+
|
|
263
|
+
const result = await tool.execute(
|
|
264
|
+
{ directory: '.', maxDepth: 2, showFiles: true, showHidden: false },
|
|
265
|
+
{
|
|
266
|
+
projectDir: '/project',
|
|
267
|
+
agentId: 'agent-1',
|
|
268
|
+
directoryAccess: { workingDirectory: '/custom/dir' }
|
|
269
|
+
}
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
expect(result.success).toBe(true);
|
|
273
|
+
});
|
|
274
|
+
});
|