File size: 2,187 Bytes
15c386f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | import type { StudioFileAttachment } from '../../domain/types'
import type { StudioRenderDriver, StudioRenderExecutionInput, StudioRenderExecutionResult } from '../../render/studio-render-driver'
import { toWorkspaceRelativePath } from '../../tools/workspace-paths'
import type { PlotRenderPort } from './plot-render-port'
/**
* Matplotlib render driver: runs the script inline, respects the AbortSignal, and completes
* immediately. There is no queue to cancel and no job to reconcile — the render is terminal
* by the time `execute` returns.
*/
export function createMatplotlibRenderDriver(options: {
renderPort: PlotRenderPort
}): StudioRenderDriver {
const { renderPort } = options
return {
kind: 'matplotlib',
async execute(input: StudioRenderExecutionInput): Promise<StudioRenderExecutionResult> {
const execution = await renderPort.execute({
workspaceDirectory: input.workspaceDirectory,
workspaceOutputDirectory: typeof input.render.metadata?.workspaceOutputDirectory === 'string'
? input.render.metadata.workspaceOutputDirectory : undefined,
renderId: input.render.id,
code: input.code,
signal: input.signal,
})
const attachments = buildAttachments(execution.imageDataUris, execution.imagePaths)
return {
status: 'completed',
attachments,
metadata: {
imageCount: execution.imageDataUris.length,
scriptPath: toWorkspaceRelativePath(input.workspaceDirectory, execution.scriptPath).replace(/\\/g, '/'),
imagePaths: execution.imagePaths.map((path) =>
toWorkspaceRelativePath(input.workspaceDirectory, path).replace(/\\/g, '/')
),
},
}
},
}
}
function buildAttachments(imageDataUris: string[], imagePaths: string[]): StudioFileAttachment[] {
return imageDataUris.map((path, index) => ({
kind: 'file',
path,
name: fileNameFromPath(imagePaths[index]) || `plot_${index + 1}.png`,
mimeType: 'image/png',
}))
}
function fileNameFromPath(path?: string): string {
if (!path) {
return ''
}
const parts = path.split(/[\\/]/)
return parts[parts.length - 1] || path
}
|