diff --git a/packages/core/src/tests/videoGeneration.test.ts b/packages/core/src/tests/videoGeneration.test.ts new file mode 100644 index 00000000000..2fb8f86573b --- /dev/null +++ b/packages/core/src/tests/videoGeneration.test.ts @@ -0,0 +1,125 @@ +import { IAgentRuntime, Memory, State } from "@ai16z/eliza"; +import { videoGenerationPlugin } from "../index"; + +// Mock the fetch function +global.fetch = jest.fn(); + +// Mock the fs module +jest.mock('fs', () => ({ + writeFileSync: jest.fn(), + existsSync: jest.fn(), + mkdirSync: jest.fn(), +})); + +describe('Video Generation Plugin', () => { + let mockRuntime: IAgentRuntime; + let mockCallback: jest.Mock; + + beforeEach(() => { + // Reset mocks + jest.clearAllMocks(); + + // Setup mock runtime + mockRuntime = { + getSetting: jest.fn().mockReturnValue('mock-api-key'), + agentId: 'mock-agent-id', + composeState: jest.fn().mockResolvedValue({}), + } as unknown as IAgentRuntime; + + mockCallback = jest.fn(); + + // Setup fetch mock for successful response + (global.fetch as jest.Mock).mockImplementation(() => + Promise.resolve({ + ok: true, + json: () => Promise.resolve({ + id: 'mock-generation-id', + status: 'completed', + assets: { + video: 'https://example.com/video.mp4' + } + }), + text: () => Promise.resolve(''), + }) + ); + }); + + it('should validate when API key is present', async () => { + const mockMessage = {} as Memory; + const result = await videoGenerationPlugin.actions[0].validate(mockRuntime, mockMessage); + expect(result).toBe(true); + expect(mockRuntime.getSetting).toHaveBeenCalledWith('LUMA_API_KEY'); + }); + + it('should handle video generation request', async () => { + const mockMessage = { + content: { + text: 'Generate a video of a sunset' + } + } as Memory; + const mockState = {} as State; + + await videoGenerationPlugin.actions[0].handler( + mockRuntime, + mockMessage, + mockState, + {}, + mockCallback + ); + + // Check initial callback + expect(mockCallback).toHaveBeenCalledWith( + expect.objectContaining({ + text: expect.stringContaining('I\'ll generate a video based on your prompt') + }) + ); + + // Check final callback with video + expect(mockCallback).toHaveBeenCalledWith( + expect.objectContaining({ + text: 'Here\'s your generated video!', + attachments: expect.arrayContaining([ + expect.objectContaining({ + source: 'videoGeneration' + }) + ]) + }), + expect.arrayContaining([expect.stringMatching(/generated_video_.*\.mp4/)]) + ); + }); + + it('should handle API errors gracefully', async () => { + // Mock API error + (global.fetch as jest.Mock).mockImplementationOnce(() => + Promise.resolve({ + ok: false, + status: 500, + statusText: 'Internal Server Error', + text: () => Promise.resolve('API Error'), + }) + ); + + const mockMessage = { + content: { + text: 'Generate a video of a sunset' + } + } as Memory; + const mockState = {} as State; + + await videoGenerationPlugin.actions[0].handler( + mockRuntime, + mockMessage, + mockState, + {}, + mockCallback + ); + + // Check error callback + expect(mockCallback).toHaveBeenCalledWith( + expect.objectContaining({ + text: expect.stringContaining('Video generation failed'), + error: true + }) + ); + }); +}); \ No newline at end of file diff --git a/packages/plugin-video-generation/src/constants.ts b/packages/plugin-video-generation/src/constants.ts new file mode 100644 index 00000000000..4f7428d8f76 --- /dev/null +++ b/packages/plugin-video-generation/src/constants.ts @@ -0,0 +1,4 @@ +export const LUMA_CONSTANTS = { + API_URL: 'https://api.lumalabs.ai/dream-machine/v1/generations', + API_KEY_SETTING: "LUMA_API_KEY" // The setting name to fetch from runtime +}; \ No newline at end of file diff --git a/packages/plugin-video-generation/src/index.ts b/packages/plugin-video-generation/src/index.ts index 7ec9f140a76..0723485263b 100644 --- a/packages/plugin-video-generation/src/index.ts +++ b/packages/plugin-video-generation/src/index.ts @@ -8,15 +8,15 @@ import { State, } from "@ai16z/eliza/src/types.ts"; import fs from "fs"; +import { LUMA_CONSTANTS } from './constants'; const generateVideo = async (prompt: string, runtime: IAgentRuntime) => { - const API_URL = 'https://api.lumalabs.ai/dream-machine/v1/generations'; - const API_KEY = runtime.getSetting("LUMA_API_KEY"); + const API_KEY = runtime.getSetting(LUMA_CONSTANTS.API_KEY_SETTING); try { elizaLogger.log("Starting video generation with prompt:", prompt); - const response = await fetch(API_URL, { + const response = await fetch(LUMA_CONSTANTS.API_URL, { method: 'POST', headers: { 'Authorization': `Bearer ${API_KEY}`, @@ -47,7 +47,7 @@ const generateVideo = async (prompt: string, runtime: IAgentRuntime) => { while (status !== 'completed' && status !== 'failed') { await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds - const statusResponse = await fetch(`${API_URL}/${generationId}`, { + const statusResponse = await fetch(`${LUMA_CONSTANTS.API_URL}/${generationId}`, { method: 'GET', headers: { 'Authorization': `Bearer ${API_KEY}`,