Studio job
A studio job (pipeline/show/text2game.js, runTextToGameJob) generates an asset
through a hosted text-to-3D studio's web UI, driven end-to-end through
Skarbiec (credentials) and the declared browser layer, Weles or the
Playwright MCP server. Nothing platform-specific is
hardcoded: endpoints and selectors come from the pipeline config, so swapping
studios is a config change, not a code change.
Entry points: glina create <prompt> [--race r], MCP tool
glina_create_asset. (--race prefixes the prompt; the MCP schema limits it
to humans | dwarves | elves | skeletons.)
Steps
Every step is named, and a failure carries its name:
text2game step '<name>' failed: <reason>. A config with no studio section
is refused first: the pipeline config has no studio section: create needs studio.loginUrl, studio.generateUrl, studio.selectors and studio.artifact.expression.
open-session/open-page— start a browser session on the browser layer the config declares and open a page.login:goto/login:user/login:pass/login:submit— navigate tostudio.loginUrl, fillstudio.selectors.loginUser/loginPasswordwith the resolvedcredentials.username/password, clickloginSubmit.studio:goto/studio:prompt/studio:submit— openstudio.generateUrl, fillpromptInput, clickgenerateSubmit.studio:artifact— one page evaluation that resolves whenstudio.artifact.expression(a page JavaScript expression) yields anhttp…string: it reads the expression at once and again on every change of the page, so nothing polls and nothing gives up after a fixed time. A studio that never produces the link leaves the run open until the operator stops it. A value that is not an http URL is refused:studio.artifact.expression resolved to <value>, not an http URL.artifact:download— fetch the artifact URL (optionalartifact.downloadHeaders); non-2xx:download failed: HTTP N. The file lands at<outDir>/<slug>.glb(defaultassets/models).blender:postprocess(only whenblender.enabled) — import → runblender.processCode(which seesINPUT_PATHandOUTPUT_PATHas injected globals) → export<name>.processed.glb. See Blender session.verify(unlessverify.enabled: false) — the verification gate withthrowOnFail, run against the processed file when one exists, else the download.
Result: { outPath, processedPath, artifactUrl, prompt, verification }.
Invariants
- The browser session closes in a
finally; a failed job never leaks a browser slot. - Credentials resolve at config load from
role://<role>/<field>through Stado and Skarbiec, or the selected owner-onlyGLINA_CREDENTIALS_FILE. Resolved values remain in memory during a job and are never logged. - The example config (
docs/examples/pipeline.config.example.json) targets Hunyuan3D's studio and requests roletext2game-accountwith fieldslogin_email/login_password; it does not select a vault item by name.