import gradio as gr
import spaces
# ponytail: never called; ZeroGPU hardware refuses to boot without one @spaces.GPU function. Delete if the Space moves
# to cpu-basic (needs PRO to downgrade).
@spaces.GPU
def _zerogpu_stub():
pass
SYSTEM_PROMPT = (
"Use only the Three.js core ES module from\n"
"https://cdnjs.cloudflare.com/ajax/libs/three.js/0.160.0/three.module.min.js.\n"
"Do not import addons or legacy examples/js paths;\n"
"implement any camera controls directly inside the HTML."
)
EXAMPLES = [
"Please create one self-contained HTML file with Three.js from cdnjs showing an elephant rehabilitation habitat.\n\n"
"A broad sheltered yard connects water, shade, and feeding areas through accessible paths. Use the elephant's scale "
"and movement clearance to guide the layout around the structures.\n\n"
"Render it as a deliberate 3D voxel model built from visible cubic blocks, with clear depth, readable silhouettes, "
"and solid spatial relationships.",
"Build a self-contained HTML scene with Three.js from cdnjs featuring a dragonrider aerie on a sea stack, with "
"perches, a hatchery, and a windlass.\n\nThe aerie occupies a flat-topped sea stack, reached by a rope windlass "
"from the shore. Four projecting stone perches ring the central hatchery, a vaulted cave with sand nests and a "
"smoke hole. A timber landing deck holds a hoist crane and harness racks, while switchback stairs connect the "
"perches to a water-level boathouse.\n\nRender it as a deliberate 3D voxel model built from visible cubic blocks, "
"with clear depth, readable silhouettes, and solid spatial relationships.",
"Please create one self-contained HTML file with Three.js from cdnjs showing a canal lock and weir complex with a "
"central island.",
"Make a standalone HTML scene with Three.js from cdnjs depicting an animated air traffic control tower with rotating "
"radar and light signals.\n\nA tapered control tower rises from a rectangular base to a cantilevered glass cab with "
"angled glazing panels and an external catwalk. A primary surveillance radar on a roof pedestal turns continuously, "
"and a rotating beacon sits above the cab.",
]
EXAMPLE_LABELS = [
"Elephant rehabilitation habitat",
"Dragonrider aerie on a sea stack",
"Canal lock and weir complex",
"Animated air traffic control tower",
]
# prefill the code fence so the model skips chatty preambles ("I cannot create files...")
NO_THINK = "\n\n\n\n```html\n"
# window.wgLive(rawOutput) re-renders the partial scene into #wg-live every few seconds.
# Unfinished JS is cut back to the last complete-looking line, open brackets are closed and a fallback render loop
# is appended; the new iframe only replaces the old one once that patched script actually ran (it posts 'wg-ok').
LIVE_JS = r"""
window.wgCode ??= (out) => {
const body = out.replace(/[\s\S]*?(<\/think>|$)/g, '');
let m = body.match(/```html\s*([\s\S]*?)(```|$)/);
return m ? m[1].trim() : ((m = body.match(/|$)/i)) ? m[0] : body.trim());
};
window.wgLive ??= (() => {
const TAIL = "\n;try{const R=renderer,S=scene,C=camera;(function f(){try{R.render(S,C)}catch(e){}"
+ "requestAnimationFrame(f)})()}catch(e){}\nparent.postMessage('wg-ok','*');\n";
const closers = (s) => {
const st = [];
for (let i = 0; i < s.length; i++) {
const c = s[i];
if (c === '/' && s[i + 1] === '/') { i = s.indexOf('\n', i); if (i < 0) break; }
else if (c === '/' && s[i + 1] === '*') { i = s.indexOf('*/', i + 2) + 1; if (i <= 0) break; }
else if (c === '"' || c === "'" || c === '`') { while (++i < s.length && s[i] !== c) if (s[i] === '\\') i++; }
else if ('([{'.includes(c)) st.push({ '(': ')', '[': ']', '{': '}' }[c]);
else if (')]}'.includes(c)) st.pop();
}
return st.reverse().join('');
};
// -> [html, isPartial], or null when there is no script to run yet
const patch = (code) => {
const i = code.lastIndexOf('