Files
probably-rendering-one-more…/scripts/save-studio-series.mjs
codex-bot 04df551f6a
studio CI and deployment / verify-and-deploy (pull_request) Successful in 6m43s
waterfall-wiki CI and deployment / verify-and-deploy (pull_request) Has been cancelled
Harden series validation and synchronize agent delivery contracts
2026-10-28 23:42:18 +08:00

18 lines
2.5 KiB
JavaScript

/** Invoke via the deployed auth-cli run on ces-control; authorization stays in memory. */
import {readFile,writeFile,mkdir} from 'node:fs/promises';
import {resolve} from 'node:path';
const [input,image,provenance,out]=process.argv.slice(4); // auth-cli.cjs run SCRIPT ARGS
if(!input||!image||!provenance||!out)throw Error('Supply input.json image.png provenance.json output-directory');
const dir=resolve(out);await mkdir(dir,{recursive:true});
const statePath=dir+'/save-state.json';let state={};try{state=JSON.parse(await readFile(statePath,'utf8'))}catch(e){if(e.code!=='ENOENT')throw e}
const base='http://8.211.154.134:18131';
if(state.designId){const r=await fetch(base+'/api/studio/series/'+state.designId);if(!r.ok)throw Error('Saved state cannot be verified');const result=await r.json();await writeFile(dir+'/design.json',JSON.stringify(result.design,null,2));console.log(JSON.stringify({existing:true,id:state.designId,url:base+result.design.url}));process.exit(0)}
// An in-flight operation is deliberately not retried: reconcile uncertain outcomes through the API.
if(state.pending)throw Error('Previous request outcome unknown; reconcile '+state.pending+' before retrying');
const save=()=>writeFile(statePath,JSON.stringify(state,null,2));
if(!state.assetId){state.pending='upload';await save();const form=new FormData();form.set('kind','image');form.set('assetOnly','true');form.append('files',new Blob([await readFile(image)],{type:'image/png'}),'ginkgo-master.png');const r=await fetch(base+'/api/upload',{method:'POST',body:form});if(!r.ok)throw Error('Upload failed: '+r.status);const uploaded=await r.json();state.assetId=uploaded.assets[0];delete state.pending;await save()}
const body=JSON.parse(await readFile(input,'utf8')),source=JSON.parse(await readFile(provenance,'utf8'));
body.document.sources=[{...source,assetId:state.assetId}];for(const page of body.document.pages)page.parameters.images.I01={...page.parameters.images.I01,assetId:state.assetId};
await writeFile(dir+'/series-request.json',JSON.stringify(body,null,2));state.pending='create';await save();
const r=await fetch(base+'/api/studio/series',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)});if(!r.ok)throw Error('Create failed: '+r.status+' '+await r.text());const {design}=await r.json();state.designId=design.id;delete state.pending;await save();await writeFile(dir+'/design.json',JSON.stringify(design,null,2));console.log(JSON.stringify({id:design.id,url:base+design.url,revision:design.revision,pages:design.document.pages.length}));