204 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			204 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { expect, tap } from '@push.rocks/tapbundle';
 | 
						|
import * as qenv from '@push.rocks/qenv';
 | 
						|
import * as smartai from '../ts/index.js';
 | 
						|
import * as path from 'path';
 | 
						|
import { promises as fs } from 'fs';
 | 
						|
 | 
						|
const testQenv = new qenv.Qenv('./', './.nogit/');
 | 
						|
 | 
						|
let openaiProvider: smartai.OpenAiProvider;
 | 
						|
 | 
						|
// Helper function to save image results
 | 
						|
async function saveImageResult(testName: string, result: any) {
 | 
						|
  const sanitizedName = testName.replace(/[^a-z0-9]/gi, '_').toLowerCase();
 | 
						|
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
 | 
						|
  const filename = `openai_${sanitizedName}_${timestamp}.json`;
 | 
						|
  const filepath = path.join('.nogit', 'testresults', 'images', filename);
 | 
						|
 | 
						|
  await fs.mkdir(path.dirname(filepath), { recursive: true });
 | 
						|
  await fs.writeFile(filepath, JSON.stringify(result, null, 2), 'utf-8');
 | 
						|
 | 
						|
  console.log(`  💾 Saved to: ${filepath}`);
 | 
						|
 | 
						|
  // Also save the actual image if b64_json is present
 | 
						|
  if (result.images && result.images[0]?.b64_json) {
 | 
						|
    const imageFilename = `openai_${sanitizedName}_${timestamp}.png`;
 | 
						|
    const imageFilepath = path.join('.nogit', 'testresults', 'images', imageFilename);
 | 
						|
    await fs.writeFile(imageFilepath, Buffer.from(result.images[0].b64_json, 'base64'));
 | 
						|
    console.log(`  🖼️  Image saved to: ${imageFilepath}`);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
tap.test('OpenAI Image Generation: should initialize provider', async () => {
 | 
						|
  const openaiToken = await testQenv.getEnvVarOnDemand('OPENAI_TOKEN');
 | 
						|
  expect(openaiToken).toBeTruthy();
 | 
						|
 | 
						|
  openaiProvider = new smartai.OpenAiProvider({
 | 
						|
    openaiToken,
 | 
						|
    imageModel: 'gpt-image-1'
 | 
						|
  });
 | 
						|
 | 
						|
  await openaiProvider.start();
 | 
						|
  expect(openaiProvider).toBeInstanceOf(smartai.OpenAiProvider);
 | 
						|
});
 | 
						|
 | 
						|
tap.test('OpenAI Image: Basic generation with gpt-image-1', async () => {
 | 
						|
  const result = await openaiProvider.imageGenerate({
 | 
						|
    prompt: 'A cute robot reading a book in a cozy library, digital art style',
 | 
						|
    model: 'gpt-image-1',
 | 
						|
    quality: 'medium',
 | 
						|
    size: '1024x1024'
 | 
						|
  });
 | 
						|
 | 
						|
  console.log('Basic gpt-image-1 Generation:');
 | 
						|
  console.log('- Images generated:', result.images.length);
 | 
						|
  console.log('- Model used:', result.metadata?.model);
 | 
						|
  console.log('- Quality:', result.metadata?.quality);
 | 
						|
  console.log('- Size:', result.metadata?.size);
 | 
						|
  console.log('- Tokens used:', result.metadata?.tokensUsed);
 | 
						|
 | 
						|
  await saveImageResult('basic_generation_gptimage1', result);
 | 
						|
 | 
						|
  expect(result.images).toBeTruthy();
 | 
						|
  expect(result.images.length).toEqual(1);
 | 
						|
  expect(result.images[0].b64_json).toBeTruthy();
 | 
						|
  expect(result.metadata?.model).toEqual('gpt-image-1');
 | 
						|
});
 | 
						|
 | 
						|
tap.test('OpenAI Image: High quality with transparent background', async () => {
 | 
						|
  const result = await openaiProvider.imageGenerate({
 | 
						|
    prompt: 'A simple geometric logo of a mountain peak, minimal design, clean lines',
 | 
						|
    model: 'gpt-image-1',
 | 
						|
    quality: 'high',
 | 
						|
    size: '1024x1024',
 | 
						|
    background: 'transparent',
 | 
						|
    outputFormat: 'png'
 | 
						|
  });
 | 
						|
 | 
						|
  console.log('High Quality Transparent:');
 | 
						|
  console.log('- Quality:', result.metadata?.quality);
 | 
						|
  console.log('- Background: transparent');
 | 
						|
  console.log('- Format:', result.metadata?.outputFormat);
 | 
						|
  console.log('- Tokens used:', result.metadata?.tokensUsed);
 | 
						|
 | 
						|
  await saveImageResult('high_quality_transparent', result);
 | 
						|
 | 
						|
  expect(result.images.length).toEqual(1);
 | 
						|
  expect(result.images[0].b64_json).toBeTruthy();
 | 
						|
});
 | 
						|
 | 
						|
tap.test('OpenAI Image: WebP format with compression', async () => {
 | 
						|
  const result = await openaiProvider.imageGenerate({
 | 
						|
    prompt: 'A futuristic cityscape at sunset with flying cars, photorealistic',
 | 
						|
    model: 'gpt-image-1',
 | 
						|
    quality: 'high',
 | 
						|
    size: '1536x1024',
 | 
						|
    outputFormat: 'webp',
 | 
						|
    outputCompression: 85
 | 
						|
  });
 | 
						|
 | 
						|
  console.log('WebP with Compression:');
 | 
						|
  console.log('- Format:', result.metadata?.outputFormat);
 | 
						|
  console.log('- Compression: 85%');
 | 
						|
  console.log('- Size:', result.metadata?.size);
 | 
						|
 | 
						|
  await saveImageResult('webp_compression', result);
 | 
						|
 | 
						|
  expect(result.images.length).toEqual(1);
 | 
						|
  expect(result.images[0].b64_json).toBeTruthy();
 | 
						|
});
 | 
						|
 | 
						|
tap.test('OpenAI Image: Text rendering with gpt-image-1', async () => {
 | 
						|
  const result = await openaiProvider.imageGenerate({
 | 
						|
    prompt: 'A vintage cafe sign that says "COFFEE & CODE" in elegant hand-lettered typography, warm colors',
 | 
						|
    model: 'gpt-image-1',
 | 
						|
    quality: 'high',
 | 
						|
    size: '1024x1024'
 | 
						|
  });
 | 
						|
 | 
						|
  console.log('Text Rendering:');
 | 
						|
  console.log('- Prompt includes text: "COFFEE & CODE"');
 | 
						|
  console.log('- gpt-image-1 has superior text rendering');
 | 
						|
  console.log('- Tokens used:', result.metadata?.tokensUsed);
 | 
						|
 | 
						|
  await saveImageResult('text_rendering', result);
 | 
						|
 | 
						|
  expect(result.images.length).toEqual(1);
 | 
						|
  expect(result.images[0].b64_json).toBeTruthy();
 | 
						|
});
 | 
						|
 | 
						|
tap.test('OpenAI Image: Multiple images generation', async () => {
 | 
						|
  const result = await openaiProvider.imageGenerate({
 | 
						|
    prompt: 'Abstract colorful geometric patterns, modern minimalist art',
 | 
						|
    model: 'gpt-image-1',
 | 
						|
    n: 2,
 | 
						|
    quality: 'medium',
 | 
						|
    size: '1024x1024'
 | 
						|
  });
 | 
						|
 | 
						|
  console.log('Multiple Images:');
 | 
						|
  console.log('- Images requested: 2');
 | 
						|
  console.log('- Images generated:', result.images.length);
 | 
						|
 | 
						|
  await saveImageResult('multiple_images', result);
 | 
						|
 | 
						|
  expect(result.images.length).toEqual(2);
 | 
						|
  expect(result.images[0].b64_json).toBeTruthy();
 | 
						|
  expect(result.images[1].b64_json).toBeTruthy();
 | 
						|
});
 | 
						|
 | 
						|
tap.test('OpenAI Image: Low moderation setting', async () => {
 | 
						|
  const result = await openaiProvider.imageGenerate({
 | 
						|
    prompt: 'A fantasy battle scene with warriors and dragons',
 | 
						|
    model: 'gpt-image-1',
 | 
						|
    moderation: 'low',
 | 
						|
    quality: 'medium'
 | 
						|
  });
 | 
						|
 | 
						|
  console.log('Low Moderation:');
 | 
						|
  console.log('- Moderation: low (less restrictive filtering)');
 | 
						|
  console.log('- Tokens used:', result.metadata?.tokensUsed);
 | 
						|
 | 
						|
  await saveImageResult('low_moderation', result);
 | 
						|
 | 
						|
  expect(result.images.length).toEqual(1);
 | 
						|
  expect(result.images[0].b64_json).toBeTruthy();
 | 
						|
});
 | 
						|
 | 
						|
tap.test('OpenAI Image Editing: edit with gpt-image-1', async () => {
 | 
						|
  // First, generate a base image
 | 
						|
  const baseResult = await openaiProvider.imageGenerate({
 | 
						|
    prompt: 'A simple white cat sitting on a red cushion',
 | 
						|
    model: 'gpt-image-1',
 | 
						|
    quality: 'low',
 | 
						|
    size: '1024x1024'
 | 
						|
  });
 | 
						|
 | 
						|
  const baseImageBuffer = Buffer.from(baseResult.images[0].b64_json!, 'base64');
 | 
						|
 | 
						|
  // Now edit it
 | 
						|
  const editResult = await openaiProvider.imageEdit({
 | 
						|
    image: baseImageBuffer,
 | 
						|
    prompt: 'Change the cat to orange and add stylish sunglasses',
 | 
						|
    model: 'gpt-image-1',
 | 
						|
    quality: 'medium'
 | 
						|
  });
 | 
						|
 | 
						|
  console.log('Image Editing:');
 | 
						|
  console.log('- Base image created');
 | 
						|
  console.log('- Edit: change color and add sunglasses');
 | 
						|
  console.log('- Result images:', editResult.images.length);
 | 
						|
 | 
						|
  await saveImageResult('image_edit', editResult);
 | 
						|
 | 
						|
  expect(editResult.images.length).toEqual(1);
 | 
						|
  expect(editResult.images[0].b64_json).toBeTruthy();
 | 
						|
});
 | 
						|
 | 
						|
tap.test('OpenAI Image: should clean up provider', async () => {
 | 
						|
  await openaiProvider.stop();
 | 
						|
  console.log('OpenAI image provider stopped successfully');
 | 
						|
});
 | 
						|
 | 
						|
export default tap.start();
 |