import { expect, tap } from '@push.rocks/tapbundle'; import * as qenv from '@push.rocks/qenv'; import * as smartrequest from '@push.rocks/smartrequest'; import * as smartfile from '@push.rocks/smartfile'; const testQenv = new qenv.Qenv('./', './.nogit/'); import * as smartai from '../ts/index.js'; let anthropicProvider: smartai.AnthropicProvider; tap.test('Anthropic: should create and start Anthropic provider', async () => { anthropicProvider = new smartai.AnthropicProvider({ anthropicToken: await testQenv.getEnvVarOnDemand('ANTHROPIC_TOKEN'), }); await anthropicProvider.start(); expect(anthropicProvider).toBeInstanceOf(smartai.AnthropicProvider); }); tap.test('Anthropic: should create chat response', async () => { const userMessage = 'What is the capital of France? Answer in one word.'; const response = await anthropicProvider.chat({ systemMessage: 'You are a helpful assistant. Be concise.', userMessage: userMessage, messageHistory: [], }); console.log(`Anthropic Chat - User: ${userMessage}`); console.log(`Anthropic Chat - Response: ${response.message}`); expect(response.role).toEqual('assistant'); expect(response.message).toBeTruthy(); expect(response.message.toLowerCase()).toInclude('paris'); }); tap.test('Anthropic: should handle message history', async () => { const messageHistory: smartai.ChatMessage[] = [ { role: 'user', content: 'My name is Claude Test' }, { role: 'assistant', content: 'Nice to meet you, Claude Test!' } ]; const response = await anthropicProvider.chat({ systemMessage: 'You are a helpful assistant with good memory.', userMessage: 'What is my name?', messageHistory: messageHistory, }); console.log(`Anthropic Memory Test - Response: ${response.message}`); expect(response.message.toLowerCase()).toInclude('claude test'); }); tap.test('Anthropic: should analyze coffee image with latte art', async () => { // Test 1: Coffee image from Unsplash by Dani const imagePath = './test/testimages/coffee-dani/coffee.jpg'; console.log(`Loading coffee image from: ${imagePath}`); const imageBuffer = await smartfile.fs.toBuffer(imagePath); console.log(`Image loaded, size: ${imageBuffer.length} bytes`); const result = await anthropicProvider.vision({ image: imageBuffer, prompt: 'Describe this coffee image. What do you see in terms of the cup, foam pattern, and overall composition?' }); console.log(`Anthropic Vision (Coffee) - Result: ${result}`); expect(result).toBeTruthy(); expect(typeof result).toEqual('string'); expect(result.toLowerCase()).toInclude('coffee'); // The image has a heart pattern in the latte art const mentionsLatte = result.toLowerCase().includes('heart') || result.toLowerCase().includes('latte') || result.toLowerCase().includes('foam'); expect(mentionsLatte).toBeTrue(); }); tap.test('Anthropic: should analyze laptop/workspace image', async () => { // Test 2: Laptop image from Unsplash by Nicolas Bichon const imagePath = './test/testimages/laptop-nicolas/laptop.jpg'; console.log(`Loading laptop image from: ${imagePath}`); const imageBuffer = await smartfile.fs.toBuffer(imagePath); console.log(`Image loaded, size: ${imageBuffer.length} bytes`); const result = await anthropicProvider.vision({ image: imageBuffer, prompt: 'Describe the technology and workspace setup in this image. What devices and equipment can you see?' }); console.log(`Anthropic Vision (Laptop) - Result: ${result}`); expect(result).toBeTruthy(); expect(typeof result).toEqual('string'); // Should mention laptop, computer, keyboard, or desk const mentionsTech = result.toLowerCase().includes('laptop') || result.toLowerCase().includes('computer') || result.toLowerCase().includes('keyboard') || result.toLowerCase().includes('desk'); expect(mentionsTech).toBeTrue(); }); tap.test('Anthropic: should analyze receipt/document image', async () => { // Test 3: Receipt image from Unsplash by Annie Spratt const imagePath = './test/testimages/receipt-annie/receipt.jpg'; console.log(`Loading receipt image from: ${imagePath}`); const imageBuffer = await smartfile.fs.toBuffer(imagePath); console.log(`Image loaded, size: ${imageBuffer.length} bytes`); const result = await anthropicProvider.vision({ image: imageBuffer, prompt: 'What type of document is this? Can you identify any text or numbers visible in the image?' }); console.log(`Anthropic Vision (Receipt) - Result: ${result}`); expect(result).toBeTruthy(); expect(typeof result).toEqual('string'); // Should mention receipt, document, text, or paper const mentionsDocument = result.toLowerCase().includes('receipt') || result.toLowerCase().includes('document') || result.toLowerCase().includes('text') || result.toLowerCase().includes('paper'); expect(mentionsDocument).toBeTrue(); }); tap.test('Anthropic: should document a PDF', async () => { const pdfUrl = 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf'; const pdfResponse = await smartrequest.SmartRequest.create() .url(pdfUrl) .get(); const result = await anthropicProvider.document({ systemMessage: 'Classify the document. Only the following answers are allowed: "invoice", "bank account statement", "contract", "test document", "other". The answer should only contain the keyword for machine use.', userMessage: 'Classify this document.', messageHistory: [], pdfDocuments: [Buffer.from(await pdfResponse.arrayBuffer())], }); console.log(`Anthropic Document - Result:`, result); expect(result).toBeTruthy(); expect(result.message).toBeTruthy(); }); tap.test('Anthropic: should handle complex document analysis', async () => { // Test with the demo PDF if it exists const pdfPath = './.nogit/demo_without_textlayer.pdf'; let pdfBuffer: Uint8Array; try { pdfBuffer = await smartfile.fs.toBuffer(pdfPath); } catch (error) { // If the file doesn't exist, use the dummy PDF console.log('Demo PDF not found, using dummy PDF instead'); const pdfUrl = 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf'; const pdfResponse = await smartrequest.SmartRequest.create() .url(pdfUrl) .get(); pdfBuffer = Buffer.from(await pdfResponse.arrayBuffer()); } const result = await anthropicProvider.document({ systemMessage: ` Analyze this document and provide a JSON response with the following structure: { "documentType": "string", "hasText": boolean, "summary": "string" } `, userMessage: 'Analyze this document.', messageHistory: [], pdfDocuments: [pdfBuffer], }); console.log(`Anthropic Complex Document Analysis:`, result); expect(result).toBeTruthy(); expect(result.message).toBeTruthy(); }); tap.test('Anthropic: should handle errors gracefully', async () => { // Test with invalid message (empty) let errorCaught = false; try { await anthropicProvider.chat({ systemMessage: '', userMessage: '', messageHistory: [], }); } catch (error) { errorCaught = true; console.log('Expected error caught:', error.message); } // Anthropic might handle empty messages, so we don't assert error console.log(`Error handling test - Error caught: ${errorCaught}`); }); tap.test('Anthropic: audio should throw not supported error', async () => { let errorCaught = false; try { await anthropicProvider.audio({ message: 'This should fail' }); } catch (error) { errorCaught = true; expect(error.message).toInclude('not yet supported'); } expect(errorCaught).toBeTrue(); }); tap.test('Anthropic: should stop the provider', async () => { await anthropicProvider.stop(); console.log('Anthropic provider stopped successfully'); }); export default tap.start();