Skip to content

Commit a6025c9

Browse files
feat: Add audio and video support to read_file
This commit enhances the `read_file` tool to support audio and video files. It updates the `detectFileType` function to recognize audio and video MIME types, and modifies the `processSingleFileContent` function to handle these new file types. This change allows the `read_file` tool to process a wider range of file formats, improving its multimodal capabilities. It adds the tests in `fileUtil.test.ts` regarding the changes and it adds a targeted mock in `read-many-files.test.ts` file to work around a dependency's bug, and tests the actual feature in its own dedicated unit test file. fixes #1556
1 parent ad7839e commit a6025c9

File tree

3 files changed

+49
-8
lines changed

3 files changed

+49
-8
lines changed

packages/core/src/tools/read-many-files.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,27 @@
66

77
import { vi } from 'vitest';
88
import type { Mock } from 'vitest';
9+
10+
vi.mock('mime-types', () => {
11+
const lookup = (filename: string) => {
12+
if (filename.endsWith('.ts') || filename.endsWith('.js')) {
13+
return 'text/plain';
14+
}
15+
if (filename.endsWith('.png')) {
16+
return 'image/png';
17+
}
18+
if (filename.endsWith('.pdf')) {
19+
return 'application/pdf';
20+
}
21+
return false;
22+
};
23+
return {
24+
default: {
25+
lookup,
26+
},
27+
lookup,
28+
};
29+
});
930
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
1031
import { mockControl } from '../__mocks__/fs/promises.js';
1132
import { ReadManyFilesTool } from './read-many-files.js';

packages/core/src/utils/fileUtils.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,16 @@ describe('fileUtils', () => {
211211
expect(detectFileType('file.pdf')).toBe('pdf');
212212
});
213213

214+
it('should detect audio type by extension', () => {
215+
mockMimeLookup.mockReturnValueOnce('audio/mpeg');
216+
expect(detectFileType('song.mp3')).toBe('audio');
217+
});
218+
219+
it('should detect video type by extension', () => {
220+
mockMimeLookup.mockReturnValueOnce('video/mp4');
221+
expect(detectFileType('movie.mp4')).toBe('video');
222+
});
223+
214224
it('should detect known binary extensions as binary (e.g. .zip)', () => {
215225
mockMimeLookup.mockReturnValueOnce('application/zip');
216226
expect(detectFileType('archive.zip')).toBe('binary');

packages/core/src/utils/fileUtils.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,19 +94,27 @@ export function isBinaryFile(filePath: string): boolean {
9494
/**
9595
* Detects the type of file based on extension and content.
9696
* @param filePath Path to the file.
97-
* @returns 'text', 'image', 'pdf', or 'binary'.
97+
* @returns 'text', 'image', 'pdf', 'audio', 'video', or 'binary'.
9898
*/
9999
export function detectFileType(
100100
filePath: string,
101-
): 'text' | 'image' | 'pdf' | 'binary' {
101+
): 'text' | 'image' | 'pdf' | 'audio' | 'video' | 'binary' {
102102
const ext = path.extname(filePath).toLowerCase();
103103
const lookedUpMimeType = mime.lookup(filePath); // Returns false if not found, or the mime type string
104104

105-
if (lookedUpMimeType && lookedUpMimeType.startsWith('image/')) {
106-
return 'image';
107-
}
108-
if (lookedUpMimeType && lookedUpMimeType === 'application/pdf') {
109-
return 'pdf';
105+
if (lookedUpMimeType) {
106+
if (lookedUpMimeType.startsWith('image/')) {
107+
return 'image';
108+
}
109+
if (lookedUpMimeType.startsWith('audio/')) {
110+
return 'audio';
111+
}
112+
if (lookedUpMimeType.startsWith('video/')) {
113+
return 'video';
114+
}
115+
if (lookedUpMimeType === 'application/pdf') {
116+
return 'pdf';
117+
}
110118
}
111119

112120
// Stricter binary check for common non-text extensions before content check
@@ -253,7 +261,9 @@ export async function processSingleFileContent(
253261
};
254262
}
255263
case 'image':
256-
case 'pdf': {
264+
case 'pdf':
265+
case 'audio':
266+
case 'video': {
257267
const contentBuffer = await fs.promises.readFile(filePath);
258268
const base64Data = contentBuffer.toString('base64');
259269
return {

0 commit comments

Comments
 (0)