eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
3 lines • 6.16 kB
JavaScript
import{dirname,join,relative}from"node:path";import{cp,mkdir,readdir,rename,writeFile}from"node:fs/promises";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"#discover/filesystem.js";import{bundleExtensionDistributionGraph}from"#internal/authored-module-loader.js";import{EXTENSION_COMPATIBILITY_MANIFEST_FILENAME}from"#compiler/extension-compatibility.js";import{emitExtensionDeclarations}from"#internal/nitro/host/extension-declarations.js";async function emitExtensionDistribution(a){let o=await collectExtensionSourceFiles(a.sourceRoot),s=a.manifest.skills.filter(e=>e.sourceKind===`skill-package`).map(e=>relative(a.sourceRoot,e.rootPath).replaceAll(`\\`,`/`)),c=o.filter(e=>isAuthoredModule(e.logicalPath)&&!s.some(t=>e.logicalPath.startsWith(`${t}/`)));await copyDistributionDataFiles({files:o,moduleLogicalPaths:new Set(c.map(e=>e.logicalPath)),stagedDistRoot:a.stagedDistRoot});let l=await bundleExtensionDistributionGraph({entries:await createDistributionEntries({...a,moduleFiles:c}),packageRoot:a.appRoot,runtimeDependencies:a.runtimeDependencies});for(let[n,r]of l){let o=join(a.stagedOutDir,n);await mkdir(dirname(o),{recursive:!0}),await writeFile(o,r,`utf8`)}await emitExtensionDeclarations({appRoot:a.appRoot,declarationsRoot:a.declarationsRoot,moduleLogicalPaths:c.map(e=>e.logicalPath),sourceRoot:a.sourceRoot});let u=relative(a.appRoot,a.sourceRoot);try{await cp(join(a.declarationsRoot,u),a.stagedDistRoot,{recursive:!0})}catch(e){throw isFileSystemError(e,`ENOENT`)?Error(`TypeScript emitted no declarations for "${u}". Ensure the package tsconfig.json \`include\` covers every module under \`eve.extension.source\`.`,{cause:e}):e}await emitDeclarationBarrels(a)}var ExtensionOutputRestoreError=class extends Error{preservedOutputPath;constructor(e,t){super(`Publishing the extension build output failed, and the previous output could not be restored. It is preserved at "${e}".`,t),this.name=`ExtensionOutputRestoreError`,this.preservedOutputPath=e}};async function replaceExtensionBuildOutput(n){await mkdir(dirname(n.outDir),{recursive:!0});let r=join(n.transactionRoot,`previous-output`),a=!1;try{await rename(n.outDir,r),a=!0}catch(e){if(!isFileSystemError(e,`ENOENT`))throw e}try{await rename(n.stagedOutDir,n.outDir)}catch(e){if(a)try{await rename(r,n.outDir)}catch{throw new ExtensionOutputRestoreError(r,{cause:e})}throw e}}async function collectExtensionSourceFiles(e,r=e){let i=[];for(let o of await readdir(r,{withFileTypes:!0})){let a=join(r,o.name);if(o.isDirectory())i.push(...await collectExtensionSourceFiles(e,a));else if(o.isFile()){let t=relative(e,a).replaceAll(`\\`,`/`);if(t===EXTENSION_COMPATIBILITY_MANIFEST_FILENAME)throw Error(`The extension source cannot contain "${EXTENSION_COMPATIBILITY_MANIFEST_FILENAME}"; eve reserves it for generated compatibility metadata.`);i.push({absolutePath:a,logicalPath:t})}else throw Error(`Extension source entry "${a}" must be a regular file or directory.`)}return i.sort((e,t)=>e.logicalPath.localeCompare(t.logicalPath))}function isAuthoredModule(e){return!/\.d\.[cm]?ts$/.test(e)&&SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS.some(t=>e.endsWith(t))}async function copyDistributionDataFiles(n){await Promise.all(n.files.filter(e=>!n.moduleLogicalPaths.has(e.logicalPath)).map(async a=>{let o=join(n.stagedDistRoot,a.logicalPath);await mkdir(dirname(o),{recursive:!0}),await cp(a.absolutePath,o)}))}async function createDistributionEntries(e){let r=relative(e.stagedOutDir,e.stagedDistRoot).replaceAll(`\\`,`/`),i=e.moduleFiles.map(e=>({name:`${r}/${stripAuthoredModuleExtension(e.logicalPath)}`,path:e.absolutePath})),a=new Set;for(let e of i){if(a.has(e.name))throw Error(`Multiple extension modules emit the same path "${e.name}.mjs".`);a.add(e.name)}let o=join(e.transactionRoot,`barrels`);return i.push(await stageRuntimeBarrel({barrelPath:join(o,`index.mjs`),name:`index`,reexports:[{name:`default`,path:join(e.sourceRoot,e.declarationModule.logicalPath)},{name:e.shortName,path:join(e.sourceRoot,e.declarationModule.logicalPath)}]}),await stageRuntimeBarrel({barrelPath:join(o,`tools.mjs`),name:`tools/index`,reexports:e.manifest.tools.map(n=>({name:toolExportName(n.logicalPath),path:join(e.sourceRoot,n.logicalPath)}))})),i}async function stageRuntimeBarrel(t){await mkdir(dirname(t.barrelPath),{recursive:!0});let n=t.reexports.map(n=>reexportLine(n.name,relativeImport(dirname(t.barrelPath),n.path)));return await writeFile(t.barrelPath,`${n.join(`
`)}\n`,`utf8`),{name:t.name,path:t.barrelPath}}async function emitDeclarationBarrels(e){await mkdir(join(e.stagedOutDir,`tools`),{recursive:!0});let n=relativeImport(e.stagedOutDir,join(e.stagedDistRoot,e.declarationModule.logicalPath));await writeDeclarationBarrel({path:join(e.stagedOutDir,`index.d.ts`),reexports:[{name:`default`,specifier:n},{name:e.shortName,specifier:n}]}),await writeDeclarationBarrel({path:join(e.stagedOutDir,`tools`,`index.d.ts`),reexports:e.manifest.tools.map(n=>({name:toolExportName(n.logicalPath),specifier:relativeImport(join(e.stagedOutDir,`tools`),join(e.stagedDistRoot,n.logicalPath))}))})}async function writeDeclarationBarrel(e){let t=e.reexports.map(e=>reexportLine(e.name,toDeclarationSpecifier(e.specifier)));await writeFile(e.path,[`// Generated by eve. Do not edit by hand.`,``,...t,``].join(`
`),`utf8`)}function stripAuthoredModuleExtension(e){for(let t of SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS)if(e.endsWith(t))return e.slice(0,e.length-t.length);return e}function toolExportName(e){let t=stripAuthoredModuleExtension(e).replace(/^tools\//,``).replace(/[^A-Za-z0-9_$]/g,`_`);return/^[A-Za-z_$]/.test(t)?t:`_${t}`}function relativeImport(e,t){let r=relative(e,t).replaceAll(`\\`,`/`);return r.startsWith(`.`)?r:`./${r}`}function reexportLine(e,t){return e==="default"?`export { default } from ${JSON.stringify(t)};`:`export { default as ${e} } from ${JSON.stringify(t)};`}function toDeclarationSpecifier(e){return e.replace(/\.mts$/,`.mjs`).replace(/\.cts$/,`.cjs`).replace(/\.tsx?$/,`.js`)}function isFileSystemError(e,t){return e instanceof Error&&`code`in e&&e.code===t}export{ExtensionOutputRestoreError,emitExtensionDistribution,replaceExtensionBuildOutput};