UNPKG

eve

Version:

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

1 lines 8.51 kB
import{toError}from"#shared/errors.js";import{createEventDeduper}from"#protocol/event-dedupe.js";import{isCurrentTurnBoundaryEvent}from"#protocol/message.js";import{Client}from"#client/client.js";import{assertExclusiveTurnInput,collectPendingAuthorizations,createAbortSignal,createSubmissionId,isAbortError,isSettledSessionTail,summarizeUserContent,toTerminalStreamFailureError,updatePendingAuthorizations}from"#client/eve-agent-store-helpers.js";const detachStore=Symbol(`detachEveAgentStore`);var EveAgentStore=class{#e;#t;#n;#r;#i=new Set;#a=createEventDeduper();#o;#s={};#c;#l;#u;#d=[];#f;#p;#m;#h;#g=`ready`;constructor(e){this.#t=e.session!==void 0,this.#e=this.#t?void 0:new Client({auth:e.auth,headers:e.headers,host:e.host??``});let t=[];for(let n of e.initialEvents??[])this.#a.admit(n)&&t.push(n);this.#u=t,this.#f=[...this.#u],this.#n=e.optimistic??!0,this.#r=e.reducer,this.#m=e.session??(e.initialSession===void 0?void 0:this.#e?.sessions.attach(e.initialSession.sessionId,{streamIndex:e.initialSession.streamIndex})),this.#c=this.#j(this.#f),this.#h=this.#M()}get snapshot(){return this.#h}setCallbacks(e){this.#s=e}subscribe(e){return this.#i.add(e),()=>{this.#i.delete(e)}}async send(e){if(this.#o!==void 0){if(this.#g===`resuming`)throw Error(`eve session is resuming.`);return await this.#v(this.#o,e)}let t=Promise.withResolvers(),n=Promise.withResolvers(),r={abortController:new AbortController,acceptedFollowUps:0,cancel:()=>r.acceptedFollowUps>0&&this.#m!==void 0?this.#m.cancel():t.promise.then(e=>e===void 0?{status:`no_active_turn`}:e.cancel()),completion:n.promise,followUpDispatches:new Set,receivedFollowUps:0,resolveCompletion:n.resolve,response:t.promise,resolveResponse:t.resolve};this.#o=r,this.#l=void 0,this.#g=`submitted`,this.#N();try{let t=await this.#s.prepareSend?.(e)??e;if(assertExclusiveTurnInput(t),!this.#S(r))return;this.#C(t),this.#w(t),this.#N();let n={...t,signal:createAbortSignal(t.signal,r.abortController.signal)},i=await this.#x(n);if(!this.#S(r))return;r.resolveResponse(i);for await(let e of i){if(!this.#S(r))return;this.#T(e)}if(!this.#S(r)||(await this.#y(r),!this.#S(r)))return;this.#g=this.#l===void 0?`ready`:`error`}catch(e){if(!this.#S(r))return;isAbortError(e)?(this.#g=`ready`,this.#O(toError(e))):(this.#l=toError(e),this.#g=`error`,this.#O(this.#l),this.#s.onError?.(this.#l))}finally{this.#S(r)&&(r.resolveResponse(void 0),this.#o=void 0,this.#s.onSessionChange?.(this.#m?.state),this.#N(),this.#s.onFinish?.(this.#h),r.resolveCompletion())}}resume(){if(this.#p!==void 0)return this.#p;let e=this.#_();this.#p=e;let clear=()=>{this.#p===e&&(this.#p=void 0)};return e.then(clear,clear),e}async#_(){if(this.#g===`resuming`||this.#g===`streaming`||this.#g===`submitted`)throw Error(`eve session is already processing a turn.`);if(this.#m===void 0)throw Error(`An eve session is required before resuming.`);let e=Promise.withResolvers(),t=Promise.withResolvers(),n=this.#m,r={abortController:new AbortController,acceptedFollowUps:0,cancel:()=>n.cancel(),completion:t.promise,followUpDispatches:new Set,receivedFollowUps:0,resolveCompletion:t.resolve,response:e.promise,resolveResponse:e.resolve};this.#o=r,r.resolveResponse(void 0),this.#l=void 0,this.#g=`resuming`,this.#N();try{let e=this.#u.length===n.state.streamIndex,t=e?[...this.#u]:[];for await(let i of n.stream({follow:!1,signal:r.abortController.signal,startIndex:e?n.state.streamIndex:0})){if(!this.#S(r))return;t.push(i),this.#T(i,{publish:!1,transitionToStreaming:!1})}if(!this.#S(r))return;let i=t.at(-1);i!==void 0&&this.#D(i);let a=isSettledSessionTail(t);if(this.#l===void 0&&(!a||i?.type===`session.waiting`)){let e=collectPendingAuthorizations(t);a||(this.#g=`streaming`),this.#N();let i=!a;for(;;){for await(let a of n.stream({follow:i?void 0:!1,signal:r.abortController.signal})){if(!this.#S(r))return;if(t.push(a),this.#T(a),updatePendingAuthorizations(e,a),i&&isCurrentTurnBoundaryEvent(a)&&(a.type!==`session.waiting`||e.size===0))break}if(!this.#S(r))return;if(i||isSettledSessionTail(t))break;i=!0}}else this.#g=this.#l===void 0?`ready`:`error`,this.#N();await this.#y(r),this.#S(r)&&(this.#g=this.#l===void 0?`ready`:`error`)}catch(e){if(!this.#S(r))return;isAbortError(e)?this.#g=`ready`:(this.#l=toError(e),this.#g=`error`,this.#s.onError?.(this.#l))}finally{this.#S(r)&&(r.resolveResponse(void 0),this.#o=void 0,this.#s.onSessionChange?.(n.state),this.#N(),this.#s.onFinish?.(this.#h),r.resolveCompletion())}}cancel(){let e=this.#o;return e===void 0?Promise.resolve({status:`no_active_turn`}):e.cancel()}[detachStore](){this.#o?.abortController.abort()}reset(){let e=this.#o;this.#o=void 0,e?.resolveResponse(void 0),e?.resolveCompletion(),e?.abortController.abort(),this.#t||(this.#m=void 0),this.#u=[],this.#a=createEventDeduper(),this.#d=[],this.#f=[],this.#c=this.#r.initial(),this.#l=void 0,this.#g=`ready`,this.#s.onSessionChange?.(this.#m?.state),this.#N()}async#v(e,t){if(t.message===void 0||t.turnPolicy!==`steer`)throw Error(`eve session is already processing a turn. Send a message with turnPolicy: "steer" to replace it.`);let n=await this.#s.prepareSend?.(t)??t;if(assertExclusiveTurnInput(n),n.message===void 0||n.turnPolicy!==`steer`)throw Error(`An in-flight follow-up requires a message with turnPolicy: "steer".`);if(!this.#S(e))return await this.send(n);let r=this.#C(n);this.#N();let i;i=(async()=>{try{if(await e.response,!this.#S(e)||this.#m===void 0)throw Error(`The active eve turn ended before the follow-up could be sent.`);let{message:t,...r}=n;await this.#m.send(t,r),e.acceptedFollowUps+=1}catch(e){throw this.#O(toError(e),r),this.#N(),e}finally{e.followUpDispatches.delete(i)}})(),e.followUpDispatches.add(i),await i,await e.completion}async#y(e){for(;e.followUpDispatches.size>0;)await Promise.allSettled(e.followUpDispatches);if(!(e.receivedFollowUps>=e.acceptedFollowUps||this.#m===void 0))for await(let t of this.#m.stream({signal:e.abortController.signal})){if(!this.#S(e))return;if(t.type===`message.received`&&(e.receivedFollowUps+=1),this.#T(t),isCurrentTurnBoundaryEvent(t)){for(;e.followUpDispatches.size>0;)await Promise.allSettled(e.followUpDispatches);if(e.receivedFollowUps>=e.acceptedFollowUps)return}}}async#b(e){if(this.#e===void 0)throw Error(`An external eve session is required before sending.`);if(e.message===void 0)throw Error(`Cannot answer an input request before the session starts.`);let t=await this.#e.sessions.create({...e,message:e.message});return this.#m=t.session,this.#s.onSessionChange?.(t.session.state),this.#N(),t.response}async#x(e){if(this.#m===void 0)return await this.#b(e);if(e.inputResponses===void 0){let{message:t,...n}=e;return await this.#m.send(t,n)}let{inputResponses:t,...n}=e;return await this.#m.respond(t,n)}#S(e){return this.#o===e}#C(e){if(!this.#n||e.message===void 0)return;let t=createSubmissionId(),n={createdAt:Date.now(),id:t,message:summarizeUserContent(e.message)};return this.#d=[...this.#d,n],this.#k({data:{createdAt:n.createdAt,message:n.message,submissionId:n.id},type:`client.message.submitted`}),t}#w(e){e.inputResponses!==void 0&&e.inputResponses.length!==0&&this.#k({data:{createdAt:Date.now(),responses:e.inputResponses},type:`client.input.responded`})}#T(e,t={}){this.#a.admit(e)&&(this.#u=[...this.#u,e],this.#E(e),this.#s.onEvent?.(e),(t.transitionToStreaming??!0)&&(this.#g=`streaming`),this.#D(e),(t.publish??!0)&&this.#N())}#E(e){let t=this.#d[0];if(e.type===`message.received`&&t!==void 0){let n=t.id;this.#d=this.#d.slice(1),this.#A(e=>e.type===`client.message.submitted`&&e.data.submissionId===n,e);return}this.#k(e)}#D(e){let t=toTerminalStreamFailureError(e);t!==void 0&&(this.#g=`error`,this.#O(t),this.#l===void 0&&(this.#l=t,this.#s.onError?.(t)))}#O(e,t){let n=t===void 0?this.#d[0]:this.#d.find(e=>e.id===t);n!==void 0&&(this.#d=this.#d.filter(e=>e.id!==n.id),this.#A(e=>e.type===`client.message.submitted`&&e.data.submissionId===n.id,{data:{createdAt:n.createdAt,error:{message:e.message},message:n.message,submissionId:n.id},type:`client.message.failed`}))}#k(e){this.#f=[...this.#f,e],this.#c=this.#r.reduce(this.#c,e)}#A(e,t){let n=!1;this.#f=this.#f.map(r=>!n&&e(r)?(n=!0,t):r),n||(this.#f=[...this.#f,t]),this.#c=this.#j(this.#f)}#j(e){let t=this.#r.initial();for(let n of e)t=this.#r.reduce(t,n);return t}#M(){return{data:this.#c,error:this.#l,events:this.#u,session:this.#m?.state,status:this.#g}}#N(){this.#h=this.#M();for(let e of this.#i)e()}};function detachEveAgentStore(e){e[detachStore]()}export{EveAgentStore,detachEveAgentStore};