eve 0.20.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/src/channel/types.d.ts +9 -5
  3. package/dist/src/chunks/{use-eve-agent-Dvy_Wjvq.js → use-eve-agent-CM24ZUEI.js} +48 -34
  4. package/dist/src/chunks/{use-eve-agent-Bh1NmXO9.js → use-eve-agent-CxcKypLZ.js} +48 -34
  5. package/dist/src/client/index.d.ts +1 -1
  6. package/dist/src/client/message-reducer-types.d.ts +11 -3
  7. package/dist/src/client/message-reducer.js +1 -1
  8. package/dist/src/compiler/manifest.js +1 -1
  9. package/dist/src/compiler/normalize-agent-config.js +1 -1
  10. package/dist/src/compiler/workspace-resources.js +1 -1
  11. package/dist/src/context/dynamic-skill-lifecycle.js +1 -1
  12. package/dist/src/context/keys.d.ts +0 -1
  13. package/dist/src/context/keys.js +1 -1
  14. package/dist/src/discover/sandbox.d.ts +0 -6
  15. package/dist/src/discover/sandbox.js +1 -1
  16. package/dist/src/execution/create-session-step.d.ts +2 -1
  17. package/dist/src/execution/create-session-step.js +1 -1
  18. package/dist/src/execution/delegated-parent-notification.d.ts +6 -0
  19. package/dist/src/execution/delegated-parent-notification.js +1 -1
  20. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  21. package/dist/src/execution/dispatch-workflow-runtime-actions-step.js +1 -1
  22. package/dist/src/execution/durable-session-store.d.ts +1 -0
  23. package/dist/src/execution/next-driver-action.d.ts +3 -0
  24. package/dist/src/execution/node-step.d.ts +6 -0
  25. package/dist/src/execution/node-step.js +1 -1
  26. package/dist/src/execution/run-session-limits.d.ts +21 -0
  27. package/dist/src/execution/run-session-limits.js +1 -0
  28. package/dist/src/execution/runtime-context.js +1 -1
  29. package/dist/src/execution/sandbox/bindings/local-backend-utils.d.ts +1 -1
  30. package/dist/src/execution/sandbox/bindings/local-backend-utils.js +1 -1
  31. package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
  32. package/dist/src/execution/sandbox/prewarm.js +1 -1
  33. package/dist/src/execution/session-callback-step.d.ts +6 -0
  34. package/dist/src/execution/session-callback-step.js +1 -1
  35. package/dist/src/execution/session.d.ts +14 -3
  36. package/dist/src/execution/session.js +2 -4
  37. package/dist/src/execution/skills/instructions.d.ts +8 -4
  38. package/dist/src/execution/skills/instructions.js +2 -2
  39. package/dist/src/execution/subagent-tool.d.ts +7 -0
  40. package/dist/src/execution/subagent-tool.js +1 -1
  41. package/dist/src/execution/subagent-usage-span.d.ts +9 -0
  42. package/dist/src/execution/subagent-usage-span.js +1 -0
  43. package/dist/src/execution/turn-execution-cursor.d.ts +2 -0
  44. package/dist/src/execution/turn-workflow.js +1 -1
  45. package/dist/src/execution/workflow-entry.d.ts +1 -0
  46. package/dist/src/execution/workflow-entry.js +1 -1
  47. package/dist/src/execution/workflow-runtime.js +1 -1
  48. package/dist/src/execution/workflow-skill-root.d.ts +6 -0
  49. package/dist/src/execution/workflow-skill-root.js +1 -0
  50. package/dist/src/execution/workflow-steps.d.ts +3 -0
  51. package/dist/src/execution/workflow-steps.js +1 -1
  52. package/dist/src/harness/advertised-tools.d.ts +1 -0
  53. package/dist/src/harness/advertised-tools.js +1 -1
  54. package/dist/src/harness/input-requests.d.ts +8 -0
  55. package/dist/src/harness/input-requests.js +1 -1
  56. package/dist/src/harness/runtime-actions.js +1 -1
  57. package/dist/src/harness/session-limit-continuation.d.ts +55 -0
  58. package/dist/src/harness/session-limit-continuation.js +1 -0
  59. package/dist/src/harness/session-limit-enforcement.d.ts +55 -0
  60. package/dist/src/harness/session-limit-enforcement.js +1 -0
  61. package/dist/src/harness/subagent-depth.d.ts +1 -4
  62. package/dist/src/harness/subagent-depth.js +1 -1
  63. package/dist/src/harness/subagent-token-budget.d.ts +14 -0
  64. package/dist/src/harness/subagent-token-budget.js +1 -0
  65. package/dist/src/harness/tool-loop.js +1 -1
  66. package/dist/src/harness/turn-tag-state.d.ts +31 -0
  67. package/dist/src/harness/turn-tag-state.js +1 -1
  68. package/dist/src/harness/types.d.ts +21 -4
  69. package/dist/src/harness/workflow-sandbox.d.ts +1 -0
  70. package/dist/src/harness/workflow-sandbox.js +1 -1
  71. package/dist/src/harness/workflow-subagent-limit.d.ts +38 -0
  72. package/dist/src/harness/workflow-subagent-limit.js +1 -0
  73. package/dist/src/harness/workflow-tool-description.d.ts +6 -1
  74. package/dist/src/harness/workflow-tool-description.js +5 -3
  75. package/dist/src/internal/application/package.js +1 -1
  76. package/dist/src/internal/authored-definition/core.js +1 -1
  77. package/dist/src/internal/authored-definition/schema-backed.js +1 -1
  78. package/dist/src/protocol/message.d.ts +19 -2
  79. package/dist/src/protocol/message.js +2 -2
  80. package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +34 -3
  81. package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
  82. package/dist/src/public/channels/chat-sdk/index.d.ts +2 -0
  83. package/dist/src/public/channels/chat-sdk/index.js +1 -1
  84. package/dist/src/public/channels/chat-sdk/messageToUserContent.d.ts +13 -0
  85. package/dist/src/public/channels/chat-sdk/messageToUserContent.js +1 -0
  86. package/dist/src/public/channels/chat-sdk/notImplemented.d.ts +7 -0
  87. package/dist/src/public/channels/chat-sdk/notImplemented.js +1 -0
  88. package/dist/src/public/channels/slack/api.d.ts +14 -12
  89. package/dist/src/public/channels/slack/api.js +1 -1
  90. package/dist/src/public/definitions/tool.d.ts +37 -0
  91. package/dist/src/public/definitions/tool.js +1 -1
  92. package/dist/src/public/tools/index.d.ts +1 -1
  93. package/dist/src/public/tools/index.js +1 -1
  94. package/dist/src/runtime/actions/types.d.ts +9 -0
  95. package/dist/src/runtime/actions/types.js +1 -1
  96. package/dist/src/runtime/agent/bootstrap.d.ts +2 -0
  97. package/dist/src/runtime/agent/bootstrap.js +1 -1
  98. package/dist/src/runtime/resolve-agent.js +1 -1
  99. package/dist/src/runtime/sandbox/keys.js +1 -1
  100. package/dist/src/runtime/sandbox/template-plan.js +1 -1
  101. package/dist/src/runtime/session-callback-route.js +1 -1
  102. package/dist/src/runtime/skills/sandbox-access.d.ts +1 -1
  103. package/dist/src/runtime/skills/sandbox-access.js +1 -1
  104. package/dist/src/runtime/workspace/seed-files.js +1 -1
  105. package/dist/src/setup/scaffold/create/project.js +1 -1
  106. package/dist/src/setup/scaffold/create/web-template.d.ts +2 -2
  107. package/dist/src/setup/scaffold/create/web-template.js +77 -3
  108. package/dist/src/shared/agent-definition.d.ts +31 -3
  109. package/dist/src/shared/skill-package.d.ts +2 -2
  110. package/dist/src/shared/skill-package.js +1 -1
  111. package/dist/src/shared/skill-paths.d.ts +28 -0
  112. package/dist/src/shared/skill-paths.js +2 -0
  113. package/dist/src/shared/token-usage.d.ts +22 -0
  114. package/dist/src/shared/token-usage.js +1 -0
  115. package/dist/src/svelte/index.js +1 -1
  116. package/dist/src/svelte/use-eve-agent.js +1 -1
  117. package/dist/src/vue/index.js +1 -1
  118. package/dist/src/vue/use-eve-agent.js +1 -1
  119. package/docs/agent-config.md +32 -15
  120. package/docs/channels/chat-sdk.mdx +209 -0
  121. package/docs/channels/meta.json +1 -0
  122. package/docs/concepts/context-control.md +2 -2
  123. package/docs/concepts/default-harness.md +10 -0
  124. package/docs/concepts/sessions-runs-and-streaming.md +1 -1
  125. package/docs/guides/client/messages.mdx +4 -0
  126. package/docs/guides/client/streaming.mdx +17 -12
  127. package/docs/guides/dynamic-workflows.md +87 -0
  128. package/docs/guides/frontend/overview.mdx +5 -1
  129. package/docs/guides/meta.json +1 -0
  130. package/docs/guides/remote-agents.md +1 -0
  131. package/docs/reference/project-layout.md +5 -4
  132. package/docs/reference/typescript-api.md +26 -26
  133. package/docs/sandbox.mdx +1 -1
  134. package/docs/skills.mdx +3 -1
  135. package/docs/subagents.mdx +2 -1
  136. package/package.json +1 -1
