import * as fs from "node:fs"; import { safeAgentKey } from "./helpers.ts"; export function monitorKeyForAgent(name:string,runCount:number){return`${safeAgentKey(name)}:${runCount}`;} export function cancelLocalOwnedProcess(input:any){try{void Promise.resolve(input.monitorBridge?.markCancelling(input.monitorKey)).catch(()=>{});}catch{}input.treeKill(input.process);} export async function cancelLocalWaitOnly(input:any){input.abort?.();try{await input.monitorBridge?.cancelWaitOnly(input.monitorKey,input.event);}catch{}} export function linuxProcessIdentity(proc:any){try{if(!Number.isInteger(proc?.pid)||proc.pid<=0)return null;const stat=fs.readFileSync(`/proc/${proc.pid}/stat`,"utf8");const close=stat.lastIndexOf(")");const fields=stat.slice(close+2).trim().split(/\s+/);const starttime=fields[19];return starttime?{pid:proc.pid,starttime}:null;}catch{return null;}} export function createOwnedHandleRegistry(deps:any={}) { const handles=new Map(); const treeKill=deps.treeKill??((proc:any,signal:string)=>deps.signal?.(proc.pid,signal)), wait=deps.wait??(async()=>false), identity=deps.identity??linuxProcessIdentity; const graceMs=deps.graceMs??5000,setTimer=deps.setTimeout??setTimeout,clearTimer=deps.clearTimeout??clearTimeout;const observe=(p:any,exit:any)=>new Promise(resolve=>{let done=false;let timer:any;const finish=(value:boolean)=>{if(done)return;done=true;if(timer!==undefined)clearTimer(timer);resolve(value);};timer=setTimer(()=>finish(false),graceMs);Promise.resolve(wait(p,exit)).then(value=>finish(!!value)).catch(()=>finish(false));});const same=(p:any,expected:any)=>{const current=identity(p);return !!current&¤t.pid===expected.pid&¤t.starttime===expected.starttime;}; return {register(v:any){const processIdentity=identity(v.process);const handle=`${v.profileKey}:${v.taskId}:${v.generation}`;handles.set(handle,{...v,processIdentity,cancelPromise:null});return handle},cancel(r:any){const v=handles.get(r.handle);if(!v)return Promise.resolve({cancelled:false,reason:"unauthorized"});if(v.profileKey!==r.profileKey||v.token!==r.token||v.taskId!==r.taskId)return Promise.resolve({cancelled:false,reason:"unauthorized"});if(v.generation!==r.generation)return Promise.resolve({cancelled:false,reason:"stale_generation"});if(v.cancelPromise)return v.cancelPromise;v.cancelPromise=(async()=>{const proc=v.process;if(!v.processIdentity||!same(proc,v.processIdentity))return{cancelled:false,reason:"stale_identity"};treeKill(proc,"SIGTERM");if(await observe(proc,v.exitPromise)){handles.delete(r.handle);return{cancelled:true,state:"cancelled"};}if(!same(proc,v.processIdentity))return{cancelled:false,reason:"stale_identity"};treeKill(proc,"SIGKILL");if(!(await observe(proc,v.exitPromise)))return{cancelled:false,reason:"exit_not_observed"};handles.delete(r.handle);return{cancelled:true,state:"cancelled"};})();return v.cancelPromise;}} } export function recordWaitOnlyCancellation(r:any){return{state:"cancelled",history:r.lateEvent?[r.lateEvent]:[]}}