import{EVE_CREATE_SESSION_ROUTE_PATH,createEveContinueSessionRoutePath}from"#protocol/routes.js";import{openStreamBody,openStreamIterable}from"#client/open-stream.js";import{EVE_SESSION_ID_HEADER,isCurrentTurnBoundaryEvent}from"#protocol/message.js";import{ClientError}from"#client/client-error.js";import{advanceSession}from"#client/session-utils.js";import{createClientUrl}from"#client/url.js";import{MessageResponse}from"#client/message-response.js";import{normalizeOutputSchemaForRequest}from"#client/output-schema.js";import{isStreamDisconnectError,readNdjsonStream}from"#client/ndjson.js";var ClientSession=class{#e;#t;constructor(e,t){this.#e=e,this.#t=t}get state(){return this.#t}async send(e){let t=normalizeSendTurnInput(e),n=this.#t,{continuationToken:r,sessionId:i}=await this.#n(t,n);return new MessageResponse({continuationToken:r,createStream:()=>this.#r(i,r,n,t),sessionId:i})}stream(e){let t=this.#t.sessionId;if(!t)throw Error(`Session has no session ID. Send a message first.`);return this.#a(t,e)}async#n(n,r){let a=r.sessionId?createEveContinueSessionRoutePath(r.sessionId):EVE_CREATE_SESSION_ROUTE_PATH,o=createClientUrl(this.#e.host,a),s=await this.#e.resolveHeaders(n.headers);s.set(`content-type`,`application/json`);let c=createHandleMessageBody({input:n,outputSchema:normalizeOutputSchemaForRequest(n.outputSchema),session:r});if(c===null)throw Error(`Session.send requires a non-empty message, inputResponses, or both.`);let l=await postTurnWithRetry({body:JSON.stringify(c),headers:s,mustDeliver:(n.inputResponses?.length??0)>0,signal:n.signal,url:o}),u=await l.json(),d=(typeof u.sessionId==`string`?u.sessionId:void 0)??l.headers.get(EVE_SESSION_ID_HEADER)?.trim()??r.sessionId;if(!d)throw Error(`Message route did not return a session id.`);return{continuationToken:typeof u.continuationToken==`string`?u.continuationToken:void 0,sessionId:d}}async*#r(e,t,n,r){let i=[];try{let t=n.sessionId===e?n.streamIndex:0,o=this.#e.maxReconnectAttempts;for(;;){let n=await this.#i(e,t,r.signal,r.headers),s=!1;try{for await(let e of readNdjsonStream(n))if(i.push(e),t+=1,yield e,isCurrentTurnBoundaryEvent(e)){s=!0;break}}catch(e){if(!isStreamDisconnectError(e))throw e}if(s||o<=0)break;--o}}finally{this.#t=advanceSession({continuationToken:t,events:i,sessionId:e,session:n})}}async#i(e,t,r,i){return await openStreamBody({host:this.#e.host,resolveHeaders:()=>this.#e.resolveHeaders(i),sessionId:e,signal:r,startIndex:t})}async*#a(e,t){let n=this.#t,i=t?.startIndex??n.streamIndex,a=[];try{for await(let n of openStreamIterable({host:this.#e.host,maxReconnectAttempts:this.#e.maxReconnectAttempts,resolveHeaders:()=>this.#e.resolveHeaders(),sessionId:e,signal:t?.signal,startIndex:i}))a.push(n),yield n}finally{this.#t=advanceSession({continuationToken:n.continuationToken,events:a,session:{...n,sessionId:e,streamIndex:i},sessionId:e})}}};async function postTurnWithRetry(e){let t=e.mustDeliver?10:1,n,r;for(let i=0;i<t;i+=1){let a=await fetch(e.url,{body:e.body,headers:e.headers,method:`POST`,signal:e.signal??null});if(a.ok)return a;if(n=a.status,r=await a.text(),!isRetryableDeliveryFailure(a.status,r))throw new ClientError(a.status,r);i<t-1&&await sleep(200)}throw new ClientError(n??0,r??`Failed to deliver session turn.`)}function isRetryableDeliveryFailure(e,t){return e===500&&/target session was not found/i.test(t)}async function sleep(e){await new Promise(t=>setTimeout(t,e))}function normalizeSendTurnInput(e){return typeof e==`string`?{message:e}:e}function createHandleMessageBody(e){let t={};return e.input.message!==void 0&&(t.message=e.input.message),e.input.inputResponses!==void 0&&e.input.inputResponses.length>0&&(t.inputResponses=e.input.inputResponses),e.input.clientContext!==void 0&&(t.clientContext=e.input.clientContext),e.outputSchema!==void 0&&(t.outputSchema=e.outputSchema),e.session.continuationToken!==void 0&&(t.continuationToken=e.session.continuationToken),Object.keys(t).length===0||e.session.continuationToken===void 0&&t.message===void 0||e.session.continuationToken!==void 0&&t.message===void 0&&t.inputResponses===void 0?null:t}export{ClientSession};