ManimCat / src /studio-agent /modes /matplotlib /plot-render-driver.ts
Bin29's picture
Sync from main: 0989c63 style(workflow): draw the plan as a rail and bring back the waiting paws
15c386f
Raw History Blame Contribute Delete
2.19 kB
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
}