mirror of
https://github.com/wassname/pi-goals.git
synced 2026-09-20 13:10:47 +08:00
29 lines
1.6 KiB
JavaScript
29 lines
1.6 KiB
JavaScript
// Event-driven trial observer. Reads only child panes named by this trial's launch trace.
|
|
import {existsSync,readFileSync,writeFileSync,watch} from 'node:fs';
|
|
import {execFile} from 'node:child_process';
|
|
import {join} from 'node:path';
|
|
const root=process.argv[2];if(!root)throw new Error('trial root required');
|
|
const trace=join(root,'launch.jsonl');if(!existsSync(trace))writeFileSync(trace,'');
|
|
const seen=new Set();const watchers=[];let count=0;
|
|
const shutdown=()=>{for(const w of watchers)w.close();process.exit(count?0:1);};
|
|
const deadline=setTimeout(shutdown,600000);
|
|
function observe(){
|
|
for(const line of readFileSync(trace,'utf8').trim().split('\n')){
|
|
let row;try{row=JSON.parse(line);}catch{continue;}
|
|
if(!['interactive.send','interactive.watch.start'].includes(row.event)||!row.sessionFile?.startsWith(root+'/agent/sessions/')||!row.surface)continue;
|
|
const pane=row.surface.replace(/^herdr:/,'');
|
|
if(seen.has(pane))continue;
|
|
seen.add(pane);
|
|
// Herdr IDs are opaque (p1A is valid); use the trace value, not a numeric-ID assumption.
|
|
row.id = row.id ?? pane.replaceAll(':','-');
|
|
// Capture once Pi renders its model/footer, without sending input or taking focus.
|
|
execFile('herdr',['pane','wait-output',pane,'--regex','gpt-|Claude|Gemini','--timeout','45000','--lines','120'],{maxBuffer:1024*1024},(error,stdout,stderr)=>{
|
|
writeFileSync(join(root,`worker-${row.id}-pane.txt`),stdout+stderr);
|
|
console.log(JSON.stringify({event:'worker-pane-captured',id:row.id,pane,ok:!error,path:join(root,`worker-${row.id}-pane.txt`)}));
|
|
count++;
|
|
if(count>=2){clearTimeout(deadline);shutdown();}
|
|
});
|
|
}
|
|
}
|
|
watchers.push(watch(trace,observe));observe();
|