eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
1 lines • 5.75 kB
JavaScript
import{createLogger}from"#internal/logging.js";import{ActivityObserverKey,SessionCallbackKey}from"#context/keys.js";import{toErrorMessage}from"#shared/errors.js";import{parseJsonValue}from"#shared/json.js";import{ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{parseSessionCallback}from"#channel/session-callback.js";import{resumeHook}from"#internal/workflow/runtime.js";import{deserializeContext}from"#context/serialize.js";import{HookNotFoundError}from"#compiled/@workflow/errors/index.js";import{SUBAGENT_EXECUTION_FAILED}from"#subagents/agent-handle-errors.js";import{postSessionCallbackRequest}from"#execution/session-callback-request.js";import{SUBAGENT_ADAPTER_KIND,isSubagentAdapterState}from"#subagents/adapter-state.js";import{readTaskIdFromInboxToken}from"#tasks/task-inbox-token.js";const log=createLogger(`execution.delegated-parent-notification`);async function notifyDelegatedParentStep(e){"use step";if(e.result===void 0)return;let t=(await deserializeContext(e.serializedContext)).get(ChannelKey);if(t?.kind!==SUBAGENT_ADAPTER_KIND)return;let n=String(t.state?.parentContinuationToken??``);if(n===``)return;let r=e.usage===void 0?e.result:{...e.result,outcome:{...e.result.outcome,usageDelta:e.usage},usage:e.usage};await resumeHook(n,{kind:`runtime-action-result`,results:[r]})}const ZERO_TOKEN_USAGE={cacheReadTokens:0,cacheWriteTokens:0,inputTokens:0,outputTokens:0};async function notifyTurnCallerStep(e){"use step";if(e.caller===void 0)return;let t=createSettledTurnResult({caller:e.caller,lifecycle:e.lifecycle,sessionId:e.sessionId,settled:e.settled});if(e.caller.replyTo.kind===`callback`){await postSettledTurnCallback({result:t,sessionId:e.sessionId,url:e.caller.replyTo.url});return}await resumeSettledTurnHook(e.caller.replyTo.token,t)}async function notifyCancelledTaskCallerStep(e){"use step";if(e.caller===void 0)return;let t=e.usage??ZERO_TOKEN_USAGE,n={code:SUBAGENT_EXECUTION_FAILED,message:`The agent invocation was cancelled.`},r={callId:e.caller.callId,isError:!0,kind:`subagent-result`,origin:`child`,outcome:{kind:`parked`,result:{kind:`cancelled`},usageDelta:t},output:n,subagentName:e.caller.subagentName},i=e.usage===void 0?r:{...r,usage:e.usage};if(e.caller.replyTo.kind===`callback`){await postSettledTurnCallback({result:i,sessionId:e.sessionId,url:e.caller.replyTo.url});return}await resumeSettledTurnHook(e.caller.replyTo.token,i)}function createSettledTurnResult(e){let t=e.settled.usage??ZERO_TOKEN_USAGE;if(e.settled.isError===!0){let n={code:SUBAGENT_EXECUTION_FAILED,message:toErrorMessage(e.settled.output)};return{callId:e.caller.callId,isError:!0,kind:`subagent-result`,origin:`child`,outcome:{kind:e.lifecycle,result:{error:n,kind:`failed`},usageDelta:t},output:n,subagentName:e.caller.subagentName}}let n=parseJsonValue(e.settled.output),r={callId:e.caller.callId,kind:`subagent-result`,origin:`child`,outcome:{kind:e.lifecycle,result:{kind:`succeeded`,output:n},usageDelta:t},output:n,subagentName:e.caller.subagentName};return e.settled.usage===void 0?r:{...r,usage:e.settled.usage}}async function resolveInitialTurnCallerStep(e){"use step";let t=e.serializedContext[SessionCallbackKey.name];if(t!==void 0){let e=parseSessionCallback(t);if(!e.ok)throw Error(`Serialized session callback is invalid.`,{cause:e.cause});return{callId:e.callback.callId,replyTo:{kind:`callback`,token:e.callback.token,url:e.callback.url},subagentName:e.callback.subagentName,taskId:e.callback.taskId??readTaskIdFromInboxToken(e.callback.token)}}let n=(await deserializeContext(e.serializedContext)).get(ChannelKey);if(n?.kind===SUBAGENT_ADAPTER_KIND&&isSubagentAdapterState(n.state))return{callId:n.state.callId,replyTo:{kind:`hook`,token:n.state.parentContinuationToken},subagentName:n.state.subagentName,taskId:n.state.taskId??readTaskIdFromInboxToken(n.state.parentContinuationToken)}}async function bindTurnCallerContextStep(e){"use step";let t=e.caller;if(t===void 0)return e.serializedContext;let n=t.activityObserver===void 0?e.serializedContext:{...e.serializedContext,[ActivityObserverKey.name]:t.activityObserver};if(t.replyTo.kind===`callback`){let e={callId:t.callId,subagentName:t.subagentName,token:t.replyTo.token,url:t.replyTo.url};return{...n,[SessionCallbackKey.name]:t.taskId===void 0?e:{...e,taskId:t.taskId}}}let r=n[ChannelKey.name];if(typeof r!=`object`||!r||Reflect.get(r,`kind`)!==SUBAGENT_ADAPTER_KIND||!isSubagentAdapterState(Reflect.get(r,`state`)))throw Error(`Delegated local turn is missing its subagent adapter binding.`);let{taskId:i,...a}=Reflect.get(r,`state`),o={...a,callId:t.callId,parentContinuationToken:t.replyTo.token,subagentName:t.subagentName};return t.taskId!==void 0&&(o.taskId=t.taskId),{...n,[ChannelKey.name]:{...r,state:o}}}async function postSettledTurnCallback(e){let{sessionId:t}=e;if(e.result.isError===!0){await postCallbackPayload({payload:{callId:e.result.callId,error:e.result.output,kind:`turn.failed`,outcome:e.result.outcome,sessionId:t,subagentName:e.result.subagentName},url:e.url});return}await postCallbackPayload({payload:{callId:e.result.callId,kind:`turn.completed`,outcome:e.result.outcome,output:e.result.output,sessionId:t,subagentName:e.result.subagentName},url:e.url})}async function postCallbackPayload(e){let t=await postSessionCallbackRequest({body:e.payload,url:e.url});if(!t.ok)throw Error(`Turn callback failed with HTTP ${t.status}.`)}async function resumeSettledTurnHook(e,t){try{await resumeHook(e,{kind:`runtime-action-result`,results:[t]})}catch(n){if(!HookNotFoundError.is(n))throw n;log.warn(`turn caller hook no longer exists`,{callId:t.callId,callerToken:e})}}export{bindTurnCallerContextStep,notifyCancelledTaskCallerStep,notifyDelegatedParentStep,notifyTurnCallerStep,resolveInitialTurnCallerStep};