Skip to content

scene3d.create

Schema

Input = {
description: string, // objects, mood, colours, motion
path: string, // destination .html, relative to the workspace
title?: string,
procedural?: boolean, // default false — skip the model, use the deterministic generator directly
}
Output = {
path: string,
size: number,
mime: 'text/html',
source: 'model' | 'procedural',
costUsd: number,
note?: string,
}

How it stays safe

The model is asked to author only the scene’s body — a buildScene(THREE, scene, camera, renderer) function returning an update(t, dt) callback, plain JavaScript, no markdown fences. That script is never eval’d against live data; validateSceneScript() parses it with new Function(...) (syntax-only) and rejects anything referencing fetch, XMLHttpRequest, WebSocket, localStorage, document.cookie, or eval — a scene can move objects and animate, never call home or touch storage. On a validation failure, the model gets one repair round-trip with the exact error; if it still fails, or no OpenRouter key is configured, a procedural scene is generated instead — deterministically seeded from the description’s text, picking one of five looks (orbit, waves, forest, city, or an abstract field of icosahedra/torus knots) so the result is never empty or broken.

The HTML shell

The final file is fully self-contained: an import map pinning three@0.170.0 from cdn.jsdelivr.net, a small HUD showing the title/description, mouse-parallax camera drift, and a render loop that keeps going even if update() throws mid-frame (caught per-frame, not fatal). This is exactly what the 3D scene generator wraps, and what a custom widget can also point at.

Example

Terminal window
curl -s -X POST http://localhost:4000/api/studio/skills/invoke \
-H 'content-type: application/json' -b cookies.txt \
-d '{"name":"scene3d.create","input":{"description":"A low-poly island at dusk with fireflies","path":"scene.html"}}'
{ "ok": true, "output": { "path": "scene.html", "size": 6412, "mime": "text/html", "source": "model", "costUsd": 0.0006 } }