eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
2 lines • 4.33 kB
JavaScript
import{findPackageJSON}from"node:module";import{readFile}from"node:fs/promises";import{dirname,isAbsolute,relative,resolve}from"node:path";import{spawn,spawnSync}from"node:child_process";import{pathToFileURL}from"node:url";const INSTALL_TIMEOUT_MS=6e5;function terminateChildTree(e,t){if(e.pid!==void 0){if(process.platform===`win32`){let n=process.env.SystemRoot??process.env.WINDIR;if(n!==void 0&&n!==``&&spawnSync(resolve(n,`System32`,`taskkill.exe`),[`/pid`,String(e.pid),`/t`,...t===`SIGKILL`?[`/f`]:[]],{stdio:`ignore`,windowsHide:!0}).status===0)return}else try{process.kill(-e.pid,t);return}catch{}}e.kill(t)}function isChildTreeAlive(e){if(process.platform===`win32`||e.pid===void 0)return!1;try{return process.kill(-e.pid,0),!0}catch{return!1}}async function resolveEveExecutable(e){let t=findPackageJSON(`eve`,pathToFileURL(resolve(e,`package.json`)));if(t===void 0)throw Error(`The "eve" package is not installed under ${e}, so registry items cannot be installed from here.`);let n=dirname(t),r=JSON.parse(await readFile(t,`utf8`)),i=typeof r==`object`&&r?r.bin:void 0,a=typeof i==`string`?i:typeof i==`object`&&i?i.eve:void 0;if(typeof a!=`string`||a.length===0)throw Error(`The installed "eve" package does not declare an "eve" binary.`);let o=resolve(n,a),s=relative(n,o);if(s.startsWith(`..`)||isAbsolute(s))throw Error(`The installed "eve" package declares its binary outside the package.`);return o}function readTerminalHeadlessEvent(e){let t;for(let n of e.split(`
`)){let e=n.trim();if(!e.startsWith(`{`))continue;let r;try{r=JSON.parse(e)}catch{continue}if(typeof r!=`object`||!r)continue;let i=r;i.version===1&&(i.type===`completed`||i.type===`blocked`||i.type===`failed`||i.type===`cancelled`||i.type===`external_action`)&&(t=i)}return t}async function runEveAdd(e){let t=await resolveEveExecutable(e.appRoot),n=e.spawn??spawn;return await new Promise(r=>{let i=n(process.execPath,[t,`add`,e.address,`--non-interactive`,`--skip-setup`],{cwd:e.appRoot,detached:process.platform!==`win32`,env:process.env,stdio:[`ignore`,`pipe`,`pipe`]}),a=``,collect=e=>{a=`${a}${String(e)}`.slice(-64e3)};i.stdout?.on(`data`,collect),i.stderr?.on(`data`,collect);let o=!1,s,c,l,finish=t=>{o||(o=!0,clearTimeout(u),c!==void 0&&clearTimeout(c),l!==void 0&&clearTimeout(l),e.signal?.removeEventListener(`abort`,abort),r(t))},finishAfterTreeExits=e=>{if(isChildTreeAlive(i)){l=setTimeout(()=>finishAfterTreeExits(e),25),l.unref?.();return}finish(s??e)},stop=e=>{s===void 0&&(s=e,terminateChildTree(i,`SIGTERM`),c=setTimeout(()=>terminateChildTree(i,`SIGKILL`),5e3),c.unref?.())},abort=()=>{stop({kind:`failed`,message:`Installing ${e.address} was cancelled.`})},u=setTimeout(()=>{stop({kind:`failed`,message:`Installing ${e.address} did not finish within ${INSTALL_TIMEOUT_MS/6e4} minutes.`})},INSTALL_TIMEOUT_MS);u.unref?.(),e.signal?.aborted===!0?abort():e.signal?.addEventListener(`abort`,abort,{once:!0}),i.on(`error`,()=>{stop({kind:`failed`,message:`Could not run \`eve add ${e.address}\`. Run the command in a terminal for details.`})}),i.on(`close`,t=>{let n,r=readTerminalHeadlessEvent(a);if(t===0&&r?.type===`completed`&&r.item===e.address)n={kind:`installed`};else if(r?.type===`blocked`&&r.item===e.address)n={kind:`blocked`,message:`Installing ${e.address} stopped for input that only a terminal can supply.`};else if(r?.type===`failed`&&r.item===e.address&&typeof r.message==`string`){let e=r.failureCode===`pnpm_build_policy`?"Dependency installation stopped because pnpm requires build-script decisions. Run `pnpm approve-builds`, then retry the eve add command.":`Dependency installation failed. Retry the eve add command in a terminal for details.`,t=Array.isArray(r.changed)?r.changed.filter(e=>typeof e==`string`&&e.length<=300&&!e.includes(`..`)&&/^[\w@+./ -]+$/u.test(e)):[],i=r.rolledBack===!0?`${e} Project files were restored.`:t.length===0?`${e} The install may have partially changed the project.`:`${e} The install partially changed: ${t.join(`, `)}. Restore those files, then retry.`;n=t.length===0?{kind:`failed`,message:i}:{kind:`failed`,message:i,changed:t}}else n={kind:`failed`,message:`\`eve add ${e.address}\` failed and may have partially changed the project. Run it in a terminal for details.`};finishAfterTreeExits(n)})})}export{readTerminalHeadlessEvent,resolveEveExecutable,runEveAdd};