eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
1 lines • 1.88 kB
JavaScript
import{createEveMessageStreamRoutePath}from"#protocol/routes.js";import{ClientError}from"#client/client-error.js";import{createClientUrl}from"#client/url.js";import{isStreamDisconnectError,readNdjsonStream}from"#client/ndjson.js";const STREAM_OPEN_RETRY_MAX_DELAY_MS=5e3,STREAM_OPEN_RETRYABLE_STATUS=new Set([404,409,425,500,502,503,504]);async function*followStreamIterable(e){let t=e.startIndex,n=250,a=0,o=!0;for(;;){let s;try{s=await openStreamBody({...e,startIndex:t})}catch(t){if(e.signal?.aborted)return;throw t}let c=!1;try{for await(let e of readNdjsonStream(s))t+=1,c=!0,n=250,a=0,yield e}catch(e){if(!isStreamDisconnectError(e))throw e}if(e.signal?.aborted||e.startIndex<0||!c&&!o&&(a+=1)>=5||(o=!1,await sleep(n,e.signal),e.signal?.aborted))return;n=Math.min(n*2,4e3)}}async function openStreamBody(i){let s,c,l,u=250;for(let d=0;d<12;d+=1){let f=createClientUrl(i.host,createEveMessageStreamRoutePath(i.sessionId),i.startIndex===0?void 0:{startIndex:String(i.startIndex)}),p=await i.resolveHeaders(),m;try{m=await fetch(f,{headers:p,redirect:i.redirect,signal:i.signal??null})}catch(e){if(i.signal?.aborted||!isStreamDisconnectError(e)||d===11)throw e;await sleep(u,i.signal),u=Math.min(u*2,STREAM_OPEN_RETRY_MAX_DELAY_MS);continue}if(m.ok){if(!m.body)throw new ClientError(m.status,`Response body is null.`,m.headers);return m.body}if(s=m.status,c=await m.text(),l=m.headers,!STREAM_OPEN_RETRYABLE_STATUS.has(m.status))throw new ClientError(m.status,c,m.headers);d<11&&(await sleep(u,i.signal),u=Math.min(u*2,STREAM_OPEN_RETRY_MAX_DELAY_MS))}throw new ClientError(s??0,c??`Failed to open message stream.`,l)}async function sleep(e,t){t?.aborted||await new Promise(n=>{let onAbort=()=>{clearTimeout(r),n()},r=setTimeout(()=>{t?.removeEventListener(`abort`,onAbort),n()},e);t?.addEventListener(`abort`,onAbort,{once:!0})})}export{followStreamIterable,openStreamBody};