@brutalist/mcp 0.5.1 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +65 -63
  2. package/dist/brutalist-server.d.ts +15 -0
  3. package/dist/brutalist-server.d.ts.map +1 -1
  4. package/dist/brutalist-server.js +405 -357
  5. package/dist/brutalist-server.js.map +1 -1
  6. package/dist/cli-agents.d.ts +8 -3
  7. package/dist/cli-agents.d.ts.map +1 -1
  8. package/dist/cli-agents.js +352 -50
  9. package/dist/cli-agents.js.map +1 -1
  10. package/dist/streaming/circuit-breaker.d.ts +186 -0
  11. package/dist/streaming/circuit-breaker.d.ts.map +1 -0
  12. package/dist/streaming/circuit-breaker.js +463 -0
  13. package/dist/streaming/circuit-breaker.js.map +1 -0
  14. package/dist/streaming/intelligent-buffer.d.ts +141 -0
  15. package/dist/streaming/intelligent-buffer.d.ts.map +1 -0
  16. package/dist/streaming/intelligent-buffer.js +555 -0
  17. package/dist/streaming/intelligent-buffer.js.map +1 -0
  18. package/dist/streaming/output-parser.d.ts +89 -0
  19. package/dist/streaming/output-parser.d.ts.map +1 -0
  20. package/dist/streaming/output-parser.js +349 -0
  21. package/dist/streaming/output-parser.js.map +1 -0
  22. package/dist/streaming/progress-tracker.d.ts +149 -0
  23. package/dist/streaming/progress-tracker.d.ts.map +1 -0
  24. package/dist/streaming/progress-tracker.js +519 -0
  25. package/dist/streaming/progress-tracker.js.map +1 -0
  26. package/dist/streaming/session-manager.d.ts +238 -0
  27. package/dist/streaming/session-manager.d.ts.map +1 -0
  28. package/dist/streaming/session-manager.js +546 -0
  29. package/dist/streaming/session-manager.js.map +1 -0
  30. package/dist/streaming/sse-transport.d.ts +95 -0
  31. package/dist/streaming/sse-transport.d.ts.map +1 -0
  32. package/dist/streaming/sse-transport.js +319 -0
  33. package/dist/streaming/sse-transport.js.map +1 -0
  34. package/dist/streaming/streaming-orchestrator.d.ts +153 -0
  35. package/dist/streaming/streaming-orchestrator.d.ts.map +1 -0
  36. package/dist/streaming/streaming-orchestrator.js +436 -0
  37. package/dist/streaming/streaming-orchestrator.js.map +1 -0
  38. package/dist/test-utils/process-manager.d.ts +61 -0
  39. package/dist/test-utils/process-manager.d.ts.map +1 -0
  40. package/dist/test-utils/process-manager.js +262 -0
  41. package/dist/test-utils/process-manager.js.map +1 -0
  42. package/dist/test-utils/server-harness.d.ts +73 -0
  43. package/dist/test-utils/server-harness.d.ts.map +1 -0
  44. package/dist/test-utils/server-harness.js +296 -0
  45. package/dist/test-utils/server-harness.js.map +1 -0
  46. package/dist/test-utils/streaming-fuzz.d.ts +57 -0
  47. package/dist/test-utils/streaming-fuzz.d.ts.map +1 -0
  48. package/dist/test-utils/streaming-fuzz.js +287 -0
  49. package/dist/test-utils/streaming-fuzz.js.map +1 -0
  50. package/dist/test-utils/test-isolation.d.ts +70 -0
  51. package/dist/test-utils/test-isolation.d.ts.map +1 -0
  52. package/dist/test-utils/test-isolation.js +193 -0
  53. package/dist/test-utils/test-isolation.js.map +1 -0
  54. package/dist/tool-definitions.d.ts +6 -0
  55. package/dist/tool-definitions.d.ts.map +1 -0
  56. package/dist/tool-definitions.js +217 -0
  57. package/dist/tool-definitions.js.map +1 -0
  58. package/dist/types/brutalist.d.ts +3 -19
  59. package/dist/types/brutalist.d.ts.map +1 -1
  60. package/dist/types/tool-config.d.ts +51 -0
  61. package/dist/types/tool-config.d.ts.map +1 -0
  62. package/dist/types/tool-config.js +24 -0
  63. package/dist/types/tool-config.js.map +1 -0
  64. package/dist/utils/pagination.d.ts +2 -2
  65. package/dist/utils/pagination.d.ts.map +1 -1
  66. package/dist/utils/pagination.js +1 -1
  67. package/dist/utils/pagination.js.map +1 -1
  68. package/dist/utils/response-cache.d.ts +96 -0
  69. package/dist/utils/response-cache.d.ts.map +1 -0
  70. package/dist/utils/response-cache.js +371 -0
  71. package/dist/utils/response-cache.js.map +1 -0
  72. package/dist/utils.d.ts.map +1 -1
  73. package/dist/utils.js +22 -3
  74. package/dist/utils.js.map +1 -1
  75. package/package.json +14 -4
