feat(tools): add file read/write/edit/list builtin tools

This commit is contained in:
William Valentin
2026-02-05 17:39:20 -08:00
parent b913941e4f
commit 32dd3ad728
7 changed files with 391 additions and 0 deletions
+52
View File
@@ -0,0 +1,52 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { webFetchTool } from './web-fetch.js';
// Mock global fetch
const mockFetch = vi.fn();
vi.stubGlobal('fetch', mockFetch);
beforeEach(() => {
mockFetch.mockReset();
});
describe('web.fetch', () => {
it('has correct metadata', () => {
expect(webFetchTool.name).toBe('web.fetch');
expect(webFetchTool.inputSchema.required).toContain('url');
});
it('fetches a URL and returns body text', async () => {
mockFetch.mockResolvedValue({
ok: true,
status: 200,
text: async () => '<html><body><h1>Hello</h1><p>World</p></body></html>',
headers: new Headers({ 'content-type': 'text/html' }),
});
const result = await webFetchTool.execute({ url: 'https://example.com' });
expect(result.success).toBe(true);
expect(result.output).toBeTruthy();
expect(mockFetch).toHaveBeenCalledWith('https://example.com', expect.any(Object));
});
it('returns error on HTTP failure', async () => {
mockFetch.mockResolvedValue({
ok: false,
status: 404,
text: async () => 'Not Found',
headers: new Headers(),
});
const result = await webFetchTool.execute({ url: 'https://example.com/nope' });
expect(result.success).toBe(false);
expect(result.error).toContain('404');
});
it('returns error on network failure', async () => {
mockFetch.mockRejectedValue(new Error('network error'));
const result = await webFetchTool.execute({ url: 'https://down.example.com' });
expect(result.success).toBe(false);
expect(result.error).toContain('network error');
});
});