eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
2 lines • 3.22 kB
JavaScript
import{Readable}from"node:stream";import{spawn,spawnSync}from"node:child_process";var DockerUnavailableError=class extends Error{hint="Install and start Docker Desktop, OrbStack, Colima, or another runtime exposing a Docker-compatible `docker` CLI (or point EVE_DOCKER_PATH at one, e.g. Podman). Alternatively use microsandbox(), the dependency-free justbash(), vercel(), or defaultSandbox() to pick by availability.";constructor(e){super("The Docker sandbox backend requires Docker, but the `docker` CLI was not found.",{cause:e}),this.name=`DockerUnavailableError`}},DockerDaemonUnavailableError=class extends Error{hint="Start Docker Desktop (or your Docker-compatible runtime) and retry. Alternatively use microsandbox(), the dependency-free justbash() (installed automatically by `eve dev`, or `pnpm add -D just-bash`), vercel(), or defaultSandbox() to pick by availability.";constructor(e){super(`The Docker sandbox backend requires a running Docker daemon, but it is not reachable. Docker reported: ${e}`),this.name=`DockerDaemonUnavailableError`}};async function assertDockerDaemonAvailable(e){let t=await e.run([`version`,`--format`,`{{.Server.Version}}`]);if(t.exitCode!==0)throw new DockerDaemonUnavailableError(firstLine(t.stderr)||`exit ${t.exitCode}`)}function resolveDockerExecutable(){let e=process.env.EVE_DOCKER_PATH?.trim();return e!==void 0&&e.length>0?e:`docker`}let cachedLinuxDockerAvailability;function isLinuxDockerDaemonAvailableSync(){return cachedLinuxDockerAvailability??=probeLinuxDockerDaemonSync(),cachedLinuxDockerAvailability}function probeLinuxDockerDaemonSync(){try{let e=spawnSync(resolveDockerExecutable(),[`version`,`--format`,`{{.Server.Os}}`],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`],timeout:5e3});return e.status===0&&e.stdout.trim().toLowerCase()===`linux`}catch{return!1}}function createDockerCli(){return{async run(e,t={}){throwIfAborted(t.signal);let n=spawn(resolveDockerExecutable(),e,{signal:t.signal,stdio:[t.stdin===void 0?`ignore`:`pipe`,`pipe`,`pipe`]}),r=[],i=[];n.stdout?.on(`data`,e=>r.push(e)),n.stderr?.on(`data`,e=>i.push(e)),t.stdin!==void 0&&n.stdin?.end(t.stdin);let a=await new Promise((e,t)=>{n.on(`error`,e=>t(adaptSpawnError(e))),n.on(`close`,t=>e(t??1))}),o=Buffer.concat(r);return{exitCode:a,stderr:Buffer.concat(i).toString(`utf8`),stdout:o.toString(`utf8`),stdoutBytes:o}},stream(e,t={}){throwIfAborted(t.signal);let n=spawn(resolveDockerExecutable(),e,{signal:t.signal,stdio:[`ignore`,`pipe`,`pipe`]}),r=new Promise((e,t)=>{n.on(`error`,e=>t(adaptSpawnError(e))),n.on(`close`,t=>e(t??1))});return r.catch(()=>{}),{stdout:Readable.toWeb(n.stdout),stderr:Readable.toWeb(n.stderr),async wait(){return{exitCode:await r}},async kill(){n.kill(`SIGKILL`),await r.catch(()=>{})}}}}}function adaptSpawnError(e){return e.code===`ENOENT`?new DockerUnavailableError(e):e.code===`ABORT_ERR`?new DOMException(`The operation was aborted.`,`AbortError`):e}function throwIfAborted(e){if(e?.aborted)throw new DOMException(`The operation was aborted.`,`AbortError`)}function firstLine(e){return e.split(`
`,1)[0]?.trim()??``}export{DockerDaemonUnavailableError,DockerUnavailableError,assertDockerDaemonAvailable,createDockerCli,isLinuxDockerDaemonAvailableSync};