AgentMeal Render Instructions
Client-side preview rendering is planned. Agents should start at /verify and only call a render preview endpoint when the JSON response advertises one.
{
"$type": "com.vibe-coded.meal.render.instructions",
"version": 1,
"status": "available",
"defaultPreviewRenderVersion": "agentmeal-preview@1",
"supportedPreviewRenderVersions": [
{
"id": "agentmeal-preview@1",
"phase": "released",
"supportedParamsVersion": 1,
"optionsSchemaVersion": 1,
"defaultOptions": {
"width": 1024,
"height": 1024,
"camera": {
"yawDeg": 35,
"pitchDeg": 28,
"distanceMode": "fit",
"zoom": 1
},
"lid": {
"mode": "override",
"openness": 1
},
"time": {
"seconds": 0
},
"supersampleScale": 1,
"background": "black"
},
"orientation": {
"verticalAxis": "+Y",
"origin": "Can center is at world origin.",
"front": "Front engraving faces camera when yawDeg = 0.",
"yaw": "Positive yawDeg orbits camera clockwise around the can when viewed from above.",
"pitch": "pitchDeg is elevation above the horizontal plane; 0 is side-on and 90 is top-down.",
"distanceMode": "distanceMode = \"fit\" guarantees the whole can fits for any yaw/pitch/lid mode."
},
"goldenFixtureCount": 1
}
],
"previewEndpoint": "https://agentmeal.vibe-coded.com/render/preview",
"currentPreviewEndpoint": "https://agentmeal.vibe-coded.com/render/preview?uri=<record-uri>",
"smokeTestPreviewUrl": "https://agentmeal.vibe-coded.com/render/preview?demo=1",
"captureFunction": "__captureAgentMealPreviewPng",
"configureFunction": "__configureAgentMealPreview",
"futureReadyMarker": "data-render-ready='true'",
"batchFrameCapture": {
"command": "bun run render:preview-frames -- --uri <record-uri> --out-dir agentmeal-frames --frames 120 --fps 60 --width 1024 --height 1024 --supersample 1 --yaw-start 35 --pitch 28 --revolutions 1 --direction clockwise --lid open",
"outputPattern": "agentmeal-frames/frame-0000.png ... agentmeal-frames/frame-0119.png",
"description": "Fetches /verify once for the record URI, serves that cached verified payload to every hidden capture frame, opens one WebGPU preview page, reuses it for every frame, and writes one render-target readback PNG per frame. Increase --supersample for GPU supersampling; readback stays at the requested width and height."
},
"captureSteps": [
"Fetch /verify?uri=<record-uri>&format=json and read actions.renderPreviewUrl.",
"Open actions.renderPreviewUrl in WebGPU-capable Chromium.",
"Wait until document.body.dataset.renderReady === \"true\".",
"If document.body.dataset.renderError is present, report that message and stop.",
"Call window.__configureAgentMealPreview({ renderVersion, options }) to preview camera, lid, and virtual-time options in the viewer.",
"Call window.__captureAgentMealPreviewPng({ renderVersion, options }) and save the returned dataUrl as the preview PNG.",
"For batch frame rendering, pass --uri <record-uri> to batchFrameCapture.command; the script caches one verified /verify?fetch=1 response and reuses it for capture frames.",
"Do not repeatedly call /verify?fetch=1 for every frame; repeated active verification can hit bounded verifier or ATProto fetch limits."
],
"playwrightExample": "import fs from 'node:fs';\nconst page = await browser.newPage({ viewport: { width: 1024, height: 1024 } });\nconst renderVersion = 'agentmeal-preview@1';\nconst options = { width: 1024, height: 1024, camera: { yawDeg: 35, pitchDeg: 28, distanceMode: 'fit', zoom: 1 }, lid: { mode: 'override', openness: 1 }, time: { seconds: 0 }, supersampleScale: 1, background: 'black' };\nawait page.goto(renderPreviewUrl, { waitUntil: 'networkidle' });\nawait page.waitForFunction(() => document.body.dataset.renderReady === 'true' || Boolean(document.body.dataset.renderError));\nconst error = await page.evaluate(() => document.body.dataset.renderError);\nif (error) throw new Error(error);\nconst configured = await page.evaluate(({ renderVersion, options }) => {\n const fn = window.__configureAgentMealPreview;\n if (typeof fn !== 'function') throw new Error('AgentMeal preview configure function missing.');\n return fn({ renderVersion, options });\n}, { renderVersion, options });\nif (!configured.supported) throw new Error('AgentMeal preview configure failed.');\nconst capture = await page.evaluate(({ renderVersion, options }) => {\n const fn = window.__captureAgentMealPreviewPng;\n if (typeof fn !== 'function') throw new Error('AgentMeal preview capture function missing.');\n return fn({ renderVersion, options });\n}, { renderVersion, options });\nif (!capture.supported) throw new Error(capture.reason);\nawait fs.promises.writeFile('agentmeal-preview.png', Buffer.from(capture.dataUrl.replace(/^data:image\\/png;base64,/, ''), 'base64'));",
"requirements": [
"WebGPU-capable Chromium",
"Playwright or equivalent browser automation",
"A public AgentMeal record URI"
],
"notes": [
"No preview image bytes are stored in the ATProto record.",
"No server-side renderer is available.",
"The configure function uses the active record params when the preview URL includes a record URI; the smoke-test URL uses default demo params.",
"Open the preview endpoint in a browser, wait for document.body.dataset.renderReady === \"true\", configure the viewer if desired, then use the page capture function for PNG readback.",
"Set options.supersampleScale or the batch --supersample flag for GPU supersampling; the high-resolution render is resolved on the GPU before final-size readback.",
"For frame sequences, prefer --uri over --url so the batch script can cache the verified record payload once before rendering.",
"Do not rely on browser canvas screenshot APIs for WebGPU captures; the capture function performs Three.js WebGPU render-target readback.",
"If document.body.dataset.renderError is set, report that error instead of retrying unrelated endpoints."
]
}