eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
1 lines • 6.63 kB
JavaScript
import{randomUUID}from"node:crypto";import{mkdir,rename,rm}from"node:fs/promises";import{dirname}from"node:path";import{withDevelopmentSandboxMetadataPathTag}from"#execution/sandbox/development-run.js";import{resolveSandboxCacheDirectory}from"#internal/application/paths.js";import{createFileBackedInternalSandboxSession,touchDirectory,writeSandboxSeedFiles}from"#execution/sandbox/bindings/local-backend-utils.js";import{createLoggingSandboxSession}from"#execution/sandbox/logging-session.js";import{buildSandboxSession}from"#execution/sandbox/session.js";import{SandboxTemplateNotProvisionedError}from"#public/definitions/sandbox-backend.js";import{MICROSANDBOX_METADATA_VERSION,readSessionMetadata,readSessionMetadataRecord,readTemplateMetadata,resolveMicrosandboxMetadataPath,writeTemplateMetadata}from"#execution/sandbox/bindings/microsandbox-metadata.js";import{connectMicrosandbox,createPreparedMicrosandbox,createProviderName,doesPathExist,isMicrosandboxNotFoundError,loadMicrosandboxModule,removeSnapshotIfExists,sandboxExists,snapshotExists}from"#execution/sandbox/bindings/microsandbox-runtime.js";import{resolveMicrosandboxSessionRootPath,resolveMicrosandboxTemplateRootPath}from"#execution/sandbox/bindings/microsandbox-templates.js";const activeMicrosandboxSessionHandles=new Map;async function prewarmMicrosandboxTemplate(e){e.prewarmInput.log?.(`loading microsandbox runtime`);let t=await loadMicrosandboxModule({appRoot:e.prewarmInput.runtimeContext.appRoot,log:e.prewarmInput.log,options:e.options}),n=resolveSandboxCacheDirectory(e.prewarmInput.runtimeContext.appRoot),r=resolveMicrosandboxTemplateRootPath(n,e.prewarmInput.templateKey),i=resolveMicrosandboxMetadataPath(r);e.prewarmInput.log?.(`checking cached snapshot`);let a=await readTemplateMetadata(i);if(a?.optionsHash===e.optionsHash&&await snapshotExists(t,a.snapshotName))return e.prewarmInput.log?.(`reusing cached snapshot`),await touchDirectory(r),{reused:!0};let o=createProviderName(`eve-sbx-tpl`,e.prewarmInput.templateKey,e.optionsHash),s=`${r}.${randomUUID()}.tmp`,c=createProviderName(`eve-sbx-tpl-tmp`,`${e.prewarmInput.templateKey}:${randomUUID()}`);await removeSnapshotIfExists(t,o),await rm(s,{force:!0,recursive:!0}),await mkdir(s,{recursive:!0}),e.prewarmInput.log?.(`creating template VM from image "${e.options.image}"`);let l=await createPreparedMicrosandbox({log:e.prewarmInput.log,module:t,name:c,networkPolicy:e.options.networkPolicy,options:e.options,sessionKey:e.prewarmInput.templateKey,setupBaseRuntime:!0,tags:void 0}),u=buildSandboxSession(createMicrosandboxInternalSession(l),async e=>{await l.setNetworkPolicy(e)});try{e.prewarmInput.seedFiles.length>0&&e.prewarmInput.log?.(`writing ${e.prewarmInput.seedFiles.length} seed file(s)`),await writeSandboxSeedFiles(u,e.prewarmInput.seedFiles),e.prewarmInput.bootstrap!==void 0&&(e.prewarmInput.log?.(`running sandbox bootstrap`),await e.prewarmInput.bootstrap({use:async t=>(t?.networkPolicy!==void 0&&await l.setNetworkPolicy(t.networkPolicy),createLoggingSandboxSession({log:e.prewarmInput.log,session:u}))})),e.prewarmInput.log?.(`snapshotting template VM`),await l.stopAndSnapshot(o),await writeTemplateMetadata(resolveMicrosandboxMetadataPath(s),{optionsHash:e.optionsHash,snapshotName:o,version:MICROSANDBOX_METADATA_VERSION}),await mkdir(dirname(r),{recursive:!0}),await rm(r,{force:!0,recursive:!0});try{await rename(s,r)}catch(e){if(await doesPathExist(r))return{reused:!0};throw e}}finally{await l.removePersisted(),await rm(s,{force:!0,recursive:!0}).catch(()=>{})}return{reused:!1}}async function createMicrosandboxHandle(e){let t=await loadMicrosandboxModule({appRoot:e.createInput.runtimeContext.appRoot,options:e.options}),n=resolveSandboxCacheDirectory(e.createInput.runtimeContext.appRoot),r=resolveMicrosandboxSessionRootPath(n,e.createInput.sessionKey),i=createActiveMicrosandboxSessionKey(r,e.optionsHash),a=activeMicrosandboxSessionHandles.get(i);if(a!==void 0)return a;let o=resolveMicrosandboxMetadataPath(r),s=readSessionMetadataRecord(e.createInput.existingMetadata)??await readSessionMetadata(o),c=withDevelopmentSandboxMetadataPathTag(e.createInput.tags,o);if(s?.optionsHash===e.optionsHash&&(await sandboxExists(t,s.sandboxName)||s.stateSnapshotName!==void 0&&await snapshotExists(t,s.stateSnapshotName))){let n=await connectMicrosandbox({metadata:s,metadataPath:o,module:t,options:e.options,sessionKey:e.createInput.sessionKey,tags:c});if(n!==null)return cacheHandle(i,createHandle(n,e.backendName,e.optionsHash,()=>{activeMicrosandboxSessionHandles.delete(i)}))}let l=null;if(e.createInput.templateKey!==null){let r=resolveMicrosandboxTemplateRootPath(n,e.createInput.templateKey),i=await readTemplateMetadata(resolveMicrosandboxMetadataPath(r));if(i===null||i.optionsHash!==e.optionsHash||!await snapshotExists(t,i.snapshotName))throw new SandboxTemplateNotProvisionedError({backendName:e.backendName,templateKey:e.createInput.templateKey});l=i.snapshotName}let u=createProviderName(`eve-sbx-ses`,`${e.createInput.sessionKey}:${randomUUID()}`),d;try{d=await createPreparedMicrosandbox({fromSnapshot:l??void 0,module:t,name:u,networkPolicy:e.options.networkPolicy,options:e.options,sessionKey:e.createInput.sessionKey,setupBaseRuntime:l===null,tags:c})}catch(t){throw l!==null&&e.createInput.templateKey!==null&&isMicrosandboxNotFoundError(t)?new SandboxTemplateNotProvisionedError({backendName:e.backendName,templateKey:e.createInput.templateKey}):t}return await d.writeMetadata(o,e.optionsHash),cacheHandle(i,createHandle(d,e.backendName,e.optionsHash,()=>{activeMicrosandboxSessionHandles.delete(i)}))}function createHandle(e,t,n,r){return{session:buildSandboxSession(createMicrosandboxInternalSession(e),async t=>{await e.setNetworkPolicy(t)}),useSessionFn:async t=>(t?.networkPolicy!==void 0&&await e.setNetworkPolicy(t.networkPolicy),buildSandboxSession(createMicrosandboxInternalSession(e),async t=>{await e.setNetworkPolicy(t)})),async captureState(){return{backendName:t,metadata:{...await e.captureState(n)},sessionKey:e.id}},async delete(){await e.shutdown(),await e.removePersisted(),r?.()},async stop(){await e.stop(),r?.()},async shutdown(){r?.(),await e.shutdown()}}}function createMicrosandboxInternalSession(e){return createFileBackedInternalSandboxSession({id:e.id,sandbox:e})}function createActiveMicrosandboxSessionKey(e,t){return`${e}\0${t}`}function cacheHandle(e,t){return activeMicrosandboxSessionHandles.set(e,t),t}function clearActiveMicrosandboxSessionHandlesForTest(){activeMicrosandboxSessionHandles.clear()}export{clearActiveMicrosandboxSessionHandlesForTest,createMicrosandboxHandle,prewarmMicrosandboxTemplate};