@codebolt/agent 6.1.3 → 6.1.5

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.
@@ -4,6 +4,7 @@ import { FlatUserMessage } from "@codebolt/types/sdk";
4
4
  export interface AtFileProcessorOptions {
5
5
  maxFileSize?: number;
6
6
  allowedExtensions?: string[];
7
+ deniedExtensions?: string[];
7
8
  enableRecursiveSearch?: boolean;
8
9
  }
9
10
  export declare class AtFileProcessorModifier extends BaseMessageModifier {
@@ -21,5 +22,7 @@ export declare class AtFileProcessorModifier extends BaseMessageModifier {
21
22
  private getFolderStructure;
22
23
  private findLastUserMessage;
23
24
  private getProjectPath;
25
+ private isReadableTextFile;
26
+ private isLikelyBinaryFile;
24
27
  private isNodeError;
25
28
  }
@@ -46,7 +46,19 @@ class AtFileProcessorModifier extends base_1.BaseMessageModifier {
46
46
  super();
47
47
  this.options = {
48
48
  maxFileSize: options.maxFileSize || 1024 * 1024, // 1MB default
49
- allowedExtensions: options.allowedExtensions || ['.ts', '.js', '.d.ts', '.json', '.md', '.txt', '.yml', '.yaml', '.xml', '.html', '.css', '.py', '.java', '.cpp', '.c', '.h'],
49
+ allowedExtensions: options.allowedExtensions || [],
50
+ deniedExtensions: options.deniedExtensions || [
51
+ '.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp', '.ico', '.svg',
52
+ '.pdf', '.zip', '.tar', '.gz', '.rar', '.7z',
53
+ '.exe', '.dll', '.so', '.dylib', '.bin', '.dat',
54
+ '.woff', '.woff2', '.ttf', '.otf', '.eot',
55
+ '.mp3', '.wav', '.ogg', '.mp4', '.mov', '.avi', '.mkv',
56
+ '.class', '.jar', '.war',
57
+ '.pyc', '.pyo',
58
+ '.db', '.sqlite', '.sqlite3',
59
+ '.min.js', '.min.css',
60
+ '.lock'
61
+ ],
50
62
  enableRecursiveSearch: options.enableRecursiveSearch !== false
51
63
  };
52
64
  }
@@ -342,12 +354,8 @@ class AtFileProcessorModifier extends base_1.BaseMessageModifier {
342
354
  if (stats.size > this.options.maxFileSize) {
343
355
  throw new Error(`File too large: ${stats.size} bytes`);
344
356
  }
345
- // Check file extension
346
- if (this.options.allowedExtensions.length > 0) {
347
- const ext = path.extname(filePath).toLowerCase();
348
- if (!this.options.allowedExtensions.includes(ext)) {
349
- throw new Error(`File type not allowed: ${ext}`);
350
- }
357
+ if (!(await this.isReadableTextFile(filePath))) {
358
+ throw new Error(`File type not allowed: ${path.extname(filePath).toLowerCase() || 'unknown'}`);
351
359
  }
352
360
  const content = await fs.readFile(filePath, 'utf-8');
353
361
  return content;
@@ -358,18 +366,8 @@ class AtFileProcessorModifier extends base_1.BaseMessageModifier {
358
366
  const files = [];
359
367
  for (const entry of entries) {
360
368
  if (entry.isFile() && !entry.name.startsWith('.')) {
361
- // Check file extension if allowed extensions are specified
362
- if (this.options.allowedExtensions.length > 0) {
363
- const ext = path.extname(entry.name).toLowerCase();
364
- // console.log(`Checking file ${entry.name} with extension ${ext}. Allowed:`, this.options.allowedExtensions);
365
- if (this.options.allowedExtensions.includes(ext)) {
366
- files.push(path.join(folderPath, entry.name));
367
- }
368
- else {
369
- // console.log(`File ${entry.name} extension ${ext} not in allowed list`);
370
- }
371
- }
372
- else {
369
+ const filePath = path.join(folderPath, entry.name);
370
+ if (await this.isReadableTextFile(filePath)) {
373
371
  files.push(path.join(folderPath, entry.name));
374
372
  }
375
373
  }
@@ -436,6 +434,47 @@ class AtFileProcessorModifier extends base_1.BaseMessageModifier {
436
434
  return process.cwd();
437
435
  }
438
436
  }
437
+ async isReadableTextFile(filePath) {
438
+ const lowerPath = filePath.toLowerCase();
439
+ if (this.options.allowedExtensions.length > 0) {
440
+ return this.options.allowedExtensions.some((ext) => lowerPath.endsWith(ext.toLowerCase()));
441
+ }
442
+ if (this.options.deniedExtensions.some((ext) => lowerPath.endsWith(ext.toLowerCase()))) {
443
+ return false;
444
+ }
445
+ return !(await this.isLikelyBinaryFile(filePath));
446
+ }
447
+ async isLikelyBinaryFile(filePath) {
448
+ const fileHandle = await fs.open(filePath, 'r');
449
+ try {
450
+ const sampleSize = 512;
451
+ const buffer = Buffer.alloc(sampleSize);
452
+ const { bytesRead } = await fileHandle.read(buffer, 0, sampleSize, 0);
453
+ if (bytesRead === 0) {
454
+ return false;
455
+ }
456
+ let suspiciousBytes = 0;
457
+ for (let index = 0; index < bytesRead; index += 1) {
458
+ const byte = buffer[index];
459
+ if (byte === undefined) {
460
+ continue;
461
+ }
462
+ if (byte === 0) {
463
+ return true;
464
+ }
465
+ const isCommonWhitespace = byte === 9 || byte === 10 || byte === 13;
466
+ const isPrintableAscii = byte >= 32 && byte <= 126;
467
+ const isExtendedTextByte = byte >= 128;
468
+ if (!isCommonWhitespace && !isPrintableAscii && !isExtendedTextByte) {
469
+ suspiciousBytes += 1;
470
+ }
471
+ }
472
+ return suspiciousBytes / bytesRead > 0.1;
473
+ }
474
+ finally {
475
+ await fileHandle.close();
476
+ }
477
+ }
439
478
  isNodeError(error) {
440
479
  return error instanceof Error && 'code' in error;
441
480
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codebolt/agent",
3
- "version": "6.1.3",
3
+ "version": "6.1.5",
4
4
  "description": "CodeBolt Agent utilities for building and managing AI agents",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",