11const mockIpfsCid = 'mock-cid-placeholder' 13const timeoutPromise = (ms) => new Promise((_, reject) => 14 setTimeout(() => reject(new Error(`AI draw timeout after ${ms}ms`)), ms) 17export const aiDrawDescription = async (/** @type {{descriptionText: string, model?: string}} */ { descriptionText, model }) => { 18 const mockCtx = aiDrawMockCtx.getStore() 19 if (mockCtx?.useMock) { 20 return { ipfsCid: mockIpfsCid, model: 'mock', costUsd: 0, genTimeMs: 0 } 23 model ||= defaultAiDrawModel 26 const startTime = Date.now() 27 const { result: resp } = await Promise.race([ 32 aiMessages: [{role: 'user', content: `Create an image: ${descriptionText}. Do not include any text, letters, numbers, or words in the image.`}], 33 modalities: ['image'], 35 context: 'aiDrawDescription', 37 timeoutPromise(aiDrawTimeoutMs), 39 const genTimeMs = Date.now() - startTime 42 betLog('aiDrawDescription unexpected: no result', {model}) 46 let imageDataUrl = resp.choices[0].message.images?.[0]?.image_url?.url 48 const content = resp.choices[0].message.content || '' 49 const m = content.match(/data:image\/[a-z]+;base64,[A-Za-z0-9+/=]+/) 50 if (m) imageDataUrl = m[0] 53 betLog('aiDrawDescription unexpected: no image', {model, choiceKeys: Object.keys(resp.choices?.[0]?.message || {})}) 57 const base64Data = imageDataUrl.replace(/^data:image\/\w+;base64,/, '') 58 const imageBuffer = Buffer.from(base64Data, 'base64') 62 betLog('addToGamesMediaRootFail', {ipfsCid, errMsg: err.message}) 65 return { ipfsCid, model, costUsd: resp.costUsd, genTimeMs } 67 betLog('aiDrawDescription error', {model, err})