UNPKG

eve

Version:

Filesystem-first framework for durable backend AI agents that run anywhere.

1 lines 5.18 kB
import{randomUUID}from"node:crypto";import{expectDockerSuccess}from"#execution/sandbox/bindings/docker-utils.js";import{markDevelopmentSandboxBackendInitialized}from"#execution/sandbox/development-run.js";import{writeSandboxSeedFiles}from"#execution/sandbox/bindings/local-backend-utils.js";import{assertDockerDaemonAvailable,createDockerCli}from"#execution/sandbox/bindings/docker-cli.js";import{DOCKER_SANDBOX_LABEL,runDockerBaseSetup,startDockerContainer}from"#execution/sandbox/bindings/docker-container.js";import{setDockerNetworkPolicy}from"#execution/sandbox/bindings/docker-network.js";import{createDockerSandboxOptionsHash,resolveDockerSandboxOptions}from"#execution/sandbox/bindings/docker-options.js";import{createDockerInternalSession}from"#execution/sandbox/bindings/docker-session.js";import{DOCKER_TEMPLATE_IMAGE_REPOSITORY,dockerImageExists,dockerTemplateImageReference,ensureDockerBaseImage,pruneDockerSandboxTemplates,resolveDockerTemplateMarkerPath,touchDockerTemplateMarker}from"#execution/sandbox/bindings/docker-templates.js";import{createLoggingSandboxSession}from"#execution/sandbox/logging-session.js";import{buildSandboxSession}from"#execution/sandbox/session.js";import{SandboxTemplateNotProvisionedError}from"#public/definitions/sandbox-backend.js";const DOCKER_BACKEND_NAME=`docker`;function createDockerSandboxBackend(c={}){let l=c.dockerCli??createDockerCli(),u=resolveDockerSandboxOptions(c.createOptions),d=createDockerSandboxOptionsHash(u),f;function ensureDaemon(){return f??=assertDockerDaemonAvailable(l).catch(e=>{throw f=void 0,e}),f}return{name:DOCKER_BACKEND_NAME,async prewarm(n){n.log?.(`checking Docker daemon`),await ensureDaemon();let i={optionsHash:d,templateKey:n.templateKey},a=dockerTemplateImageReference(i),o=resolveDockerTemplateMarkerPath(n.runtimeContext.appRoot,i);if(n.log?.(`checking cached template image "${a}"`),await dockerImageExists(l,a))return n.log?.(`reusing cached template image`),await touchDockerTemplateMarker(o,a),{reused:!0};n.log?.(`checking base image "${u.image}"`),await ensureDockerBaseImage(l,u);let s=`${n.templateKey}-build-${randomUUID().slice(0,8)}`;n.log?.(`starting template build container`),await startDockerContainer({cli:l,containerName:s,image:u.image,initialNetworkPolicy:`allow-all`,options:u,role:`template-build`});try{n.log?.(`preparing base runtime inside container`),await runDockerBaseSetup(l,s),u.networkPolicy!==`allow-all`&&(n.log?.(`applying network policy`),await setDockerNetworkPolicy(l,s,u.networkPolicy));let e=buildSandboxSession(createDockerInternalSession({cli:l,containerName:s,id:n.templateKey}),e=>setDockerNetworkPolicy(l,s,e));n.bootstrap!==void 0&&(n.log?.(`running sandbox bootstrap`),await n.bootstrap({use:async()=>createLoggingSandboxSession({log:n.log,session:e})})),n.seedFiles.length>0&&n.log?.(`writing ${n.seedFiles.length} seed file(s)`),await writeSandboxSeedFiles(e,n.seedFiles),n.log?.(`stopping template build container`),expectDockerSuccess(await l.run([`stop`,`-t`,`0`,s]),`stop template build container "${s}"`),n.log?.(`committing template image "${a}"`),expectDockerSuccess(await l.run([`commit`,`--change`,`LABEL ${DOCKER_SANDBOX_LABEL}=1`,`--change`,`LABEL ${DOCKER_SANDBOX_LABEL}.role=template`,`--change`,`LABEL ${DOCKER_SANDBOX_LABEL}.template-key=${n.templateKey}`,s,a]),`commit sandbox template image "${a}"`),await touchDockerTemplateMarker(o,a)}finally{await l.run([`rm`,`-f`,s]).catch(()=>{})}return{reused:!1}},async create(e){await ensureDaemon(),markDevelopmentSandboxBackendInitialized(DOCKER_BACKEND_NAME);let r=getDockerContainerName(e.existingMetadata)??e.sessionKey,i=await l.run([`container`,`inspect`,`--format`,`{{.State.Running}}`,r]);if(i.exitCode===0)i.stdout.trim()!==`true`&&expectDockerSuccess(await l.run([`start`,r]),`restart sandbox session container "${r}"`);else{let t;if(e.templateKey===null)await ensureDockerBaseImage(l,u),t=u.image;else{let n={optionsHash:d,templateKey:e.templateKey};if(t=dockerTemplateImageReference(n),!await dockerImageExists(l,t))throw new SandboxTemplateNotProvisionedError({backendName:DOCKER_BACKEND_NAME,templateKey:e.templateKey});await touchDockerTemplateMarker(resolveDockerTemplateMarkerPath(e.runtimeContext.appRoot,n),t)}try{await startDockerContainer({cli:l,containerName:r,image:t,initialNetworkPolicy:e.templateKey===null?`allow-all`:u.networkPolicy,options:u,role:`session`,tags:e.tags})}catch(t){throw e.templateKey===null?t:new SandboxTemplateNotProvisionedError({backendName:DOCKER_BACKEND_NAME,templateKey:e.templateKey})}e.templateKey===null&&(await runDockerBaseSetup(l,r),u.networkPolicy!==`allow-all`&&await setDockerNetworkPolicy(l,r,u.networkPolicy))}let a=buildSandboxSession(createDockerInternalSession({cli:l,containerName:r,id:e.sessionKey}),e=>setDockerNetworkPolicy(l,r,e));return{session:a,useSessionFn:async()=>a,async captureState(){return{backendName:DOCKER_BACKEND_NAME,metadata:{containerName:r},sessionKey:e.sessionKey}},async dispose(){}}}}}function getDockerContainerName(e){let t=e?.containerName;return typeof t==`string`?t:void 0}export{DOCKER_BACKEND_NAME,DOCKER_TEMPLATE_IMAGE_REPOSITORY,createDockerSandboxBackend,pruneDockerSandboxTemplates};