eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
1 lines • 7.66 kB
JavaScript
import{createHook}from"#compiled/@workflow/core/index.js";import{closeHookIterator,disposeHook}from"#execution/hook-ownership.js";import{cancelAllIndexedSessionTasksStep}from"#execution/cancel-indexed-session-tasks-step.js";import{reportDroppedWirePayloadStep}from"#execution/report-dropped-wire-payload-step.js";import{SessionInboxWireError,sessionInboxWire}from"#execution/wire/session-inbox-wire.js";import{rebuildSerializableError}from"#execution/workflow-errors.js";import{turnCancellationHookToken}from"#execution/turn-cancellation-token.js";import{forwardTurnCancellationStep}from"#execution/forward-turn-cancellation-step.js";import{forwardTurnDeliveryStep}from"#execution/forward-turn-delivery-step.js";var TurnControlReceiver=class{bufferedDeliveries;bufferedSessionControls;commandInbox;control;controlIterator;expectedTurnId;cancelledTaskIds;seenTaskDeliveries;stateCursor;pendingControl=null;constructor(e){this.bufferedDeliveries=e.bufferedDeliveries,this.bufferedSessionControls=e.bufferedSessionControls,this.cancelledTaskIds=e.cancelledTaskIds??new Set,this.commandInbox=e.commandInbox,this.seenTaskDeliveries=e.seenTaskDeliveries??new Set,this.stateCursor=e.stateCursor,this.control=createHook({token:e.token}),this.controlIterator=this.control[Symbol.asyncIterator](),this.expectedTurnId=e.expectedTurnId}get token(){return this.control.token}async dispose(){await closeHookIterator(this.controlIterator),await disposeHook(this.control)}async waitForAction(){for(;;){let e=await this.nextControlOrCommand();if(e.kind===`command`){let t=await this.handleSessionCommand(e.command);if(t!==void 0)return t;continue}let t=e.payload,n=this.readTerminalControl(t);if(n!==void 0)return n;if(t.kind===`turn-delivery-request`){let e=await this.serviceDeliveryRequest(t);if(e!==void 0)return e}}}async handleSessionCommand(e){if(e.kind===`deliver`){if(!this.acceptTaskDelivery(e))return;await this.bufferDelivery(e);return}if(e.kind===`clear`||e.kind===`compact`){this.bufferedSessionControls.push(e.kind);return}if(e.kind===`session-timeout`){this.bufferedSessionControls.push(`expired`);return}if(e.kind===`cancel`){`tasks`in e&&e.tasks===!0&&await cancelAllIndexedSessionTasksStep({serializedContext:this.stateCursor.serializedContext,sessionState:this.stateCursor.sessionState}),e.taskId!==void 0&&this.discardTaskDeliveries(e.taskId);let t=e.taskId!==void 0&&e.turnId!==void 0&&e.turnId!==this.expectedTurnId?void 0:e.turnId,n={tasks:e.tasks};t!==void 0&&(n.turnId=t),await forwardTurnCancellationStep({payload:n,token:turnCancellationHookToken(this.control.token)});return}if(e.kind===`reset`){await forwardTurnCancellationStep({payload:{},token:turnCancellationHookToken(this.control.token)}),this.bufferedSessionControls.push(`reset`);return}return unsupportedSessionCommand(e)}async bufferDelivery(e){this.bufferedDeliveries.push(e),e.turnPolicy===`steer`&&deliveryHasMessage(e)&&await forwardTurnCancellationStep({payload:{},token:turnCancellationHookToken(this.control.token)})}bufferTurnDeliveries(e){e.bufferedDeliveries!==void 0&&this.bufferedDeliveries.unshift(...e.bufferedDeliveries.filter(e=>!this.shouldDiscard(e)))}consumeControl(){this.pendingControl=null}getControlPromise(){return this.pendingControl??=this.controlIterator.next(),this.pendingControl}async nextControlOrCommand(){let e=await Promise.race([this.getControlPromise().then(e=>({kind:`control`,value:e})),this.commandInbox.next().then(e=>({kind:`command`,value:e}))]);if(e.kind===`command`){if(e.value.done)throw Error(`Session command inbox closed before the active turn settled.`);if(this.commandInbox.consumeNext(),e.value.value.kind===`runtime-action-result`)return await this.nextControlOrCommand();try{return{command:sessionInboxWire.decode(e.value.value),kind:`command`}}catch(e){if(!(e instanceof SessionInboxWireError))throw e;return await reportDroppedWirePayloadStep({detail:e.message,family:`session-inbox`}),await this.nextControlOrCommand()}}if(this.consumeControl(),e.value.done)throw Error(`Turn control hook closed before delivering a result.`);let t=e.value.value;if(t.kind===`turn-error`)throw rebuildSerializableError(t.error);return t.kind===`turn-continuation-token`?(await this.commandInbox.rekeyContinuation(t.continuationToken),await this.nextControlOrCommand()):{kind:`control`,payload:t}}readTerminalControl(e){if(e.kind===`turn-error`)throw rebuildSerializableError(e.error);if(e.kind===`turn-result`)return this.bufferTurnDeliveries(e),e.action}async serviceDeliveryRequest(e){await this.commandInbox.rekeyContinuation(e.continuationToken);let t=this.takeInputResponseDelivery();for(;t===void 0;){let n=await Promise.race([this.getControlPromise().then(e=>({kind:`control`,value:e})),this.commandInbox.next().then(e=>({kind:`command`,value:e}))]);if(n.kind===`control`){if(this.consumeControl(),n.value.done)throw Error(`Turn control hook closed during a delivery request.`);if(n.value.value.kind===`turn-continuation-token`){await this.commandInbox.rekeyContinuation(n.value.value.continuationToken);continue}let t=this.readTerminalControl(n.value.value);if(t!==void 0)return t;if(n.value.value.kind===`turn-delivery-cancelled`&&n.value.value.requestId===e.requestId)return;continue}if(n.value.done)throw Error(`Session command inbox closed during a turn delivery request.`);if(this.commandInbox.consumeNext(),n.value.value.kind===`runtime-action-result`)continue;let r;try{r=sessionInboxWire.decode(n.value.value)}catch(e){if(!(e instanceof SessionInboxWireError))throw e;await reportDroppedWirePayloadStep({detail:e.message,family:`session-inbox`});continue}if(r.kind===`deliver`){if(!this.acceptTaskDelivery(r))continue;deliveryHasMessage(r)?await this.bufferDelivery(r):t=r;continue}let i=await this.handleSessionCommand(r);if(i!==void 0)return i}try{await forwardTurnDeliveryStep({inboxToken:e.inboxToken,payload:{delivery:t,kind:`driver-delivery`,requestId:e.requestId}})}catch(e){if(!(e instanceof Error&&e.name===`HookNotFoundError`))throw e}return await this.awaitForwardedDelivery(e.requestId,t)}takeInputResponseDelivery(){let e=this.bufferedDeliveries.findIndex(e=>!deliveryHasMessage(e));if(e!==-1)return this.bufferedDeliveries.splice(e,1)[0]}async awaitForwardedDelivery(e,t){for(;;){let n=await this.nextControlOrCommand();if(n.kind===`command`){let e=await this.handleSessionCommand(n.command);if(e!==void 0)return this.shouldDiscard(t)||this.bufferedDeliveries.unshift(t),e;continue}let r=n.payload;if(r.kind===`turn-delivery-accepted`){if(r.requestId===e)return;continue}if(r.kind===`turn-delivery-cancelled`&&r.requestId===e){this.shouldDiscard(t)||this.bufferedDeliveries.unshift(t);return}r.kind===`turn-result`&&(this.shouldDiscard(t)||this.bufferedDeliveries.unshift(t));let i=this.readTerminalControl(r);if(i!==void 0)return i}}acceptTaskDelivery(e){let t=e.taskDeliveryId??e.caller?.taskId;return t===void 0?!0:this.originatesFromCancelledTask(t)||this.seenTaskDeliveries.has(t)?!1:(this.seenTaskDeliveries.add(t),!0)}discardTaskDeliveries(e){this.cancelledTaskIds.add(e);let t=this.bufferedDeliveries.filter(e=>!this.shouldDiscard(e));this.bufferedDeliveries.splice(0,this.bufferedDeliveries.length,...t)}originatesFromCancelledTask(e){return[...this.cancelledTaskIds].some(t=>deliveryOriginatesFromTask(e,t))}shouldDiscard(e){let t=e.taskDeliveryId??e.caller?.taskId;return t!==void 0&&this.originatesFromCancelledTask(t)}};function deliveryOriginatesFromTask(e,t){return e===t||e.startsWith(`${t}:`)}function deliveryHasMessage(e){return e.payloads.some(e=>e.message!==void 0)}function unsupportedSessionCommand(e){throw Error(`Unsupported session command: ${JSON.stringify(e)}`)}export{TurnControlReceiver};