eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
2 lines • 7.32 kB
JavaScript
import{createRegistrySession}from"./registry-session.js";import{PlannerNavigationError}from"#setup/prompter.js";import{WizardCancelledError}from"#setup/step.js";import{HumanActionRequiredError}from"#setup/human-action.js";import{withSpinner}from"#setup/with-spinner.js";const PLANNER_STEPS=[`Channels`,`Integrations`,`Review`];var RegistryFlowFailedError=class extends Error{completed;constructor(e,t){super(e instanceof Error?e.message:String(e),{cause:e}),this.name=`RegistryFlowFailedError`,this.completed=t}};const SECTIONS={channels:{title:`Where should people reach your agent?`,description:`You can add more later with /add.`,featured:[`channel/web`,`channel/slack`,`channel/github`,`channel/linear-agent`,`channel/photon-imessage`],includes:e=>e.name.startsWith(`channel/`)},integrations:{title:`What should your agent be able to work with?`,featured:[`extension/github-tools`,`connection/linear`,`connection/notion`,`connection/vercel`,`extension/agent-browser`,`experimental/self-modification`],includes:e=>!e.name.startsWith(`channel/`)}};function label(e){return e.title??e.name.split(`/`).at(-1)??e.name}function isPlannerItem(e,t){return t.name.includes(`/`)&&SECTIONS[e].includes(t)}function orderedSectionItems(e,t){let n=t.filter(t=>isPlannerItem(e,t)),r=SECTIONS[e].featured.map(e=>n.find(t=>t.name===e)).filter(e=>e!==void 0),i=new Set(r.map(e=>e.address));return[...r,...n.filter(e=>!i.has(e.address))]}function plannerLabel(e){return e.name===`connection/linear`?`Linear MCP`:label(e)}function sectionRows(e,t){return orderedSectionItems(e,t).map(e=>({value:e.address,label:plannerLabel(e),hint:e.description}))}function selectedInSection(e,t,n){return t.filter(t=>isPlannerItem(e,t)&&n.has(t.address)).map(e=>e.address)}function plannerNavigation(e,t){let n=(t.plannerContext?.prefixSteps??[]).map(e=>({label:e.label,complete:e.complete}));return{kind:`planner`,activeStep:n.length+e,firstNavigableStep:n.length,steps:[...n,...PLANNER_STEPS.map((e,n)=>{if(n===2)return{label:e};let r=selectedInSection(n===0?`channels`:`integrations`,t.catalog,t.selected).length;return r===0?{label:e}:{label:e,count:r}})]}}function replaceSectionSelection(e){for(let t of e.catalog)isPlannerItem(e.section,t)&&e.selected.delete(t.address);for(let t of e.addresses)e.selected.add(t)}async function editSection(e){let{section:t,catalog:n,prompter:r,selected:i}=e,a={message:SECTIONS[t].title,multiple:!0,search:!0,placeholder:t===`channels`?`Search channels`:`Search integrations`,navigation:plannerNavigation(t===`channels`?0:1,e),initialValues:selectedInSection(t,n,i),options:sectionRows(t,n)};t===`channels`&&(a.description=SECTIONS.channels.description),e.notices!==void 0&&(a.notices=e.notices);try{return replaceSectionSelection({section:t,catalog:n,selected:i,addresses:await r.select(a)}),`forward`}catch(e){if(!(e instanceof PlannerNavigationError))throw e;return replaceSectionSelection({section:t,catalog:n,selected:i,addresses:e.values.map(e=>{if(typeof e!=`string`)throw Error(`Registry planner returned a non-string item.`);return e})}),e.direction}}async function editPlan(e){let t=`channels`,n=e.notices;for(;;){if(t!==`review`){e.onScreen?.({screen:t===`channels`?`registry_channels`:`registry_integrations`});try{let r=await editSection({...e,section:t,notices:n});n=void 0,r===`back`?t===`integrations`&&(t=`channels`):t=t===`channels`?`integrations`:`review`}catch(e){if(!(e instanceof WizardCancelledError))throw e;return`cancelled`}continue}try{e.onScreen?.({screen:`registry_review`,registrySelectedCount:e.selected.size});let t=e.selected.size>0,r=[...e.selected].map(t=>{let n=e.itemsByAddress.get(t);if(n===void 0)throw Error(`Registry item "${t}" is no longer available.`);return n}),i=r.filter(e=>e.name.startsWith(`channel/`)),a=r.filter(e=>!e.name.startsWith(`channel/`)),o=[...i.length===0?[]:[{label:`Channels`,value:i.map(label).join(`, `)}],...a.length===0?[]:[{label:`Integrations`,value:a.map(label).join(`, `)}]],s={message:e.plannerContext?.reviewMessage??`Review additions`,metadata:[...e.plannerContext?.reviewMetadata??[],...o],navigation:plannerNavigation(2,e),options:[{value:`install`,label:t?e.plannerContext?.primaryActionLabel??`Install and set up`:e.plannerContext?.emptyActionLabel??`Finish without adding`},{value:`back`,label:`Back`}]};t||(s.description=`No channels or integrations selected.`),n!==void 0&&(s.notices=n);let c=await e.prompter.select(s);if(n=void 0,c===`install`)return`install`}catch(e){if(e instanceof PlannerNavigationError&&e.direction===`back`){t=`integrations`;continue}if(!(e instanceof WizardCancelledError))throw e;return`cancelled`}t=`integrations`}}function hasSettledOutcomes(e){return e!==void 0&&(e.items.length>0||e.failures.length>0||e.outcomes!==void 0)}async function runRegistryFlow(e){let t;try{let n=e.initialAddress?.trim(),r;if(n!==void 0&&n!==``){if(await e.prompter.select({message:`Add ${n}?`,options:[{value:`install`,label:`Install and set up`},{value:`cancel`,label:`Cancel`}]})===`cancel`)return{kind:`cancelled`};r=[{address:n,name:n,source:`Registry`}]}else{let t=e.deps?.browseRegistryCatalog??(await import(`#cli/commands/registry.js`)).browseRegistryCatalog,n=await withSpinner(e.prompter,`Loading registry…`,()=>t(e.appRoot)),i=[...n.items],a=new Set,o=n.errors.map(e=>({tone:`warning`,text:`${e.registry}: ${e.message}`})),s=new Map(i.map(e=>[e.address,e]));if(await editPlan({prompter:e.prompter,catalog:i,itemsByAddress:s,selected:a,notices:o,plannerContext:e.plannerContext,onScreen:e.onScreen})!==`install`)return{kind:`cancelled`};r=[...a].map(e=>{let t=s.get(e);if(t===void 0)throw Error(`Registry item "${e}" is no longer available.`);return t})}let i=e.deps?.installRegistryItem??(await import(`#cli/commands/registry.js`)).installRegistryItem,a=e.deps?.detectDeployment??(await import(`#setup/project-resolution.js`)).detectDeployment,o=e.deps?.runDeployFlow??(await import(`./deploy.js`)).runDeployFlow;t=createRegistrySession({detectDeployment:a,runDeployFlow:o}),e.onScreen?.({screen:`registry_install`});let s=t;for(let[t,n]of r.entries()){e.signal?.throwIfAborted(),e.onItemStart?.(n,t,r.length);try{let install=(t=e.signal)=>i(e.appRoot,n.address,{silent:!0,prompter:e.prompter,signal:t}),run=()=>e.runItem===void 0?install():e.runItem(install),t=await(e.prompter.withExclusiveTerminal?.(run)??run());s.add(label(n),t.output,t.setup)}catch(t){if(e.signal?.throwIfAborted(),t instanceof WizardCancelledError){s.addCancellation(label(n));continue}if(t instanceof HumanActionRequiredError)throw t;let r=(t instanceof Error?t.message:String(t)).trim()||`Installation failed.`,i=r.split(`
`).find(e=>e.trim()!==``);s.addFailure(label(n),r);let a={message:`Couldn't add ${label(n)}`,options:[{value:`skip`,label:`Skip ${label(n)}`},{value:`cancel`,label:`Cancel setup`}]};if(i!==void 0&&(a.description=i),await e.prompter.select(a)===`cancel`)return{kind:`done`,result:{...s.result(),cancelled:!0}}}}return{kind:`done`,result:await s.continueAfterInstall({appRoot:e.appRoot,prompter:e.prompter,signal:e.signal})}}catch(e){if(e instanceof WizardCancelledError){let e=t?.result();return hasSettledOutcomes(e)?{kind:`done`,result:{...e,cancelled:!0}}:{kind:`cancelled`}}let n=t?.result();throw hasSettledOutcomes(n)?new RegistryFlowFailedError(e,n):e}}export{RegistryFlowFailedError,runRegistryFlow};