(
params: GenerateImageArgs,
context?: ServerToolContext
)
| 54 | name: GenerateImage.id, |
| 55 | |
| 56 | async execute( |
| 57 | params: GenerateImageArgs, |
| 58 | context?: ServerToolContext |
| 59 | ): Promise<GenerateImageResult> { |
| 60 | const withMessageId = (message: string) => |
| 61 | context?.messageId ? `${message} [messageId:${context.messageId}]` : message |
| 62 | |
| 63 | if (!context?.userId) { |
| 64 | throw new Error('Authentication required') |
| 65 | } |
| 66 | const workspaceId = context.workspaceId |
| 67 | if (!workspaceId) { |
| 68 | return { success: false, message: 'Workspace ID is required' } |
| 69 | } |
| 70 | |
| 71 | const { prompt } = params |
| 72 | if (!prompt) { |
| 73 | return { success: false, message: 'prompt is required' } |
| 74 | } |
| 75 | |
| 76 | try { |
| 77 | const apiKey = getRotatingApiKey('gemini') |
| 78 | const ai = new GoogleGenAI({ apiKey }) |
| 79 | |
| 80 | const aspectRatio = params.aspectRatio || '1:1' |
| 81 | const sizeHint = ASPECT_RATIO_TO_SIZE[aspectRatio] |
| 82 | |
| 83 | const parts: Part[] = [] |
| 84 | |
| 85 | const referencePaths = params.inputs?.files?.map((file) => file.path) ?? [] |
| 86 | |
| 87 | if (referencePaths.length) { |
| 88 | for (const filePath of referencePaths) { |
| 89 | try { |
| 90 | const fileRecord = await resolveWorkspaceFileReference(workspaceId, filePath) |
| 91 | if (fileRecord) { |
| 92 | const buffer = await fetchWorkspaceFileBuffer(fileRecord) |
| 93 | const base64 = buffer.toString('base64') |
| 94 | const mime = fileRecord.type || 'image/png' |
| 95 | parts.push({ |
| 96 | inlineData: { mimeType: mime, data: base64 }, |
| 97 | }) |
| 98 | logger.info('Loaded reference image', { |
| 99 | filePath, |
| 100 | name: fileRecord.name, |
| 101 | size: buffer.length, |
| 102 | mimeType: mime, |
| 103 | }) |
| 104 | } else { |
| 105 | logger.warn('Reference file not found, skipping', { filePath }) |
| 106 | } |
| 107 | } catch (err) { |
| 108 | logger.warn('Failed to load reference image, skipping', { |
| 109 | filePath, |
| 110 | error: toError(err).message, |
| 111 | }) |
| 112 | } |
| 113 | } |
nothing calls this directly
no test coverage detected