@@ -0,0 +1,57 @@
1
+ import { Readable, Transform } from 'stream';
2
+ /**
3
+ * Utilities for fuzz testing streaming parsers with random chunking,
4
+ * corrupted data, and various edge cases
5
+ */
6
+ export declare class StreamingFuzzHarness {
7
+ /**
8
+ * Split data into random-sized chunks
9
+ */
10
+ randomChunker(data: string | Buffer, minChunk?: number, maxChunk?: number): Buffer[];
11
+ /**
12
+ * Create a readable stream that emits data in random chunks
13
+ */
14
+ createRandomChunkStream(data: string | Buffer, minChunk?: number, maxChunk?: number, delayMs?: number): Readable;
15
+ /**
16
+ * Inject invalid UTF-8 sequences into a string
17
+ */
18
+ corruptWithInvalidUtf8(data: string): Buffer;
19
+ /**
20
+ * Truncate data at various boundaries to test partial parsing
21
+ */
22
+ truncateAtBoundaries(data: string): string[];
23
+ /**
24
+ * Create a transform stream that randomly corrupts data
25
+ */
26
+ createCorruptionStream(corruptionRate?: number): Transform;
27
+ /**
28
+ * Create a transform stream that simulates slow delivery
29
+ */
30
+ createThrottleStream(bytesPerSecond: number): Transform;
31
+ /**
32
+ * Create a transform stream that simulates backpressure
33
+ */
34
+ createBackpressureStream(bufferSize?: number): Transform;
35
+ /**
36
+ * Test a parser with various fuzzing strategies
37
+ */
38
+ fuzzTestParser(parser: (input: string) => any, validInput: string, options?: {
39
+ testTruncation?: boolean;
40
+ testCorruption?: boolean;
41
+ testInvalidUtf8?: boolean;
42
+ testRandomChunking?: boolean;
43
+ }): Promise<{
44
+ passed: number;
45
+ failed: number;
46
+ errors: Error[];
47
+ }>;
48
+ /**
49
+ * Generate test cases for NDJSON streaming
50
+ */
51
+ generateNdjsonTestCases(): string[];
52
+ /**
53
+ * Generate test cases for Codex JSON output
54
+ */
55
+ generateCodexJsonTestCases(): string[];
56
+ }
57
+ //# sourceMappingURL=streaming-fuzz.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming-fuzz.d.ts","sourceRoot":"","sources":["../../src/test-utils/streaming-fuzz.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAG7C;;;GAGG;AACH,qBAAa,oBAAoB;IAC/B;;OAEG;IACH,aAAa,CACX,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,QAAQ,GAAE,MAAU,EACpB,QAAQ,GAAE,MAAY,GACrB,MAAM,EAAE;IAeX;;OAEG;IACH,uBAAuB,CACrB,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,QAAQ,GAAE,MAAU,EACpB,QAAQ,GAAE,MAAY,EACtB,OAAO,GAAE,MAAU,GAClB,QAAQ;IAoBX;;OAEG;IACH,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAuB5C;;OAEG;IACH,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IAuB5C;;OAEG;IACH,sBAAsB,CAAC,cAAc,GAAE,MAAa,GAAG,SAAS;IAmBhE;;OAEG;IACH,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS;IAsBvD;;OAEG;IACH,wBAAwB,CAAC,UAAU,GAAE,MAAa,GAAG,SAAS;IA8B9D;;OAEG;IACG,cAAc,CAClB,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,GAAG,EAC9B,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;QACP,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;KACzB,GACL,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,KAAK,EAAE,CAAA;KAAE,CAAC;IAgF/D;;OAEG;IACH,uBAAuB,IAAI,MAAM,EAAE;IA+BnC;;OAEG;IACH,0BAA0B,IAAI,MAAM,EAAE;CA2BvC"}
@@ -0,0 +1,287 @@
1
+ import { Readable, Transform } from 'stream';
2
+ import { logger } from '../logger.js';
3
+ /**
4
+ * Utilities for fuzz testing streaming parsers with random chunking,
5
+ * corrupted data, and various edge cases
6
+ */
7
+ export class StreamingFuzzHarness {
8
+ /**
9
+ * Split data into random-sized chunks
10
+ */
11
+ randomChunker(data, minChunk = 1, maxChunk = 100) {
12
+ const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
13
+ const chunks = [];
14
+ let offset = 0;
15
+ while (offset < buffer.length) {
16
+ const chunkSize = Math.floor(Math.random() * (maxChunk - minChunk + 1)) + minChunk;
17
+ const end = Math.min(offset + chunkSize, buffer.length);
18
+ chunks.push(buffer.slice(offset, end));
19
+ offset = end;
20
+ }
21
+ return chunks;
22
+ }
23
+ /**
24
+ * Create a readable stream that emits data in random chunks
25
+ */
26
+ createRandomChunkStream(data, minChunk = 1, maxChunk = 100, delayMs = 0) {
27
+ const chunks = this.randomChunker(data, minChunk, maxChunk);
28
+ let index = 0;
29
+ return new Readable({
30
+ async read() {
31
+ if (index >= chunks.length) {
32
+ this.push(null); // End stream
33
+ return;
34
+ }
35
+ if (delayMs > 0) {
36
+ await new Promise(resolve => setTimeout(resolve, delayMs));
37
+ }
38
+ this.push(chunks[index++]);
39
+ }
40
+ });
41
+ }
42
+ /**
43
+ * Inject invalid UTF-8 sequences into a string
44
+ */
45
+ corruptWithInvalidUtf8(data) {
46
+ const buffer = Buffer.from(data);
47
+ const corrupted = Buffer.allocUnsafe(buffer.length + 10);
48
+ buffer.copy(corrupted);
49
+ // Inject some invalid UTF-8 sequences
50
+ const invalidSequences = [
51
+ Buffer.from([0xFF, 0xFF]), // Invalid start bytes
52
+ Buffer.from([0xC0, 0x80]), // Overlong encoding
53
+ Buffer.from([0xED, 0xA0, 0x80]), // UTF-16 surrogate
54
+ Buffer.from([0xF4, 0x90, 0x80, 0x80]), // Code point > U+10FFFF
55
+ ];
56
+ // Insert random invalid sequences
57
+ for (let i = 0; i < 3; i++) {
58
+ const pos = Math.floor(Math.random() * corrupted.length);
59
+ const invalidSeq = invalidSequences[Math.floor(Math.random() * invalidSequences.length)];
60
+ invalidSeq.copy(corrupted, pos);
61
+ }
62
+ return corrupted;
63
+ }
64
+ /**
65
+ * Truncate data at various boundaries to test partial parsing
66
+ */
67
+ truncateAtBoundaries(data) {
68
+ const truncated = [];
69
+ // Truncate at different percentages
70
+ const percentages = [0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.99];
71
+ for (const pct of percentages) {
72
+ const len = Math.floor(data.length * pct);
73
+ truncated.push(data.substring(0, len));
74
+ }
75
+ // Truncate in middle of likely JSON structures
76
+ const jsonBoundaries = ['{', '}', '[', ']', '"', ':', ','];
77
+ for (const boundary of jsonBoundaries) {
78
+ const index = data.indexOf(boundary);
79
+ if (index > 0 && index < data.length - 1) {
80
+ truncated.push(data.substring(0, index));
81
+ truncated.push(data.substring(0, index + 1));
82
+ }
83
+ }
84
+ return truncated;
85
+ }
86
+ /**
87
+ * Create a transform stream that randomly corrupts data
88
+ */
89
+ createCorruptionStream(corruptionRate = 0.01) {
90
+ return new Transform({
91
+ transform(chunk, encoding, callback) {
92
+ const corrupted = Buffer.allocUnsafe(chunk.length);
93
+ for (let i = 0; i < chunk.length; i++) {
94
+ if (Math.random() < corruptionRate) {
95
+ // Corrupt this byte
96
+ corrupted[i] = Math.floor(Math.random() * 256);
97
+ }
98
+ else {
99
+ corrupted[i] = chunk[i];
100
+ }
101
+ }
102
+ callback(null, corrupted);
103
+ }
104
+ });
105
+ }
106
+ /**
107
+ * Create a transform stream that simulates slow delivery
108
+ */
109
+ createThrottleStream(bytesPerSecond) {
110
+ let lastEmit = Date.now();
111
+ let bytesSent = 0;
112
+ return new Transform({
113
+ async transform(chunk, encoding, callback) {
114
+ const now = Date.now();
115
+ const elapsed = (now - lastEmit) / 1000;
116
+ const allowedBytes = Math.floor(elapsed * bytesPerSecond);
117
+ if (bytesSent >= allowedBytes) {
118
+ // Need to wait
119
+ const waitTime = ((bytesSent + chunk.length) / bytesPerSecond - elapsed) * 1000;
120
+ await new Promise(resolve => setTimeout(resolve, waitTime));
121
+ }
122
+ bytesSent += chunk.length;
123
+ callback(null, chunk);
124
+ }
125
+ });
126
+ }
127
+ /**
128
+ * Create a transform stream that simulates backpressure
129
+ */
130
+ createBackpressureStream(bufferSize = 1024) {
131
+ let buffer = [];
132
+ let totalSize = 0;
133
+ let paused = false;
134
+ return new Transform({
135
+ transform(chunk, encoding, callback) {
136
+ buffer.push(chunk);
137
+ totalSize += chunk.length;
138
+ if (totalSize > bufferSize && !paused) {
139
+ paused = true;
140
+ logger.debug('StreamingFuzz: Simulating backpressure');
141
+ // Simulate processing delay
142
+ setTimeout(() => {
143
+ // Flush buffer
144
+ const combined = Buffer.concat(buffer);
145
+ buffer = [];
146
+ totalSize = 0;
147
+ paused = false;
148
+ callback(null, combined);
149
+ }, 100);
150
+ }
151
+ else if (!paused) {
152
+ callback(null, chunk);
153
+ }
154
+ }
155
+ });
156
+ }
157
+ /**
158
+ * Test a parser with various fuzzing strategies
159
+ */
160
+ async fuzzTestParser(parser, validInput, options = {}) {
161
+ const results = { passed: 0, failed: 0, errors: [] };
162
+ // Test with valid input first
163
+ try {
164
+ parser(validInput);
165
+ results.passed++;
166
+ }
167
+ catch (error) {
168
+ results.failed++;
169
+ results.errors.push(new Error(`Failed on valid input: ${error.message}`));
170
+ }
171
+ // Test truncation
172
+ if (options.testTruncation) {
173
+ const truncated = this.truncateAtBoundaries(validInput);
174
+ for (const input of truncated) {
175
+ try {
176
+ parser(input);
177
+ // Parser should handle partial input gracefully
178
+ results.passed++;
179
+ }
180
+ catch (error) {
181
+ // Expected to fail on truncated input, but should not crash
182
+ if (error.message.includes('Unexpected end') ||
183
+ error.message.includes('Unexpected token') ||
184
+ error.message.includes('Unterminated')) {
185
+ results.passed++;
186
+ }
187
+ else {
188
+ results.failed++;
189
+ results.errors.push(new Error(`Unexpected error on truncated input: ${error.message}`));
190
+ }
191
+ }
192
+ }
193
+ }
194
+ // Test corruption
195
+ if (options.testCorruption) {
196
+ // Corrupt random characters
197
+ for (let i = 0; i < 10; i++) {
198
+ const corrupted = validInput.split('');
199
+ const pos = Math.floor(Math.random() * corrupted.length);
200
+ const charCode = Math.floor(Math.random() * 128);
201
+ corrupted[pos] = String.fromCharCode(charCode);
202
+ try {
203
+ parser(corrupted.join(''));
204
+ // Parser might succeed if corruption didn't affect structure
205
+ results.passed++;
206
+ }
207
+ catch (error) {
208
+ // Should handle corruption gracefully
209
+ if (!error.message.includes('Cannot read properties of undefined') &&
210
+ !error.message.includes('Maximum call stack')) {
211
+ results.passed++;
212
+ }
213
+ else {
214
+ results.failed++;
215
+ results.errors.push(new Error(`Parser crashed on corrupted input: ${error.message}`));
216
+ }
217
+ }
218
+ }
219
+ }
220
+ // Test invalid UTF-8
221
+ if (options.testInvalidUtf8) {
222
+ try {
223
+ const invalidUtf8 = this.corruptWithInvalidUtf8(validInput);
224
+ parser(invalidUtf8.toString('utf-8'));
225
+ results.passed++;
226
+ }
227
+ catch (error) {
228
+ // Should handle invalid UTF-8 gracefully
229
+ if (!error.message.includes('Cannot read properties of undefined')) {
230
+ results.passed++;
231
+ }
232
+ else {
233
+ results.failed++;
234
+ results.errors.push(new Error(`Parser crashed on invalid UTF-8: ${error.message}`));
235
+ }
236
+ }
237
+ }
238
+ return results;
239
+ }
240
+ /**
241
+ * Generate test cases for NDJSON streaming
242
+ */
243
+ generateNdjsonTestCases() {
244
+ const cases = [];
245
+ // Valid NDJSON
246
+ cases.push('{"type":"message","content":"test"}\n{"type":"content_block_delta","delta":"more"}\n');
247
+ // Missing newlines
248
+ cases.push('{"type":"message","content":"test"}{"type":"content_block_delta","delta":"more"}');
249
+ // Extra newlines
250
+ cases.push('\n\n{"type":"message","content":"test"}\n\n\n{"type":"content_block_delta","delta":"more"}\n\n');
251
+ // Partial JSON at end
252
+ cases.push('{"type":"message","content":"test"}\n{"type":"content_block_delta"');
253
+ // Invalid JSON in middle
254
+ cases.push('{"type":"message","content":"test"}\n{invalid json}\n{"type":"content_block_delta","delta":"more"}\n');
255
+ // Unicode in content
256
+ cases.push('{"type":"message","content":"🚀 测试 テスト"}\n{"type":"emoji","value":"😀"}\n');
257
+ // Very long lines
258
+ const longContent = 'x'.repeat(10000);
259
+ cases.push(`{"type":"message","content":"${longContent}"}\n`);
260
+ // Nested JSON structures
261
+ cases.push('{"type":"complex","data":{"nested":{"deep":{"value":123}}}}\n');
262
+ return cases;
263
+ }
264
+ /**
265
+ * Generate test cases for Codex JSON output
266
+ */
267
+ generateCodexJsonTestCases() {
268
+ const cases = [];
269
+ // Valid Codex output
270
+ cases.push('[{"type":"thinking","content":"analyzing"},{"type":"agent_message","content":"result"}]');
271
+ // Only agent messages
272
+ cases.push('[{"type":"agent_message","content":"first"},{"type":"agent_message","content":"second"}]');
273
+ // Mixed with other types
274
+ cases.push('[{"type":"file_read","path":"/test"},{"type":"agent_message","content":"found"},{"type":"thinking","content":"done"}]');
275
+ // Empty array
276
+ cases.push('[]');
277
+ // Not an array
278
+ cases.push('{"type":"agent_message","content":"not in array"}');
279
+ // Malformed JSON
280
+ cases.push('[{"type":"agent_message","content":"unclosed"');
281
+ // Very large output
282
+ const largeContent = 'x'.repeat(100000);
283
+ cases.push(`[{"type":"agent_message","content":"${largeContent}"}]`);
284
+ return cases;
285
+ }
286
+ }
287
+ //# sourceMappingURL=streaming-fuzz.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming-fuzz.js","sourceRoot":"","sources":["../../src/test-utils/streaming-fuzz.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Provides isolated test environments with unique workspaces,
3
+ * cache namespaces, and environment variables
4
+ */
5
+ export declare class TestIsolation {
6
+ private static activeWorkspaces;
7
+ private static originalEnv;
8
+ private testId;
9
+ private workspacePath;
10
+ private envOverrides;
11
+ private cacheNamespace;
12
+ constructor(testName: string);
13
+ /**
14
+ * Create an isolated workspace directory for the test
15
+ */
16
+ createWorkspace(): Promise<string>;
17
+ /**
18
+ * Get the cache namespace for this test
19
+ */
20
+ getCacheNamespace(): string;
21
+ /**
22
+ * Set isolated environment variables for the test
23
+ */
24
+ setEnv(overrides: Record<string, string>): void;
25
+ /**
26
+ * Create a test file in the workspace
27
+ */
28
+ createFile(relativePath: string, content: string): Promise<string>;
29
+ /**
30
+ * Create a test directory structure
31
+ */
32
+ createDirectory(relativePath: string): Promise<string>;
33
+ /**
34
+ * Read a file from the workspace
35
+ */
36
+ readFile(relativePath: string): Promise<string>;
37
+ /**
38
+ * Check if a file exists in the workspace
39
+ */
40
+ fileExists(relativePath: string): Promise<boolean>;
41
+ /**
42
+ * Clean up the test workspace and restore environment
43
+ */
44
+ cleanup(): Promise<void>;
45
+ /**
46
+ * Clean up all active workspaces (for global cleanup)
47
+ */
48
+ static cleanupAll(): Promise<void>;
49
+ /**
50
+ * Assert no workspaces are leaked
51
+ */
52
+ static assertNoLeakedWorkspaces(): void;
53
+ /**
54
+ * Get diagnostic information
55
+ */
56
+ getDiagnostics(): string;
57
+ }
58
+ /**
59
+ * Jest test helpers for isolation
60
+ */
61
+ export declare function setupTestIsolation(testName: string): TestIsolation;
62
+ /**
63
+ * Global test setup for isolation
64
+ */
65
+ export declare function globalTestSetup(): Promise<void>;
66
+ /**
67
+ * Global test teardown for isolation
68
+ */
69
+ export declare function globalTestTeardown(): Promise<void>;
70
+ //# sourceMappingURL=test-isolation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-isolation.d.ts","sourceRoot":"","sources":["../../src/test-utils/test-isolation.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAA0B;IACzD,OAAO,CAAC,MAAM,CAAC,WAAW,CAAyC;IACnE,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,cAAc,CAAS;gBAEnB,QAAQ,EAAE,MAAM;IAM5B;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;IAgBxC;;OAEG;IACH,iBAAiB,IAAI,MAAM;IAI3B;;OAEG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAS/C;;OAEG;IACG,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAaxE;;OAEG;IACG,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAS5D;;OAEG;IACG,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IASrD;;OAEG;IACG,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAcxD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB9B;;OAEG;WACU,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBxC;;OAEG;IACH,MAAM,CAAC,wBAAwB,IAAI,IAAI;IAOvC;;OAEG;IACH,cAAc,IAAI,MAAM;CAQzB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CASlE;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAGrD;AAED;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMxD"}
@@ -0,0 +1,193 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
+ import { logger } from '../logger.js';
5
+ import crypto from 'crypto';
6
+ /**
7
+ * Provides isolated test environments with unique workspaces,
8
+ * cache namespaces, and environment variables
9
+ */
10
+ export class TestIsolation {
11
+ static activeWorkspaces = new Set();
12
+ static originalEnv = { ...process.env };
13
+ testId;
14
+ workspacePath;
15
+ envOverrides = {};
16
+ cacheNamespace;
17
+ constructor(testName) {
18
+ // Generate unique test ID
19
+ this.testId = `${testName.replace(/[^a-z0-9]/gi, '_')}_${Date.now()}_${crypto.randomBytes(4).toString('hex')}`;
20
+ this.cacheNamespace = `test_cache_${this.testId}`;
21
+ }
22
+ /**
23
+ * Create an isolated workspace directory for the test
24
+ */
25
+ async createWorkspace() {
26
+ if (this.workspacePath) {
27
+ return this.workspacePath;
28
+ }
29
+ const tmpDir = os.tmpdir();
30
+ this.workspacePath = path.join(tmpDir, 'brutalist-test', this.testId);
31
+ // Create directory recursively
32
+ await fs.promises.mkdir(this.workspacePath, { recursive: true });
33
+ TestIsolation.activeWorkspaces.add(this.workspacePath);
34
+ logger.debug(`TestIsolation: Created workspace ${this.workspacePath}`);
35
+ return this.workspacePath;
36
+ }
37
+ /**
38
+ * Get the cache namespace for this test
39
+ */
40
+ getCacheNamespace() {
41
+ return this.cacheNamespace;
42
+ }
43
+ /**
44
+ * Set isolated environment variables for the test
45
+ */
46
+ setEnv(overrides) {
47
+ this.envOverrides = { ...this.envOverrides, ...overrides };
48
+ // Apply overrides to process.env
49
+ for (const [key, value] of Object.entries(overrides)) {
50
+ process.env[key] = value;
51
+ }
52
+ }
53
+ /**
54
+ * Create a test file in the workspace
55
+ */
56
+ async createFile(relativePath, content) {
57
+ const workspace = await this.createWorkspace();
58
+ const filePath = path.join(workspace, relativePath);
59
+ // Create directory if needed
60
+ await fs.promises.mkdir(path.dirname(filePath), { recursive: true });
61
+ // Write file
62
+ await fs.promises.writeFile(filePath, content, 'utf-8');
63
+ return filePath;
64
+ }
65
+ /**
66
+ * Create a test directory structure
67
+ */
68
+ async createDirectory(relativePath) {
69
+ const workspace = await this.createWorkspace();
70
+ const dirPath = path.join(workspace, relativePath);
71
+ await fs.promises.mkdir(dirPath, { recursive: true });
72
+ return dirPath;
73
+ }
74
+ /**
75
+ * Read a file from the workspace
76
+ */
77
+ async readFile(relativePath) {
78
+ if (!this.workspacePath) {
79
+ throw new Error('Workspace not created');
80
+ }
81
+ const filePath = path.join(this.workspacePath, relativePath);
82
+ return fs.promises.readFile(filePath, 'utf-8');
83
+ }
84
+ /**
85
+ * Check if a file exists in the workspace
86
+ */
87
+ async fileExists(relativePath) {
88
+ if (!this.workspacePath) {
89
+ return false;
90
+ }
91
+ const filePath = path.join(this.workspacePath, relativePath);
92
+ try {
93
+ await fs.promises.access(filePath);
94
+ return true;
95
+ }
96
+ catch {
97
+ return false;
98
+ }
99
+ }
100
+ /**
101
+ * Clean up the test workspace and restore environment
102
+ */
103
+ async cleanup() {
104
+ // Restore original environment variables
105
+ for (const key of Object.keys(this.envOverrides)) {
106
+ if (TestIsolation.originalEnv[key] !== undefined) {
107
+ process.env[key] = TestIsolation.originalEnv[key];
108
+ }
109
+ else {
110
+ delete process.env[key];
111
+ }
112
+ }
113
+ this.envOverrides = {};
114
+ // Remove workspace directory
115
+ if (this.workspacePath) {
116
+ try {
117
+ await fs.promises.rm(this.workspacePath, { recursive: true, force: true });
118
+ TestIsolation.activeWorkspaces.delete(this.workspacePath);
119
+ logger.debug(`TestIsolation: Cleaned up workspace ${this.workspacePath}`);
120
+ }
121
+ catch (error) {
122
+ logger.error(`Failed to clean up workspace ${this.workspacePath}:`, error);
123
+ }
124
+ this.workspacePath = undefined;
125
+ }
126
+ }
127
+ /**
128
+ * Clean up all active workspaces (for global cleanup)
129
+ */
130
+ static async cleanupAll() {
131
+ const cleanupPromises = Array.from(TestIsolation.activeWorkspaces).map(async (workspace) => {
132
+ try {
133
+ await fs.promises.rm(workspace, { recursive: true, force: true });
134
+ logger.debug(`TestIsolation: Cleaned up orphaned workspace ${workspace}`);
135
+ }
136
+ catch (error) {
137
+ logger.error(`Failed to clean up orphaned workspace ${workspace}:`, error);
138
+ }
139
+ });
140
+ await Promise.all(cleanupPromises);
141
+ TestIsolation.activeWorkspaces.clear();
142
+ // Restore original environment
143
+ process.env = { ...TestIsolation.originalEnv };
144
+ }
145
+ /**
146
+ * Assert no workspaces are leaked
147
+ */
148
+ static assertNoLeakedWorkspaces() {
149
+ if (TestIsolation.activeWorkspaces.size > 0) {
150
+ const leaked = Array.from(TestIsolation.activeWorkspaces);
151
+ throw new Error(`Test leaked ${leaked.length} workspaces:\n ${leaked.join('\n ')}`);
152
+ }
153
+ }
154
+ /**
155
+ * Get diagnostic information
156
+ */
157
+ getDiagnostics() {
158
+ const lines = ['TestIsolation diagnostics:'];
159
+ lines.push(` Test ID: ${this.testId}`);
160
+ lines.push(` Workspace: ${this.workspacePath || 'not created'}`);
161
+ lines.push(` Cache namespace: ${this.cacheNamespace}`);
162
+ lines.push(` Env overrides: ${Object.keys(this.envOverrides).join(', ') || 'none'}`);
163
+ return lines.join('\n');
164
+ }
165
+ }
166
+ /**
167
+ * Jest test helpers for isolation
168
+ */
169
+ export function setupTestIsolation(testName) {
170
+ const isolation = new TestIsolation(testName);
171
+ // Register cleanup in afterEach
172
+ afterEach(async () => {
173
+ await isolation.cleanup();
174
+ });
175
+ return isolation;
176
+ }
177
+ /**
178
+ * Global test setup for isolation
179
+ */
180
+ export async function globalTestSetup() {
181
+ // Clean up any leftover workspaces from previous runs
182
+ await TestIsolation.cleanupAll();
183
+ }
184
+ /**
185
+ * Global test teardown for isolation
186
+ */
187
+ export async function globalTestTeardown() {
188
+ // Clean up all workspaces
189
+ await TestIsolation.cleanupAll();
190
+ // Assert no leaks
191
+ TestIsolation.assertNoLeakedWorkspaces();
192
+ }
193
+ //# sourceMappingURL=test-isolation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-isolation.js","sourceRoot":"","sources":["../../src/test-utils/test-isolation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B;;;GAGG;AACH,MAAM,OAAO,aAAa;IAChB,MAAM,CAAC,gBAAgB,GAAgB,IAAI,GAAG,EAAE,CAAC;IACjD,MAAM,CAAC,WAAW,GAAsB,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC3D,MAAM,CAAS;IACf,aAAa,CAAqB;IAClC,YAAY,GAA2B,EAAE,CAAC;IAC1C,cAAc,CAAS;IAE/B,YAAY,QAAgB;QAC1B,0BAA0B;QAC1B,IAAI,CAAC,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/G,IAAI,CAAC,cAAc,GAAG,cAAc,IAAI,CAAC,MAAM,EAAE,CAAC;IACpD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe;QACnB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC,aAAa,CAAC;QAC5B,CAAC;QAED,MAAM,MAAM,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAEtE,+BAA+B;QAC/B,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,aAAa,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAEvD,MAAM,CAAC,KAAK,CAAC,oCAAoC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;QACvE,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,iBAAiB;QACf,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,SAAiC;QACtC,IAAI,CAAC,YAAY,GAAG,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,GAAG,SAAS,EAAE,CAAC;QAE3D,iCAAiC;QACjC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YACrD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QAC3B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,YAAoB,EAAE,OAAe;QACpD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAEpD,6BAA6B;QAC7B,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAErE,aAAa;QACb,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAExD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,YAAoB;QACxC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAEnD,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEtD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ,CAAC,YAAoB;QACjC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC3C,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;QAC7D,OAAO,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,YAAoB;QACnC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;QAC7D,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACnC,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACX,yCAAyC;QACzC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;YACjD,IAAI,aAAa,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;gBACjD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YACpD,CAAC;iBAAM,CAAC;gBACN,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QAEvB,6BAA6B;QAC7B,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC3E,aAAa,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBAC1D,MAAM,CAAC,KAAK,CAAC,uCAAuC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;YAC5E,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,gCAAgC,IAAI,CAAC,aAAa,GAAG,EAAE,KAAK,CAAC,CAAC;YAC7E,CAAC;YACD,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;QACjC,CAAC;IACH,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,UAAU;QACrB,MAAM,eAAe,GAAG,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE;YACzF,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClE,MAAM,CAAC,KAAK,CAAC,gDAAgD,SAAS,EAAE,CAAC,CAAC;YAC5E,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,yCAAyC,SAAS,GAAG,EAAE,KAAK,CAAC,CAAC;YAC7E,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QACnC,aAAa,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;QAEvC,+BAA+B;QAC/B,OAAO,CAAC,GAAG,GAAG,EAAE,GAAG,aAAa,CAAC,WAAW,EAAE,CAAC;IACjD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,wBAAwB;QAC7B,IAAI,aAAa,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAC5C,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,eAAe,MAAM,CAAC,MAAM,mBAAmB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,MAAM,KAAK,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC7C,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,aAAa,IAAI,aAAa,EAAE,CAAC,CAAC;QAClE,KAAK,CAAC,IAAI,CAAC,sBAAsB,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;QACxD,KAAK,CAAC,IAAI,CAAC,oBAAoB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC;QACtF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;;AAGH;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC,QAAQ,CAAC,CAAC;IAE9C,gCAAgC;IAChC,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,SAAS,CAAC,OAAO,EAAE,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,sDAAsD;IACtD,MAAM,aAAa,CAAC,UAAU,EAAE,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,0BAA0B;IAC1B,MAAM,aAAa,CAAC,UAAU,EAAE,CAAC;IAEjC,kBAAkB;IAClB,aAAa,CAAC,wBAAwB,EAAE,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { ToolConfig } from './types/tool-config.js';
2
+ /**
3
+ * All brutalist tool configurations
4
+ */
5
+ export declare const TOOL_CONFIGS: ToolConfig[];
6
+ //# sourceMappingURL=tool-definitions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-definitions.d.ts","sourceRoot":"","sources":["../src/tool-definitions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,UAAU,EA4MpC,CAAC"}