@@ -1 +1 @@
1
- import{createLogger,formatError}from"#internal/logging.js";import{callAdapterEventHandler,defaultDeliverResult}from"#channel/adapter.js";import{AuthKey,CapabilitiesKey,ContinuationTokenKey,ModeKey}from"#context/keys.js";import{createAuthorizationCompletedEvent,createSessionFailedEvent,encodeMessageStreamEvent,timestampHandleMessageStreamEvent}from"#protocol/message.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{getHarnessEmissionState}from"#harness/emission.js";import{createDurableSessionState,readDurableSession}from"#execution/durable-session-store.js";import{hydrateDurableSession,refreshSessionFromTurnAgent}from"#execution/session.js";import{deserializeContext,serializeContext}from"#context/serialize.js";import{resumeHook}from"#internal/workflow/runtime.js";import{buildAdapterContext}from"#channel/adapter-context.js";import{getPendingRuntimeActionBatch}from"#harness/runtime-actions.js";import{createWorkflowRuntime,startWorkflowPreferLatest,turnWorkflowReference}from"#execution/workflow-runtime.js";import{getPendingWorkflowInterrupt}from"#harness/workflow-interrupt-state.js";import{getRuntimeActionKeysFromWorkflowInterrupt,isWorkflowRuntimeActionInterrupt}from"#harness/workflow-runtime-action-state.js";import{upsertProxyInputRequests}from"#harness/proxy-input-requests.js";import{resolveWorkflowCallbackBaseUrl}from"#execution/workflow-callback-url.js";import{setChannelContext}from"#execution/channel-context.js";import{CallbackBaseUrlKey,PendingAuthorizationResultKey,clearPendingAuthorization,getPendingAuthorization}from"#harness/authorization.js";import{createTurnWorkflowInput}from"#execution/durable-session-migrations/turn-workflow.js";import{coalesceTurnInputs}from"#harness/messages.js";import{buildTurnAttributes,readRootSessionId}from"#execution/eve-workflow-attributes.js";import{normalizeEveAttributes}from"#runtime/attributes/normalize.js";import{dispatchStreamEventHooks}from"#context/hook-lifecycle.js";import{dispatchDynamicInstructionEvent}from"#context/dynamic-instruction-lifecycle.js";import{dispatchDynamicSkillEvent}from"#context/dynamic-skill-lifecycle.js";import{dispatchDynamicToolEvent}from"#context/dynamic-tool-lifecycle.js";import{runStep,withContextScope}from"#context/run-step.js";import{hasPendingInputBatch}from"#harness/input-requests.js";import{getRuntimeActionRequestKey}from"#runtime/actions/keys.js";import{createExecutionNodeStep}from"#execution/node-step.js";import{emitProxiedInputRequest,routeDeliverPayload}from"#execution/subagent-hitl-proxy.js";async function turnStep(e){"use step";let t=e,o=await readDurableSession(t.sessionState),l=await deserializeContext(t.serializedContext),f=l.require(ChannelKey),p=l.require(BundleKey);try{let{getWorkflowMetadata:e}=await import(`#compiled/@workflow/core/index.js`),t=e();typeof t.url==`string`&&l.set(CallbackBaseUrlKey,resolveWorkflowCallbackBaseUrl(t.url))}catch{}let m=getPendingAuthorization(o.state),h;if(m&&t.input?.kind===`deliver`){let e=[],n=[],r=[];for(let i of t.input.payloads){let t=i.authorizationCallback;if(t){let r=m.challenges.find(e=>e.name===t.connectionName);r&&(e.push({name:r.name,resume:r.resume,callback:t.callback,hookUrl:r.hookUrl}),n.push({name:r.name,authorization:r.challenge}))}else r.push(i)}e.length>0&&(l.set(PendingAuthorizationResultKey,e),o={...o,state:clearPendingAuthorization(o.state,e.map(e=>e.name))},h=n,t=r.length>0?{...t,input:{...t.input,payloads:r}}:{...t,input:void 0})}t.input?.kind===`deliver`&&t.input.auth!==void 0&&l.set(AuthKey,t.input.auth??null);let g=hydrateDurableSession({compactionOverrides:{thresholdPercent:p.resolvedAgent.config.compaction?.thresholdPercent},durable:o,turnAgent:p.turnAgent}),_=buildAdapterContext(f,l),v;if(t.input?.kind===`deliver`){let e=[];for(let n of t.input.payloads){let t=f.deliver?await f.deliver(n,_):defaultDeliverResult(n);t!=null&&e.push(t)}v=e.length===0?void 0:e.reduce(coalesceTurnInputs)}else t.input?.kind===`runtime-action-result`&&(v={runtimeActionResults:t.input.results});if(t.input?.kind===`deliver`&&setChannelContext(l,{...f,state:{..._.state}}),t.input?.kind===`deliver`&&v===void 0){let e=reconcileSessionContinuationToken(l,g),n=serializeContext(l),r=e===g?t.sessionState:createDurableSessionState({session:e});return{action:`park`,...derivePendingState(e),serializedContext:n,sessionState:r}}let y=t.parentWritable.getWriter(),b=p.hookRegistry,x=p.resolvedAgent.dynamicInstructionsResolvers??[],S=p.resolvedAgent.dynamicSkillResolvers??[],C=p.resolvedAgent.dynamicToolResolvers??[],emit=async e=>{let t=await callAdapterEventHandler(f,e,_);return setChannelContext(l,{...f,state:{..._.state}}),await y.write(encodeMessageStreamEvent(timestampHandleMessageStreamEvent(t))),t},handleEvent=async(e,t)=>{let n=await emit(e);await dispatchStreamEventHooks({ctx:l,registry:b,event:n}),await dispatchDynamicToolEvent({ctx:l,resolvers:C,event:n,messages:t??[]}),await dispatchDynamicSkillEvent({ctx:l,resolvers:S,event:n,messages:t??[]}),await dispatchDynamicInstructionEvent({ctx:l,resolvers:x,event:n,messages:t??[]})},w=l.require(ModeKey),T=await runStep(l,g,async e=>{let n=resolveEffectiveOutputSchema({agentOutputSchema:p.turnAgent.outputSchema,input:v,mode:w,session:e});if(h){let e=getHarnessEmissionState(n.state);for(let{name:t,authorization:n}of h)await handleEvent(createAuthorizationCompletedEvent({authorization:n,name:t,outcome:`authorized`,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId}))}let r=l.get(CapabilitiesKey);return(async(e,n)=>{let i=refreshSessionFromTurnAgent({compactionOverrides:{thresholdPercent:p.resolvedAgent.config.compaction?.thresholdPercent},session:e,turnAgent:p.turnAgent});return createExecutionNodeStep({abortSignal:t.abortSignal,capabilities:r,createRuntime:createWorkflowRuntime,handleEvent,mode:w,modelResolutionScope:{moduleMap:p.moduleMap,nodeId:p.nodeId},node:p.graph.root})(i,n)})(n,v)}),E=reconcileSessionContinuationToken(l,T.session),D=serializeContext(l);T={...T,session:E};let O=createDurableSessionState({session:T.session});if(T.next!==null&&typeof T.next==`object`&&`done`in T.next)return await y.close(),{action:`done`,output:T.next.output,isError:T.next.isError,serializedContext:D,sessionState:O};if(T.next===null){y.releaseLock();let e=getPendingWorkflowInterrupt(T.session.state);return e!==void 0&&isWorkflowRuntimeActionInterrupt(e.interrupt)?{action:`dispatch-workflow-runtime-actions`,pendingRuntimeActionKeys:getRuntimeActionKeysFromWorkflowInterrupt(e.interrupt),serializedContext:D,sessionState:O}:{action:`park`,...derivePendingState(T.session),serializedContext:D,sessionState:O}}return y.releaseLock(),{action:`continue`,serializedContext:D,sessionState:O}}function derivePendingState(e){let t=getPendingRuntimeActionBatch(e.state),n=getPendingAuthorization(e.state),r={authorizationNames:n?.challenges.map(e=>e.name),hasPendingAuthorization:n!==void 0,hasPendingInputBatch:hasPendingInputBatch(e.state)};return t===void 0?r:{...r,pendingRuntimeActionKeys:t.actions.map(e=>getRuntimeActionRequestKey(e))}}function reconcileSessionContinuationToken(e,t){let n=e.get(ContinuationTokenKey);return n===void 0||n===t.continuationToken?t:{...t,continuationToken:n}}function resolveEffectiveOutputSchema(e){let{agentOutputSchema:t,input:n,mode:r,session:i}=e;return n?.outputSchema===void 0?r===`task`&&i.outputSchema===void 0&&t!==void 0?{...i,outputSchema:t}:i:{...i,outputSchema:n.outputSchema}}const log=createLogger(`execution.workflow-entry`);async function emitTerminalSessionFailureStep(e){"use step";let r=formatError(e.error),i=typeof r.name==`string`?r.name:`WORKFLOW_EXECUTION_FAILED`,a=typeof r.message==`string`?r.message:String(e.error),o=e.serializedContext[`eve.sessionId`]??``;log.error(`workflow loop threw — emitting terminal session.failed`,{sessionId:o,errorId:typeof r.errorId==`string`?r.errorId:void 0,code:i,message:a,detail:typeof r.detail==`string`?r.detail:void 0});let s=createSessionFailedEvent({code:i,details:r,message:a,sessionId:o});try{let t=await deserializeContext(e.serializedContext),r=t.get(ChannelKey);r!==void 0&&await callAdapterEventHandler(r,s,buildAdapterContext(r,t))}catch(e){log.error(`adapter failed to handle terminal session.failed event`,{errorId:typeof r.errorId==`string`?r.errorId:void 0,sessionId:o,error:e})}try{let t=e.parentWritable.getWriter();try{await t.write(encodeMessageStreamEvent(timestampHandleMessageStreamEvent(s)))}finally{t.releaseLock()}}catch(e){log.error(`failed to write terminal session.failed event to durable stream`,{errorId:typeof r.errorId==`string`?r.errorId:void 0,sessionId:o,error:e})}}async function runProxyInputRequestStep(e){"use step";let t=await readDurableSession(e.sessionState),r=await deserializeContext(e.serializedContext),i=r.require(ChannelKey),a=buildAdapterContext(i,r),o=r.require(ModeKey),c=r.require(BundleKey),l=hydrateDurableSession({compactionOverrides:{thresholdPercent:c.resolvedAgent.config.compaction?.thresholdPercent},durable:t,turnAgent:c.turnAgent}),u=e.parentWritable.getWriter(),d;try{let emit=async e=>{let t=await callAdapterEventHandler(i,e,a);await u.write(encodeMessageStreamEvent(timestampHandleMessageStreamEvent(t)))};d=await withContextScope(r,l,async t=>{let n=await emitProxiedInputRequest({emit,hookPayload:e.hookPayload,mode:o,session:t});return{result:n.entries,session:n.session}})}finally{u.releaseLock()}return setChannelContext(r,{...i,state:{...a.state}}),{serializedContext:serializeContext(r),sessionState:createDurableSessionState({session:reconcileSessionContinuationToken(r,upsertProxyInputRequests({entries:d.result,forChildContinuationToken:e.hookPayload.childContinuationToken,session:d.session}))})}}async function routeProxiedDeliverStep(e){"use step";let t=await readDurableSession(e.sessionState),n=routeDeliverPayload({payload:e.payload,state:t.state});for(let t of n.forChildren)await resumeHook(t.childContinuationToken,{auth:e.auth,kind:`deliver`,payloads:[t.payload]});return{remainder:n.forSelf}}async function dispatchTurnStep(e){"use step";return{runId:(await startWorkflowPreferLatest(turnWorkflowReference,[createTurnWorkflowInput(e)],{allowReservedAttributes:!0,attributes:normalizeEveAttributes(buildTurnAttributes({parentSessionId:e.sessionState.sessionId,requestId:e.delivery.kind===`deliver`?e.delivery.requestId:void 0,rootSessionId:readRootSessionId(e.serializedContext)??e.sessionState.sessionId}))})).runId}}export{dispatchTurnStep,emitTerminalSessionFailureStep,reconcileSessionContinuationToken,resolveEffectiveOutputSchema,routeProxiedDeliverStep,runProxyInputRequestStep,turnStep};
1
+ import{createLogger,formatError}from"#internal/logging.js";import{callAdapterEventHandler,defaultDeliverResult}from"#channel/adapter.js";import{AuthKey,CapabilitiesKey,ContinuationTokenKey,ModeKey}from"#context/keys.js";import{createAuthorizationCompletedEvent,createSessionFailedEvent,encodeMessageStreamEvent,timestampHandleMessageStreamEvent}from"#protocol/message.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{getHarnessEmissionState}from"#harness/emission.js";import{createDurableSessionState,readDurableSession}from"#execution/durable-session-store.js";import{hydrateDurableSession,refreshSessionFromTurnAgent}from"#execution/session.js";import{deserializeContext,serializeContext}from"#context/serialize.js";import{resumeHook}from"#internal/workflow/runtime.js";import{buildAdapterContext}from"#channel/adapter-context.js";import{getPendingRuntimeActionBatch}from"#harness/runtime-actions.js";import{createWorkflowRuntime,startWorkflowPreferLatest,turnWorkflowReference}from"#execution/workflow-runtime.js";import{getPendingWorkflowInterrupt}from"#harness/workflow-interrupt-state.js";import{getRuntimeActionKeysFromWorkflowInterrupt,isWorkflowRuntimeActionInterrupt}from"#harness/workflow-runtime-action-state.js";import{upsertProxyInputRequests}from"#harness/proxy-input-requests.js";import{resolveWorkflowCallbackBaseUrl}from"#execution/workflow-callback-url.js";import{setChannelContext}from"#execution/channel-context.js";import{CallbackBaseUrlKey,PendingAuthorizationResultKey,clearPendingAuthorization,getPendingAuthorization}from"#harness/authorization.js";import{createTurnWorkflowInput}from"#execution/durable-session-migrations/turn-workflow.js";import{coalesceTurnInputs}from"#harness/messages.js";import{buildTurnAttributes,readRootSessionId}from"#execution/eve-workflow-attributes.js";import{normalizeEveAttributes}from"#runtime/attributes/normalize.js";import{dispatchStreamEventHooks}from"#context/hook-lifecycle.js";import{dispatchDynamicInstructionEvent}from"#context/dynamic-instruction-lifecycle.js";import{dispatchDynamicSkillEvent}from"#context/dynamic-skill-lifecycle.js";import{dispatchDynamicToolEvent}from"#context/dynamic-tool-lifecycle.js";import{runStep,withContextScope}from"#context/run-step.js";import{hasPendingInputBatch}from"#harness/input-requests.js";import{getTurnUsageState,toUsage}from"#harness/turn-tag-state.js";import{getRuntimeActionRequestKey}from"#runtime/actions/keys.js";import{createExecutionNodeStep}from"#execution/node-step.js";import{emitProxiedInputRequest,routeDeliverPayload}from"#execution/subagent-hitl-proxy.js";import{recordSubagentUsageSpans}from"#execution/subagent-usage-span.js";import{resolveSessionSkillRoot}from"#execution/workflow-skill-root.js";async function turnStep(e){"use step";let t=e,o=await readDurableSession(t.sessionState),l=await deserializeContext(t.serializedContext),f=l.require(ChannelKey),p=l.require(BundleKey);try{let{getWorkflowMetadata:e}=await import(`#compiled/@workflow/core/index.js`),t=e();typeof t.url==`string`&&l.set(CallbackBaseUrlKey,resolveWorkflowCallbackBaseUrl(t.url))}catch{}let m=getPendingAuthorization(o.state),h;if(m&&t.input?.kind===`deliver`){let e=[],n=[],r=[];for(let i of t.input.payloads){let t=i.authorizationCallback;if(t){let r=m.challenges.find(e=>e.name===t.connectionName);r&&(e.push({name:r.name,resume:r.resume,callback:t.callback,hookUrl:r.hookUrl}),n.push({name:r.name,authorization:r.challenge}))}else r.push(i)}e.length>0&&(l.set(PendingAuthorizationResultKey,e),o={...o,state:clearPendingAuthorization(o.state,e.map(e=>e.name))},h=n,t=r.length>0?{...t,input:{...t.input,payloads:r}}:{...t,input:void 0})}t.input?.kind===`deliver`&&t.input.auth!==void 0&&l.set(AuthKey,t.input.auth??null);let g=hydrateDurableSession({compactionOverrides:{thresholdPercent:p.resolvedAgent.config.compaction?.thresholdPercent},durable:o,turnAgent:p.turnAgent}),_=buildAdapterContext(f,l),v;if(t.input?.kind===`deliver`){let e=[];for(let n of t.input.payloads){let t=f.deliver?await f.deliver(n,_):defaultDeliverResult(n);t!=null&&e.push(t)}v=e.length===0?void 0:e.reduce(coalesceTurnInputs)}else t.input?.kind===`runtime-action-result`&&(recordSubagentUsageSpans(t.input.results),v={runtimeActionResults:t.input.results});if(t.input?.kind===`deliver`&&setChannelContext(l,{...f,state:{..._.state}}),t.input?.kind===`deliver`&&v===void 0){let e=reconcileSessionContinuationToken(l,g),n=serializeContext(l),r=e===g?t.sessionState:createDurableSessionState({session:e});return{action:`park`,...derivePendingState(e),serializedContext:n,sessionState:r}}let y=t.parentWritable.getWriter(),b=p.hookRegistry,x=p.resolvedAgent.dynamicInstructionsResolvers??[],S=p.resolvedAgent.dynamicSkillResolvers??[],C=p.resolvedAgent.dynamicToolResolvers??[],emit=async e=>{let t=await callAdapterEventHandler(f,e,_);return setChannelContext(l,{...f,state:{..._.state}}),await y.write(encodeMessageStreamEvent(timestampHandleMessageStreamEvent(t))),t},handleEvent=async(e,t)=>{let n=await emit(e);await dispatchStreamEventHooks({ctx:l,registry:b,event:n}),await dispatchDynamicToolEvent({ctx:l,resolvers:C,event:n,messages:t??[]}),await dispatchDynamicSkillEvent({ctx:l,resolvers:S,event:n,messages:t??[]}),await dispatchDynamicInstructionEvent({ctx:l,resolvers:x,event:n,messages:t??[]})},w=l.require(ModeKey),T=await runStep(l,g,async e=>{let n=resolveEffectiveOutputSchema({agentOutputSchema:p.turnAgent.outputSchema,input:v,mode:w,session:e});if(h){let e=getHarnessEmissionState(n.state);for(let{name:t,authorization:n}of h)await handleEvent(createAuthorizationCompletedEvent({authorization:n,name:t,outcome:`authorized`,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId}))}let r=l.get(CapabilitiesKey);return(async(e,n)=>{let i=await resolveSessionSkillRoot({ctx:l,turnAgent:p.turnAgent}),a=refreshSessionFromTurnAgent({compactionOverrides:{thresholdPercent:p.resolvedAgent.config.compaction?.thresholdPercent},session:e,skillRoot:i,turnAgent:p.turnAgent});return createExecutionNodeStep({abortSignal:t.abortSignal,capabilities:r,createRuntime:createWorkflowRuntime,handleEvent,mode:w,modelResolutionScope:{moduleMap:p.moduleMap,nodeId:p.nodeId},node:p.graph.root,workflowMaxSubagents:a.workflowMaxSubagents})(a,n)})(n,v)}),E=reconcileSessionContinuationToken(l,T.session),D=serializeContext(l);T={...T,session:E};let O=createDurableSessionState({session:T.session});if(T.next!==null&&typeof T.next==`object`&&`done`in T.next){await y.close();let e=getTurnUsageState(T.session.state)?.session;return{action:`done`,output:T.next.output,isError:T.next.isError,serializedContext:D,sessionState:O,usage:e===void 0?void 0:toUsage(e)}}if(T.next===null){y.releaseLock();let e=getPendingWorkflowInterrupt(T.session.state);return e!==void 0&&isWorkflowRuntimeActionInterrupt(e.interrupt)?{action:`dispatch-workflow-runtime-actions`,pendingRuntimeActionKeys:getRuntimeActionKeysFromWorkflowInterrupt(e.interrupt),serializedContext:D,sessionState:O}:{action:`park`,...derivePendingState(T.session),serializedContext:D,sessionState:O}}return y.releaseLock(),{action:`continue`,serializedContext:D,sessionState:O}}function derivePendingState(e){let t=getPendingRuntimeActionBatch(e.state),n=getPendingAuthorization(e.state),r={authorizationNames:n?.challenges.map(e=>e.name),hasPendingAuthorization:n!==void 0,hasPendingInputBatch:hasPendingInputBatch(e.state)};return t===void 0?r:{...r,pendingRuntimeActionKeys:t.actions.map(e=>getRuntimeActionRequestKey(e))}}function reconcileSessionContinuationToken(e,t){let n=e.get(ContinuationTokenKey);return n===void 0||n===t.continuationToken?t:{...t,continuationToken:n}}function resolveEffectiveOutputSchema(e){let{agentOutputSchema:t,input:n,mode:r,session:i}=e;return n?.outputSchema===void 0?r===`task`&&i.outputSchema===void 0&&t!==void 0?{...i,outputSchema:t}:i:{...i,outputSchema:n.outputSchema}}const log=createLogger(`execution.workflow-entry`);async function emitTerminalSessionFailureStep(e){"use step";let r=formatError(e.error),i=typeof r.name==`string`?r.name:`WORKFLOW_EXECUTION_FAILED`,a=typeof r.message==`string`?r.message:String(e.error),o=e.serializedContext[`eve.sessionId`]??``;log.error(`workflow loop threw — emitting terminal session.failed`,{sessionId:o,errorId:typeof r.errorId==`string`?r.errorId:void 0,code:i,message:a,detail:typeof r.detail==`string`?r.detail:void 0});let s=createSessionFailedEvent({code:i,details:r,message:a,sessionId:o});try{let t=await deserializeContext(e.serializedContext),r=t.get(ChannelKey);r!==void 0&&await callAdapterEventHandler(r,s,buildAdapterContext(r,t))}catch(e){log.error(`adapter failed to handle terminal session.failed event`,{errorId:typeof r.errorId==`string`?r.errorId:void 0,sessionId:o,error:e})}try{let t=e.parentWritable.getWriter();try{await t.write(encodeMessageStreamEvent(timestampHandleMessageStreamEvent(s)))}finally{t.releaseLock()}}catch(e){log.error(`failed to write terminal session.failed event to durable stream`,{errorId:typeof r.errorId==`string`?r.errorId:void 0,sessionId:o,error:e})}}async function runProxyInputRequestStep(e){"use step";let t=await readDurableSession(e.sessionState),r=await deserializeContext(e.serializedContext),i=r.require(ChannelKey),a=buildAdapterContext(i,r),o=r.require(ModeKey),c=r.require(BundleKey),l=hydrateDurableSession({compactionOverrides:{thresholdPercent:c.resolvedAgent.config.compaction?.thresholdPercent},durable:t,turnAgent:c.turnAgent}),u=e.parentWritable.getWriter(),d;try{let emit=async e=>{let t=await callAdapterEventHandler(i,e,a);await u.write(encodeMessageStreamEvent(timestampHandleMessageStreamEvent(t)))};d=await withContextScope(r,l,async t=>{let n=await emitProxiedInputRequest({emit,hookPayload:e.hookPayload,mode:o,session:t});return{result:n.entries,session:n.session}})}finally{u.releaseLock()}return setChannelContext(r,{...i,state:{...a.state}}),{serializedContext:serializeContext(r),sessionState:createDurableSessionState({session:reconcileSessionContinuationToken(r,upsertProxyInputRequests({entries:d.result,forChildContinuationToken:e.hookPayload.childContinuationToken,session:d.session}))})}}async function routeProxiedDeliverStep(e){"use step";let t=await readDurableSession(e.sessionState),n=routeDeliverPayload({payload:e.payload,state:t.state});for(let t of n.forChildren)await resumeHook(t.childContinuationToken,{auth:e.auth,kind:`deliver`,payloads:[t.payload]});return{remainder:n.forSelf}}async function dispatchTurnStep(e){"use step";return{runId:(await startWorkflowPreferLatest(turnWorkflowReference,[createTurnWorkflowInput(e)],{allowReservedAttributes:!0,attributes:normalizeEveAttributes(buildTurnAttributes({parentSessionId:e.sessionState.sessionId,requestId:e.delivery.kind===`deliver`?e.delivery.requestId:void 0,rootSessionId:readRootSessionId(e.serializedContext)??e.sessionState.sessionId}))})).runId}}export{dispatchTurnStep,emitTerminalSessionFailureStep,reconcileSessionContinuationToken,resolveEffectiveOutputSchema,routeProxiedDeliverStep,runProxyInputRequestStep,turnStep};
@@ -20,6 +20,7 @@ type AdvertisedModelToolsInput = {
20
20
  readonly session: HarnessSession;
21
21
  readonly tools: HarnessToolMap;
22
22
  }) => WorkflowSandboxLifecycle | undefined;
23
+ readonly maxSubagents?: number;
23
24
  };
24
25
  };
