Files
ARCADIA-Studio/harness/experiments/state-bends-b868541-20260923/native/capture.js
T

34 lines
2.3 KiB
JavaScript

// Evidence serialization only. Root supplies a freshly observed Sky state.
globalThis.captureStateBends = async function(name, note, currentState) {
if (!/^[a-zA-Z0-9_-]+$/.test(name)) throw Error('Invalid capture name');
if (!currentState?.screenshots?.length) throw Error('Fresh screenshot required');
const {fileURLToPath} = await import('node:url');
const root = fileURLToPath(new URL('.', import.meta.url)).replaceAll('\\','/').replace(/\/$/,'');
const run = globalThis.stateBendsRunRoot;
if (!run || !run.startsWith(root+'/runs/run-')) throw Error('Bind current run first');
const file = await import('node:fs/promises');
const crypto = await import('node:crypto');
const hash = bytes => crypto.createHash('sha256').update(bytes).digest('hex');
const launchBytes = await file.readFile(run+'/launch.json');
const launch = JSON.parse(launchBytes.toString('utf8').replace(/^\uFEFF/,''));
const manifestBytes = await file.readFile(root+'/input-manifest.json');
if (hash(manifestBytes) !== launch.manifest_sha256) throw Error('Manifest changed');
const working = await file.readFile(root+'/working/attachments.arcadia');
const dir = run+'/captures';
await file.mkdir(dir,{recursive:true});
const images=[];
for (let i=0;i<currentState.screenshots.length;i++) {
const s=currentState.screenshots[i];
const mime=s.url.slice(5,s.url.indexOf(';'));
if (!['image/jpeg','image/png'].includes(mime)) throw Error('Unexpected image type');
const bytes=Buffer.from(s.url.split(',')[1],'base64');
const filename=name+(i ? '-'+i : '')+(mime==='image/jpeg'?'.jpg':'.png');
await file.writeFile(dir+'/'+filename,bytes,{flag:'wx'});
images.push({file:filename,id:s.id,width:s.width,height:s.height,originX:s.originX,originY:s.originY,zIndex:s.zIndex,mime,bytes:bytes.length,sha256:hash(bytes)});
}
const record={utc:new Date().toISOString(),source_commit:launch.source_commit,launch_sha256:hash(launchBytes),pid:launch.pid,process_started_utc:launch.started_utc,manifest_sha256:launch.manifest_sha256,window:currentState.window,images,working_source_sha256:hash(working),note};
await file.writeFile(dir+'/'+name+'.json',JSON.stringify(record,null,2)+'\n',{flag:'wx'});
return {name,images:images.length,source_commit:record.source_commit};
};