25
26
  type AdvertisedModelTools = {
@@ -1 +1 @@
1
- import{resolveSubagentDelegationLimit}from"#harness/subagent-depth.js";import{ensureWorkflowContinuationSecurity,getWorkflowContinuationSecurity}from"#harness/workflow-continuation-security.js";import{applyWorkflowTool}from"#harness/workflow-sandbox.js";function getAdvertisedTools(e){return`modelTools`in e?getAdvertisedModelTools(e):isToolDefinitionList(e.tools)?filterSubagentToolDefinitionsAtDepthLimit(e.tools,e.session):filterSubagentToolMapAtDepthLimit(e.tools,e.session)}async function getAdvertisedModelTools(e){let i=filterSubagentToolMapAtDepthLimit(e.tools,e.session);if(e.workflow===void 0)return{harnessTools:i,modelTools:e.modelTools,session:e.session};let a=filterWorkflowHostToolsForRootSession(i,e.session);if(a.size===0)return{harnessTools:i,modelTools:e.modelTools,session:e.session};let o=ensureWorkflowContinuationSecurity(e.session),{modelTools:s}=await applyWorkflowTool({continuationSecurity:getWorkflowContinuationSecurity(o),harnessTools:a,lifecycle:e.workflow.lifecycle?.({session:o,tools:a}),tools:e.modelTools});return{harnessTools:i,modelTools:s,session:o}}function filterSubagentToolDefinitionsAtDepthLimit(t,n){let r=resolveSubagentDelegationLimit(n),i=[];for(let e of t)r.reached&&isDelegatedRuntimeActionTool(e)||i.push(e);return i}function filterSubagentToolMapAtDepthLimit(t,n){let r=resolveSubagentDelegationLimit(n),i=new Map;for(let[e,n]of t)r.reached&&isDelegatedRuntimeActionTool(n)||i.set(e,n);return i}function filterWorkflowHostToolsForRootSession(t,n){let r=new Map,i=resolveSubagentDelegationLimit(n);if(n.rootSessionId!==void 0||i.currentDepth>0)return r;for(let[e,n]of t)isDelegatedRuntimeActionTool(n)&&r.set(e,n);return r}function isDelegatedRuntimeActionTool(e){let t=e.runtimeAction;return t?.kind===`subagent-call`||t?.kind===`remote-agent-call`}function isToolDefinitionList(e){return Array.isArray(e)}export{getAdvertisedTools};
1
+ import{resolveSubagentDelegationLimit}from"#harness/subagent-depth.js";import{ensureWorkflowContinuationSecurity,getWorkflowContinuationSecurity}from"#harness/workflow-continuation-security.js";import{applyWorkflowTool}from"#harness/workflow-sandbox.js";function getAdvertisedTools(e){return`modelTools`in e?getAdvertisedModelTools(e):isToolDefinitionList(e.tools)?filterSubagentToolDefinitionsAtDepthLimit(e.tools,e.session):filterSubagentToolMapAtDepthLimit(e.tools,e.session)}async function getAdvertisedModelTools(e){let i=filterSubagentToolMapAtDepthLimit(e.tools,e.session);if(e.workflow===void 0)return{harnessTools:i,modelTools:e.modelTools,session:e.session};let a=filterWorkflowHostToolsForRootSession(i,e.session);if(a.size===0)return{harnessTools:i,modelTools:e.modelTools,session:e.session};let o=ensureWorkflowContinuationSecurity(e.session),{modelTools:s}=await applyWorkflowTool({continuationSecurity:getWorkflowContinuationSecurity(o),harnessTools:a,lifecycle:e.workflow.lifecycle?.({session:o,tools:a}),maxSubagents:e.workflow.maxSubagents,tools:e.modelTools});return{harnessTools:i,modelTools:s,session:o}}function filterSubagentToolDefinitionsAtDepthLimit(t,n){let r=resolveSubagentDelegationLimit(n),i=[];for(let e of t)r.reached&&isDelegatedRuntimeActionTool(e)||i.push(e);return i}function filterSubagentToolMapAtDepthLimit(t,n){let r=resolveSubagentDelegationLimit(n),i=new Map;for(let[e,n]of t)r.reached&&isDelegatedRuntimeActionTool(n)||i.set(e,n);return i}function filterWorkflowHostToolsForRootSession(t,n){let r=new Map,i=resolveSubagentDelegationLimit(n);if(n.rootSessionId!==void 0||i.currentDepth>0)return r;for(let[e,n]of t)isDelegatedRuntimeActionTool(n)&&r.set(e,n);return r}function isDelegatedRuntimeActionTool(e){let t=e.runtimeAction;return t?.kind===`subagent-call`||t?.kind===`remote-agent-call`}function isToolDefinitionList(e){return Array.isArray(e)}export{getAdvertisedTools};
@@ -62,6 +62,14 @@ export declare function resolvePendingInput(input: {
62
62
  type ResolvePendingInputResult = {
63
63
  readonly consumedMessage?: boolean;
64
64
  readonly deferredMessage?: boolean;
65
+ /**
66
+ * Present when the resolved batch answered a session-limit continuation
67
+ * prompt. The tool loop grants a fresh token budget window or terminates
68
+ * the session based on `granted`.
69
+ */
70
+ readonly limitContinuation?: {
71
+ readonly granted: boolean;
72
+ };
65
73
  readonly outcome: "resolved" | "continue" | "unresolved";
66
74
  readonly messages: ModelMessage[];
67
75
  readonly rejectedActions?: RejectedActionBatch;
@@ -1 +1 @@
1
- import{resolveTextToResponses}from"#channel/resolve-text.js";import{parseJsonObject}from"#shared/json.js";import{coalesceTurnInputs}from"#harness/messages.js";const PENDING_INPUT_BATCH_KEY=`eve.runtime.pendingInputBatch`,APPROVED_TOOLS_KEY=`eve.runtime.hitl.approvedTools`,DEFERRED_STEP_INPUT_KEY=`eve.runtime.deferredStepInput`,TOOL_EXECUTION_DENIED_MESSAGE=`Tool execution was denied.`;function hasStepInput(e){return e===void 0?!1:e.message!==void 0||(e.inputResponses?.length??0)>0}function consumeDeferredStepInput(e){let t=getDeferredStepInput(e.session);if(t===void 0)return e;let r=clearDeferredStepInput(e.session);return e.input===void 0?{input:t,session:r}:{input:coalesceTurnInputs(t,e.input),session:r}}function hasDeferredStepInput(e){return getDeferredStepInput(e)!==void 0}function resolvePendingInput(e){let{stepInput:t}=e,n=e.session,r=[...e.history??n.history],i=getPendingInputBatch(n.state);if(i===void 0)return{outcome:`continue`,messages:r,session:n};let a=resolveTextMessageInput(i,t),o=a?.inputResponses??[];if(o.length===0&&a?.message===void 0)return{outcome:`unresolved`,messages:r,session:n};if(i.requests.some(e=>isApprovalRequest(e))&&hasUnansweredApproval({pendingBatch:i,responses:o}))return n=queueDeferredStepInput(n,compactStepInput(a)),{deferredMessage:!0,outcome:`unresolved`,messages:r,session:n};if(o.length===0&&a?.message!==void 0){let e=buildToolResponseParts(i,[]),t=[...r,...i.responseMessages];e.length>0&&t.push({content:e,role:`tool`});let o=buildRejectedActionBatch(i,[]);return n=clearPendingInputBatch(n),{consumedMessage:a?.messageConsumed,outcome:`resolved`,messages:t,rejectedActions:o,session:n}}n=recordApprovedTools({pendingBatch:i,resolveApprovalKey:e.resolveApprovalKey,responses:o,session:n});let s=buildToolResponseParts(i,o),c=[...r,...i.responseMessages];s.length>0&&c.push({content:s,role:`tool`});let l=buildRejectedActionBatch(i,o);return n=clearPendingInputBatch(n),a?.message!==void 0&&i.requests.some(e=>isApprovalRequest(e))?(n=queueDeferredStepInput(n,{message:a.message}),{consumedMessage:a?.messageConsumed,deferredMessage:!0,outcome:`resolved`,messages:c,rejectedActions:l,session:n}):{consumedMessage:a?.messageConsumed,outcome:`resolved`,messages:c,rejectedActions:l,session:n}}function resolveTextMessageInput(t,n){if(typeof n?.message!=`string`||(n.inputResponses?.length??0)>0)return n;let r=resolveTextToResponses(n.message,t.requests);return r.length===0?n:compactStepInput({...n,inputResponses:r,messageConsumed:!0,message:void 0})}function compactStepInput(e){if(e===void 0)return{};let t={};return(e.context?.length??0)>0&&(t.context=e.context),(e.inputResponses?.length??0)>0&&(t.inputResponses=e.inputResponses),e.message!==void 0&&(t.message=e.message),e.messageConsumed===!0&&(t.messageConsumed=!0),e.outputSchema!==void 0&&(t.outputSchema=e.outputSchema),t}function hasUnansweredApproval(e){let t=new Set(e.responses.map(e=>e.requestId));return e.pendingBatch.requests.some(e=>isApprovalRequest(e)&&!t.has(e.requestId))}function hasPendingInputBatch(e){return getPendingInputBatch(e)!==void 0}function getPendingInputBatch(e){let t=e?.[PENDING_INPUT_BATCH_KEY];if(typeof t!=`object`||!t)return;let n=t;if(!(!Array.isArray(n.requests)||!Array.isArray(n.responseMessages)))return n}function setPendingInputBatch(e){let t={...e.session.state};return t[PENDING_INPUT_BATCH_KEY]={event:e.event,requests:[...e.requests],responseMessages:[...e.responseMessages]},{...e.session,state:t}}function clearPendingInputBatch(e){if(e.state?.[PENDING_INPUT_BATCH_KEY]===void 0)return e;let t={...e.state};return delete t[PENDING_INPUT_BATCH_KEY],{...e,state:Object.keys(t).length>0?t:void 0}}function getDeferredStepInput(e){return e.state?.[DEFERRED_STEP_INPUT_KEY]}function queueDeferredStepInput(e,t){let r=getDeferredStepInput(e),i=r===void 0?t:coalesceTurnInputs(r,t),o={...e.state};return o[DEFERRED_STEP_INPUT_KEY]=i,{...e,state:o}}function clearDeferredStepInput(e){if(e.state?.[DEFERRED_STEP_INPUT_KEY]===void 0)return e;let t={...e.state};return delete t[DEFERRED_STEP_INPUT_KEY],{...e,state:Object.keys(t).length>0?t:void 0}}function getApprovedTools(e){let t=e.state?.[APPROVED_TOOLS_KEY];return Array.isArray(t)?new Set(t):new Set}function recordApprovedTools(e){let t=new Set(e.responses.filter(e=>e.optionId===`approve`).map(e=>e.requestId)),n=e.pendingBatch.requests.filter(e=>t.has(e.requestId)).map(t=>e.resolveApprovalKey?.(t)??t.action.toolName);if(n.length===0)return e.session;let r=getApprovedTools(e.session),a=[...new Set([...r,...n])],o={...e.session.state};return o[APPROVED_TOOLS_KEY]=a,{...e.session,state:o}}function resolveApprovalOutcome(e){return e===void 0?{approved:!1,reason:`Ignored because the user continued without responding.`,status:`ignored`}:e.optionId===`approve`?{approved:!0,reason:void 0,status:`approved`}:e.optionId===`deny`?{approved:!1,reason:TOOL_EXECUTION_DENIED_MESSAGE,status:`denied`}:{approved:!1,reason:`Invalid approval response.`,status:`invalid`}}function buildRejectedActionBatch(e,t){if(e.event===void 0)return;let n=new Map(t.map(e=>[e.requestId,e])),r=[];for(let t of e.requests){if(!isApprovalRequest(t))continue;let{approved:e,reason:i,status:a}=resolveApprovalOutcome(n.get(t.requestId));e||r.push({callId:t.action.callId,isError:!0,kind:`tool-result`,output:{approval:{requestId:t.requestId,status:a},code:`TOOL_EXECUTION_DENIED`,message:i??TOOL_EXECUTION_DENIED_MESSAGE,tool:{result:`not_run`}},toolName:t.action.toolName})}return r.length>0?{event:e.event,results:r}:void 0}function buildToolResponseParts(e,t){let n=new Map(t.map(e=>[e.requestId,e])),r=[];for(let t of e.requests)r.push(...buildToolResponsePartsForRequest(t,n.get(t.requestId)));return r}function buildToolResponsePartsForRequest(e,t){if(isApprovalRequest(e)){let{approved:n,reason:r}=resolveApprovalOutcome(t),i=[{approvalId:e.requestId,approved:n,reason:r,type:`tool-approval-response`}];return n||i.push({output:{type:`execution-denied`,reason:r},toolCallId:e.action.callId,toolName:e.action.toolName,type:`tool-result`}),i}return[{output:{type:`json`,value:t===void 0?{status:`ignored`}:{optionId:t.optionId,text:t.text,status:`answered`}},toolCallId:e.action.callId,toolName:e.action.toolName,type:`tool-result`}]}function isApprovalRequest(e){return e.options?.length===2&&e.options[0]?.id===`approve`&&e.options[1]?.id===`deny`}function createRuntimeToolCallActionFromToolCall(e){return{callId:e.toolCall.toolCallId,input:resolveToolCallInputObject(e.toolCall.input),kind:`tool-call`,toolName:e.toolCall.toolName}}function resolveToolCallInputObject(e){return e==null?{}:parseJsonObject(e)}export{consumeDeferredStepInput,createRuntimeToolCallActionFromToolCall,getApprovedTools,hasDeferredStepInput,hasPendingInputBatch,hasStepInput,resolvePendingInput,setPendingInputBatch};
1
+ import{resolveTextToResponses}from"#channel/resolve-text.js";import{parseJsonObject}from"#shared/json.js";import{coalesceTurnInputs}from"#harness/messages.js";import{isSessionLimitContinuationRequest,resolveSessionLimitContinuation}from"#harness/session-limit-continuation.js";const PENDING_INPUT_BATCH_KEY=`eve.runtime.pendingInputBatch`,APPROVED_TOOLS_KEY=`eve.runtime.hitl.approvedTools`,DEFERRED_STEP_INPUT_KEY=`eve.runtime.deferredStepInput`,TOOL_EXECUTION_DENIED_MESSAGE=`Tool execution was denied.`;function hasStepInput(e){return e===void 0?!1:e.message!==void 0||(e.inputResponses?.length??0)>0}function consumeDeferredStepInput(e){let t=getDeferredStepInput(e.session);if(t===void 0)return e;let r=clearDeferredStepInput(e.session);return e.input===void 0?{input:t,session:r}:{input:coalesceTurnInputs(t,e.input),session:r}}function hasDeferredStepInput(e){return getDeferredStepInput(e)!==void 0}function resolvePendingInput(e){let{stepInput:t}=e,n=e.session,r=[...e.history??n.history],a=getPendingInputBatch(n.state);if(a===void 0)return{outcome:`continue`,messages:r,session:n};let o=resolveTextMessageInput(a,t),s=o?.inputResponses??[];if(s.length===0&&o?.message===void 0)return{outcome:`unresolved`,messages:r,session:n};if(a.requests.some(e=>isApprovalRequest(e))&&hasUnansweredApproval({pendingBatch:a,responses:s}))return n=queueDeferredStepInput(n,compactStepInput(o)),{deferredMessage:!0,outcome:`unresolved`,messages:r,session:n};if(s.length===0&&o?.message!==void 0){let e=buildToolResponseParts(a,[]),t=[...r,...a.responseMessages];e.length>0&&t.push({content:e,role:`tool`});let i=buildRejectedActionBatch(a,[]);return n=clearPendingInputBatch(n),{consumedMessage:o?.messageConsumed,outcome:`resolved`,messages:t,rejectedActions:i,session:n}}let c=resolveSessionLimitContinuation({requests:a.requests,responses:s});n=recordApprovedTools({pendingBatch:a,resolveApprovalKey:e.resolveApprovalKey,responses:s,session:n});let l=buildToolResponseParts(a,s),u=[...r,...a.responseMessages];l.length>0&&u.push({content:l,role:`tool`});let d=buildRejectedActionBatch(a,s);return n=clearPendingInputBatch(n),o?.message!==void 0&&a.requests.some(e=>isApprovalRequest(e))?(n=queueDeferredStepInput(n,{message:o.message}),{consumedMessage:o?.messageConsumed,deferredMessage:!0,limitContinuation:c,outcome:`resolved`,messages:u,rejectedActions:d,session:n}):{consumedMessage:o?.messageConsumed,limitContinuation:c,outcome:`resolved`,messages:u,rejectedActions:d,session:n}}function resolveTextMessageInput(t,n){if(typeof n?.message!=`string`||(n.inputResponses?.length??0)>0)return n;let r=resolveTextToResponses(n.message,t.requests);return r.length===0?n:compactStepInput({...n,inputResponses:r,messageConsumed:!0,message:void 0})}function compactStepInput(e){if(e===void 0)return{};let t={};return(e.context?.length??0)>0&&(t.context=e.context),(e.inputResponses?.length??0)>0&&(t.inputResponses=e.inputResponses),e.message!==void 0&&(t.message=e.message),e.messageConsumed===!0&&(t.messageConsumed=!0),e.outputSchema!==void 0&&(t.outputSchema=e.outputSchema),t}function hasUnansweredApproval(e){let t=new Set(e.responses.map(e=>e.requestId));return e.pendingBatch.requests.some(e=>isApprovalRequest(e)&&!t.has(e.requestId))}function hasPendingInputBatch(e){return getPendingInputBatch(e)!==void 0}function getPendingInputBatch(e){let t=e?.[PENDING_INPUT_BATCH_KEY];if(typeof t!=`object`||!t)return;let n=t;if(!(!Array.isArray(n.requests)||!Array.isArray(n.responseMessages)))return n}function setPendingInputBatch(e){let t={...e.session.state};return t[PENDING_INPUT_BATCH_KEY]={event:e.event,requests:[...e.requests],responseMessages:[...e.responseMessages]},{...e.session,state:t}}function clearPendingInputBatch(e){if(e.state?.[PENDING_INPUT_BATCH_KEY]===void 0)return e;let t={...e.state};return delete t[PENDING_INPUT_BATCH_KEY],{...e,state:Object.keys(t).length>0?t:void 0}}function getDeferredStepInput(e){return e.state?.[DEFERRED_STEP_INPUT_KEY]}function queueDeferredStepInput(e,t){let r=getDeferredStepInput(e),i=r===void 0?t:coalesceTurnInputs(r,t),a={...e.state};return a[DEFERRED_STEP_INPUT_KEY]=i,{...e,state:a}}function clearDeferredStepInput(e){if(e.state?.[DEFERRED_STEP_INPUT_KEY]===void 0)return e;let t={...e.state};return delete t[DEFERRED_STEP_INPUT_KEY],{...e,state:Object.keys(t).length>0?t:void 0}}function getApprovedTools(e){let t=e.state?.[APPROVED_TOOLS_KEY];return Array.isArray(t)?new Set(t):new Set}function recordApprovedTools(e){let t=new Set(e.responses.filter(e=>e.optionId===`approve`).map(e=>e.requestId)),n=e.pendingBatch.requests.filter(e=>t.has(e.requestId)).map(t=>e.resolveApprovalKey?.(t)??t.action.toolName);if(n.length===0)return e.session;let r=getApprovedTools(e.session),i=[...new Set([...r,...n])],a={...e.session.state};return a[APPROVED_TOOLS_KEY]=i,{...e.session,state:a}}function resolveApprovalOutcome(e){return e===void 0?{approved:!1,reason:`Ignored because the user continued without responding.`,status:`ignored`}:e.optionId===`approve`?{approved:!0,reason:void 0,status:`approved`}:e.optionId===`deny`?{approved:!1,reason:TOOL_EXECUTION_DENIED_MESSAGE,status:`denied`}:{approved:!1,reason:`Invalid approval response.`,status:`invalid`}}function buildRejectedActionBatch(e,t){if(e.event===void 0)return;let n=new Map(t.map(e=>[e.requestId,e])),r=[];for(let t of e.requests){if(!isApprovalRequest(t))continue;let{approved:e,reason:i,status:a}=resolveApprovalOutcome(n.get(t.requestId));e||r.push({callId:t.action.callId,isError:!0,kind:`tool-result`,output:{approval:{requestId:t.requestId,status:a},code:`TOOL_EXECUTION_DENIED`,message:i??TOOL_EXECUTION_DENIED_MESSAGE,tool:{result:`not_run`}},toolName:t.action.toolName})}return r.length>0?{event:e.event,results:r}:void 0}function buildToolResponseParts(e,t){let n=new Map(t.map(e=>[e.requestId,e])),r=[];for(let t of e.requests)r.push(...buildToolResponsePartsForRequest(t,n.get(t.requestId)));return r}function buildToolResponsePartsForRequest(e,t){if(isSessionLimitContinuationRequest(e))return[];if(isApprovalRequest(e)){let{approved:n,reason:r}=resolveApprovalOutcome(t),i=[{approvalId:e.requestId,approved:n,reason:r,type:`tool-approval-response`}];return n||i.push({output:{type:`execution-denied`,reason:r},toolCallId:e.action.callId,toolName:e.action.toolName,type:`tool-result`}),i}return[{output:{type:`json`,value:t===void 0?{status:`ignored`}:{optionId:t.optionId,text:t.text,status:`answered`}},toolCallId:e.action.callId,toolName:e.action.toolName,type:`tool-result`}]}function isApprovalRequest(e){return e.options?.length===2&&e.options[0]?.id===`approve`&&e.options[1]?.id===`deny`}function createRuntimeToolCallActionFromToolCall(e){return{callId:e.toolCall.toolCallId,input:resolveToolCallInputObject(e.toolCall.input),kind:`tool-call`,toolName:e.toolCall.toolName}}function resolveToolCallInputObject(e){return e==null?{}:parseJsonObject(e)}export{consumeDeferredStepInput,createRuntimeToolCallActionFromToolCall,getApprovedTools,hasDeferredStepInput,hasPendingInputBatch,hasStepInput,resolvePendingInput,setPendingInputBatch};
@@ -1 +1 @@
1
- import{createActionResultEvent}from"#protocol/message.js";import{parseJsonObject}from"#shared/json.js";import{clearProxyInputRequestsForChild}from"#harness/proxy-input-requests.js";import{getRuntimeActionRequestKey,getRuntimeActionResultKey}from"#runtime/actions/keys.js";const PENDING_RUNTIME_ACTION_BATCH_KEY=`eve.runtime.pendingActionBatch`;function getPendingRuntimeActionBatch(e){let t=e?.[PENDING_RUNTIME_ACTION_BATCH_KEY];if(typeof t!=`object`||!t)return;let n=t;if(!(!Array.isArray(n.actions)||!Array.isArray(n.responseMessages)||typeof n.event!=`object`||n.event===null))return n}function hasPendingRuntimeActionBatch(e){return getPendingRuntimeActionBatch(e)!==void 0}function clearPendingRuntimeActionBatch(e){if(e.state?.[PENDING_RUNTIME_ACTION_BATCH_KEY]===void 0)return e;let t={...e.state};return delete t[PENDING_RUNTIME_ACTION_BATCH_KEY],{...e,state:Object.keys(t).length>0?t:void 0}}function setPendingRuntimeActionBatch(e){let t={...e.session.state};return t[PENDING_RUNTIME_ACTION_BATCH_KEY]={actions:[...e.actions],event:e.event,responseMessages:[...e.responseMessages]},{...e.session,state:t}}function recordPendingSubagentChildToken(e){let t=getPendingRuntimeActionBatch(e.session.state);if(t===void 0)return e.session;let n={...e.session.state};return n[PENDING_RUNTIME_ACTION_BATCH_KEY]={...t,childContinuationTokens:{...t.childContinuationTokens,[e.callId]:e.childContinuationToken}},{...e.session,state:n}}function resolveReadyRuntimeActionResults(e){let t=getPendingRuntimeActionBatch(e.session.state);if(t!==void 0)return resolveRuntimeActionResultsForBatch({batch:t,results:e.results})}function resolveRuntimeActionResultsForBatch(e){return resolveRuntimeActionResultsForKeys({pendingKeys:e.batch.actions.map(e=>getRuntimeActionRequestKey(e)),results:e.results})}function resolveRuntimeActionResultsForKeys(e){let t=new Set(e.pendingKeys),n=new Map;for(let r of e.results){let e=getRuntimeActionResultKey(r);t.has(e)&&n.set(e,r)}let r=[];for(let t of e.pendingKeys){let e=n.get(t);if(e===void 0)return;r.push(e)}return r}async function resolvePendingRuntimeActions(t){let r=getPendingRuntimeActionBatch(t.session.state);if(r===void 0)return{messages:[...t.session.history],outcome:`continue`,session:t.session};let i=resolveReadyRuntimeActionResults({results:t.stepInput?.runtimeActionResults??[],session:t.session});if(i===void 0)return{messages:[...t.session.history],outcome:`unresolved`,session:t.session};if(t.emit!==void 0)for(let n of i)n.kind===`subagent-result`&&n.isError!==!0&&await t.emit({data:{callId:n.callId,output:typeof n.output==`string`?n.output:JSON.stringify(n.output),subagentName:n.subagentName},type:`subagent.completed`}),await t.emit(createActionResultEvent({result:n,sequence:r.event.sequence,stepIndex:r.event.stepIndex,turnId:r.event.turnId}));let a={...t.session.state};delete a[PENDING_RUNTIME_ACTION_BATCH_KEY];let o={...t.session,state:Object.keys(a).length>0?a:void 0},s=r.childContinuationTokens;if(s!==void 0)for(let e of i){if(e.kind!==`subagent-result`)continue;let t=s[e.callId];t!==void 0&&(o=clearProxyInputRequestsForChild(o,t))}let c=i.map(e=>{switch(e.kind){case`load-skill-result`:return{output:toToolResultOutput(e),toolCallId:e.callId,toolName:`load_skill`,type:`tool-result`};case`subagent-result`:return{output:toToolResultOutput(e),toolCallId:e.callId,toolName:e.subagentName,type:`tool-result`};case`tool-result`:return{output:toToolResultOutput(e),toolCallId:e.callId,toolName:e.toolName,type:`tool-result`}}throw Error(`Unsupported runtime action result kind "${String(e)}".`)}),l=[...o.history,...r.responseMessages];return c.length>0&&l.push({content:c,role:`tool`}),{messages:l,outcome:`resolved`,session:o}}function createRuntimeActionRequestFromToolCall(e){let t=e.tools.get(e.toolCall.toolName);return t?.runtimeAction?.kind===`subagent-call`?{callId:e.toolCall.toolCallId,description:t.description,input:resolveToolCallInputObject(e.toolCall.input,{callId:e.toolCall.toolCallId,toolName:e.toolCall.toolName}),kind:`subagent-call`,name:t.name,nodeId:t.runtimeAction.nodeId,subagentName:t.runtimeAction.subagentName}:t?.runtimeAction?.kind===`remote-agent-call`?{callId:e.toolCall.toolCallId,description:t.description,input:resolveToolCallInputObject(e.toolCall.input,{callId:e.toolCall.toolCallId,toolName:e.toolCall.toolName}),kind:`remote-agent-call`,name:t.name,nodeId:t.runtimeAction.nodeId,remoteAgentName:t.runtimeAction.remoteAgentName??t.name}:{callId:e.toolCall.toolCallId,input:resolveToolCallInputObject(e.toolCall.input,{callId:e.toolCall.toolCallId,toolName:e.toolCall.toolName}),kind:`tool-call`,toolName:e.toolCall.toolName}}function resolveToolCallInputObject(e,n){if(e==null)return{};try{return parseJsonObject(e)}catch(e){let t=e instanceof Error?e.message:String(e);throw TypeError(`Failed to parse tool-call arguments for "${n.toolName}" (${n.callId}): ${t}`,{cause:e})}}function toToolResultOutput(e){return typeof e.output==`string`?e.isError===!0?{type:`error-text`,value:e.output}:{type:`text`,value:e.output}:e.isError===!0?{type:`error-json`,value:toMutableJsonValue(e.output)}:{type:`json`,value:toMutableJsonValue(e.output)}}function toMutableJsonValue(e){if(e===null||typeof e==`string`||typeof e==`number`||typeof e==`boolean`)return e;if(Array.isArray(e))return e.map(e=>toMutableJsonValue(e));let t={};for(let[n,r]of Object.entries(e))t[n]=toMutableJsonValue(r);return t}export{clearPendingRuntimeActionBatch,createRuntimeActionRequestFromToolCall,getPendingRuntimeActionBatch,hasPendingRuntimeActionBatch,recordPendingSubagentChildToken,resolvePendingRuntimeActions,resolveRuntimeActionResultsForKeys,resolveToolCallInputObject,setPendingRuntimeActionBatch};
1
+ import{createActionResultEvent}from"#protocol/message.js";import{parseJsonObject}from"#shared/json.js";import{clearProxyInputRequestsForChild}from"#harness/proxy-input-requests.js";import{accumulateSessionUsage,getTurnUsageState,setTurnUsageState}from"#harness/turn-tag-state.js";import{getRuntimeActionRequestKey,getRuntimeActionResultKey}from"#runtime/actions/keys.js";const PENDING_RUNTIME_ACTION_BATCH_KEY=`eve.runtime.pendingActionBatch`;function getPendingRuntimeActionBatch(e){let t=e?.[PENDING_RUNTIME_ACTION_BATCH_KEY];if(typeof t!=`object`||!t)return;let n=t;if(!(!Array.isArray(n.actions)||!Array.isArray(n.responseMessages)||typeof n.event!=`object`||n.event===null))return n}function hasPendingRuntimeActionBatch(e){return getPendingRuntimeActionBatch(e)!==void 0}function clearPendingRuntimeActionBatch(e){if(e.state?.[PENDING_RUNTIME_ACTION_BATCH_KEY]===void 0)return e;let t={...e.state};return delete t[PENDING_RUNTIME_ACTION_BATCH_KEY],{...e,state:Object.keys(t).length>0?t:void 0}}function setPendingRuntimeActionBatch(e){let t={...e.session.state};return t[PENDING_RUNTIME_ACTION_BATCH_KEY]={actions:[...e.actions],event:e.event,responseMessages:[...e.responseMessages]},{...e.session,state:t}}function recordPendingSubagentChildToken(e){let t=getPendingRuntimeActionBatch(e.session.state);if(t===void 0)return e.session;let n={...e.session.state};return n[PENDING_RUNTIME_ACTION_BATCH_KEY]={...t,childContinuationTokens:{...t.childContinuationTokens,[e.callId]:e.childContinuationToken}},{...e.session,state:n}}function resolveReadyRuntimeActionResults(e){let t=getPendingRuntimeActionBatch(e.session.state);if(t!==void 0)return resolveRuntimeActionResultsForBatch({batch:t,results:e.results})}function resolveRuntimeActionResultsForBatch(e){return resolveRuntimeActionResultsForKeys({pendingKeys:e.batch.actions.map(e=>getRuntimeActionRequestKey(e)),results:e.results})}function resolveRuntimeActionResultsForKeys(e){let t=new Set(e.pendingKeys),n=new Map;for(let r of e.results){let e=getRuntimeActionResultKey(r);t.has(e)&&n.set(e,r)}let r=[];for(let t of e.pendingKeys){let e=n.get(t);if(e===void 0)return;r.push(e)}return r}async function resolvePendingRuntimeActions(t){let i=getPendingRuntimeActionBatch(t.session.state);if(i===void 0)return{messages:[...t.session.history],outcome:`continue`,session:t.session};let a=resolveReadyRuntimeActionResults({results:t.stepInput?.runtimeActionResults??[],session:t.session});if(a===void 0)return{messages:[...t.session.history],outcome:`unresolved`,session:t.session};if(t.emit!==void 0)for(let n of a)n.kind===`subagent-result`&&n.isError!==!0&&await t.emit({data:{callId:n.callId,output:typeof n.output==`string`?n.output:JSON.stringify(n.output),subagentName:n.subagentName},type:`subagent.completed`}),await t.emit(createActionResultEvent({result:n,sequence:i.event.sequence,stepIndex:i.event.stepIndex,turnId:i.event.turnId}));let o={...t.session.state};delete o[PENDING_RUNTIME_ACTION_BATCH_KEY];let s={...t.session,state:Object.keys(o).length>0?o:void 0},c=i.childContinuationTokens;if(c!==void 0)for(let e of a){if(e.kind!==`subagent-result`)continue;let t=c[e.callId];t!==void 0&&(s=clearProxyInputRequestsForChild(s,t))}for(let e of a)e.kind!==`subagent-result`||e.usage===void 0||(s=setTurnUsageState(s,accumulateSessionUsage({previous:getTurnUsageState(s.state),usage:e.usage})));let l=a.map(e=>{switch(e.kind){case`load-skill-result`:return{output:toToolResultOutput(e),toolCallId:e.callId,toolName:`load_skill`,type:`tool-result`};case`subagent-result`:return{output:toToolResultOutput(e),toolCallId:e.callId,toolName:e.subagentName,type:`tool-result`};case`tool-result`:return{output:toToolResultOutput(e),toolCallId:e.callId,toolName:e.toolName,type:`tool-result`}}throw Error(`Unsupported runtime action result kind "${String(e)}".`)}),u=[...s.history,...i.responseMessages];return l.length>0&&u.push({content:l,role:`tool`}),{messages:u,outcome:`resolved`,session:s}}function createRuntimeActionRequestFromToolCall(e){let t=e.tools.get(e.toolCall.toolName);return t?.runtimeAction?.kind===`subagent-call`?{callId:e.toolCall.toolCallId,description:t.description,input:resolveToolCallInputObject(e.toolCall.input,{callId:e.toolCall.toolCallId,toolName:e.toolCall.toolName}),kind:`subagent-call`,name:t.name,nodeId:t.runtimeAction.nodeId,subagentName:t.runtimeAction.subagentName}:t?.runtimeAction?.kind===`remote-agent-call`?{callId:e.toolCall.toolCallId,description:t.description,input:resolveToolCallInputObject(e.toolCall.input,{callId:e.toolCall.toolCallId,toolName:e.toolCall.toolName}),kind:`remote-agent-call`,name:t.name,nodeId:t.runtimeAction.nodeId,remoteAgentName:t.runtimeAction.remoteAgentName??t.name}:{callId:e.toolCall.toolCallId,input:resolveToolCallInputObject(e.toolCall.input,{callId:e.toolCall.toolCallId,toolName:e.toolCall.toolName}),kind:`tool-call`,toolName:e.toolCall.toolName}}function resolveToolCallInputObject(e,n){if(e==null)return{};try{return parseJsonObject(e)}catch(e){let t=e instanceof Error?e.message:String(e);throw TypeError(`Failed to parse tool-call arguments for "${n.toolName}" (${n.callId}): ${t}`,{cause:e})}}function toToolResultOutput(e){return typeof e.output==`string`?e.isError===!0?{type:`error-text`,value:e.output}:{type:`text`,value:e.output}:e.isError===!0?{type:`error-json`,value:toMutableJsonValue(e.output)}:{type:`json`,value:toMutableJsonValue(e.output)}}function toMutableJsonValue(e){if(e===null||typeof e==`string`||typeof e==`number`||typeof e==`boolean`)return e;if(Array.isArray(e))return e.map(e=>toMutableJsonValue(e));let t={};for(let[n,r]of Object.entries(e))t[n]=toMutableJsonValue(r);return t}export{clearPendingRuntimeActionBatch,createRuntimeActionRequestFromToolCall,getPendingRuntimeActionBatch,hasPendingRuntimeActionBatch,recordPendingSubagentChildToken,resolvePendingRuntimeActions,resolveRuntimeActionResultsForKeys,resolveToolCallInputObject,setPendingRuntimeActionBatch};
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Deterministic HITL continuation prompt for session token limits.
3
+ *
4
+ * When a durable session reaches its configured token budget, the harness
5
+ * parks on a harness-authored input request instead of failing the session.
6
+ * The request is derived only from the session identity and violation, so
7
+ * identical session state always produces an identical prompt — no model call
8
+ * is involved.
9
+ */
10
+ import type { InputRequest, InputResponse } from "#runtime/input/types.js";
11
+ import type { SessionTokenLimitViolation } from "#harness/turn-tag-state.js";
12
+ /** Synthetic action tool name carried by session-limit continuation requests. */
13
+ export declare const SESSION_LIMIT_CONTINUATION_TOOL_NAME = "session_limit_continuation";
14
+ /** Option id that grants a fresh token budget window. */
15
+ export declare const SESSION_LIMIT_CONTINUE_OPTION_ID = "continue";
16
+ /** Option id that declines continuation and ends the session. */
17
+ export declare const SESSION_LIMIT_STOP_OPTION_ID = "stop";
18
+ /**
19
+ * Builds the deterministic continuation prompt for one session token limit
20
+ * violation.
21
+ */
22
+ export declare function createSessionLimitContinuationRequest(input: {
23
+ readonly sessionId: string;
24
+ /**
25
+ * Absolute session total of the violated kind (not the window-relative
26
+ * `violation.usedTokens`, which can repeat across grants — e.g. a second
27
+ * violation can land on exactly the same window usage). The absolute total
28
+ * is strictly increasing across violations, so each prompt gets its own id
29
+ * while staying deterministic: stale chat controls from an earlier,
30
+ * already-resolved prompt carry an unknown requestId, resolve nothing, and
31
+ * the harness harmlessly re-prompts instead of letting an old "Stop"
32
+ * button end a freshly granted session.
33
+ */
34
+ readonly totalUsedTokens: number;
35
+ readonly violation: SessionTokenLimitViolation;
36
+ }): InputRequest;
37
+ /**
38
+ * Returns true when a request is a harness-authored session-limit
39
+ * continuation prompt.
40
+ */
41
+ export declare function isSessionLimitContinuationRequest(request: InputRequest): boolean;
42
+ /**
43
+ * Resolves the user's answer to a session-limit continuation prompt.
44
+ *
45
+ * Returns `{ granted: true }` for "continue", `{ granted: false }` for
46
+ * "stop", and `undefined` when the batch carries no continuation request or
47
+ * the user has not answered it — an unanswered prompt is re-raised on the
48
+ * next step because the violation still holds.
49
+ */
50
+ export declare function resolveSessionLimitContinuation(input: {
51
+ readonly requests: readonly InputRequest[];
52
+ readonly responses: readonly InputResponse[];
53
+ }): {
54
+ readonly granted: boolean;
55
+ } | undefined;
@@ -0,0 +1 @@
1
+ const SESSION_LIMIT_CONTINUATION_TOOL_NAME=`session_limit_continuation`,SESSION_LIMIT_CONTINUE_OPTION_ID=`continue`,SESSION_LIMIT_STOP_OPTION_ID=`stop`;function createSessionLimitContinuationRequest(r){let{sessionId:i,totalUsedTokens:a,violation:o}=r,s=`${i}:limit:${o.kind}:${String(a)}`,c=o.limit.toLocaleString(`en-US`),l=o.usedTokens.toLocaleString(`en-US`);return{action:{callId:s,input:{kind:o.kind,limit:o.limit,usedTokens:o.usedTokens},kind:`tool-call`,toolName:SESSION_LIMIT_CONTINUATION_TOOL_NAME},allowFreeform:!1,display:`confirmation`,options:[{description:`Reset quota and keep going`,id:SESSION_LIMIT_CONTINUE_OPTION_ID,label:`Continue`,style:`primary`},{description:`End the session here`,id:SESSION_LIMIT_STOP_OPTION_ID,label:`Stop`,style:`danger`}],prompt:`The session used ${l} of its ${c} ${o.kind}-token budget. Continue with a fresh budget?`,requestId:s}}function isSessionLimitContinuationRequest(t){return t.action.toolName===SESSION_LIMIT_CONTINUATION_TOOL_NAME}function resolveSessionLimitContinuation(e){let t=e.requests.find(isSessionLimitContinuationRequest);if(t===void 0)return;let n=e.responses.find(e=>e.requestId===t.requestId);if(n!==void 0){if(n.optionId===`continue`)return{granted:!0};if(n.optionId===`stop`)return{granted:!1}}}export{SESSION_LIMIT_CONTINUATION_TOOL_NAME,SESSION_LIMIT_CONTINUE_OPTION_ID,SESSION_LIMIT_STOP_OPTION_ID,createSessionLimitContinuationRequest,isSessionLimitContinuationRequest,resolveSessionLimitContinuation};
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Session token limit policy for the tool-loop harness.
3
+ *
4
+ * Two seams into the harness step:
5
+ *
6
+ * 1. {@link applySessionLimitContinuation} runs after pending-input
7
+ * resolution and acts on the user's answer to a continuation prompt —
8
+ * grant a fresh budget window, or end the session.
9
+ * 2. {@link enforceSessionTokenLimit} runs before each model call and, when
10
+ * the session is over budget, parks it on the deterministic continuation
11
+ * prompt (sessions that can reach a human) or fails it (task-mode sessions
12
+ * without HITL — nobody can answer the prompt).
13
+ */
14
+ import type { ModelMessage } from "ai";
15
+ import { type HarnessEmissionState } from "#harness/emission.js";
16
+ import type { HarnessSession, StepResult, ToolLoopHarnessConfig } from "#harness/types.js";
17
+ interface SessionLimitPolicyInput {
18
+ readonly config: ToolLoopHarnessConfig;
19
+ readonly emit?: ToolLoopHarnessConfig["handleEvent"];
20
+ readonly emissionState: HarnessEmissionState;
21
+ readonly session: HarnessSession;
22
+ }
23
+ /**
24
+ * Acts on a resolved session-limit continuation answer.
25
+ *
26
+ * Granted: resets the token budget windows via
27
+ * {@link extendSessionTokenBudget} and lets the step continue transparently.
28
+ * Declined: a user decision, not an error — conversation sessions end
29
+ * gracefully (`turn.completed` → `session.completed`, no extra copy; the
30
+ * resolved prompt is the acknowledgment), while task mode keeps the
31
+ * structured failure so the parent tool call receives an error result rather
32
+ * than an empty success.
33
+ *
34
+ * Returns `result: null` when the step should continue with `session`.
35
+ */
36
+ export declare function applySessionLimitContinuation(input: SessionLimitPolicyInput & {
37
+ readonly limitContinuation: {
38
+ readonly granted: boolean;
39
+ } | undefined;
40
+ }): Promise<{
41
+ readonly result: StepResult | null;
42
+ readonly session: HarnessSession;
43
+ }>;
44
+ /**
45
+ * Pre-model-call gate for the session token budget.
46
+ *
47
+ * Returns `null` when the session is within budget. Over budget, sessions
48
+ * that can reach a human park on the deterministic continuation prompt;
49
+ * task-mode sessions without HITL fail fast with
50
+ * `SESSION_TOKEN_LIMIT_REACHED`.
51
+ */
52
+ export declare function enforceSessionTokenLimit(input: SessionLimitPolicyInput & {
53
+ readonly messages: readonly ModelMessage[];
54
+ }): Promise<StepResult | null>;
55
+ export {};
@@ -0,0 +1 @@
1
+ import{createInputRequestedEvent,createSessionCompletedEvent,createTurnCompletedEvent}from"#protocol/message.js";import{emitFailedStep,emitTurnEpilogue,setHarnessEmissionState}from"#harness/emission.js";import{setPendingInputBatch}from"#harness/input-requests.js";import{extendSessionTokenBudget,getSessionTokenLimitViolation,getSessionTokenUsage}from"#harness/turn-tag-state.js";import{createSessionLimitContinuationRequest}from"#harness/session-limit-continuation.js";async function applySessionLimitContinuation(e){if(e.limitContinuation===void 0)return{result:null,session:e.session};if(e.limitContinuation.granted)return{result:null,session:extendSessionTokenBudget(e.session)};let r=getSessionTokenLimitViolation(e.session);return r===null?{result:null,session:e.session}:e.config.mode===`task`?{result:await failSessionTokenLimit({...e,violation:r}),session:e.session}:(e.emit&&(await e.emit(createTurnCompletedEvent({sequence:e.emissionState.sequence,turnId:e.emissionState.turnId})),await e.emit(createSessionCompletedEvent())),{result:{next:{done:!0,output:``},session:e.session},session:e.session})}async function enforceSessionTokenLimit(e){let t=getSessionTokenLimitViolation(e.session);if(t===null)return null;let{emit:n}=e;return n!==void 0&&(e.config.mode===`conversation`||e.config.capabilities?.requestInput===!0)?parkOnSessionTokenLimit({...e,emit:n,violation:t}):failSessionTokenLimit({...e,violation:t})}async function parkOnSessionTokenLimit(t){let n=getSessionTokenUsage(t.session),r=createSessionLimitContinuationRequest({sessionId:t.session.sessionId,totalUsedTokens:t.violation.kind===`input`?n.inputTokens:n.outputTokens,violation:t.violation}),a=t.emissionState,o=setPendingInputBatch({event:{sequence:a.sequence,stepIndex:a.stepIndex,turnId:a.turnId},requests:[r],responseMessages:[],session:{...t.session,history:[...t.messages]}});return await t.emit(createInputRequestedEvent({requests:[r],sequence:a.sequence,stepIndex:a.stepIndex,turnId:a.turnId})),t.config.mode===`conversation`&&(a=await emitTurnEpilogue(t.emit,a,t.config.mode)),{next:null,session:setHarnessEmissionState(o,a)}}function formatSessionTokenLimitMessage(e){return`The session reached its configured ${e} token limit.`}async function failSessionTokenLimit(e){let t=getSessionTokenUsage(e.session),n=formatSessionTokenLimitMessage(e.violation.kind),i={inputTokens:t.inputTokens,kind:e.violation.kind,limit:e.violation.limit,outputTokens:t.outputTokens,usedTokens:e.violation.usedTokens};return e.emit&&await emitFailedStep(e.emit,e.emissionState,{code:`SESSION_TOKEN_LIMIT_REACHED`,details:i,message:n,sessionId:e.session.sessionId}),{next:{done:!0,isError:e.config.mode===`task`?!0:void 0,output:e.config.mode===`task`?n:``},session:e.session}}export{applySessionLimitContinuation,enforceSessionTokenLimit};
@@ -9,9 +9,6 @@ export type SubagentDelegationLimit = {
9
9
  readonly reached: boolean;
10
10
  };
11
11
  export declare function resolveSubagentDelegationLimit(session: Pick<HarnessSession, "subagentDepth" | "subagentMaxDepth">): SubagentDelegationLimit;
12
- export declare function readSerializedSubagentSessionDepth(serializedContext: Readonly<Record<string, unknown>>): {
13
- readonly subagentDepth?: number;
14
- readonly subagentMaxDepth?: number;
15
- };
12
+ export declare function readSerializedSubagentDepth(serializedContext: Readonly<Record<string, unknown>>): number | undefined;
16
13
  export declare function isSubagentDelegationAction(action: RuntimeActionRequest): action is DelegatedRuntimeActionRequest;
17
14
  export declare function getSubagentDelegationName(action: DelegatedRuntimeActionRequest): string;
@@ -1 +1 @@
1
- import{SubagentDepthKey,SubagentMaxDepthKey}from"#context/keys.js";const DEFAULT_SUBAGENT_MAX_DEPTH=3;function resolveSubagentDelegationLimit(e){let t=parseSubagentDepth(e.subagentDepth),n=parseSubagentMaxDepth(e.subagentMaxDepth)??3;return{currentDepth:t,maxDepth:n,nextChildDepth:t+1,reached:t>=n}}function readSerializedSubagentSessionDepth(n){let r=parseSubagentDepth(n[SubagentDepthKey.name]),i=parseSubagentMaxDepth(n[SubagentMaxDepthKey.name]);return{subagentDepth:r===0?void 0:r,subagentMaxDepth:i}}function isSubagentDelegationAction(e){return e.kind===`subagent-call`||e.kind===`remote-agent-call`}function getSubagentDelegationName(e){switch(e.kind){case`remote-agent-call`:return e.remoteAgentName;case`subagent-call`:return e.subagentName;default:return e}}function parseSubagentDepth(e){return typeof e==`number`&&Number.isInteger(e)&&e>0?e:0}function parseSubagentMaxDepth(e){return typeof e==`number`&&Number.isInteger(e)&&e>0?e:void 0}export{DEFAULT_SUBAGENT_MAX_DEPTH,getSubagentDelegationName,isSubagentDelegationAction,readSerializedSubagentSessionDepth,resolveSubagentDelegationLimit};
1
+ import{SubagentDepthKey}from"#context/keys.js";const DEFAULT_SUBAGENT_MAX_DEPTH=3;function resolveSubagentDelegationLimit(e){let t=parseSubagentDepth(e.subagentDepth),n=parseSubagentMaxDepth(e.subagentMaxDepth)??3;return{currentDepth:t,maxDepth:n,nextChildDepth:t+1,reached:t>=n}}function readSerializedSubagentDepth(t){let n=parseSubagentDepth(t[SubagentDepthKey.name]);return n===0?void 0:n}function isSubagentDelegationAction(e){return e.kind===`subagent-call`||e.kind===`remote-agent-call`}function getSubagentDelegationName(e){switch(e.kind){case`remote-agent-call`:return e.remoteAgentName;case`subagent-call`:return e.subagentName;default:return e}}function parseSubagentDepth(e){return typeof e==`number`&&Number.isInteger(e)&&e>0?e:0}function parseSubagentMaxDepth(e){return typeof e==`number`&&Number.isInteger(e)&&e>0?e:void 0}export{DEFAULT_SUBAGENT_MAX_DEPTH,getSubagentDelegationName,isSubagentDelegationAction,readSerializedSubagentDepth,resolveSubagentDelegationLimit};
@@ -0,0 +1,14 @@
1
+ import type { RunSessionLimits } from "#channel/types.js";
2
+ import type { HarnessSession } from "#harness/types.js";
3
+ /**
4
+ * Computes the session token limits a delegated child inherits from its parent:
5
+ * the remaining quota (configured limit minus accumulated usage) split evenly
6
+ * across the batch's delegated calls, per axis, at dispatch time. `false`
7
+ * marks an axis with no inherited cap.
8
+ *
9
+ * Splitting by `fanoutSize` makes one dispatch batch collectively
10
+ * bounded by the parent's remainder. N parallel children cannot each spend
11
+ * the full remainder. Sequential batches see the quota net of completed
12
+ * children because their usage folds back into the parent's session totals.
13
+ */
14
+ export declare function resolveRemainingSessionTokenLimits(session: Pick<HarnessSession, "limits" | "state">, fanoutSize?: number): RunSessionLimits;
@@ -0,0 +1 @@
1
+ import{getSessionTokenUsage}from"#harness/turn-tag-state.js";function resolveRemainingSessionTokenLimits(t,n=1){let r=Math.max(1,Math.floor(n)),i=getSessionTokenUsage(t);return{maxInputTokensPerSession:grantShare(remainingQuota(t.limits?.maxInputTokensPerSession,i.inputTokens),r),maxOutputTokensPerSession:grantShare(remainingQuota(t.limits?.maxOutputTokensPerSession,i.outputTokens),r)}}function remainingQuota(e,t){return e===void 0?!1:Math.max(0,e-t)}function grantShare(e,t){return e===!1?!1:Math.floor(e/t)}export{resolveRemainingSessionTokenLimits};
@@ -1 +1 @@
1
- import{createErrorId,createLogger,formatError,logError,recordErrorOnSpan}from"#internal/logging.js";import{isScheduleAppAuth}from"#channel/schedule-auth.js";import{AuthKey,ParentSessionKey}from"#context/keys.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{EmptyModelResponseError,classifyModelCallError,extractModelCallErrorDetails,extractUnsupportedProviderToolTypes,isNoOutputGeneratedError,summarizeKnownModelCallConfigError,summarizeKnownModelCallRequestError}from"#harness/model-call-error.js";import{toErrorMessage}from"#shared/errors.js";import{createActionResultEvent,createAuthorizationRequiredEvent,createCompactionCompletedEvent,createCompactionRequestedEvent,createInputRequestedEvent,createResultCompletedEvent}from"#protocol/message.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{contextStorage}from"#context/container.js";import{ToolLoopAgent,isStepCount}from"ai";import{advanceStep,emitFailedStep,emitRecoverableFailedTurn,emitStepStarted,emitStreamContent,emitTurnEpilogue,emitTurnPreamble,getHarnessEmissionState,setHarnessEmissionState}from"#harness/emission.js";import{createRuntimeActionRequestFromToolCall,resolvePendingRuntimeActions,setPendingRuntimeActionBatch}from"#harness/runtime-actions.js";import{clearPendingWorkflowInterrupt,getPendingWorkflowInterrupt,setPendingWorkflowInterrupt}from"#harness/workflow-interrupt-state.js";import{getWorkflowRuntimeActionInterrupts,isWorkflowRuntimeActionInterrupt}from"#harness/workflow-runtime-action-state.js";import{isAuthorizationSignal,setPendingAuthorization}from"#harness/authorization.js";import{resolveAssistantStepText}from"#harness/messages.js";import{buildDynamicInstructionMessages}from"#context/dynamic-instruction-lifecycle.js";import{PendingSkillAnnouncementKey}from"#context/dynamic-skill-lifecycle.js";import{consumeDeferredStepInput,getApprovedTools,hasDeferredStepInput,hasStepInput,resolvePendingInput,setPendingInputBatch}from"#harness/input-requests.js";import{getWorkflowContinuationSecurity,readWorkflowContinuationSecurity}from"#harness/workflow-continuation-security.js";import{buildWorkflowHostTools}from"#harness/workflow-sandbox.js";import{CONDITIONAL_DELIVERY_INSTRUCTION,EMPTY_DELIVERY_SENTINEL,hasEmptyDeliverySentinel}from"#shared/empty-delivery.js";import{readToolInterrupt}from"#harness/tool-interrupts.js";import{ASK_QUESTION_TOOL_NAME}from"#runtime/framework-tools/ask-question.js";import{throwIfTurnAborted}from"#harness/turn-cancellation.js";import{extractQuestionInputRequests,extractToolApprovalInputRequests}from"#harness/input-extraction.js";import{applyLastToolCacheBreakpoint,applySystemCacheBreakpoint,detectPromptCachePath,getAnthropicCacheMarker}from"#harness/prompt-cache.js";import{context,trace}from"#compiled/@opentelemetry/api/index.js";import{buildDynamicTools}from"#context/build-dynamic-tools.js";import{hydrateSandboxAttachments,stageAttachmentsToSandbox}from"#harness/attachment-staging.js";import{createWorkflowLifecycle}from"#harness/workflow-lifecycle.js";import{compactMessages,getInputTokenCount,resolveCompactionModel,shouldCompact}from"#harness/compaction.js";import{accumulateTurnUsage,getSessionTokenLimitViolation,getSessionTokenUsage,getTurnUsageState,setTurnUsageState}from"#harness/turn-tag-state.js";import{setEveAttributes}from"#runtime/attributes/emit.js";import{buildTelemetryRuntimeContext}from"#harness/instrumentation-runtime-context.js";import{getInstrumentationConfig}from"#harness/instrumentation-config.js";import{normalizeProviderToolHistory}from"#harness/provider-tool-history.js";import{extractWorkflowStreamWriteErrorDetails}from"#harness/workflow-stream-error.js";import{ensureOtelIntegration}from"#harness/otel-integration.js";import{getAdvertisedTools}from"#harness/advertised-tools.js";import{resolveFrameworkToolFromUpstreamType}from"#harness/provider-tools.js";import{buildStepHooks,emitStepActions,isInvalidToolCall}from"#harness/step-hooks.js";import{buildToolApproval,buildToolSetFromDefinitions,buildToolSetWithProviderTools}from"#harness/tools.js";import{continueWorkflowSandboxInterrupt,getWorkflowSandboxInterrupt,unwrapWorkflowSandboxResult}from"#shared/workflow-sandbox.js";import{FINAL_OUTPUT_TOOL_NAME,buildFinalOutputTool}from"#runtime/framework-tools/final-output.js";const environment=process.env.NODE_ENV??`unknown`,eveVersion=resolveInstalledPackageInfo().version,log=createLogger(`harness.tool-loop`);function logToolExecutionError(e){e.toolOutput.type===`tool-error`&&logError(log,`tool execution failed`,e.toolOutput.error,{toolName:e.toolCall.toolName,toolCallId:e.toolCall.toolCallId})}function enrichTelemetry(e,t,n){if(e===void 0)return;let r={};for(let e of Object.keys(n??{}))r[e]=!0;return{functionId:e.functionId??t,includeRuntimeContext:r,isEnabled:!0,recordInputs:e.recordInputs??!0,recordOutputs:e.recordOutputs??!0}}function buildGatewayAttributionHeaders(e,t){if(typeof e!=`string`)return;let n=t?.agentName??t?.agentId,r=process.env.VERCEL_PROJECT_PRODUCTION_URL||process.env.VERCEL_URL,i=r?`https://${r}`:void 0;if(!n&&!i)return;let a={};return n&&(a[`x-title`]=n),i&&(a[`http-referer`]=i),a}const TURN_TRACE_STATE_KEY=`eve.harness.turnTrace`;function getTurnTraceState(e){return e.state?.[TURN_TRACE_STATE_KEY]}function setTurnTraceState(e,t){let n={traceId:t.traceId,spanId:t.spanId,traceFlags:t.traceFlags};return{...e,state:{...e.state,[TURN_TRACE_STATE_KEY]:n}}}function resolveStepOtelContext(e,t,n){if(t)return trace.setSpan(context.active(),t);if(e){let e=getTurnTraceState(n);if(e){let t=trace.wrapSpanContext({traceId:e.traceId,spanId:e.spanId,traceFlags:e.traceFlags});return trace.setSpan(context.active(),t)}}}function createToolLoopHarness(t){let n=t.handleEvent,c=getInstrumentationConfig();c!==void 0&&ensureOtelIntegration();let f=c===void 0?void 0:trace.getTracer(`eve`),p=t.runtimeIdentity?.agentName;async function runStep(e,t){let n;if(f&&hasStepInput(t)){let t=c?.functionId??p,r={"eve.version":eveVersion,"eve.environment":environment,"eve.session.id":e.sessionId};t&&(r[`ai.telemetry.functionId`]=t),n=f.startSpan(`ai.eve.turn`,{attributes:r})}let r=resolveStepOtelContext(f,n,e),executeStep=()=>executeStepBody(e,t,n);try{return r?await context.with(r,executeStep):await executeStep()}finally{n?.end()}}async function executeStepBody(f,v,y){let b=f;y&&(b=setTurnTraceState(b,y.spanContext()));let x=getHarnessEmissionState(b.state),S=consumeDeferredStepInput({input:v,session:b});b=S.session;let D=await resolvePendingRuntimeActions({emit:n,session:b,stepInput:S.input});if(D.outcome===`unresolved`)return{next:null,session:D.session};b=D.session;let A=resolvePendingInput({history:D.messages,resolveApprovalKey:resolveApprovalKeyFromTools(t.tools),session:b,stepInput:S.input});if(A.outcome===`unresolved`)return n&&A.deferredMessage===!0&&hasStepInput(v)?(x=await emitTurnPreamble(n,v??{},x,t.runtimeIdentity),x=await emitTurnEpilogue(n,x,t.mode),{next:null,session:setHarnessEmissionState(A.session,x)}):{next:null,session:A.session};if(n&&A.rejectedActions)for(let e of A.rejectedActions.results)await n(createActionResultEvent({rejected:!0,result:e,sequence:A.rejectedActions.event.sequence,stepIndex:A.rejectedActions.event.stepIndex,turnId:A.rejectedActions.event.turnId}));n&&hasStepInput(v)&&(x=await emitTurnPreamble(n,v??{},x,t.runtimeIdentity),b=setHarnessEmissionState(b,x),y&&y.setAttribute(`eve.turn.id`,x.turnId)),b=A.session;let j=A.messages;if(S.input?.context!==void 0)for(let e of S.input.context)j.push({content:e,role:`user`});if(S.input?.message!==void 0&&!A.deferredMessage&&!A.consumedMessage){let e=await stageAttachmentsToSandbox(S.input.message);j.push({content:e,role:`user`})}let M=await t.resolveModel(b.agent.modelReference),N=detectPromptCachePath(M),P=N.kind===`anthropic-direct`?getAnthropicCacheMarker():void 0,F=buildGatewayAttributionHeaders(M,t.runtimeIdentity);({messages:j,session:b}=await maybeCompact({abortSignal:t.abortSignal,emit:n,emissionState:x,headers:F,messages:j,model:M,onCompaction:t.onCompaction,resolveModel:t.resolveModel,session:b,telemetry:enrichTelemetry(c,p)??void 0}));let I=getApprovedTools(b),L=contextStorage.getStore(),R=b.outputSchema===void 0&&L!==void 0&&isScheduleAppAuth(L.get(AuthKey))&&L.get(ParentSessionKey)===void 0,z=await hydrateSandboxAttachments(j),B=[],V=[];for(let e of z)e.role===`system`?B.push(e):V.push(e);if(L!==void 0){B.push(...buildDynamicInstructionMessages(L));let e=L.get(PendingSkillAnnouncementKey);e!==void 0&&e.length>0&&B.push({role:`system`,content:e})}R&&B.push({role:`system`,content:CONDITIONAL_DELIVERY_INSTRUCTION});let H=V,prepareModelCallInput=e=>{let t=e?[{role:`system`,content:e}]:[],n=b.agent.system?[{role:`system`,content:b.agent.system}]:[],r=B.length>0||t.length>0?[...t,...n,...B]:void 0,i=r!==void 0&&P?applySystemCacheBreakpoint(r,P):r??b.agent.system??void 0;return{instructions:i,telemetryRuntimeContext:buildTelemetryRuntimeContext({eveVersion,authored:c,emissionState:x,environment,modelInput:{instructions:i,messages:H},session:b})}},runOneModelCall=async e=>{let{instructions:i,telemetryRuntimeContext:a={}}=e.preparedInput??prepareModelCallInput(e.extraSystemNote);e.retryReason&&(a[`eve.retry.reason`]=e.retryReason);let o=e.trailingUserNote?[...H,{role:`user`,content:e.trailingUserNote}]:H,s=getAdvertisedTools({session:b,tools:t.tools}),u=await buildToolSetWithProviderTools({approvedTools:I,capabilities:t.capabilities,disabledProviderTools:e.disabledProviderTools,modelReference:b.agent.modelReference,tools:s});if(L!==void 0){let n=getAdvertisedTools({session:b,tools:buildDynamicTools(L)}),r=buildToolSetFromDefinitions({approvedTools:I,capabilities:t.capabilities,disabledProviderTools:e.disabledProviderTools,tools:n});for(let[e,t]of Object.entries(r))u[e]=t}b.outputSchema!==void 0&&(u[FINAL_OUTPUT_TOOL_NAME]=buildFinalOutputTool(b.outputSchema));let d=n===void 0?void 0:({tools:e})=>createWorkflowLifecycle({emit:n,emissionState:x,tools:e}),f=t.workflow===!0?{lifecycle:d}:void 0,h=await getAdvertisedTools({modelTools:u,session:b,tools:s,workflow:f});b=h.session;let g=h.modelTools,_=P?applyLastToolCacheBreakpoint(g,P):g,v=buildStepHooks({cachePath:N,emit:n,emissionState:x,emitStepStarted:e.suppressStepStartedEmission!==!0,marker:P,session:b}),y=new ToolLoopAgent({headers:F,instructions:i,model:M,onToolExecutionEnd:logToolExecutionError,onError(e){summarizeKnownModelCallConfigError(e.error)===null&&logError(log,`tool-loop stream error`,e.error)},onStepFinish:v.onStepFinish,prepareStep:v.prepareStep,reasoning:b.agent.reasoning,runtimeContext:a,stopWhen:isStepCount(1),telemetry:enrichTelemetry(c,p,a),toolApproval:buildToolApproval(g),tools:_}),executeModelCall=async()=>{if(n){let e=[...t.tools].filter(([e,t])=>t.runtimeAction!==void 0&&s.get(e)===void 0).map(([e])=>e),r=new Set([ASK_QUESTION_TOOL_NAME,FINAL_OUTPUT_TOOL_NAME,...e]),i=await y.stream({abortSignal:t.abortSignal,messages:o}),{emittedActionCallIds:a,handledInlineToolResultCallIds:c,inlineAuthorizationResults:u,inlineToolResultParts:d,trailingInlineToolResultParts:f}=await emitStreamContent(n,x,i.fullStream,{excludedActionToolNames:r,tools:t.tools});throwIfTurnAborted(t.abortSignal);let p=await v.stepResult;if(isEmptyModelResponse(p)&&d.length===0&&u.length===0&&f.length===0)throw new EmptyModelResponseError;if(await emitStepActions(n,x,p,{emittedActionCallIds:a,excludedActionToolNames:r,handledInlineToolResultCallIds:c,tools:s}),d.length>0||u.length>0||f.length>0){let e=p.toolResults,t=new Map(e.map(e=>[e.toolCallId,e]));for(let e of u)t.set(e.toolCallId,e);return{content:p.content,finishReason:p.finishReason,response:{...p.response,...d.length>0||f.length>0?{messages:insertInlineToolResultMessages({append:f,prepend:d,responseMessages:p.response.messages})}:{}},providerMetadata:p.providerMetadata,text:p.text,toolCalls:p.toolCalls,toolResults:[...t.values()],usage:p.usage}}return p}await y.generate({abortSignal:t.abortSignal,messages:o}),throwIfTurnAborted(t.abortSignal);let e=await v.stepResult;if(isEmptyModelResponse(e))throw new EmptyModelResponseError;return e};return runModelCallWithRetries(()=>executeModelCall().catch(rethrowNoOutputAsEmptyResponse),{sessionId:b.sessionId,turnId:x.turnId},t.abortSignal)},U=prepareModelCallInput();n&&await emitStepStarted(n,x,j);let W=await continuePendingWorkflowInterrupt({childResults:S.input?.runtimeActionResults,config:t,emit:n,emissionState:x,runStep,session:b});if(W!==null)return W;let G=getSessionTokenLimitViolation(b);if(G!==null)return failSessionTokenLimit({config:t,emit:n,emissionState:x,session:b,violation:G});let K;try{K=await runOneModelCall({preparedInput:U,suppressStepStartedEmission:!0})}catch(r){throwIfTurnAborted(t.abortSignal);let a=await runModelCallRecoveryPipeline({error:r,stages:[e=>attemptUnsupportedProviderToolRecovery({error:e.error,runOneModelCall,sessionId:b.sessionId,turnId:x.turnId}),e=>attemptEmptyResponseRecovery({emptyDeliveryEnabled:R,error:e.error,retryCallOptions:e.retryCallOptions,runOneModelCall,sessionId:b.sessionId,turnId:x.turnId})]});if(throwIfTurnAborted(t.abortSignal),a.outcome===`recovered`)K=a.result;else{let r=a.error;if(y&&recordErrorOnSpan(y,r),!n)throw r;let o=extractWorkflowStreamWriteErrorDetails(r);if(o!==null){let t=createErrorId();return log.error(`workflow stream write failed — parking session for retry by the user`,{...o,errorId:t,error:r,sessionId:b.sessionId,turnId:x.turnId}),x=await emitRecoverableFailedTurn(n,x,{code:`WORKFLOW_STREAM_WRITE_FAILED`,details:{...o,errorId:t},message:toErrorMessage(r)}),{next:null,session:setHarnessEmissionState(b,x)}}let s=classifyModelCallError(r),c=createErrorId(),l=s===`terminal`?summarizeKnownModelCallConfigError(r):null,f=l===null?summarizeKnownModelCallRequestError(r):null,p=l?.message??f?.message??toErrorMessage(r),_=extractModelCallErrorDetails(r),v=buildModelCallFailureDetails({configSummary:l,error:r,errorId:c,modelCallDetails:_,requestSummary:f}),S=buildModelCallFailureLogFields({error:r,errorId:c,modelCallDetails:_,requestSummary:f,sessionId:b.sessionId,turnId:x.turnId});return s===`terminal`?(l===null?log.error(f?.message??`model call failed terminally`,S):log.error(`${l.name}: ${l.message}`,{errorId:c,sessionId:b.sessionId,turnId:x.turnId}),await emitFailedStep(n,x,{code:`MODEL_CALL_FAILED`,details:v,message:p,sessionId:b.sessionId}),{next:t.mode===`task`?{done:!0,isError:!0,output:p}:{done:!0,output:``},session:b}):t.mode===`task`?(log.error(f?.message??`model call failed; failing the task run`,S),await emitFailedStep(n,x,{code:`MODEL_CALL_FAILED`,details:v,message:p,sessionId:b.sessionId}),{next:{done:!0,isError:!0,output:p},session:b}):(log.error(f?.message??`model call failed — parking session for retry by the user`,S),x=await emitRecoverableFailedTurn(n,x,{code:`MODEL_CALL_FAILED`,details:v,message:p}),{next:null,session:setHarnessEmissionState(b,x)})}}let q=accumulateTurnUsage({previous:getTurnUsageState(b.state),turnId:x.turnId,usage:extractTokenUsageDelta({costUsd:extractGatewayCostUsd(K.providerMetadata),usage:K.usage})});b=setTurnUsageState(b,q);let J;try{J=formatLanguageModelGatewayId(M)}catch{J=void 0}return await setEveAttributes({"$eve.model":J,"$eve.input_tokens":q.inputTokens,"$eve.output_tokens":q.outputTokens,"$eve.cache_read_tokens":q.cacheReadTokens,"$eve.cache_write_tokens":q.cacheWriteTokens,"$eve.cost_usd":q.sawCost?q.costUsd:void 0,"$eve.tool_count":t.tools.size}),handleStepResult({config:t,emit:n,emissionState:x,promptMessages:j,result:K,runStep,session:b})}return runStep}function extractTokenUsageDelta(e){let t=e.usage;if(!(t===void 0&&e.costUsd===void 0))return{cacheReadTokens:t?.inputTokenDetails?.cacheReadTokens,cacheWriteTokens:t?.inputTokenDetails?.cacheWriteTokens,costUsd:e.costUsd,inputTokens:t?.inputTokens,outputTokens:t?.outputTokens}}function extractGatewayCostUsd(e){let t=readGatewayMetadata(e)?.cost;if(typeof t==`number`&&Number.isFinite(t))return t;if(typeof t==`string`){let e=Number(t);return Number.isFinite(e)?e:void 0}}function readGatewayMetadata(e){let t=e?.gateway;return t&&typeof t==`object`&&!Array.isArray(t)?t:void 0}function formatSessionTokenLimitMessage(e){return`The session reached its configured ${e} token limit.`}async function failSessionTokenLimit(e){let t=getSessionTokenUsage(e.session),n=formatSessionTokenLimitMessage(e.violation.kind),r={inputTokens:t.inputTokens,kind:e.violation.kind,limit:e.violation.limit,outputTokens:t.outputTokens,usedTokens:e.violation.usedTokens};return e.emit&&await emitFailedStep(e.emit,e.emissionState,{code:`SESSION_TOKEN_LIMIT_REACHED`,details:r,message:n,sessionId:e.session.sessionId}),{next:{done:!0,isError:e.config.mode===`task`?!0:void 0,output:e.config.mode===`task`?n:``},session:e.session}}function buildModelCallFailureDetails(e){let{configSummary:t,error:r,errorId:i,modelCallDetails:a,requestSummary:o}=e;return t===null?o===null?{...formatError(r,i),...a}:{errorId:i,message:toErrorMessage(r),name:o.name,...a}:{errorId:i,message:t.message,name:t.name,...a}}function buildModelCallFailureLogFields(e){let t={errorId:e.errorId,sessionId:e.sessionId,turnId:e.turnId};return e.requestSummary===null?{...t,error:e.error}:{...t,details:e.modelCallDetails}}async function runModelCallRecoveryPipeline(e){let t=e.error,n;for(let r of e.stages){let e=await r({error:t,retryCallOptions:n});if(e.outcome===`recovered`)return e;e.outcome===`failed`&&(t=e.error,n=e.retryCallOptions)}return{outcome:`failed`,error:t}}function insertInlineToolResultMessages(e){let t=extractToolResultCallIds(e.responseMessages),n=e.prepend.filter(e=>!t.has(e.toolCallId)),r=e.append.filter(e=>!t.has(e.toolCallId));return[...n.length>0?[{role:`tool`,content:[...n]}]:[],...e.responseMessages,...r.length>0?[{role:`tool`,content:[...r]}]:[]]}function extractToolResultCallIds(e){let t=new Set;for(let n of e)if(!(n.role!==`tool`||!Array.isArray(n.content)))for(let e of n.content)e.type===`tool-result`&&t.add(e.toolCallId);return t}async function attemptUnsupportedProviderToolRecovery(e){let t=extractUnsupportedProviderToolTypes(e.error);if(t.length===0)return{outcome:`skipped`};let n=[];for(let e of t){let t=resolveFrameworkToolFromUpstreamType(e);t!==null&&!n.includes(t)&&n.push(t)}if(n.length===0)return{outcome:`skipped`};log.warn(`disabling unsupported provider tool(s); retrying step once`,{disabled:n,sessionId:e.sessionId,turnId:e.turnId,upstreamTypes:t});let r={disabledProviderTools:new Set(n),extraSystemNote:buildDisabledToolNote(n)};try{return{outcome:`recovered`,result:await e.runOneModelCall({...r,suppressStepStartedEmission:!0})}}catch(e){return{outcome:`failed`,error:e,retryCallOptions:r}}}function buildDisabledToolNote(e){let t=e.join(`, `);return`The following ${e.length===1?`tool is`:`tools are`} not available with the current model and has been removed: ${t}. Proceed using the remaining tools or your training knowledge.`}function isEmptyModelResponse(e){return e.toolCalls.length===0&&e.toolResults.length===0&&resolveAssistantStepText(e.response.messages,e.text)===null}function rethrowNoOutputAsEmptyResponse(e){throw isNoOutputGeneratedError(e)?new EmptyModelResponseError({cause:e}):e}const EMPTY_RESPONSE_NUDGE=`Your previous reply was empty and was not delivered. Answer now from the tool results above; do not re-run tools or mention this notice.`;function buildEmptyResponseNudge(e){return e?`${EMPTY_RESPONSE_NUDGE} If the current task explicitly requires conditional delivery and there is nothing to report, reply with exactly ${EMPTY_DELIVERY_SENTINEL}.`:EMPTY_RESPONSE_NUDGE}async function attemptEmptyResponseRecovery(e){if(!(e.error instanceof EmptyModelResponseError))return{outcome:`skipped`};log.warn(`empty model response; reissuing the model call once`,{sessionId:e.sessionId,turnId:e.turnId});try{return{outcome:`recovered`,result:await e.runOneModelCall({...e.retryCallOptions,retryReason:`empty-response`,suppressStepStartedEmission:!0,trailingUserNote:buildEmptyResponseNudge(e.emptyDeliveryEnabled)})}}catch(t){return{outcome:`failed`,error:t,retryCallOptions:e.retryCallOptions}}}async function handleStepResult(e){let{config:t,emit:n,promptMessages:r,result:i,runStep:a}=e,{emissionState:o,session:s}=e,c=resolveAssistantStepText(i.response.messages,i.text),l=i.finishReason!==`tool-calls`&&i.toolCalls.length===0&&hasEmptyDeliverySentinel(c),u=l?[]:i.response.messages,d=l?null:c,f=new Set;for(let e of[...i.content??[],...i.toolResults??[]])(e.type===`tool-result`||e.type===`tool-error`)&&e.providerExecuted===!0&&f.add(e.toolCallId);let p=normalizeProviderToolHistory({messages:u,providerExecutedOutcomeIds:f}),m=p.messages,h={...s,compaction:createNextCompactionConfig(s.compaction,r,i)},g=t.workflow===!0?readWorkflowContinuationSecurity(h):void 0;if(g!==void 0){let e=await getWorkflowSandboxInterrupt(i,g);if(e!==void 0){if(!isWorkflowRuntimeActionInterrupt(e))throw Error(`Unsupported Workflow interrupt kind "${e.payload.kind}".`);return parkOnWorkflowInterrupt({baseSession:h,emissionState:o,interrupt:e,promptMessages:r,responseMessages:m})}}let _=extractToolApprovalInputRequests({content:i.content??[]}),y=new Set(_.map(e=>e.action.callId)),b=extractQuestionInputRequests({toolCalls:i.toolCalls,excludedCallIds:y}),S=[..._,...b],C=getAdvertisedTools({session:h,tools:t.tools}),w=(i.toolCalls??[]).filter(e=>!isInvalidToolCall(e)).filter(e=>t.tools.get(e.toolName)?.runtimeAction!==void 0).filter(e=>C.get(e.toolName)?.runtimeAction===void 0?(log.warn(`runtime action tool call blocked because tool is not advertised`,{callId:e.toolCallId,sessionId:h.sessionId,toolName:e.toolName}),!1):!0).map(e=>createRuntimeActionRequestFromToolCall({toolCall:e,tools:C}));if(w.length>0)return{next:null,session:setHarnessEmissionState(setPendingRuntimeActionBatch({actions:w,event:{sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId},responseMessages:m,session:{...h,history:[...r]}}),o)};if(S.length>0){let e=setPendingInputBatch({event:{sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId},requests:S,responseMessages:m,session:{...h,history:[...r]}});return n&&(await n(createInputRequestedEvent({requests:S,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})),t.mode===`conversation`&&(o=await emitTurnEpilogue(n,o,t.mode),e=setHarnessEmissionState(e,o))),{next:null,session:e}}let T=findAuthorizationSignalFromToolResults(i.toolResults);if(T){let{challenges:e}=T;if(n)for(let t of e)await n(createAuthorizationRequiredEvent({authorization:t.challenge,name:t.name,description:t.challenge.instructions??`Authorization required for ${t.name}`,webhookUrl:t.hookUrl,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId}));return{next:null,session:setHarnessEmissionState({...h,history:[...r],state:setPendingAuthorization(h.state,{challenges:e})},o)}}let E=m,O=[...r,...E],k={...h,history:O};return!(k.outputSchema!==void 0&&extractFinalOutput(i)!==void 0)&&(E.at(-1)?.role===`tool`||p.outcomeEndsResponse||hasDeferredStepInput(k))?(n&&(o=advanceStep(o),k=setHarnessEmissionState(k,o)),{next:a,session:k}):t.mode===`task`?finishTaskTurn({emissionState:o,emit:n,history:r,result:i,schema:k.outputSchema,session:k,stepOutput:d}):finishConversationTurn({emissionState:o,emit:n,history:r,result:i,schema:k.outputSchema,session:k})}const OUTPUT_SCHEMA_NOT_FULFILLED={code:`OUTPUT_SCHEMA_NOT_FULFILLED`,message:`The agent could not produce a result matching the requested schema.`};function extractFinalOutput(e){return(e.toolCalls??[]).find(e=>e.toolName===FINAL_OUTPUT_TOOL_NAME)?.input}function persistStructuredAssistantTurn(e,t,n){return{...e,history:[...t,{content:JSON.stringify(n),role:`assistant`}],outputSchema:void 0}}async function emitStructuredResult(e,t,n,r){return await e(createResultCompletedEvent({result:n,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId})),emitTurnEpilogue(e,t,r)}async function finishTaskTurn(e){let{emit:t,history:n,result:r,schema:i,stepOutput:a}=e,{emissionState:o,session:s}=e;if(i===void 0)return t&&(o=await emitTurnEpilogue(t,o,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:a??``},session:s};let c=extractFinalOutput(r);return c===void 0?(t&&await emitFailedStep(t,o,{...OUTPUT_SCHEMA_NOT_FULFILLED,sessionId:s.sessionId}),{next:{done:!0,isError:!0,output:OUTPUT_SCHEMA_NOT_FULFILLED.message},session:s}):(s=persistStructuredAssistantTurn(s,n,c),t&&(o=await emitStructuredResult(t,o,c,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:c},session:s})}async function finishConversationTurn(e){let{emit:t,history:n,result:r,schema:i}=e,{emissionState:a,session:o}=e;if(i===void 0)return t&&(a=await emitTurnEpilogue(t,a,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o};let s=extractFinalOutput(r);return s===void 0?(t&&(a=await emitRecoverableFailedTurn(t,a,OUTPUT_SCHEMA_NOT_FULFILLED),o=setHarnessEmissionState(o,a)),{next:null,session:o}):(o=persistStructuredAssistantTurn(o,n,s),t&&(a=await emitStructuredResult(t,a,s,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o})}async function continuePendingWorkflowInterrupt(e){let t=getPendingWorkflowInterrupt(e.session.state);if(t===void 0)return null;let n=t.interrupt;if(!isWorkflowRuntimeActionInterrupt(n))throw Error(`Unsupported Workflow interrupt kind "${n.payload.kind}".`);let i=e.emit===void 0?void 0:createWorkflowLifecycle({emit:e.emit,emissionState:e.emissionState,skipReplayed:!0,tools:e.config.tools}),a=getWorkflowContinuationSecurity(e.session),o;try{let t=buildWorkflowHostTools({tools:e.config.tools}),r=e.childResults??[],s=n,c=0;for(;;){o=await continueWorkflowSandboxInterrupt({continuationSecurity:a,interrupt:s,lifecycle:i,resolution:r[c]?.output,tools:t});let e=await unwrapWorkflowSandboxResult(o,a);if(e.status!==`interrupted`||!isWorkflowRuntimeActionInterrupt(e.interrupt)||c+1>=r.length)break;let n=getWorkflowRuntimeActionInterrupts(e.interrupt)[0];if(n===void 0)throw Error(`Workflow continuation contains no pending runtime-action interrupt.`);c++,s=n}}catch(e){logError(log,`Workflow interrupt continuation failed`,e),o={error:`workflow_continuation_failed`,message:toErrorMessage(e),retryable:!1}}let s=await unwrapWorkflowSandboxResult(o,a),c=s.status===`interrupted`?s.interrupt:s.output,l=replaceWorkflowToolResult([...e.session.history,...t.responseMessages],n.outerToolCallId,c),u=clearPendingWorkflowInterrupt({...e.session,history:l});if(s.status===`interrupted`){if(!isWorkflowRuntimeActionInterrupt(s.interrupt))throw Error(`Unsupported Workflow interrupt kind "${s.interrupt.payload.kind}".`);let t=e.session.history.length,n=l.slice(0,t),r=l.slice(t);return u={...u,history:n},parkOnWorkflowInterrupt({baseSession:u,emissionState:e.emissionState,interrupt:s.interrupt,promptMessages:n,responseMessages:r})}return{next:e.runStep,session:u}}function replaceWorkflowToolResult(e,t,n){if(t===void 0)return[...e];let r=typeof n==`string`?{type:`text`,value:n}:{type:`json`,value:n};return e.map(e=>{if(e.role!==`tool`)return e;let n=e.content.map(e=>e.type!==`tool-result`||e.toolCallId!==t?e:{...e,output:r});return{...e,content:n}})}function parkOnWorkflowInterrupt(e){let t=getWorkflowRuntimeActionInterrupts(e.interrupt)[0];if(t===void 0)throw Error(`Workflow continuation contains no pending runtime-action interrupt.`);let n={...e.baseSession,history:[...e.promptMessages]};return{next:null,session:setHarnessEmissionState(setPendingWorkflowInterrupt({interrupt:t,responseMessages:e.responseMessages,session:n}),e.emissionState)}}function createNextCompactionConfig(e,t,n){let r={recentWindowSize:e.recentWindowSize,threshold:e.threshold};return n.usage?.inputTokens!==void 0&&(r.lastKnownInputTokens=n.usage.inputTokens,r.lastKnownPromptMessageCount=t.length),r}async function maybeCompact(e){let{emit:t,emissionState:n}=e,r=e.messages,i=e.session;if(!shouldCompact(r,i.compaction))return{messages:r,session:i};let a=await resolveCompactionModel({compactionModelReference:i.agent.compactionModelReference,model:e.model,modelReference:i.agent.modelReference,resolveModel:e.resolveModel});if(t&&await t(createCompactionRequestedEvent({modelId:formatLanguageModelGatewayId(a.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId,usageInputTokens:getInputTokenCount(r,i.compaction)})),r=await compactMessages(r,a.model,i.compaction,a.providerOptions,e.telemetry,e.headers,e.abortSignal),e.onCompaction)for(let t of e.onCompaction())r.push(t);return t&&await t(createCompactionCompletedEvent({modelId:formatLanguageModelGatewayId(a.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId})),{messages:r,session:i}}function resolveApprovalKeyFromTools(e){return t=>{let n=e.get(t.action.toolName);if(n?.approvalKey!==void 0)return n.approvalKey(t.action.input)}}async function runModelCallWithRetries(e,t,n){for(let r=1;;r++){throwIfTurnAborted(n);try{return await e()}catch(e){if(throwIfTurnAborted(n),r===3||classifyModelCallError(e)!==`retry`)throw e;let i=500*2**(r-1)+Math.floor(Math.random()*250);log.warn(`model call failed transiently — retrying`,{attempt:r,delayMs:i,sessionId:t.sessionId,turnId:t.turnId,error:e}),await new Promise(e=>setTimeout(e,i))}}}function findAuthorizationSignalFromToolResults(e){let t=contextStorage.getStore();if(t!==void 0)for(let n of e??[]){let e=readToolInterrupt(t,n.toolCallId);if(e!==void 0&&isAuthorizationSignal(e))return e}for(let t of e??[])if(isAuthorizationSignal(t.output))return t.output}export{createToolLoopHarness};
1
+ import{createErrorId,createLogger,formatError,logError,recordErrorOnSpan}from"#internal/logging.js";import{isScheduleAppAuth}from"#channel/schedule-auth.js";import{AuthKey,ParentSessionKey}from"#context/keys.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{EmptyModelResponseError,classifyModelCallError,extractModelCallErrorDetails,extractUnsupportedProviderToolTypes,isNoOutputGeneratedError,summarizeKnownModelCallConfigError,summarizeKnownModelCallRequestError}from"#harness/model-call-error.js";import{toErrorMessage}from"#shared/errors.js";import{createActionResultEvent,createAuthorizationRequiredEvent,createCompactionCompletedEvent,createCompactionRequestedEvent,createInputRequestedEvent,createResultCompletedEvent}from"#protocol/message.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{contextStorage}from"#context/container.js";import{ToolLoopAgent,isStepCount}from"ai";import{advanceStep,emitFailedStep,emitRecoverableFailedTurn,emitStepStarted,emitStreamContent,emitTurnEpilogue,emitTurnPreamble,getHarnessEmissionState,setHarnessEmissionState}from"#harness/emission.js";import{createRuntimeActionRequestFromToolCall,resolvePendingRuntimeActions,setPendingRuntimeActionBatch}from"#harness/runtime-actions.js";import{clearPendingWorkflowInterrupt,getPendingWorkflowInterrupt,setPendingWorkflowInterrupt}from"#harness/workflow-interrupt-state.js";import{getWorkflowRuntimeActionInterrupts,isWorkflowRuntimeActionInterrupt}from"#harness/workflow-runtime-action-state.js";import{context,trace}from"#compiled/@opentelemetry/api/index.js";import{isAuthorizationSignal,setPendingAuthorization}from"#harness/authorization.js";import{resolveAssistantStepText}from"#harness/messages.js";import{buildDynamicInstructionMessages}from"#context/dynamic-instruction-lifecycle.js";import{PendingSkillAnnouncementKey}from"#context/dynamic-skill-lifecycle.js";import{consumeDeferredStepInput,getApprovedTools,hasDeferredStepInput,hasStepInput,resolvePendingInput,setPendingInputBatch}from"#harness/input-requests.js";import{accumulateTurnUsage,getTurnUsageState,setTurnUsageState}from"#harness/turn-tag-state.js";import{getWorkflowContinuationSecurity,readWorkflowContinuationSecurity}from"#harness/workflow-continuation-security.js";import{buildWorkflowHostTools}from"#harness/workflow-sandbox.js";import{CONDITIONAL_DELIVERY_INSTRUCTION,EMPTY_DELIVERY_SENTINEL,hasEmptyDeliverySentinel}from"#shared/empty-delivery.js";import{readToolInterrupt}from"#harness/tool-interrupts.js";import{ASK_QUESTION_TOOL_NAME}from"#runtime/framework-tools/ask-question.js";import{throwIfTurnAborted}from"#harness/turn-cancellation.js";import{extractQuestionInputRequests,extractToolApprovalInputRequests}from"#harness/input-extraction.js";import{applyLastToolCacheBreakpoint,applySystemCacheBreakpoint,detectPromptCachePath,getAnthropicCacheMarker}from"#harness/prompt-cache.js";import{buildDynamicTools}from"#context/build-dynamic-tools.js";import{hydrateSandboxAttachments,stageAttachmentsToSandbox}from"#harness/attachment-staging.js";import{createWorkflowLifecycle}from"#harness/workflow-lifecycle.js";import{compactMessages,getInputTokenCount,resolveCompactionModel,shouldCompact}from"#harness/compaction.js";import{applySessionLimitContinuation,enforceSessionTokenLimit}from"#harness/session-limit-enforcement.js";import{setEveAttributes}from"#runtime/attributes/emit.js";import{buildTelemetryRuntimeContext}from"#harness/instrumentation-runtime-context.js";import{getInstrumentationConfig}from"#harness/instrumentation-config.js";import{normalizeProviderToolHistory}from"#harness/provider-tool-history.js";import{extractWorkflowStreamWriteErrorDetails}from"#harness/workflow-stream-error.js";import{ensureOtelIntegration}from"#harness/otel-integration.js";import{getAdvertisedTools}from"#harness/advertised-tools.js";import{resolveFrameworkToolFromUpstreamType}from"#harness/provider-tools.js";import{buildStepHooks,emitStepActions,isInvalidToolCall}from"#harness/step-hooks.js";import{buildToolApproval,buildToolSetFromDefinitions,buildToolSetWithProviderTools}from"#harness/tools.js";import{continueWorkflowSandboxInterrupt,getWorkflowSandboxInterrupt,unwrapWorkflowSandboxResult}from"#shared/workflow-sandbox.js";import{FINAL_OUTPUT_TOOL_NAME,buildFinalOutputTool}from"#runtime/framework-tools/final-output.js";const environment=process.env.NODE_ENV??`unknown`,eveVersion=resolveInstalledPackageInfo().version,log=createLogger(`harness.tool-loop`);function logToolExecutionError(e){e.toolOutput.type===`tool-error`&&logError(log,`tool execution failed`,e.toolOutput.error,{toolName:e.toolCall.toolName,toolCallId:e.toolCall.toolCallId})}function enrichTelemetry(e,t,n){if(e===void 0)return;let r={};for(let e of Object.keys(n??{}))r[e]=!0;return{functionId:e.functionId??t,includeRuntimeContext:r,isEnabled:!0,recordInputs:e.recordInputs??!0,recordOutputs:e.recordOutputs??!0}}function buildGatewayAttributionHeaders(e,t){if(typeof e!=`string`)return;let n=t?.agentName??t?.agentId,r=process.env.VERCEL_PROJECT_PRODUCTION_URL||process.env.VERCEL_URL,i=r?`https://${r}`:void 0;if(!n&&!i)return;let a={};return n&&(a[`x-title`]=n),i&&(a[`http-referer`]=i),a}const TURN_TRACE_STATE_KEY=`eve.harness.turnTrace`;function getTurnTraceState(e){return e.state?.[TURN_TRACE_STATE_KEY]}function setTurnTraceState(e,t){let n={traceId:t.traceId,spanId:t.spanId,traceFlags:t.traceFlags};return{...e,state:{...e.state,[TURN_TRACE_STATE_KEY]:n}}}function resolveStepOtelContext(e,t,n){if(t)return trace.setSpan(context.active(),t);if(e){let e=getTurnTraceState(n);if(e){let t=trace.wrapSpanContext({traceId:e.traceId,spanId:e.spanId,traceFlags:e.traceFlags});return trace.setSpan(context.active(),t)}}}function createToolLoopHarness(t){let n=t.handleEvent,c=getInstrumentationConfig();c!==void 0&&ensureOtelIntegration();let f=c===void 0?void 0:trace.getTracer(`eve`),p=t.runtimeIdentity?.agentName;async function runStep(e,t){let n;if(f&&hasStepInput(t)){let t=c?.functionId??p,r={"eve.version":eveVersion,"eve.environment":environment,"eve.session.id":e.sessionId};t&&(r[`ai.telemetry.functionId`]=t),n=f.startSpan(`ai.eve.turn`,{attributes:r})}let r=resolveStepOtelContext(f,n,e),executeStep=()=>executeStepBody(e,t,n);try{return r?await context.with(r,executeStep):await executeStep()}finally{n?.end()}}async function executeStepBody(f,v,y){let b=f;y&&(b=setTurnTraceState(b,y.spanContext()));let x=getHarnessEmissionState(b.state),S=consumeDeferredStepInput({input:v,session:b});b=S.session;let D=await resolvePendingRuntimeActions({emit:n,session:b,stepInput:S.input});if(D.outcome===`unresolved`)return{next:null,session:D.session};b=D.session;let A=resolvePendingInput({history:D.messages,resolveApprovalKey:resolveApprovalKeyFromTools(t.tools),session:b,stepInput:S.input});if(A.outcome===`unresolved`)return n&&A.deferredMessage===!0&&hasStepInput(v)?(x=await emitTurnPreamble(n,v??{},x,t.runtimeIdentity),x=await emitTurnEpilogue(n,x,t.mode),{next:null,session:setHarnessEmissionState(A.session,x)}):{next:null,session:A.session};if(n&&A.rejectedActions)for(let e of A.rejectedActions.results)await n(createActionResultEvent({rejected:!0,result:e,sequence:A.rejectedActions.event.sequence,stepIndex:A.rejectedActions.event.stepIndex,turnId:A.rejectedActions.event.turnId}));n&&hasStepInput(v)&&(x=await emitTurnPreamble(n,v??{},x,t.runtimeIdentity),b=setHarnessEmissionState(b,x),y&&y.setAttribute(`eve.turn.id`,x.turnId)),b=A.session;let j=A.messages,M=await applySessionLimitContinuation({config:t,emit:n,emissionState:x,limitContinuation:A.limitContinuation,session:b});if(M.result!==null)return M.result;if(b=M.session,S.input?.context!==void 0)for(let e of S.input.context)j.push({content:e,role:`user`});if(S.input?.message!==void 0&&!A.deferredMessage&&!A.consumedMessage){let e=await stageAttachmentsToSandbox(S.input.message);j.push({content:e,role:`user`})}let N=await t.resolveModel(b.agent.modelReference),P=detectPromptCachePath(N),F=P.kind===`anthropic-direct`?getAnthropicCacheMarker():void 0,I=buildGatewayAttributionHeaders(N,t.runtimeIdentity);({messages:j,session:b}=await maybeCompact({abortSignal:t.abortSignal,emit:n,emissionState:x,headers:I,messages:j,model:N,onCompaction:t.onCompaction,resolveModel:t.resolveModel,session:b,telemetry:enrichTelemetry(c,p)??void 0}));let L=getApprovedTools(b),R=contextStorage.getStore(),z=b.outputSchema===void 0&&R!==void 0&&isScheduleAppAuth(R.get(AuthKey))&&R.get(ParentSessionKey)===void 0,B=await hydrateSandboxAttachments(j),V=[],H=[];for(let e of B)e.role===`system`?V.push(e):H.push(e);if(R!==void 0){V.push(...buildDynamicInstructionMessages(R));let e=R.get(PendingSkillAnnouncementKey);e!==void 0&&e.length>0&&V.push({role:`system`,content:e})}z&&V.push({role:`system`,content:CONDITIONAL_DELIVERY_INSTRUCTION});let U=H,prepareModelCallInput=e=>{let t=e?[{role:`system`,content:e}]:[],n=b.agent.system?[{role:`system`,content:b.agent.system}]:[],r=V.length>0||t.length>0?[...t,...n,...V]:void 0,i=r!==void 0&&F?applySystemCacheBreakpoint(r,F):r??b.agent.system??void 0;return{instructions:i,telemetryRuntimeContext:buildTelemetryRuntimeContext({eveVersion,authored:c,emissionState:x,environment,modelInput:{instructions:i,messages:U},session:b})}},runOneModelCall=async e=>{let{instructions:i,telemetryRuntimeContext:a={}}=e.preparedInput??prepareModelCallInput(e.extraSystemNote);e.retryReason&&(a[`eve.retry.reason`]=e.retryReason);let o=e.trailingUserNote?[...U,{role:`user`,content:e.trailingUserNote}]:U,s=getAdvertisedTools({session:b,tools:t.tools}),u=await buildToolSetWithProviderTools({approvedTools:L,capabilities:t.capabilities,disabledProviderTools:e.disabledProviderTools,modelReference:b.agent.modelReference,tools:s});if(R!==void 0){let n=getAdvertisedTools({session:b,tools:buildDynamicTools(R)}),r=buildToolSetFromDefinitions({approvedTools:L,capabilities:t.capabilities,disabledProviderTools:e.disabledProviderTools,tools:n});for(let[e,t]of Object.entries(r))u[e]=t}b.outputSchema!==void 0&&(u[FINAL_OUTPUT_TOOL_NAME]=buildFinalOutputTool(b.outputSchema));let d=n===void 0?void 0:({tools:e})=>createWorkflowLifecycle({emit:n,emissionState:x,tools:e}),f=t.workflow===!0?{lifecycle:d,maxSubagents:t.workflowMaxSubagents}:void 0,h=await getAdvertisedTools({modelTools:u,session:b,tools:s,workflow:f});b=h.session;let g=h.modelTools,_=F?applyLastToolCacheBreakpoint(g,F):g,v=buildStepHooks({cachePath:P,emit:n,emissionState:x,emitStepStarted:e.suppressStepStartedEmission!==!0,marker:F,session:b}),y=new ToolLoopAgent({headers:I,instructions:i,model:N,onToolExecutionEnd:logToolExecutionError,onError(e){summarizeKnownModelCallConfigError(e.error)===null&&logError(log,`tool-loop stream error`,e.error)},onStepFinish:v.onStepFinish,prepareStep:v.prepareStep,reasoning:b.agent.reasoning,runtimeContext:a,stopWhen:isStepCount(1),telemetry:enrichTelemetry(c,p,a),toolApproval:buildToolApproval(g),tools:_}),executeModelCall=async()=>{if(n){let e=[...t.tools].filter(([e,t])=>t.runtimeAction!==void 0&&s.get(e)===void 0).map(([e])=>e),r=new Set([ASK_QUESTION_TOOL_NAME,FINAL_OUTPUT_TOOL_NAME,...e]),i=await y.stream({abortSignal:t.abortSignal,messages:o}),{emittedActionCallIds:a,handledInlineToolResultCallIds:c,inlineAuthorizationResults:u,inlineToolResultParts:d,trailingInlineToolResultParts:f}=await emitStreamContent(n,x,i.fullStream,{excludedActionToolNames:r,tools:t.tools});throwIfTurnAborted(t.abortSignal);let p=await v.stepResult;if(isEmptyModelResponse(p)&&d.length===0&&u.length===0&&f.length===0)throw new EmptyModelResponseError;if(await emitStepActions(n,x,p,{emittedActionCallIds:a,excludedActionToolNames:r,handledInlineToolResultCallIds:c,tools:s}),d.length>0||u.length>0||f.length>0){let e=p.toolResults,t=new Map(e.map(e=>[e.toolCallId,e]));for(let e of u)t.set(e.toolCallId,e);return{content:p.content,finishReason:p.finishReason,response:{...p.response,...d.length>0||f.length>0?{messages:insertInlineToolResultMessages({append:f,prepend:d,responseMessages:p.response.messages})}:{}},providerMetadata:p.providerMetadata,text:p.text,toolCalls:p.toolCalls,toolResults:[...t.values()],usage:p.usage}}return p}await y.generate({abortSignal:t.abortSignal,messages:o}),throwIfTurnAborted(t.abortSignal);let e=await v.stepResult;if(isEmptyModelResponse(e))throw new EmptyModelResponseError;return e};return runModelCallWithRetries(()=>executeModelCall().catch(rethrowNoOutputAsEmptyResponse),{sessionId:b.sessionId,turnId:x.turnId},t.abortSignal)},W=prepareModelCallInput();n&&await emitStepStarted(n,x,j);let G=await continuePendingWorkflowInterrupt({childResults:S.input?.runtimeActionResults,config:t,emit:n,emissionState:x,runStep,session:b});if(G!==null)return G;let K=await enforceSessionTokenLimit({config:t,emit:n,emissionState:x,messages:j,session:b});if(K!==null)return K;let q;try{q=await runOneModelCall({preparedInput:W,suppressStepStartedEmission:!0})}catch(r){throwIfTurnAborted(t.abortSignal);let a=await runModelCallRecoveryPipeline({error:r,stages:[e=>attemptUnsupportedProviderToolRecovery({error:e.error,runOneModelCall,sessionId:b.sessionId,turnId:x.turnId}),e=>attemptEmptyResponseRecovery({emptyDeliveryEnabled:z,error:e.error,retryCallOptions:e.retryCallOptions,runOneModelCall,sessionId:b.sessionId,turnId:x.turnId})]});if(throwIfTurnAborted(t.abortSignal),a.outcome===`recovered`)q=a.result;else{let r=a.error;if(y&&recordErrorOnSpan(y,r),!n)throw r;let o=extractWorkflowStreamWriteErrorDetails(r);if(o!==null){let t=createErrorId();return log.error(`workflow stream write failed — parking session for retry by the user`,{...o,errorId:t,error:r,sessionId:b.sessionId,turnId:x.turnId}),x=await emitRecoverableFailedTurn(n,x,{code:`WORKFLOW_STREAM_WRITE_FAILED`,details:{...o,errorId:t},message:toErrorMessage(r)}),{next:null,session:setHarnessEmissionState(b,x)}}let s=classifyModelCallError(r),c=createErrorId(),l=s===`terminal`?summarizeKnownModelCallConfigError(r):null,f=l===null?summarizeKnownModelCallRequestError(r):null,p=l?.message??f?.message??toErrorMessage(r),_=extractModelCallErrorDetails(r),v=buildModelCallFailureDetails({configSummary:l,error:r,errorId:c,modelCallDetails:_,requestSummary:f}),S=buildModelCallFailureLogFields({error:r,errorId:c,modelCallDetails:_,requestSummary:f,sessionId:b.sessionId,turnId:x.turnId});return s===`terminal`?(l===null?log.error(f?.message??`model call failed terminally`,S):log.error(`${l.name}: ${l.message}`,{errorId:c,sessionId:b.sessionId,turnId:x.turnId}),await emitFailedStep(n,x,{code:`MODEL_CALL_FAILED`,details:v,message:p,sessionId:b.sessionId}),{next:t.mode===`task`?{done:!0,isError:!0,output:p}:{done:!0,output:``},session:b}):t.mode===`task`?(log.error(f?.message??`model call failed; failing the task run`,S),await emitFailedStep(n,x,{code:`MODEL_CALL_FAILED`,details:v,message:p,sessionId:b.sessionId}),{next:{done:!0,isError:!0,output:p},session:b}):(log.error(f?.message??`model call failed — parking session for retry by the user`,S),x=await emitRecoverableFailedTurn(n,x,{code:`MODEL_CALL_FAILED`,details:v,message:p}),{next:null,session:setHarnessEmissionState(b,x)})}}let J=accumulateTurnUsage({previous:getTurnUsageState(b.state),turnId:x.turnId,usage:extractTokenUsageDelta({costUsd:extractGatewayCostUsd(q.providerMetadata),usage:q.usage})});b=setTurnUsageState(b,J);let Y;try{Y=formatLanguageModelGatewayId(N)}catch{Y=void 0}return await setEveAttributes({"$eve.model":Y,"$eve.input_tokens":J.inputTokens,"$eve.output_tokens":J.outputTokens,"$eve.cache_read_tokens":J.cacheReadTokens,"$eve.cache_write_tokens":J.cacheWriteTokens,"$eve.cost_usd":J.sawCost?J.costUsd:void 0,"$eve.tool_count":t.tools.size}),handleStepResult({config:t,emit:n,emissionState:x,promptMessages:j,result:q,runStep,session:b})}return runStep}function extractTokenUsageDelta(e){let t=e.usage;if(!(t===void 0&&e.costUsd===void 0))return{cacheReadTokens:t?.inputTokenDetails?.cacheReadTokens,cacheWriteTokens:t?.inputTokenDetails?.cacheWriteTokens,costUsd:e.costUsd,inputTokens:t?.inputTokens,outputTokens:t?.outputTokens}}function extractGatewayCostUsd(e){let t=readGatewayMetadata(e)?.cost;if(typeof t==`number`&&Number.isFinite(t))return t;if(typeof t==`string`){let e=Number(t);return Number.isFinite(e)?e:void 0}}function readGatewayMetadata(e){let t=e?.gateway;return t&&typeof t==`object`&&!Array.isArray(t)?t:void 0}function buildModelCallFailureDetails(e){let{configSummary:t,error:r,errorId:i,modelCallDetails:a,requestSummary:o}=e;return t===null?o===null?{...formatError(r,i),...a}:{errorId:i,message:toErrorMessage(r),name:o.name,...a}:{errorId:i,message:t.message,name:t.name,...a}}function buildModelCallFailureLogFields(e){let t={errorId:e.errorId,sessionId:e.sessionId,turnId:e.turnId};return e.requestSummary===null?{...t,error:e.error}:{...t,details:e.modelCallDetails}}async function runModelCallRecoveryPipeline(e){let t=e.error,n;for(let r of e.stages){let e=await r({error:t,retryCallOptions:n});if(e.outcome===`recovered`)return e;e.outcome===`failed`&&(t=e.error,n=e.retryCallOptions)}return{outcome:`failed`,error:t}}function insertInlineToolResultMessages(e){let t=extractToolResultCallIds(e.responseMessages),n=e.prepend.filter(e=>!t.has(e.toolCallId)),r=e.append.filter(e=>!t.has(e.toolCallId));return[...n.length>0?[{role:`tool`,content:[...n]}]:[],...e.responseMessages,...r.length>0?[{role:`tool`,content:[...r]}]:[]]}function extractToolResultCallIds(e){let t=new Set;for(let n of e)if(!(n.role!==`tool`||!Array.isArray(n.content)))for(let e of n.content)e.type===`tool-result`&&t.add(e.toolCallId);return t}async function attemptUnsupportedProviderToolRecovery(e){let t=extractUnsupportedProviderToolTypes(e.error);if(t.length===0)return{outcome:`skipped`};let n=[];for(let e of t){let t=resolveFrameworkToolFromUpstreamType(e);t!==null&&!n.includes(t)&&n.push(t)}if(n.length===0)return{outcome:`skipped`};log.warn(`disabling unsupported provider tool(s); retrying step once`,{disabled:n,sessionId:e.sessionId,turnId:e.turnId,upstreamTypes:t});let r={disabledProviderTools:new Set(n),extraSystemNote:buildDisabledToolNote(n)};try{return{outcome:`recovered`,result:await e.runOneModelCall({...r,suppressStepStartedEmission:!0})}}catch(e){return{outcome:`failed`,error:e,retryCallOptions:r}}}function buildDisabledToolNote(e){let t=e.join(`, `);return`The following ${e.length===1?`tool is`:`tools are`} not available with the current model and has been removed: ${t}. Proceed using the remaining tools or your training knowledge.`}function isEmptyModelResponse(e){return e.toolCalls.length===0&&e.toolResults.length===0&&resolveAssistantStepText(e.response.messages,e.text)===null}function rethrowNoOutputAsEmptyResponse(e){throw isNoOutputGeneratedError(e)?new EmptyModelResponseError({cause:e}):e}const EMPTY_RESPONSE_NUDGE=`Your previous reply was empty and was not delivered. Answer now from the tool results above; do not re-run tools or mention this notice.`;function buildEmptyResponseNudge(e){return e?`${EMPTY_RESPONSE_NUDGE} If the current task explicitly requires conditional delivery and there is nothing to report, reply with exactly ${EMPTY_DELIVERY_SENTINEL}.`:EMPTY_RESPONSE_NUDGE}async function attemptEmptyResponseRecovery(e){if(!(e.error instanceof EmptyModelResponseError))return{outcome:`skipped`};log.warn(`empty model response; reissuing the model call once`,{sessionId:e.sessionId,turnId:e.turnId});try{return{outcome:`recovered`,result:await e.runOneModelCall({...e.retryCallOptions,retryReason:`empty-response`,suppressStepStartedEmission:!0,trailingUserNote:buildEmptyResponseNudge(e.emptyDeliveryEnabled)})}}catch(t){return{outcome:`failed`,error:t,retryCallOptions:e.retryCallOptions}}}async function handleStepResult(e){let{config:t,emit:n,promptMessages:r,result:i,runStep:a}=e,{emissionState:o,session:s}=e,c=resolveAssistantStepText(i.response.messages,i.text),l=i.finishReason!==`tool-calls`&&i.toolCalls.length===0&&hasEmptyDeliverySentinel(c),u=l?[]:i.response.messages,d=l?null:c,f=new Set;for(let e of[...i.content??[],...i.toolResults??[]])(e.type===`tool-result`||e.type===`tool-error`)&&e.providerExecuted===!0&&f.add(e.toolCallId);let p=normalizeProviderToolHistory({messages:u,providerExecutedOutcomeIds:f}),m=p.messages,h={...s,compaction:createNextCompactionConfig(s.compaction,r,i)},g=t.workflow===!0?readWorkflowContinuationSecurity(h):void 0;if(g!==void 0){let e=await getWorkflowSandboxInterrupt(i,g);if(e!==void 0){if(!isWorkflowRuntimeActionInterrupt(e))throw Error(`Unsupported Workflow interrupt kind "${e.payload.kind}".`);return parkOnWorkflowInterrupt({baseSession:h,emissionState:o,interrupt:e,promptMessages:r,responseMessages:m})}}let _=extractToolApprovalInputRequests({content:i.content??[]}),y=new Set(_.map(e=>e.action.callId)),b=extractQuestionInputRequests({toolCalls:i.toolCalls,excludedCallIds:y}),S=[..._,...b],C=getAdvertisedTools({session:h,tools:t.tools}),w=(i.toolCalls??[]).filter(e=>!isInvalidToolCall(e)).filter(e=>t.tools.get(e.toolName)?.runtimeAction!==void 0).filter(e=>C.get(e.toolName)?.runtimeAction===void 0?(log.warn(`runtime action tool call blocked because tool is not advertised`,{callId:e.toolCallId,sessionId:h.sessionId,toolName:e.toolName}),!1):!0).map(e=>createRuntimeActionRequestFromToolCall({toolCall:e,tools:C}));if(w.length>0)return{next:null,session:setHarnessEmissionState(setPendingRuntimeActionBatch({actions:w,event:{sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId},responseMessages:m,session:{...h,history:[...r]}}),o)};if(S.length>0){let e=setPendingInputBatch({event:{sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId},requests:S,responseMessages:m,session:{...h,history:[...r]}});return n&&(await n(createInputRequestedEvent({requests:S,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})),t.mode===`conversation`&&(o=await emitTurnEpilogue(n,o,t.mode),e=setHarnessEmissionState(e,o))),{next:null,session:e}}let T=findAuthorizationSignalFromToolResults(i.toolResults);if(T){let{challenges:e}=T;if(n)for(let t of e)await n(createAuthorizationRequiredEvent({authorization:t.challenge,name:t.name,description:t.challenge.instructions??`Authorization required for ${t.name}`,webhookUrl:t.hookUrl,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId}));return{next:null,session:setHarnessEmissionState({...h,history:[...r],state:setPendingAuthorization(h.state,{challenges:e})},o)}}let E=m,O=[...r,...E],k={...h,history:O};return!(k.outputSchema!==void 0&&extractFinalOutput(i)!==void 0)&&(E.at(-1)?.role===`tool`||p.outcomeEndsResponse||hasDeferredStepInput(k))?(n&&(o=advanceStep(o),k=setHarnessEmissionState(k,o)),{next:a,session:k}):t.mode===`task`?finishTaskTurn({emissionState:o,emit:n,history:r,result:i,schema:k.outputSchema,session:k,stepOutput:d}):finishConversationTurn({emissionState:o,emit:n,history:r,result:i,schema:k.outputSchema,session:k})}const OUTPUT_SCHEMA_NOT_FULFILLED={code:`OUTPUT_SCHEMA_NOT_FULFILLED`,message:`The agent could not produce a result matching the requested schema.`};function extractFinalOutput(e){return(e.toolCalls??[]).find(e=>e.toolName===FINAL_OUTPUT_TOOL_NAME)?.input}function persistStructuredAssistantTurn(e,t,n){return{...e,history:[...t,{content:JSON.stringify(n),role:`assistant`}],outputSchema:void 0}}async function emitStructuredResult(e,t,n,r){return await e(createResultCompletedEvent({result:n,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId})),emitTurnEpilogue(e,t,r)}async function finishTaskTurn(e){let{emit:t,history:n,result:r,schema:i,stepOutput:a}=e,{emissionState:o,session:s}=e;if(i===void 0)return t&&(o=await emitTurnEpilogue(t,o,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:a??``},session:s};let c=extractFinalOutput(r);return c===void 0?(t&&await emitFailedStep(t,o,{...OUTPUT_SCHEMA_NOT_FULFILLED,sessionId:s.sessionId}),{next:{done:!0,isError:!0,output:OUTPUT_SCHEMA_NOT_FULFILLED.message},session:s}):(s=persistStructuredAssistantTurn(s,n,c),t&&(o=await emitStructuredResult(t,o,c,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:c},session:s})}async function finishConversationTurn(e){let{emit:t,history:n,result:r,schema:i}=e,{emissionState:a,session:o}=e;if(i===void 0)return t&&(a=await emitTurnEpilogue(t,a,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o};let s=extractFinalOutput(r);return s===void 0?(t&&(a=await emitRecoverableFailedTurn(t,a,OUTPUT_SCHEMA_NOT_FULFILLED),o=setHarnessEmissionState(o,a)),{next:null,session:o}):(o=persistStructuredAssistantTurn(o,n,s),t&&(a=await emitStructuredResult(t,a,s,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o})}async function continuePendingWorkflowInterrupt(e){let t=getPendingWorkflowInterrupt(e.session.state);if(t===void 0)return null;let n=t.interrupt;if(!isWorkflowRuntimeActionInterrupt(n))throw Error(`Unsupported Workflow interrupt kind "${n.payload.kind}".`);let i=e.emit===void 0?void 0:createWorkflowLifecycle({emit:e.emit,emissionState:e.emissionState,skipReplayed:!0,tools:e.config.tools}),a=getWorkflowContinuationSecurity(e.session),o;try{let t=buildWorkflowHostTools({tools:e.config.tools}),r=e.childResults??[],s=n,c=0;for(;;){o=await continueWorkflowSandboxInterrupt({continuationSecurity:a,interrupt:s,lifecycle:i,resolution:r[c]?.output,tools:t});let e=await unwrapWorkflowSandboxResult(o,a);if(e.status!==`interrupted`||!isWorkflowRuntimeActionInterrupt(e.interrupt)||c+1>=r.length)break;let n=getWorkflowRuntimeActionInterrupts(e.interrupt)[0];if(n===void 0)throw Error(`Workflow continuation contains no pending runtime-action interrupt.`);c++,s=n}}catch(e){logError(log,`Workflow interrupt continuation failed`,e),o={error:`workflow_continuation_failed`,message:toErrorMessage(e),retryable:!1}}let s=await unwrapWorkflowSandboxResult(o,a),c=s.status===`interrupted`?s.interrupt:s.output,l=replaceWorkflowToolResult([...e.session.history,...t.responseMessages],n.outerToolCallId,c),u=clearPendingWorkflowInterrupt({...e.session,history:l});if(s.status===`interrupted`){if(!isWorkflowRuntimeActionInterrupt(s.interrupt))throw Error(`Unsupported Workflow interrupt kind "${s.interrupt.payload.kind}".`);let t=e.session.history.length,n=l.slice(0,t),r=l.slice(t);return u={...u,history:n},parkOnWorkflowInterrupt({baseSession:u,emissionState:e.emissionState,interrupt:s.interrupt,promptMessages:n,responseMessages:r})}return{next:e.runStep,session:u}}function replaceWorkflowToolResult(e,t,n){if(t===void 0)return[...e];let r=typeof n==`string`?{type:`text`,value:n}:{type:`json`,value:n};return e.map(e=>{if(e.role!==`tool`)return e;let n=e.content.map(e=>e.type!==`tool-result`||e.toolCallId!==t?e:{...e,output:r});return{...e,content:n}})}function parkOnWorkflowInterrupt(e){let t=getWorkflowRuntimeActionInterrupts(e.interrupt)[0];if(t===void 0)throw Error(`Workflow continuation contains no pending runtime-action interrupt.`);let n={...e.baseSession,history:[...e.promptMessages]};return{next:null,session:setHarnessEmissionState(setPendingWorkflowInterrupt({interrupt:t,responseMessages:e.responseMessages,session:n}),e.emissionState)}}function createNextCompactionConfig(e,t,n){let r={recentWindowSize:e.recentWindowSize,threshold:e.threshold};return n.usage?.inputTokens!==void 0&&(r.lastKnownInputTokens=n.usage.inputTokens,r.lastKnownPromptMessageCount=t.length),r}async function maybeCompact(e){let{emit:t,emissionState:n}=e,r=e.messages,i=e.session;if(!shouldCompact(r,i.compaction))return{messages:r,session:i};let a=await resolveCompactionModel({compactionModelReference:i.agent.compactionModelReference,model:e.model,modelReference:i.agent.modelReference,resolveModel:e.resolveModel});if(t&&await t(createCompactionRequestedEvent({modelId:formatLanguageModelGatewayId(a.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId,usageInputTokens:getInputTokenCount(r,i.compaction)})),r=await compactMessages(r,a.model,i.compaction,a.providerOptions,e.telemetry,e.headers,e.abortSignal),e.onCompaction)for(let t of e.onCompaction())r.push(t);return t&&await t(createCompactionCompletedEvent({modelId:formatLanguageModelGatewayId(a.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId})),{messages:r,session:i}}function resolveApprovalKeyFromTools(e){return t=>{let n=e.get(t.action.toolName);if(n?.approvalKey!==void 0)return n.approvalKey(t.action.input)}}async function runModelCallWithRetries(e,t,n){for(let r=1;;r++){throwIfTurnAborted(n);try{return await e()}catch(e){if(throwIfTurnAborted(n),r===3||classifyModelCallError(e)!==`retry`)throw e;let i=500*2**(r-1)+Math.floor(Math.random()*250);log.warn(`model call failed transiently — retrying`,{attempt:r,delayMs:i,sessionId:t.sessionId,turnId:t.turnId,error:e}),await new Promise(e=>setTimeout(e,i))}}}function findAuthorizationSignalFromToolResults(e){let t=contextStorage.getStore();if(t!==void 0)for(let n of e??[]){let e=readToolInterrupt(t,n.toolCallId);if(e!==void 0&&isAuthorizationSignal(e))return e}for(let t of e??[])if(isAuthorizationSignal(t.output))return t.output}export{createToolLoopHarness};
@@ -14,8 +14,16 @@
14
14
  * `turnId` keys the turn totals so a fresh turn starts at zero without relying
15
15
  * on a separate "reset" code path. Session totals stay in the same state record
16
16
  * and keep accumulating until the durable session ends.
17
+ *
18
+ * `TokenUsageTotals` carries `costUsd`/`sawCost` alongside the token counts
19
+ * for the `$eve.*` dashboard tags and session limits — fields the
20
+ * cross-cutting {@link TokenUsage} contract (subagent results, callback
21
+ * bodies, usage spans) does not carry. {@link toUsage} projects a total down
22
+ * to that shared shape at the one site (the driver's `done` action) where a
23
+ * session total crosses into it.
17
24
  */
18
25
  import type { HarnessSession, SessionStateMap } from "#harness/types.js";
26
+ import type { TokenUsage } from "#shared/token-usage.js";
19
27
  export interface TokenUsageTotals {
20
28
  readonly cacheReadTokens: number;
21
29
  readonly cacheWriteTokens: number;
@@ -48,6 +56,18 @@ export type SessionTokenLimitViolation = {
48
56
  readonly usedTokens: number;
49
57
  };
50
58
  export declare function getSessionTokenUsage(session: Pick<HarnessSession, "state">): TokenUsageTotals;
59
+ /** Projects a {@link TokenUsageTotals} down to the cross-cutting {@link TokenUsage} shape. */
60
+ export declare function toUsage(totals: TokenUsageTotals): TokenUsage;
61
+ /**
62
+ * Resets the session token budget windows to the current usage totals.
63
+ *
64
+ * Called when the user grants a continuation after a session token limit was
65
+ * reached. The configured limits keep their values and act as the size of the
66
+ * next budget window, measured from the moment of the grant. Both windows
67
+ * reset together so a session near two limits gets one prompt, not two
68
+ * back-to-back.
69
+ */
70
+ export declare function extendSessionTokenBudget(session: HarnessSession): HarnessSession;
51
71
  export declare function getSessionTokenLimitViolation(session: Pick<HarnessSession, "limits" | "state">): SessionTokenLimitViolation | null;
52
72
  /** Writes per-turn token state onto a new copy of the session. */
53
73
  export declare function setTurnUsageState(session: HarnessSession, next: TurnUsageState): HarnessSession;
@@ -62,3 +82,14 @@ export declare function accumulateTurnUsage(input: {
62
82
  readonly turnId: string;
63
83
  readonly usage: TokenUsageDelta | undefined;
64
84
  }): TurnUsageState;
85
+ /**
86
+ * Folds a delegated child session's reported totals into the parent's
87
+ * session totals without touching the in-flight turn totals. Turn tags
88
+ * attribute only the parent's own model calls (child spend is attributed by
89
+ * the caller-side `invoke_agent` span); session totals feed the session
90
+ * token limits and the remaining-quota budget granted to later delegations.
91
+ */
92
+ export declare function accumulateSessionUsage(input: {
93
+ readonly previous: TurnUsageState | undefined;
94
+ readonly usage: TokenUsageDelta;
95
+ }): TurnUsageState;
@@ -1 +1 @@
1
- const HARNESS_TURN_USAGE_STATE_KEY=`eve.harness.turnUsage`,ZERO_TOKEN_USAGE={cacheReadTokens:0,cacheWriteTokens:0,costUsd:0,inputTokens:0,outputTokens:0,sawCost:!1};function getTurnUsageState(t){return t?.[HARNESS_TURN_USAGE_STATE_KEY]}function getSessionTokenUsage(e){return getTurnUsageState(e.state)?.session??ZERO_TOKEN_USAGE}function getSessionTokenLimitViolation(e){let t=getSessionTokenUsage(e),n=e.limits?.maxInputTokensPerSession,r=e.limits?.maxOutputTokensPerSession;return n!==void 0&&t.inputTokens>=n?{kind:`input`,limit:n,usedTokens:t.inputTokens}:r!==void 0&&t.outputTokens>=r?{kind:`output`,limit:r,usedTokens:t.outputTokens}:null}function setTurnUsageState(t,n){return{...t,state:{...t.state,[HARNESS_TURN_USAGE_STATE_KEY]:n}}}function accumulateTurnUsage(e){let n=toTokenUsageDelta(e.usage),r=e.previous?.session??ZERO_TOKEN_USAGE;return{...addTokenUsage(e.previous!==void 0&&e.previous.turnId===e.turnId?e.previous:ZERO_TOKEN_USAGE,n),turnId:e.turnId,session:addTokenUsage(r,n)}}function addTokenUsage(e,t){return{cacheReadTokens:e.cacheReadTokens+t.cacheReadTokens,cacheWriteTokens:e.cacheWriteTokens+t.cacheWriteTokens,costUsd:e.costUsd+t.costUsd,inputTokens:e.inputTokens+t.inputTokens,outputTokens:e.outputTokens+t.outputTokens,sawCost:e.sawCost||t.sawCost}}function toTokenUsageDelta(e){if(e===void 0)return ZERO_TOKEN_USAGE;let n=e.inputTokens??0,r=e.outputTokens??0;return{cacheReadTokens:e.cacheReadTokens??0,cacheWriteTokens:e.cacheWriteTokens??0,costUsd:e.costUsd??0,inputTokens:n,outputTokens:r,sawCost:e.costUsd!==void 0}}export{accumulateTurnUsage,getSessionTokenLimitViolation,getSessionTokenUsage,getTurnUsageState,setTurnUsageState};
1
+ const HARNESS_TURN_USAGE_STATE_KEY=`eve.harness.turnUsage`,SESSION_TOKEN_BUDGET_BASELINE_KEY=`eve.harness.sessionTokenBudgetBaseline`,ZERO_TOKEN_USAGE={cacheReadTokens:0,cacheWriteTokens:0,costUsd:0,inputTokens:0,outputTokens:0,sawCost:!1};function getTurnUsageState(t){return t?.[HARNESS_TURN_USAGE_STATE_KEY]}function getSessionTokenUsage(e){return getTurnUsageState(e.state)?.session??ZERO_TOKEN_USAGE}function toUsage(e){return{cacheReadTokens:e.cacheReadTokens,cacheWriteTokens:e.cacheWriteTokens,inputTokens:e.inputTokens,outputTokens:e.outputTokens}}const ZERO_BUDGET_BASELINE={inputTokens:0,outputTokens:0};function getSessionTokenBudgetBaseline(e){return e?.[SESSION_TOKEN_BUDGET_BASELINE_KEY]??ZERO_BUDGET_BASELINE}function extendSessionTokenBudget(e){let n=getSessionTokenUsage(e);return{...e,state:{...e.state,[SESSION_TOKEN_BUDGET_BASELINE_KEY]:{inputTokens:n.inputTokens,outputTokens:n.outputTokens}}}}function getSessionTokenLimitViolation(e){let t=getSessionTokenUsage(e),n=getSessionTokenBudgetBaseline(e.state),r=e.limits?.maxInputTokensPerSession,i=e.limits?.maxOutputTokensPerSession,a=t.inputTokens-n.inputTokens,o=t.outputTokens-n.outputTokens;return r!==void 0&&a>=r?{kind:`input`,limit:r,usedTokens:a}:i!==void 0&&o>=i?{kind:`output`,limit:i,usedTokens:o}:null}function setTurnUsageState(t,n){return{...t,state:{...t.state,[HARNESS_TURN_USAGE_STATE_KEY]:n}}}function accumulateTurnUsage(e){let t=toTokenUsageDelta(e.usage),r=e.previous?.session??ZERO_TOKEN_USAGE;return{...addTokenUsage(e.previous!==void 0&&e.previous.turnId===e.turnId?e.previous:ZERO_TOKEN_USAGE,t),turnId:e.turnId,session:addTokenUsage(r,t)}}function accumulateSessionUsage(e){let t=toTokenUsageDelta(e.usage),r=e.previous??{...ZERO_TOKEN_USAGE,session:ZERO_TOKEN_USAGE,turnId:``};return{...r,session:addTokenUsage(r.session,t)}}function addTokenUsage(e,t){return{cacheReadTokens:e.cacheReadTokens+t.cacheReadTokens,cacheWriteTokens:e.cacheWriteTokens+t.cacheWriteTokens,costUsd:e.costUsd+t.costUsd,inputTokens:e.inputTokens+t.inputTokens,outputTokens:e.outputTokens+t.outputTokens,sawCost:e.sawCost||t.sawCost}}function toTokenUsageDelta(e){if(e===void 0)return ZERO_TOKEN_USAGE;let t=e.inputTokens??0,r=e.outputTokens??0;return{cacheReadTokens:e.cacheReadTokens??0,cacheWriteTokens:e.cacheWriteTokens??0,costUsd:e.costUsd??0,inputTokens:t,outputTokens:r,sawCost:e.costUsd!==void 0}}export{accumulateSessionUsage,accumulateTurnUsage,extendSessionTokenBudget,getSessionTokenLimitViolation,getSessionTokenUsage,getTurnUsageState,setTurnUsageState,toUsage};
@@ -79,15 +79,24 @@ export interface HarnessSession {
79
79
  * harness uses the framework default.
80
80
  */
81
81
  readonly subagentMaxDepth?: number;
82
+ /**
83
+ * Effective maximum subagent calls one `Workflow` invocation may dispatch
84
+ * for this session. Resolved at session creation as the tighter of the
85
+ * agent's `limits.maxSubagents` and any cap inherited from the parent run.
86
+ * When omitted, the dispatch step applies the framework default.
87
+ */
88
+ readonly workflowMaxSubagents?: number;
82
89
  }
83
90
  /**
84
91
  * Token limits stored on one durable session.
85
92
  */
86
93
  export interface SessionLimits {
87
94
  /**
88
- * Maximum provider-reported input tokens this durable session may spend before
89
- * eve refuses to start another model call. Defaults to 40M for root sessions
90
- * and 5M for delegated subagent sessions.
95
+ * Maximum provider-reported input tokens this durable session may spend
96
+ * before eve refuses to start another model call. Absent when the session
97
+ * is uncapped. Root sessions default to 40M unless authored otherwise;
98
+ * delegated subagent sessions receive the parent's remaining quota at
99
+ * dispatch time.
91
100
  */
92
101
  readonly maxInputTokensPerSession?: number;
93
102
  /**
@@ -201,10 +210,18 @@ export interface ToolLoopHarnessConfig {
201
210
  * Exposes the `Workflow` orchestration tool — an isolated JavaScript sandbox
202
211
  * whose only callable operations are this agent's subagents and remote
203
212
  * agents. Resolved by the runtime from the agent's `workflowEnabled` flag
204
- * in the compiled manifest.
213
+ * (set when `agent/tools/workflow.ts` re-exports the `ExperimentalWorkflow`
214
+ * marker). Only root sessions ever see the tool.
205
215
  * Defaults to `false`.
206
216
  */
207
217
  readonly workflow?: boolean;
218
+ /**
219
+ * Maximum subagent calls one `Workflow` invocation may dispatch, from the
220
+ * agent's `limits.maxSubagents`. Advertised in the tool description; the
221
+ * dispatch step enforces it. Defaults to
222
+ * {@link import("#harness/workflow-subagent-limit.js").DEFAULT_WORKFLOW_MAX_SUBAGENTS}.
223
+ */
224
+ readonly workflowMaxSubagents?: number;
208
225
  readonly handleEvent?: HandleEventFn;
209
226
  /**
210
227
  * Execution mode for the current harness.
@@ -13,6 +13,7 @@ export declare function applyWorkflowTool(input: {
13
13
  readonly continuationSecurity: WorkflowSandboxContinuationSecurity;
14
14
  readonly harnessTools: HarnessToolMap;
15
15
  readonly lifecycle?: WorkflowSandboxLifecycle;
16
+ readonly maxSubagents?: number;
16
17
  readonly tools: ToolSet;
17
18
  }): Promise<WorkflowToolSet>;
18
19
  /** Rebuilds the subagent-only host surface used to resume a parked workflow. */
@@ -1,2 +1,2 @@
1
- import{jsonSchema}from"ai";import{WORKFLOW_RUNTIME_ACTION_INTERRUPT_KIND}from"#harness/workflow-runtime-action-state.js";import{WORKFLOW_TOOL_NAME,createWorkflowSandboxTool,readWorkflowSandboxResolution,requestWorkflowSandboxInterrupt}from"#shared/workflow-sandbox.js";import{workflowToolDescription}from"#harness/workflow-tool-description.js";async function applyWorkflowTool(t){let i=createWorkflowHostTools(t.harnessTools,Object.keys(t.tools));if(Object.keys(i).length===0)return{hostTools:i,modelTools:t.tools};let a=await createWorkflowSandboxTool({continuationSecurity:t.continuationSecurity,hostTools:i,lifecycle:t.lifecycle}),s=typeof a.description==`string`?a.description:``,c=workflowToolDescription(Object.keys(i)),l=workflowApiReference(s),u={...t.tools};return u[WORKFLOW_TOOL_NAME]={...a,description:l.length>0?`${c}\n\n${l}`:c,inputSchema:jsonSchema({type:`object`,properties:{js:{type:`string`,description:`Complete JavaScript orchestration program. Call only the agents listed in the Workflow description and return one JSON-serializable result.`}},required:[`js`],additionalProperties:!1})},{hostTools:i,modelTools:u}}function workflowApiReference(e){let t=e.indexOf(`Tools:
1
+ import{jsonSchema}from"ai";import{WORKFLOW_RUNTIME_ACTION_INTERRUPT_KIND}from"#harness/workflow-runtime-action-state.js";import{WORKFLOW_TOOL_NAME,createWorkflowSandboxTool,readWorkflowSandboxResolution,requestWorkflowSandboxInterrupt}from"#shared/workflow-sandbox.js";import{workflowToolDescription}from"#harness/workflow-tool-description.js";async function applyWorkflowTool(t){let i=createWorkflowHostTools(t.harnessTools,Object.keys(t.tools));if(Object.keys(i).length===0)return{hostTools:i,modelTools:t.tools};let a=await createWorkflowSandboxTool({continuationSecurity:t.continuationSecurity,hostTools:i,lifecycle:t.lifecycle}),s=typeof a.description==`string`?a.description:``,c=workflowToolDescription(Object.keys(i),{maxSubagents:t.maxSubagents}),l=workflowApiReference(s),u={...t.tools};return u[WORKFLOW_TOOL_NAME]={...a,description:l.length>0?`${c}\n\n${l}`:c,inputSchema:jsonSchema({type:`object`,properties:{js:{type:`string`,description:`Complete JavaScript orchestration program. Call only the agents listed in the Workflow description and return one JSON-serializable result.`}},required:[`js`],additionalProperties:!1})},{hostTools:i,modelTools:u}}function workflowApiReference(e){let t=e.indexOf(`Tools:
2
2
  `);return t<0?e:`Available agent API:\n${e.slice(t+7)}`}function buildWorkflowHostTools(e){return createWorkflowHostTools(e.tools,e.tools.keys())}function createWorkflowHostTools(e,t){let n={};for(let r of t){let t=e.get(r);t?.runtimeAction!==void 0&&(n[r]=createWorkflowRuntimeActionHostTool(t))}return n}function createWorkflowRuntimeActionHostTool(e){return{description:e.description,inputSchema:e.inputSchema,execute:async(n,r)=>{let o=readWorkflowSandboxResolution(r);return o===void 0?requestWorkflowSandboxInterrupt({kind:WORKFLOW_RUNTIME_ACTION_INTERRUPT_KIND,runtimeAction:e.runtimeAction,toolInput:n,toolName:e.name}):o}}}export{applyWorkflowTool,buildWorkflowHostTools};