eve 0.83.0 → 0.83.2
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.
- package/CHANGELOG.md +33 -0
- package/dist/src/channel/types.d.ts +3 -2
- package/dist/src/chunks/{use-eve-agent-Ci5dr0aR.js → use-eve-agent-DnbG9c7c.js} +33 -9
- package/dist/src/chunks/{use-eve-agent-3-WRmJkd.js → use-eve-agent-ZY7NQ2VW.js} +33 -9
- package/dist/src/cli/run.js +1 -1
- package/dist/src/client/message-response.d.ts +18 -0
- package/dist/src/client/message-response.js +1 -1
- package/dist/src/client/session.js +1 -1
- package/dist/src/compiled/.vendor-stamp.json +2 -2
- package/dist/src/compiled/@ai-sdk/mcp/index.js +1 -1
- package/dist/src/compiled/@eve/catalog/index.js +1 -1
- package/dist/src/context/build-dynamic-tools.js +1 -1
- package/dist/src/context/dynamic-skill-lifecycle.d.ts +2 -2
- package/dist/src/context/dynamic-skill-lifecycle.js +1 -1
- package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
- package/dist/src/context/prewarm.d.ts +27 -0
- package/dist/src/context/prewarm.js +1 -0
- package/dist/src/context/providers/sandbox.d.ts +7 -0
- package/dist/src/context/providers/sandbox.js +1 -1
- package/dist/src/context/run-step.js +1 -1
- package/dist/src/discover/lib.d.ts +4 -3
- package/dist/src/discover/lib.js +1 -1
- package/dist/src/discover/named-source-directory.d.ts +3 -2
- package/dist/src/evals/assertions/run.js +1 -1
- package/dist/src/evals/cli/eval.d.ts +2 -0
- package/dist/src/evals/cli/eval.js +2 -2
- package/dist/src/evals/define-eval-config.d.ts +5 -4
- package/dist/src/evals/define-eval-config.js +1 -1
- package/dist/src/evals/index.d.ts +1 -1
- package/dist/src/evals/runner/artifacts.js +2 -2
- package/dist/src/evals/runner/attempt-label.d.ts +2 -0
- package/dist/src/evals/runner/attempt-label.js +1 -0
- package/dist/src/evals/runner/derive-run-facts.d.ts +13 -0
- package/dist/src/evals/runner/derive-run-facts.js +1 -1
- package/dist/src/evals/runner/reporters/braintrust.js +1 -1
- package/dist/src/evals/runner/reporters/console.js +1 -1
- package/dist/src/evals/runner/reporters/datadog.js +1 -1
- package/dist/src/evals/runner/reporters/junit.js +2 -2
- package/dist/src/evals/runner/reporters/types.d.ts +2 -0
- package/dist/src/evals/runner/run-evals.d.ts +5 -0
- package/dist/src/evals/runner/run-evals.js +1 -1
- package/dist/src/evals/session-manager.js +1 -1
- package/dist/src/evals/session.d.ts +4 -1
- package/dist/src/evals/session.js +2 -2
- package/dist/src/evals/types.d.ts +37 -1
- package/dist/src/eve-channel/request.js +1 -1
- package/dist/src/execution/catalog/connection-entry.js +1 -1
- package/dist/src/execution/connections/callback-route.d.ts +3 -2
- package/dist/src/execution/connections/callback-route.js +1 -1
- package/dist/src/execution/dynamic-workflow/tool.js +1 -1
- package/dist/src/execution/node-step.d.ts +1 -0
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
- package/dist/src/execution/sandbox/ensure.d.ts +8 -0
- package/dist/src/execution/sandbox/ensure.js +1 -1
- package/dist/src/execution/sandbox/multiplexed-command.d.ts +9 -3
- package/dist/src/execution/sandbox/multiplexed-command.js +1 -1
- package/dist/src/execution/sandbox/read-file.js +1 -1
- package/dist/src/execution/session/handoff-steps.d.ts +1 -0
- package/dist/src/execution/session/handoff-steps.js +1 -1
- package/dist/src/execution/session/handoff.js +1 -1
- package/dist/src/execution/session/handover-tracing.d.ts +3 -0
- package/dist/src/execution/session/handover-tracing.js +1 -0
- package/dist/src/execution/session/prewarm-step.d.ts +13 -0
- package/dist/src/execution/session/prewarm-step.js +1 -0
- package/dist/src/execution/session/program.d.ts +4 -1
- package/dist/src/execution/session/program.js +1 -1
- package/dist/src/execution/session/state-cursor.d.ts +11 -0
- package/dist/src/execution/session/state-cursor.js +1 -1
- package/dist/src/execution/session/turn-step-types.d.ts +2 -0
- package/dist/src/execution/session/turn-step.js +1 -1
- package/dist/src/execution/session/turn.d.ts +1 -0
- package/dist/src/execution/session/turn.js +1 -1
- package/dist/src/execution/session-event-stream.d.ts +6 -0
- package/dist/src/execution/session-event-stream.js +1 -1
- package/dist/src/execution/session-inbox/inbox.d.ts +8 -0
- package/dist/src/execution/session-inbox/inbox.js +1 -1
- package/dist/src/execution/tools/agent-router-workflow.js +1 -1
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/extensions/git/extension/lib/gh-tool.d.ts +11 -2
- package/dist/src/extensions/git/extension/lib/gh-tool.js +1 -1
- package/dist/src/harness/attachment-staging.d.ts +3 -0
- package/dist/src/harness/attachment-staging.js +1 -1
- package/dist/src/harness/compaction/step.d.ts +7 -1
- package/dist/src/harness/compaction/step.js +1 -1
- package/dist/src/harness/hitl/approvals.d.ts +2 -0
- package/dist/src/harness/hitl/approvals.js +1 -1
- package/dist/src/harness/hitl/delivery.d.ts +1 -0
- package/dist/src/harness/hitl/delivery.js +1 -1
- package/dist/src/harness/hitl/intake.js +1 -1
- package/dist/src/harness/model-call/call.d.ts +2 -0
- package/dist/src/harness/model-call/call.js +1 -1
- package/dist/src/harness/model-call/request.d.ts +2 -1
- package/dist/src/harness/token-estimate.js +1 -1
- package/dist/src/harness/types.d.ts +6 -0
- package/dist/src/internal/application/stamped-package-version.js +1 -1
- package/dist/src/internal/attachments/media-metadata.d.ts +0 -2
- package/dist/src/internal/attachments/media-metadata.js +1 -1
- package/dist/src/internal/attachments/read-media-metadata.d.ts +7 -0
- package/dist/src/internal/attachments/read-media-metadata.js +2 -0
- package/dist/src/internal/authored-asset-import-plugin.d.ts +7 -0
- package/dist/src/internal/authored-asset-import-plugin.js +1 -1
- package/dist/src/internal/authored-module-build-options.js +1 -1
- package/dist/src/internal/authored-module-graph.js +1 -1
- package/dist/src/internal/authored-module-loader.d.ts +0 -1
- package/dist/src/internal/authored-module-loader.js +1 -1
- package/dist/src/internal/authored-package-boundary.d.ts +3 -0
- package/dist/src/internal/authored-package-boundary.js +1 -1
- package/dist/src/internal/input-text.d.ts +2 -1
- package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
- package/dist/src/internal/workflow-bundle/builder.js +2 -2
- package/dist/src/internal/workflow-bundle/dynamic-tool-transform.js +1 -1
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/runtime/connections/authorization-complete-page.d.ts +14 -2
- package/dist/src/runtime/connections/authorization-complete-page.js +5 -5
- package/dist/src/runtime/subagents/workflow.js +1 -1
- package/dist/src/sandbox/state.d.ts +17 -0
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/tools/definition.js +1 -1
- package/dist/src/tools/durable-callbacks.d.ts +5 -1
- package/dist/src/tools/durable-callbacks.js +1 -1
- package/dist/src/tools/dynamic.d.ts +3 -3
- package/dist/src/tools/provided/ask-question-workflow.js +1 -1
- package/dist/src/tools/provided/sleep-workflow.js +1 -1
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/channels/custom.mdx +4 -0
- package/docs/channels/slack.mdx +2 -0
- package/docs/concepts/built-in-tools.md +1 -1
- package/docs/connections/mcp.mdx +1 -1
- package/docs/evals/overview.mdx +1 -1
- package/docs/evals/reporters.mdx +4 -4
- package/docs/evals/running.mdx +19 -1
- package/docs/guides/dynamic-capabilities.md +2 -2
- package/docs/guides/frontend/overview.mdx +7 -3
- package/docs/guides/instrumentation/otel.mdx +23 -0
- package/docs/meta.json +1 -0
- package/docs/reference/agent-files.md +1 -1
- package/docs/reference/cli.md +17 -15
- package/docs/sandbox/custom-providers.mdx +10 -10
- package/docs/sandbox/index.mdx +6 -4
- package/docs/tools/human-in-the-loop.md +3 -1
- package/docs/tools/overview.mdx +1 -1
- package/docs/use-cases.mdx +250 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{resolveRuntimeCompiledArtifactsVersionedCacheKey}from"#runtime/cache-key.js";import{defaultDeliverResult}from"#channel/adapter.js";import{contextStorage}from"#context/container.js";import{currentProjection,enterSessionProjection,saveSessionProjection}from"#harness/session-machine/current.js";import{AuthKey,CapabilitiesKey,ChannelDeliveryKey,HandleEventKey,InitiatorAuthKey,OccurrenceIdKey,ParentSessionKey,ScheduleIdKey,ScheduleInstanceKey,SessionDynamicSubagentRuntimeRevisionKey,SessionDynamicToolRuntimeRevisionKey,SessionTitleKey,StaticModelReferenceKey,TurnDeliveryIdsKey}from"#context/keys.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{coalesceTurnInputs,validateHarnessModelMessages}from"#harness/messages.js";import{activeTurnId,isBetweenTurns,storedProjection,turnPosition}from"#harness/session-machine/view.js";import{createWorkflowRuntime}from"#execution/workflow-runtime.js";import{resolveWorkflowCallbackBaseUrl}from"#execution/workflow-callback-url.js";import{createDurableSessionValues,readDurableSession}from"#execution/durable-session-store.js";import{runStep}from"#context/run-step.js";import{deserializeContext,serializeContext}from"#context/serialize.js";import{readHitlState}from"#harness/hitl/index.js";import*as agentTraceState from"#tracing/eve/agent-trace-context-store.js";import{CallbackBaseUrlKey,PendingAuthorizationResultKey}from"#harness/authorization.js";import{refreshDynamicSessionSubagentsForRuntimeRevision}from"#context/dynamic-subagent-lifecycle.js";import{hydrateDurableSession,refreshSessionFromTurnAgent}from"#execution/session.js";import{resolveEffectiveAgentRuntime,resolveSessionUsageLimit}from"#execution/effective-agent-config.js";import{openSessionEventPublisher}from"#execution/publish-session-events.js";import{withSessionStateDelta}from"#execution/session/state-delta.js";import{matchSignIns}from"#harness/session-machine/transitions.js";import{readPendingHistory,withoutPendingHistory}from"#execution/session/pending-history.js";import{dropClosedRecords,saveTransition,sessionView}from"#harness/session-machine/commit.js";import{sessionStartedForResolvers,turnStartedForResolvers}from"#harness/session-machine/resolver-events.js";import{derivePendingState}from"#execution/session/pending-turn-state.js";import{rebindMissingCompiledDynamicToolCallbacks,refreshDynamicSessionToolsForRuntimeRevision}from"#context/dynamic-tool-lifecycle.js";import{setChannelContext}from"#execution/channel-context.js";import{reconcileSessionContinuationToken}from"#execution/reconcile-session-continuation-token.js";import{createTurnEventHandler}from"#execution/session/turn-event-handler.js";import{isTurnCancellation,throwIfTurnAborted}from"#harness/turn-cancellation.js";import{bindSessionInstrumentation}from"#instrumentation/runtime.js";import{deriveSessionTitle}from"#execution/eve-workflow-attributes.js";import{bindTurnCallerContext}from"#subagents/parent-notification.js";import{bindDynamicConnections}from"#execution/dynamic-connections.js";import{recoverDynamicConnectionRehydration}from"#execution/dynamic-connection-recovery.js";import{setEveAttributes}from"#runtime/attributes/emit.js";import{RuntimeActionSettlementTimesKey}from"#harness/runtime-action-settlement-state.js";import{matchAuthorizationCallbacks}from"#execution/authorization-callback-match.js";import{attributeAnswers}from"#execution/session/answer-caller.js";import{resolveSessionStepResult}from"#execution/session/turn-step-result.js";import{countRunUsage}from"#execution/agent-sessions/usage.js";import{buildRuntimeIdentity,createExecutionNodeStep}from"#execution/node-step.js";import{createExecutionHistoryView}from"#execution/history-view.js";import{runModelCallBatch}from"#execution/model-call-batching.js";import{createCancelledModelCallBatchResult}from"#execution/cancelled-model-call-batch.js";function channelDeliveryErrorCode(e){if(typeof e==`object`&&e&&`code`in e){let t=e.code;if(typeof t==`string`&&t.length>0)return t}return`CHANNEL_DELIVERY_FAILED`}async function turnStep(e){"use step";return await withSessionStateDelta(e,e=>runSessionStep({...e,serializedContext:bindTurnCallerContext(e.caller,e.serializedContext)}))}async function runSessionStep(e){let t={};try{return await runSessionStepBody(e,t)}finally{await t.title}}async function runSessionStepBody(e,t){let n=e.input?.delivery,r=n,i=e.input?.runtimeResults,a=readDurableSession(e.sessionState);for(let e of i?.delegatedUsage??[])a=countRunUsage(a,e);let o=await deserializeContext(e.serializedContext);enterSessionProjection(o,a.state);let s=o.require(ChannelKey),c=o.require(BundleKey),l=resolveEffectiveAgentRuntime(c,o);try{let{getWorkflowMetadata:e}=await import(`#compiled/@workflow/core/index.js`),t=e();typeof t.url==`string`&&o.set(CallbackBaseUrlKey,resolveWorkflowCallbackBaseUrl(t.url))}catch{}let{signIns:u}=readHitlState(a.state),d;if(u.length>0&&r!==void 0){let{matches:e,remainingPayloads:t}=matchAuthorizationCallbacks(u,r.payloads);if(r={...r,payloads:t},e.length>0){let n=e.map(e=>e.result.attemptId),i=e.map(e=>e.result);o.set(PendingAuthorizationResultKey,i);let s=sessionView(storedProjection(a.state),a.state),c=matchSignIns(s,{attemptIds:n});if(c.events.length!==0)throw Error(`matchSignIns must not emit events.`);a=saveTransition(a,c),d=e,t.length===0&&(r=void 0)}}r?.payloads.some(e=>e.message!==void 0)&&(o.delete(ScheduleIdKey),o.delete(ScheduleInstanceKey),o.delete(OccurrenceIdKey),r.schedule!==void 0&&(o.set(ScheduleIdKey,r.schedule.definition),r.schedule.instance!==void 0&&o.set(ScheduleInstanceKey,r.schedule.instance),r.schedule.occurrenceId!==void 0&&o.set(OccurrenceIdKey,r.schedule.occurrenceId)));let f=o.get(AuthKey),p=o.has(InitiatorAuthKey);r?.auth!==void 0&&(o.set(AuthKey,r.auth??null),o.has(InitiatorAuthKey)||o.set(InitiatorAuthKey,r.auth??null));let m=r===void 0?d?.find(({challenge:e})=>e.candidateId===void 0)?.challenge.requester:void 0;m!==void 0&&o.set(AuthKey,m);let h=r?.payloads.some(e=>e.message!==void 0)===!0?readPendingHistory(a.state):[],g={...hydrateDurableSession({compactionOverrides:{thresholdPercent:l.thresholdPercent},durable:a,turnAgent:l.turnAgent}),history:validateHarnessModelMessages(e.history)},_=createExecutionHistoryView(g),v=bindSessionInstrumentation({agentName:l.turnAgent.id,ctx:o,rootSessionId:g.rootSessionId??g.sessionId,sessionId:g.sessionId}),y=turnPosition(currentProjection(o)),b=isBetweenTurns(currentProjection(o));if(!y.sessionStarted&&!o.has(SessionTitleKey)&&!o.has(ParentSessionKey)){let e=n?.payloads.find(e=>e.message!==void 0)?.message,r=deriveSessionTitle(n?.title??e);r!==void 0&&(o.set(SessionTitleKey,r),t.title=setEveAttributes({"$eve.title":r}))}n!==void 0&&(await contextStorage.run(o,()=>v?.preparePreamble({sequence:y.sequence,sessionStarted:y.sessionStarted})),await contextStorage.run(o,()=>v?.instrumentChannelDelivery({agentName:c.turnAgent.id,ctx:o,delivery:n,rootSessionId:g.rootSessionId??g.sessionId,sequence:y.sequence,sessionId:g.sessionId,turnId:activeTurnId(y)})));let failChannelDeliveries=async e=>{await contextStorage.run(o,()=>v?.instrumentChannelDelivery({ctx:o,error:e,errorCode:channelDeliveryErrorCode(e),includeTurn:!1,outcome:`failed`})),await v?.flush()},x=openSessionEventPublisher({ctx:o,origin:`own`,sessionWritable:e.sessionWritable}),{adapterCtx:S}=x.dispatcher,C=new AbortController,w=e.abortSignal===void 0?C.signal:AbortSignal.any([e.abortSignal,C.signal]);try{let u=bindDynamicConnections(o,c.resolvedAgent),m={...c.graph.root,turnAgent:l.turnAgent},T=resolveSessionUsageLimit(c),E=!1,D=createTurnEventHandler({abortSignal:w,bundle:c,canCancelTurn:e.input?.control===void 0,hookCancellation:C,ctx:o,dynamicConnections:u,effectiveAgent:l,effectiveNode:m,instrumentation:v,publisher:x}),handleEvent=async(e,t)=>{e.type===`compaction.completed`&&(E=!0),await D(e,t)},O=r!==void 0&&!b?structuredClone(S.state):void 0,k;if(r!==void 0){let e=[];try{for(let t of r.payloads){let n=s.deliver?await s.deliver(t,S):defaultDeliverResult(t);if(n!=null){let r=[...e.length===0?h:[],...t.history??[]];e.push(r.length===0?n:{...n,history:r})}}}catch(e){throw await failChannelDeliveries(e),e}e.length>0&&h.length>0&&(g={...g,state:withoutPendingHistory(g.state)}),k=e.length===0?void 0:e.reduce(coalesceTurnInputs)}let A=r?.auth===void 0?void 0:attributeAnswers({responder:r.auth,state:a.state,stepInput:k});if(A!==void 0&&(k=A,f===void 0?o.delete(AuthKey):o.set(AuthKey,f),p||o.delete(InitiatorAuthKey)),r!==void 0&&k===void 0&&!b)f===void 0?o.delete(AuthKey):o.set(AuthKey,f),S.state=O;else if(n?.payloads.some(e=>e.message!==void 0)){let e=n.deliveryMetadata?.map(e=>e.deliveryId)??[];o.set(TurnDeliveryIdsKey,y.turnId?[...new Set([...o.get(TurnDeliveryIdsKey)??[],...e])]:e)}else!y.sessionStarted&&o.get(ChannelDeliveryKey)!==void 0&&o.set(TurnDeliveryIdsKey,[o.require(ChannelDeliveryKey).deliveryId]);if(i!==void 0&&(i.acceptedAtMsByCallId!==void 0&&o.set(RuntimeActionSettlementTimesKey,i.acceptedAtMsByCallId),k={...k,runtimeActionResults:i.results}),n!==void 0){let e={...s,state:{...S.state}};setChannelContext(o,e)}if(r!==void 0&&k===void 0&&b){await contextStorage.run(o,()=>v?.instrumentChannelDelivery({ctx:o,includeTurn:!1,outcome:`completed`})),await v?.flush();let t=saveSessionProjection(reconcileSessionContinuationToken(o,g),o),n=serializeContext(o),r=t===g?{history:e.history,sessionState:e.sessionState}:createDurableSessionValues(t);return{action:`park`,...derivePendingState(t,currentProjection(o)),serializedContext:n,...r}}let j=c.subagentRegistry.dynamicResolvers??[],M=c.resolvedAgent.dynamicToolResolvers??[],N=buildRuntimeIdentity(m);try{let e=process.env.VERCEL_DEPLOYMENT_ID?.trim(),t=e?`deployment:${e}`:await resolveRuntimeCompiledArtifactsVersionedCacheKey(c.compiledArtifactsSource),n=y.sessionStarted;if(o.setVirtualContext(StaticModelReferenceKey,l.turnAgent.model??null),!n)o.set(SessionDynamicSubagentRuntimeRevisionKey,t),o.set(SessionDynamicToolRuntimeRevisionKey,t);else{let e=sessionStartedForResolvers(N);await Promise.all([refreshDynamicSessionSubagentsForRuntimeRevision({ctx:o,resolvers:j,event:e,messages:_.initial.messages,runtimeRevision:t}),contextStorage.run(o,async()=>await refreshDynamicSessionToolsForRuntimeRevision({ctx:o,resolvers:M,event:e,messages:_.initial.messages,runtimeRevision:t}))]),b||await rebindMissingCompiledDynamicToolCallbacks({ctx:o,event:turnStartedForResolvers({sequence:y.sequence,turnId:activeTurnId(y)}),messages:_.initial.messages,resolvers:M})}}catch(e){throw await failChannelDeliveries(e),e}let P=c.resolvedAgent.config?.experimental?.workflow?.modelCallsPerStep??1,F=o.get(CapabilitiesKey),runHarnessStep=async(n,r,i)=>{let a=refreshSessionFromTurnAgent({compactionOverrides:{thresholdPercent:l.thresholdPercent},session:n,turnAgent:l.turnAgent});return createExecutionNodeStep({steeringSignal:e.steeringSignal,abortSignal:w,capabilities:F,clearOnly:e.input?.control===`clear`,compactOnly:e.input?.control===`compact`,createRuntime:createWorkflowRuntime,handleEvent,prepareApprovalTurn:e=>u.dispatch(turnStartedForResolvers(e)),signInCompletions:i,historyProjector:_.projector,historyView:_.prepare(a),instrumentation:v,modelResolutionScope:{moduleMap:c.moduleMap,nodeId:c.nodeId},node:m,sessionUsageLimit:T,titleAttributeWrite:t.title})(a,r)},I,L;try{throwIfTurnAborted(w),L=await runModelCallBatch({steeringSignal:e.steeringSignal,initialInput:k,initialSession:g,modelCallsPerStep:P,runStep:async({firstCall:e,session:t,stepInput:n})=>{let r=await runStep(o,t,async t=>{o.setVirtualContext(HandleEventKey,handleEvent),o.setVirtualContext(StaticModelReferenceKey,l.turnAgent.model??null);let r=e&&k?.outputSchema!==void 0?{...t,outputSchema:k.outputSchema}:t,i=turnPosition(currentProjection(o));try{await u.rehydrate(i,N,isBetweenTurns(currentProjection(o))?void 0:{sequence:i.sequence,turnId:activeTurnId(i)})}catch(e){let t=await recoverDynamicConnectionRehydration({emit:handleEvent,error:e,projection:currentProjection(o),session:r});if(t!==void 0)return t;throw e}let a=e&&d!==void 0?d.map(({challenge:e})=>e):void 0;return runHarnessStep(r,n,a)});r.settledTurn===void 0&&throwIfTurnAborted(w);let i={...r,session:saveSessionProjection(r.session,o)};return I={result:i,serializedContext:serializeContext(o)},i}})}catch(t){if(!isTurnCancellation(t)&&!w.aborted)throw await failChannelDeliveries(t),t;return createCancelledModelCallBatchResult({beforeBatchContext:e.serializedContext,checkpoint:I,ctx:o,initialSession:g,stepInput:k})}let R=saveSessionProjection(dropClosedRecords(reconcileSessionContinuationToken(o,L.session),currentProjection(o)),o);agentTraceState.pruneAgentTraceState(o,R.sessionId,R.state);let z=serializeContext(o);L={...L,session:R};let B=resolveSessionStepResult(L,z);return B.action===`done`&&await x.writer.close(),E?{...B,compacted:!0}:B}finally{x.writer.release()}}export{turnStep};
|
|
1
|
+
import{resolveRuntimeCompiledArtifactsVersionedCacheKey}from"#runtime/cache-key.js";import{defaultDeliverResult}from"#channel/adapter.js";import{contextStorage}from"#context/container.js";import{currentProjection,enterSessionProjection,saveSessionProjection}from"#harness/session-machine/current.js";import{AuthKey,CapabilitiesKey,ChannelDeliveryKey,HandleEventKey,InitiatorAuthKey,OccurrenceIdKey,ParentSessionKey,ScheduleIdKey,ScheduleInstanceKey,SessionDynamicSubagentRuntimeRevisionKey,SessionDynamicToolRuntimeRevisionKey,SessionTitleKey,StaticModelReferenceKey,TurnDeliveryIdsKey}from"#context/keys.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{coalesceTurnInputs,validateHarnessModelMessages}from"#harness/messages.js";import{activeTurnId,isBetweenTurns,storedProjection,turnPosition}from"#harness/session-machine/view.js";import{createWorkflowRuntime}from"#execution/workflow-runtime.js";import{resolveWorkflowCallbackBaseUrl}from"#execution/workflow-callback-url.js";import{createDurableSessionValues,readDurableSession}from"#execution/durable-session-store.js";import{runStep}from"#context/run-step.js";import{deserializeContext,serializeContext}from"#context/serialize.js";import{readHitlState}from"#harness/hitl/index.js";import*as agentTraceState from"#tracing/eve/agent-trace-context-store.js";import{CallbackBaseUrlKey,PendingAuthorizationResultKey}from"#harness/authorization.js";import{refreshDynamicSessionSubagentsForRuntimeRevision}from"#context/dynamic-subagent-lifecycle.js";import{hydrateDurableSession,refreshSessionFromTurnAgent}from"#execution/session.js";import{resolveEffectiveAgentRuntime,resolveSessionUsageLimit}from"#execution/effective-agent-config.js";import{openSessionEventPublisher}from"#execution/publish-session-events.js";import{withSessionStateDelta}from"#execution/session/state-delta.js";import{matchSignIns}from"#harness/session-machine/transitions.js";import{readPendingHistory,withoutPendingHistory}from"#execution/session/pending-history.js";import{dropClosedRecords,saveTransition,sessionView}from"#harness/session-machine/commit.js";import{sessionStartedForResolvers,turnStartedForResolvers}from"#harness/session-machine/resolver-events.js";import{derivePendingState}from"#execution/session/pending-turn-state.js";import{rebindMissingCompiledDynamicToolCallbacks,refreshDynamicSessionToolsForRuntimeRevision}from"#context/dynamic-tool-lifecycle.js";import{hasDelegatedSessionContext}from"#execution/delegated-session-context.js";import{setChannelContext}from"#execution/channel-context.js";import{reconcileSessionContinuationToken}from"#execution/reconcile-session-continuation-token.js";import{createTurnEventHandler}from"#execution/session/turn-event-handler.js";import{isTurnCancellation,throwIfTurnAborted}from"#harness/turn-cancellation.js";import{bindSessionInstrumentation}from"#instrumentation/runtime.js";import{deriveSessionTitle}from"#execution/eve-workflow-attributes.js";import{bindTurnCallerContext}from"#subagents/parent-notification.js";import{traceSessionHandover}from"#execution/session/handover-tracing.js";import{startSessionPrewarmers}from"#context/prewarm.js";import{bindDynamicConnections}from"#execution/dynamic-connections.js";import{recoverDynamicConnectionRehydration}from"#execution/dynamic-connection-recovery.js";import{setEveAttributes}from"#runtime/attributes/emit.js";import{RuntimeActionSettlementTimesKey}from"#harness/runtime-action-settlement-state.js";import{matchAuthorizationCallbacks}from"#execution/authorization-callback-match.js";import{attributeAnswers}from"#execution/session/answer-caller.js";import{resolveSessionStepResult}from"#execution/session/turn-step-result.js";import{countRunUsage}from"#execution/agent-sessions/usage.js";import{buildRuntimeIdentity,createExecutionNodeStep}from"#execution/node-step.js";import{createExecutionHistoryView}from"#execution/history-view.js";import{runModelCallBatch}from"#execution/model-call-batching.js";import{createCancelledModelCallBatchResult}from"#execution/cancelled-model-call-batch.js";function channelDeliveryErrorCode(e){if(typeof e==`object`&&e&&`code`in e){let t=e.code;if(typeof t==`string`&&t.length>0)return t}return`CHANNEL_DELIVERY_FAILED`}async function turnStep(e){"use step";return e.handover!==void 0&&traceSessionHandover(`inbox_unblocked`,e.sessionState.sessionId,e.handover.attemptKey,{"eve.handoff.buffered_payload_count":e.handover.payloadCount,"eve.handoff.applied_at_ms":e.handover.appliedAtMs,"eve.handoff.applied_at_clock":`workflow`}),await withSessionStateDelta(e,e=>runSessionStep({...e,serializedContext:bindTurnCallerContext(e.caller,e.serializedContext)}))}async function runSessionStep(e){let t={};try{return await runSessionStepBody(e,t)}finally{await t.title}}async function runSessionStepBody(e,t){let n=e.input?.delivery,r=n,i=e.input?.runtimeResults,a=readDurableSession(e.sessionState);for(let e of i?.delegatedUsage??[])a=countRunUsage(a,e);let o=await deserializeContext(e.serializedContext);enterSessionProjection(o,a.state);let s=o.require(ChannelKey),c=o.require(BundleKey),l=resolveEffectiveAgentRuntime(c,o);try{let{getWorkflowMetadata:e}=await import(`#compiled/@workflow/core/index.js`),t=e();typeof t.url==`string`&&o.set(CallbackBaseUrlKey,resolveWorkflowCallbackBaseUrl(t.url))}catch{}let{signIns:u}=readHitlState(a.state),d;if(u.length>0&&r!==void 0){let{matches:e,remainingPayloads:t}=matchAuthorizationCallbacks(u,r.payloads);if(r={...r,payloads:t},e.length>0){let n=e.map(e=>e.result.attemptId),i=e.map(e=>e.result);o.set(PendingAuthorizationResultKey,i);let s=sessionView(storedProjection(a.state),a.state),c=matchSignIns(s,{attemptIds:n});if(c.events.length!==0)throw Error(`matchSignIns must not emit events.`);a=saveTransition(a,c),d=e,t.length===0&&(r=void 0)}}r?.payloads.some(e=>e.message!==void 0)&&(o.delete(ScheduleIdKey),o.delete(ScheduleInstanceKey),o.delete(OccurrenceIdKey),r.schedule!==void 0&&(o.set(ScheduleIdKey,r.schedule.definition),r.schedule.instance!==void 0&&o.set(ScheduleInstanceKey,r.schedule.instance),r.schedule.occurrenceId!==void 0&&o.set(OccurrenceIdKey,r.schedule.occurrenceId)));let f=o.get(AuthKey),p=o.has(InitiatorAuthKey);r?.auth!==void 0&&(o.set(AuthKey,r.auth??null),o.has(InitiatorAuthKey)||o.set(InitiatorAuthKey,r.auth??null));let m=r===void 0?d?.find(({challenge:e})=>e.candidateId===void 0)?.challenge.requester:void 0;m!==void 0&&o.set(AuthKey,m);let h=r?.payloads.some(e=>e.message!==void 0)===!0?readPendingHistory(a.state):[],g={...hydrateDurableSession({compactionOverrides:{thresholdPercent:l.thresholdPercent},durable:a,turnAgent:l.turnAgent}),history:validateHarnessModelMessages(e.history)},_=createExecutionHistoryView(g),v=bindSessionInstrumentation({agentName:l.turnAgent.id,ctx:o,rootSessionId:g.rootSessionId??g.sessionId,sessionId:g.sessionId}),y=turnPosition(currentProjection(o)),b=isBetweenTurns(currentProjection(o));if(!y.sessionStarted&&!o.has(SessionTitleKey)&&!o.has(ParentSessionKey)){let e=n?.payloads.find(e=>e.message!==void 0)?.message,r=deriveSessionTitle(n?.title??e);r!==void 0&&(o.set(SessionTitleKey,r),t.title=setEveAttributes({"$eve.title":r}))}n!==void 0&&(await contextStorage.run(o,()=>v?.preparePreamble({sequence:y.sequence,sessionStarted:y.sessionStarted})),await contextStorage.run(o,()=>v?.instrumentChannelDelivery({agentName:c.turnAgent.id,ctx:o,delivery:n,rootSessionId:g.rootSessionId??g.sessionId,sequence:y.sequence,sessionId:g.sessionId,turnId:activeTurnId(y)})));let failChannelDeliveries=async e=>{await contextStorage.run(o,()=>v?.instrumentChannelDelivery({ctx:o,error:e,errorCode:channelDeliveryErrorCode(e),includeTurn:!1,outcome:`failed`})),await v?.flush()},x=openSessionEventPublisher({ctx:o,origin:`own`,sessionWritable:e.sessionWritable}),{adapterCtx:S}=x.dispatcher,C=new AbortController,w=e.abortSignal===void 0?C.signal:AbortSignal.any([e.abortSignal,C.signal]);try{let u=bindDynamicConnections(o,c.resolvedAgent),m={...c.graph.root,turnAgent:l.turnAgent},T=resolveSessionUsageLimit(c),E=!1,D=createTurnEventHandler({abortSignal:w,bundle:c,canCancelTurn:e.input?.control===void 0,hookCancellation:C,ctx:o,dynamicConnections:u,effectiveAgent:l,effectiveNode:m,instrumentation:v,publisher:x}),handleEvent=async(e,t)=>{e.type===`compaction.completed`&&(E=!0),await D(e,t)},O=r!==void 0&&!b?structuredClone(S.state):void 0,k;if(r!==void 0){let e=[];try{for(let t of r.payloads){let n=s.deliver?await s.deliver(t,S):defaultDeliverResult(t);if(n!=null){let r=[...e.length===0?h:[],...t.history??[]];e.push(r.length===0?n:{...n,history:r})}}}catch(e){throw await failChannelDeliveries(e),e}e.length>0&&h.length>0&&(g={...g,state:withoutPendingHistory(g.state)}),k=e.length===0?void 0:e.reduce(coalesceTurnInputs)}let A=r?.auth===void 0?void 0:attributeAnswers({responder:r.auth,state:a.state,stepInput:k});if(A!==void 0&&(k=A,f===void 0?o.delete(AuthKey):o.set(AuthKey,f),p||o.delete(InitiatorAuthKey)),r!==void 0&&k===void 0&&!b)f===void 0?o.delete(AuthKey):o.set(AuthKey,f),S.state=O;else if(n?.payloads.some(e=>e.message!==void 0)){let e=n.deliveryMetadata?.map(e=>e.deliveryId)??[];o.set(TurnDeliveryIdsKey,y.turnId?[...new Set([...o.get(TurnDeliveryIdsKey)??[],...e])]:e)}else!y.sessionStarted&&o.get(ChannelDeliveryKey)!==void 0&&o.set(TurnDeliveryIdsKey,[o.require(ChannelDeliveryKey).deliveryId]);if(i!==void 0&&(i.acceptedAtMsByCallId!==void 0&&o.set(RuntimeActionSettlementTimesKey,i.acceptedAtMsByCallId),k={...k,runtimeActionResults:i.results}),n!==void 0){let e={...s,state:{...S.state}};setChannelContext(o,e)}if(r!==void 0&&k===void 0&&b){await contextStorage.run(o,()=>v?.instrumentChannelDelivery({ctx:o,includeTurn:!1,outcome:`completed`})),await v?.flush();let t=saveSessionProjection(reconcileSessionContinuationToken(o,g),o),n=serializeContext(o),r=t===g?{history:e.history,sessionState:e.sessionState}:createDurableSessionValues(t);return{action:`park`,...derivePendingState(t,currentProjection(o)),serializedContext:n,...r}}let j=c.subagentRegistry.dynamicResolvers??[],M=c.resolvedAgent.dynamicToolResolvers??[],N=buildRuntimeIdentity(m);try{let e=process.env.VERCEL_DEPLOYMENT_ID?.trim(),t=e?`deployment:${e}`:await resolveRuntimeCompiledArtifactsVersionedCacheKey(c.compiledArtifactsSource),n=y.sessionStarted;if(o.setVirtualContext(StaticModelReferenceKey,l.turnAgent.model??null),!n)o.set(SessionDynamicSubagentRuntimeRevisionKey,t),o.set(SessionDynamicToolRuntimeRevisionKey,t);else{let e=sessionStartedForResolvers(N);await Promise.all([refreshDynamicSessionSubagentsForRuntimeRevision({ctx:o,resolvers:j,event:e,messages:_.initial.messages,runtimeRevision:t}),contextStorage.run(o,async()=>await refreshDynamicSessionToolsForRuntimeRevision({ctx:o,resolvers:M,event:e,messages:_.initial.messages,runtimeRevision:t}))]),b||await rebindMissingCompiledDynamicToolCallbacks({ctx:o,event:turnStartedForResolvers({sequence:y.sequence,turnId:activeTurnId(y)}),messages:_.initial.messages,resolvers:M})}}catch(e){throw await failChannelDeliveries(e),e}let P=c.resolvedAgent.config?.experimental?.workflow?.modelCallsPerStep??1,F=o.get(CapabilitiesKey),runHarnessStep=async(n,r,i)=>{let a=refreshSessionFromTurnAgent({compactionOverrides:{thresholdPercent:l.thresholdPercent},session:n,turnAgent:l.turnAgent});return createExecutionNodeStep({steeringSignal:e.steeringSignal,abortSignal:w,capabilities:F,clearOnly:e.input?.control===`clear`,compactOnly:e.input?.control===`compact`,createRuntime:createWorkflowRuntime,handleEvent,prepareApprovalTurn:e=>u.dispatch(turnStartedForResolvers(e)),signInCompletions:i,typedAnswers:!hasDelegatedSessionContext(e.serializedContext),historyProjector:_.projector,historyView:_.prepare(a),instrumentation:v,modelResolutionScope:{moduleMap:c.moduleMap,nodeId:c.nodeId},node:m,sessionUsageLimit:T,titleAttributeWrite:t.title})(a,r)},I,L;try{throwIfTurnAborted(w),L=await runModelCallBatch({steeringSignal:e.steeringSignal,initialInput:k,initialSession:g,modelCallsPerStep:P,runStep:async({firstCall:t,session:n,stepInput:r})=>{let i=await runStep(o,n,async n=>{t&&e.input?.control===void 0&&startSessionPrewarmers(o,`turn`),o.setVirtualContext(HandleEventKey,handleEvent),o.setVirtualContext(StaticModelReferenceKey,l.turnAgent.model??null);let i=t&&k?.outputSchema!==void 0?{...n,outputSchema:k.outputSchema}:n,a=turnPosition(currentProjection(o));try{await u.rehydrate(a,N,isBetweenTurns(currentProjection(o))?void 0:{sequence:a.sequence,turnId:activeTurnId(a)})}catch(e){let t=await recoverDynamicConnectionRehydration({emit:handleEvent,error:e,projection:currentProjection(o),session:i});if(t!==void 0)return t;throw e}let s=t&&d!==void 0?d.map(({challenge:e})=>e):void 0;return runHarnessStep(i,r,s)});i.settledTurn===void 0&&throwIfTurnAborted(w);let a={...i,session:saveSessionProjection(i.session,o)};return I={result:a,serializedContext:serializeContext(o)},a}})}catch(t){if(!isTurnCancellation(t)&&!w.aborted)throw await failChannelDeliveries(t),t;return createCancelledModelCallBatchResult({beforeBatchContext:e.serializedContext,checkpoint:I,ctx:o,initialSession:g,stepInput:k})}let R=saveSessionProjection(dropClosedRecords(reconcileSessionContinuationToken(o,L.session),currentProjection(o)),o);agentTraceState.pruneAgentTraceState(o,R.sessionId,R.state);let z=serializeContext(o);L={...L,session:R};let B=resolveSessionStepResult(L,z);return B.action===`done`&&await x.writer.close(),E?{...B,compacted:!0}:B}finally{x.writer.release()}}export{turnStep};
|
|
@@ -23,6 +23,7 @@ export interface SessionExecutionInput {
|
|
|
23
23
|
*/
|
|
24
24
|
export declare class SessionExecution {
|
|
25
25
|
private readonly input;
|
|
26
|
+
private observedHandoverAttemptKey;
|
|
26
27
|
constructor(input: SessionExecutionInput);
|
|
27
28
|
get cursor(): SessionStateCursor;
|
|
28
29
|
runTurn(delivery: TurnStepPayload | undefined, options?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{sessionCommandHookToken,sessionInboxHookToken}from"#execution/session-inbox/address.js";import{TASK_WAIT_TOOL_NAME}from"#protocol/task-tools.js";import{renderTaskWaitResult}from"#execution/tasks/render.js";import{sleep}from"#compiled/@workflow/core/index.js";import{findBlockingWorkflowToolRun,getBlockingWorkflowToolRuns,isInboxToolResultFromRecordedWorkflowToolRun}from"#harness/workflow-tool-runs.js";import{taskWaitResult}from"#execution/tasks/table.js";import{handleWorkflowToolRunMessage,isAppliedRunMessage,takeLeadingAppliedRunMessages}from"#execution/session-workflow-tool-run.js";import{resolveTurnPrincipal}from"#execution/session/principal.js";import{answerTaskCancel,cancelWorkingTasks,sessionTaskTable}from"#execution/tasks/session.js";import{cancelDescendantTurnsStep}from"#execution/cancel-descendant-turns-step.js";import{dispatchCoordinationStep,publishTaskStartedStep}from"#execution/coordination-dispatch-step.js";import{taskToolResult}from"#execution/tasks/calls.js";import{publishTurnWaitingStep}from"#execution/session/turn-waiting-step.js";import{applyRunMessagesStep}from"#execution/tools/workflow/apply-run-messages-step.js";import{interruptWorkflowToolRun}from"#execution/tools/workflow/interrupt.js";import{turnStep}from"#execution/session/turn-step.js";import{ActiveTurn}from"#execution/session/active-turn.js";import{resolveRuntimeActionResultsForCallIds}from"#runtime/actions/results.js";import{startTaskToolCallsStep,traceTaskToolCallStep}from"#execution/session/task-tool-tracing-step.js";function hasDelegatedCallerContext(e){if(e[`eve.sessionCallback`]!==void 0)return!0;let t=e[`eve.channel`];return typeof t==`object`&&!!t&&Reflect.get(t,`kind`)===`subagent`}var SessionExecution=class{input;constructor(e){this.input=e}get cursor(){return this.input.cursor}async runTurn(e,t={}){let n=new ActiveTurn(this.input,{caller:t.caller,principal:resolveTurnPrincipal(e,this.input.cursor.serializedContext)},t.control);try{let t=await this.runTurnSteps(n,e);return await this.handleBoundaryMessages(n.takeBoundaryMessages(),t.kind===`done`),t.kind===`park`&&t.settled!==void 0&&await cancelWorkingTasks(this.input.cursor,`turn_ended`),{...t,...n.caller!==void 0&&{caller:n.caller},...n.compacted&&{compacted:!0}}}finally{n.dispose()}}async handleBoundaryMessages(e,t=!1,n){let r=[];for(let i of e)isAppliedRunMessage(i)?(!t||i.kind!==`agent-started`)&&r.push(i):(await this.applyRunMessages(r,n),r=[],await handleWorkflowToolRunMessage({cursor:this.input.cursor,message:i}));await this.applyRunMessages(r,n)}async applyRunMessages(e,t){if(e.length===0)return;let{cancelled:n}=await this.input.cursor.advance(n=>applyRunMessagesStep({...n,canCancelTurn:t!==void 0,messages:e}));n&&t?.abort()}async runTurnSteps(e,t){let n=t,r=e.caller;for(;;){let{cursor:t}=this.input,i=r;r=void 0;let a=await t.advanceWithHistory(t=>turnStep({...t,abortSignal:e.signal,caller:i,input:n,steeringSignal:e.steeringSignal}));a.compacted===!0&&(e.compacted=!0);let o=a.action===`park`?a.pendingCoordinationCallIds:void 0,s=a.action===`park`&&a.settled!==void 0,c=this.input.queue.nextAdmission;await e.admitBoundary();let l=a.action===`done`;if(await this.handleBoundaryMessages(e.takeBoundaryMessages(),l,l?void 0:e),a.action===`cancelled`||!s&&e.signal.aborted&&o===void 0)return await this.finishCancelledTurn(e);if(a.action===`done`)return{isError:a.isError,kind:`done`,output:a.output??``,usage:a.usage,usageDelta:a.usageDelta};if(a.action===`held`&&a.hold===`request`){if(a.hasPendingInputBatch&&this.input.capabilities?.requestInput!==!0&&!hasDelegatedCallerContext(this.input.cursor.serializedContext))throw Error(`This session cannot request human input, so it cannot wait for a tool approval or question. Configure unattended tools with an approval policy that does not require human input.`);let t=await this.waitForHeldRequest(e,a,c);if(t===`cancelled`)return await this.finishCancelledTurn(e);n={delivery:t};continue}if(a.action===`held`){if(await this.waitForHeldTurn(e)===`cancelled`)return await this.finishCancelledTurn(e);let t=await e.takeSteering();n=t===void 0?void 0:{delivery:t};continue}if(o!==void 0&&a.action===`park`){let t=a.hasRunsToDispatch===!1?[]:await this.dispatchRuns(),r=t.length===0?void 0:Date.now(),i=await this.waitForRuntimeActionResults({initialAcceptedAtMs:r,initialResults:t,taskToolCalls:a.pendingTaskToolCalls??[],pendingCallIds:o,turn:e});if(i===`cancelled`)return await this.finishCancelledTurn(e);n={delivery:await e.takeSteering(),runtimeResults:i};continue}if(a.action===`park`)return{kind:`park`,settled:a.settled};let u=await e.takeSteering();n=u===void 0?void 0:{delivery:u}}}async dispatchRuns(){let{cursor:e}=this.input,t=await e.advance(({serializedContext:e,sessionState:t})=>dispatchCoordinationStep({action:`park`,serializedContext:e,sessionState:t,workflowToolRunOwner:{inbox:sessionInboxHookToken(sessionCommandHookToken(this.input.sessionId))}}));return t.started.length>0&&await e.advance(e=>publishTaskStartedStep({...e,started:t.started})),t.results}async handleWorkflowMessage(e,t){if(isAppliedRunMessage(e)){let n=t?.takeAppliedRunMessages()??takeLeadingAppliedRunMessages(this.input.inbox);await this.applyRunMessages([e,...n],t);return}return await handleWorkflowToolRunMessage({cursor:this.input.cursor,message:e})}async cancelTurnWork(){let{cursor:e}=this.input;mayWaitOnWorkflowToolRuns(e.sessionState)&&await cancelDescendantTurnsStep({serializedContext:e.serializedContext,sessionState:e.sessionState}),await cancelWorkingTasks(e,`turn_cancelled`)}async finishCancelledTurn(e){return await this.handleBoundaryMessages(e.takeBoundaryMessages(`agent-started`)),await this.cancelTurnWork(),{cancelled:!0,kind:`park`}}async waitForHeldTurn(e){let t=!1;for(;;){let n={interrupted:t,timedOut:!1};if(taskWaitResult(sessionTaskTable(this.input.cursor),n)!==void 0)return`woke`;let r=await e.nextRuntimeEvent([]);if(r===`cancelled`)return r;switch(r.kind){case`steering`:t=!0;continue;case`workflow`:await this.handleWorkflowMessage(r.message,e);continue;case`input`:case`runtime-action-result`:case`timeout`:continue}}}async waitForHeldRequest(e,t,n){let r=new Set(t.authorizationAttemptIds),i=new Set(t.inputRequestIds);for(;;){let t=this.input.queue.takeAuthorizations(r);if(t!==void 0)return{kind:`deliver`,payloads:t};let a=await e.takeInputResponses(i);if(a!==void 0)return a;let o=await e.takeSteering({heldSince:n});if(o!==void 0)return o;let s=await e.nextRuntimeEvent([]);if(s===`cancelled`)return s;s.kind===`workflow`&&await this.handleWorkflowMessage(s.message,e)}}async waitForRuntimeActionResults(e){let t=[...e.initialResults],n=!1,r=new Map,i=new Map;if(e.initialAcceptedAtMs!==void 0)for(let n of t)r.set(n.callId,e.initialAcceptedAtMs);let accept=e=>{t.push(e),r.set(e.callId,Date.now())},a=await this.answerTaskToolCalls(e.taskToolCalls,accept);try{for(;;){a=await this.resolveTaskWaits(a,n,accept);let o=resolveRuntimeActionResultsForCallIds({pendingCallIds:e.pendingCallIds,results:t});if(o!==void 0){let e=o.flatMap(e=>{let t=i.get(e.callId);return t===void 0?[]:[t]});return{acceptedAtMsByCallId:Object.fromEntries(o.map(e=>[e.callId,r.get(e.callId)])),...e.length>0&&{delegatedUsage:e},results:o}}let s=a.flatMap(e=>e.timer===void 0?[]:[e.timer]),c=await e.turn.nextRuntimeEvent(s);if(c===`cancelled`)return c;if(c.kind===`timeout`){for(let e of a)e.callId===c.callId&&(e.timedOut=!0);continue}if(c.kind===`input`)continue;if(c.kind===`steering`){n||await this.interruptWaitedWorkflowCalls(e.pendingCallIds,t),n=!0;continue}if(c.kind===`runtime-action-result`){let e=this.input.cursor.sessionState.snapshot.session.state,n=c.results.filter(t=>t.kind===`tool-result`&&isInboxToolResultFromRecordedWorkflowToolRun(e,t));if(n.length>0){let e=Date.now();t.push(...n);for(let t of n)r.set(t.callId,e)}continue}let l=await this.handleWorkflowMessage(c.message,e.turn);l!==void 0&&(accept(l),c.message.kind===`outcome`&&c.message.usage!==void 0&&i.set(l.callId,c.message.usage))}}finally{for(let e of a)await this.traceTaskWait(e,void 0,!0)}}async resolveTaskWaits(e,t,n){let r=sessionTaskTable(this.input.cursor),i=[];for(let a of e){let e=taskWaitResult(r,{interrupted:t,timedOut:a.timedOut});if(e===void 0){i.push(a);continue}let o=renderTaskWaitResult(e,Date.now()-a.startedAtMs);await this.traceTaskWait(a,o,t),n(taskToolResult(a.callId,TASK_WAIT_TOOL_NAME,o))}return i}async answerTaskToolCalls(e,t){let n=[],r=e.length===0?0:await startTaskToolCallsStep();for(let i of e)if(i.kind===TASK_WAIT_TOOL_NAME)n.push(startTaskWait(i,r));else{let e;try{e=await answerTaskCancel(this.input.cursor,i)}catch(e){throw await this.input.cursor.advance(e=>traceTaskToolCallStep(e,{callId:i.callId,toolName:i.kind,startedAtMs:r,completedAtMs:Date.now(),input:{taskId:i.taskId},failed:!0})),e}await this.input.cursor.advance(t=>traceTaskToolCallStep(t,{callId:i.callId,toolName:i.kind,startedAtMs:r,completedAtMs:Date.now(),input:{taskId:i.taskId},output:e.output})),t(e)}let i=await this.resolveTaskWaits(n,!1,t);return i.length>0&&await this.input.cursor.advance(publishTurnWaitingStep),i}async traceTaskWait(e,t,n=!1){await this.input.cursor.advance(r=>traceTaskToolCallStep(r,{callId:e.callId,toolName:TASK_WAIT_TOOL_NAME,startedAtMs:e.startedAtMs,completedAtMs:Date.now(),input:e.input,output:t,failed:n}))}async interruptWaitedWorkflowCalls(e,t){let n=this.input.cursor.sessionState.snapshot.session.state,r=new Set(t.map(e=>e.callId)),i=e.filter(e=>!r.has(e)).flatMap(e=>{let t=findBlockingWorkflowToolRun(n,e);return t===void 0?[]:[t.address]});await Promise.all(i.map(e=>interruptWorkflowToolRun(e)))}};function startTaskWait(e,t){let{callId:n,timeoutMs:r}=e,i=r===void 0?void 0:sleep(r).then(()=>n);return{callId:n,startedAtMs:t,input:r===void 0?{}:{timeoutSeconds:r/1e3},timedOut:r===0,timer:i}}function mayWaitOnWorkflowToolRuns(e){try{return getBlockingWorkflowToolRuns(e.snapshot?.session?.state).length>0}catch{return!0}}export{SessionExecution,hasDelegatedCallerContext};
|
|
1
|
+
import{sessionCommandHookToken,sessionInboxHookToken}from"#execution/session-inbox/address.js";import{TASK_WAIT_TOOL_NAME}from"#protocol/task-tools.js";import{renderTaskWaitResult}from"#execution/tasks/render.js";import{sleep}from"#compiled/@workflow/core/index.js";import{findBlockingWorkflowToolRun,getBlockingWorkflowToolRuns,isInboxToolResultFromRecordedWorkflowToolRun}from"#harness/workflow-tool-runs.js";import{taskWaitResult}from"#execution/tasks/table.js";import{handleWorkflowToolRunMessage,isAppliedRunMessage,takeLeadingAppliedRunMessages}from"#execution/session-workflow-tool-run.js";import{resolveTurnPrincipal}from"#execution/session/principal.js";import{answerTaskCancel,cancelWorkingTasks,sessionTaskTable}from"#execution/tasks/session.js";import{cancelDescendantTurnsStep}from"#execution/cancel-descendant-turns-step.js";import{dispatchCoordinationStep,publishTaskStartedStep}from"#execution/coordination-dispatch-step.js";import{taskToolResult}from"#execution/tasks/calls.js";import{publishTurnWaitingStep}from"#execution/session/turn-waiting-step.js";import{applyRunMessagesStep}from"#execution/tools/workflow/apply-run-messages-step.js";import{interruptWorkflowToolRun}from"#execution/tools/workflow/interrupt.js";import{turnStep}from"#execution/session/turn-step.js";import{ActiveTurn}from"#execution/session/active-turn.js";import{resolveRuntimeActionResultsForCallIds}from"#runtime/actions/results.js";import{startTaskToolCallsStep,traceTaskToolCallStep}from"#execution/session/task-tool-tracing-step.js";function hasDelegatedCallerContext(e){if(e[`eve.sessionCallback`]!==void 0)return!0;let t=e[`eve.channel`];return typeof t==`object`&&!!t&&Reflect.get(t,`kind`)===`subagent`}var SessionExecution=class{input;observedHandoverAttemptKey;constructor(e){this.input=e}get cursor(){return this.input.cursor}async runTurn(e,t={}){let n=new ActiveTurn(this.input,{caller:t.caller,principal:resolveTurnPrincipal(e,this.input.cursor.serializedContext)},t.control);try{let t=await this.runTurnSteps(n,e);return await this.handleBoundaryMessages(n.takeBoundaryMessages(),t.kind===`done`),t.kind===`park`&&t.settled!==void 0&&await cancelWorkingTasks(this.input.cursor,`turn_ended`),{...t,...n.caller!==void 0&&{caller:n.caller},...n.compacted&&{compacted:!0}}}finally{n.dispose()}}async handleBoundaryMessages(e,t=!1,n){let r=[];for(let i of e)isAppliedRunMessage(i)?(!t||i.kind!==`agent-started`)&&r.push(i):(await this.applyRunMessages(r,n),r=[],await handleWorkflowToolRunMessage({cursor:this.input.cursor,message:i}));await this.applyRunMessages(r,n)}async applyRunMessages(e,t){if(e.length===0)return;let{cancelled:n}=await this.input.cursor.advance(n=>applyRunMessagesStep({...n,canCancelTurn:t!==void 0,messages:e}));n&&t?.abort()}async runTurnSteps(e,t){let n=t,r=e.caller;for(;;){let{cursor:t}=this.input,i=r;r=void 0;let a=this.input.inbox.handoverObservation,o=a?.attemptKey===this.observedHandoverAttemptKey?void 0:a,s=await t.advanceWithHistory(t=>turnStep({...t,handover:o,abortSignal:e.signal,caller:i,input:n,steeringSignal:e.steeringSignal}));o!==void 0&&(this.observedHandoverAttemptKey=o.attemptKey),s.compacted===!0&&(e.compacted=!0);let c=s.action===`park`?s.pendingCoordinationCallIds:void 0,l=s.action===`park`&&s.settled!==void 0,u=this.input.queue.nextAdmission;await e.admitBoundary();let d=s.action===`done`;if(await this.handleBoundaryMessages(e.takeBoundaryMessages(),d,d?void 0:e),s.action===`cancelled`||!l&&e.signal.aborted&&c===void 0)return await this.finishCancelledTurn(e);if(s.action===`done`)return{isError:s.isError,kind:`done`,output:s.output??``,usage:s.usage,usageDelta:s.usageDelta};if(s.action===`held`&&s.hold===`request`){if(s.hasPendingInputBatch&&this.input.capabilities?.requestInput!==!0&&!hasDelegatedCallerContext(this.input.cursor.serializedContext))throw Error(`This session cannot request human input, so it cannot wait for a tool approval or question. Configure unattended tools with an approval policy that does not require human input.`);let t=await this.waitForHeldRequest(e,s,u);if(t===`cancelled`)return await this.finishCancelledTurn(e);n={delivery:t};continue}if(s.action===`held`){if(await this.waitForHeldTurn(e)===`cancelled`)return await this.finishCancelledTurn(e);let t=await e.takeSteering();n=t===void 0?void 0:{delivery:t};continue}if(c!==void 0&&s.action===`park`){let t=s.hasRunsToDispatch===!1?[]:await this.dispatchRuns(),r=t.length===0?void 0:Date.now(),i=await this.waitForRuntimeActionResults({initialAcceptedAtMs:r,initialResults:t,taskToolCalls:s.pendingTaskToolCalls??[],pendingCallIds:c,turn:e});if(i===`cancelled`)return await this.finishCancelledTurn(e);n={delivery:await e.takeSteering(),runtimeResults:i};continue}if(s.action===`park`)return{kind:`park`,settled:s.settled};let f=await e.takeSteering();n=f===void 0?void 0:{delivery:f}}}async dispatchRuns(){let{cursor:e}=this.input,t=await e.advance(({serializedContext:e,sessionState:t})=>dispatchCoordinationStep({action:`park`,serializedContext:e,sessionState:t,workflowToolRunOwner:{inbox:sessionInboxHookToken(sessionCommandHookToken(this.input.sessionId))}}));return t.started.length>0&&await e.advance(e=>publishTaskStartedStep({...e,started:t.started})),t.results}async handleWorkflowMessage(e,t){if(isAppliedRunMessage(e)){let n=t?.takeAppliedRunMessages()??takeLeadingAppliedRunMessages(this.input.inbox);await this.applyRunMessages([e,...n],t);return}return await handleWorkflowToolRunMessage({cursor:this.input.cursor,message:e})}async cancelTurnWork(){let{cursor:e}=this.input;mayWaitOnWorkflowToolRuns(e.sessionState)&&await cancelDescendantTurnsStep({serializedContext:e.serializedContext,sessionState:e.sessionState}),await cancelWorkingTasks(e,`turn_cancelled`)}async finishCancelledTurn(e){return await this.handleBoundaryMessages(e.takeBoundaryMessages(`agent-started`)),await this.cancelTurnWork(),{cancelled:!0,kind:`park`}}async waitForHeldTurn(e){let t=!1;for(;;){let n={interrupted:t,timedOut:!1};if(taskWaitResult(sessionTaskTable(this.input.cursor),n)!==void 0)return`woke`;let r=await e.nextRuntimeEvent([]);if(r===`cancelled`)return r;switch(r.kind){case`steering`:t=!0;continue;case`workflow`:await this.handleWorkflowMessage(r.message,e);continue;case`input`:case`runtime-action-result`:case`timeout`:continue}}}async waitForHeldRequest(e,t,n){let r=new Set(t.authorizationAttemptIds),i=new Set(t.inputRequestIds);for(;;){let t=this.input.queue.takeAuthorizations(r);if(t!==void 0)return{kind:`deliver`,payloads:t};let a=await e.takeInputResponses(i);if(a!==void 0)return a;let o=await e.takeSteering({heldSince:n});if(o!==void 0)return o;let s=await e.nextRuntimeEvent([]);if(s===`cancelled`)return s;s.kind===`workflow`&&await this.handleWorkflowMessage(s.message,e)}}async waitForRuntimeActionResults(e){let t=[...e.initialResults],n=!1,r=new Map,i=new Map;if(e.initialAcceptedAtMs!==void 0)for(let n of t)r.set(n.callId,e.initialAcceptedAtMs);let accept=e=>{t.push(e),r.set(e.callId,Date.now())},a=await this.answerTaskToolCalls(e.taskToolCalls,accept);try{for(;;){a=await this.resolveTaskWaits(a,n,accept);let o=resolveRuntimeActionResultsForCallIds({pendingCallIds:e.pendingCallIds,results:t});if(o!==void 0){let e=o.flatMap(e=>{let t=i.get(e.callId);return t===void 0?[]:[t]});return{acceptedAtMsByCallId:Object.fromEntries(o.map(e=>[e.callId,r.get(e.callId)])),...e.length>0&&{delegatedUsage:e},results:o}}let s=a.flatMap(e=>e.timer===void 0?[]:[e.timer]),c=await e.turn.nextRuntimeEvent(s);if(c===`cancelled`)return c;if(c.kind===`timeout`){for(let e of a)e.callId===c.callId&&(e.timedOut=!0);continue}if(c.kind===`input`)continue;if(c.kind===`steering`){n||await this.interruptWaitedWorkflowCalls(e.pendingCallIds,t),n=!0;continue}if(c.kind===`runtime-action-result`){let e=this.input.cursor.sessionState.snapshot.session.state,n=c.results.filter(t=>t.kind===`tool-result`&&isInboxToolResultFromRecordedWorkflowToolRun(e,t));if(n.length>0){let e=Date.now();t.push(...n);for(let t of n)r.set(t.callId,e)}continue}let l=await this.handleWorkflowMessage(c.message,e.turn);l!==void 0&&(accept(l),c.message.kind===`outcome`&&c.message.usage!==void 0&&i.set(l.callId,c.message.usage))}}finally{for(let e of a)await this.traceTaskWait(e,void 0,!0)}}async resolveTaskWaits(e,t,n){let r=sessionTaskTable(this.input.cursor),i=[];for(let a of e){let e=taskWaitResult(r,{interrupted:t,timedOut:a.timedOut});if(e===void 0){i.push(a);continue}let o=renderTaskWaitResult(e,Date.now()-a.startedAtMs);await this.traceTaskWait(a,o,t),n(taskToolResult(a.callId,TASK_WAIT_TOOL_NAME,o))}return i}async answerTaskToolCalls(e,t){let n=[],r=e.length===0?0:await startTaskToolCallsStep();for(let i of e)if(i.kind===TASK_WAIT_TOOL_NAME)n.push(startTaskWait(i,r));else{let e;try{e=await answerTaskCancel(this.input.cursor,i)}catch(e){throw await this.input.cursor.advance(e=>traceTaskToolCallStep(e,{callId:i.callId,toolName:i.kind,startedAtMs:r,completedAtMs:Date.now(),input:{taskId:i.taskId},failed:!0})),e}await this.input.cursor.advance(t=>traceTaskToolCallStep(t,{callId:i.callId,toolName:i.kind,startedAtMs:r,completedAtMs:Date.now(),input:{taskId:i.taskId},output:e.output})),t(e)}let i=await this.resolveTaskWaits(n,!1,t);return i.length>0&&await this.input.cursor.advance(publishTurnWaitingStep),i}async traceTaskWait(e,t,n=!1){await this.input.cursor.advance(r=>traceTaskToolCallStep(r,{callId:e.callId,toolName:TASK_WAIT_TOOL_NAME,startedAtMs:e.startedAtMs,completedAtMs:Date.now(),input:e.input,output:t,failed:n}))}async interruptWaitedWorkflowCalls(e,t){let n=this.input.cursor.sessionState.snapshot.session.state,r=new Set(t.map(e=>e.callId)),i=e.filter(e=>!r.has(e)).flatMap(e=>{let t=findBlockingWorkflowToolRun(n,e);return t===void 0?[]:[t.address]});await Promise.all(i.map(e=>interruptWorkflowToolRun(e)))}};function startTaskWait(e,t){let{callId:n,timeoutMs:r}=e,i=r===void 0?void 0:sleep(r).then(()=>n);return{callId:n,startedAtMs:t,input:r===void 0?{}:{timeoutSeconds:r/1e3},timedOut:r===0,timer:i}}function mayWaitOnWorkflowToolRuns(e){try{return getBlockingWorkflowToolRuns(e.snapshot?.session?.state).length>0}catch{return!0}}export{SessionExecution,hasDelegatedCallerContext};
|
|
@@ -28,6 +28,12 @@ export declare function readSessionEventStream(sessionId: string, startIndex?: n
|
|
|
28
28
|
export declare function readSessionEventHistory(sessionId: string, startIndex?: number): ReadableStream<MessageStreamEvent>;
|
|
29
29
|
/** Returns the index of the last durably recorded event, or `-1` before the first. */
|
|
30
30
|
export declare function readSessionStreamTailIndex(sessionId: string): Promise<number>;
|
|
31
|
+
/**
|
|
32
|
+
* Throws when the session's run does not exist or its recorded history has
|
|
33
|
+
* passed retention. Cheaper than {@link readSessionStreamTailIndex}, whose
|
|
34
|
+
* lookup on the local world opens every chunk file.
|
|
35
|
+
*/
|
|
36
|
+
export declare function assertSessionHistoryReadable(sessionId: string): Promise<void>;
|
|
31
37
|
/**
|
|
32
38
|
* Iterates one session's durable events in process, without the HTTP stream
|
|
33
39
|
* route.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{normalizePersistedMessageStreamEvent}from"#protocol/message-version.js";import{getRun,getWorld}from"#internal/workflow/runtime.js";import{RunExpiredError}from"#compiled/@workflow/errors/index.js";import{parseNdjsonStream}from"#execution/ndjson-stream.js";function readSessionEventStream(e,t){return parseNdjsonStream(()=>getRun(e).getReadable({startIndex:t}),normalizePersistedEvent)}function readSessionEventHistory(e,t){let n=streamSessionEvents(e,{follow:!1,startIndex:t});return new ReadableStream({async pull(e){let t=await n.next();t.done?e.close():e.enqueue(t.value)},async cancel(){await n.return(void 0)}})}async function readSessionStreamTailIndex(e){let t=getRun(e).getReadable();try{let
|
|
1
|
+
import{normalizePersistedMessageStreamEvent}from"#protocol/message-version.js";import{getRun,getWorld}from"#internal/workflow/runtime.js";import{RunExpiredError}from"#compiled/@workflow/errors/index.js";import{parseNdjsonStream}from"#execution/ndjson-stream.js";function readSessionEventStream(e,t){return parseNdjsonStream(()=>getRun(e).getReadable({startIndex:t}),normalizePersistedEvent)}function readSessionEventHistory(e,t){let n=streamSessionEvents(e,{follow:!1,startIndex:t});return new ReadableStream({async pull(e){let t=await n.next();t.done?e.close():e.enqueue(t.value)},async cancel(){await n.return(void 0)}})}async function readSessionStreamTailIndex(e){let t=getRun(e).getReadable();try{let[,n]=await Promise.all([assertSessionHistoryReadable(e),t.getTailIndex()]);return n}finally{await t.cancel().catch(()=>{})}}async function assertSessionHistoryReadable(e){let t=await(await getWorld()).runs.get(e,{resolveData:`none`});if(t.expiredAt!==void 0&&t.expiredAt.getTime()<=Date.now())throw new RunExpiredError(`Session history is no longer available.`,e,t.status,t.expiredAt)}async function*streamSessionEvents(e,t={}){let{follow:n=!0,signal:r}=t,i=t.startIndex??0;if(r?.aborted)return;let a,o=i;if((!n||i<0)&&(a=await readSessionStreamTailIndex(e),i<0&&(o=Math.max(0,a+1+i))),!n&&a!==void 0&&o>a)return;let s=readSessionEventStream(e,o).getReader(),cancel=()=>void s.cancel(r?.reason).catch(()=>{});r?.addEventListener(`abort`,cancel,{once:!0});try{let e=o;for(;!r?.aborted;){let{done:t,value:r}=await s.read();if(t||(yield r,!n&&a!==void 0&&e>=a))return;e+=1}}finally{r?.removeEventListener(`abort`,cancel),await s.cancel().catch(()=>{}),s.releaseLock()}}function normalizePersistedEvent(e){return normalizePersistedMessageStreamEvent(e)}export{assertSessionHistoryReadable,readSessionEventHistory,readSessionEventStream,readSessionStreamTailIndex,streamSessionEvents};
|
|
@@ -27,12 +27,20 @@ export interface SessionHandoverPayload {
|
|
|
27
27
|
readonly final?: true;
|
|
28
28
|
readonly payloads: readonly Exclude<SessionInboxPayload, SessionHandoverPayload>[];
|
|
29
29
|
}
|
|
30
|
+
/** Replay-stable evidence that every buffered part and the final marker were applied. */
|
|
31
|
+
export interface SessionHandoverObservation {
|
|
32
|
+
readonly attemptKey: string;
|
|
33
|
+
readonly payloadCount: number;
|
|
34
|
+
/** Workflow event time, not the host wall clock when replay reached this point. */
|
|
35
|
+
readonly appliedAtMs: number;
|
|
36
|
+
}
|
|
30
37
|
export type SessionInboxPayload = SessionPrewarmPayload | SessionFailurePayload | SessionHandoverPayload | HookPayload | SessionCommand | WorkflowToolRunMessage | AuthorizationCallbackPayload;
|
|
31
38
|
/**
|
|
32
39
|
* While a handover is awaited (see {@link SessionHookBatchClaimOptions.handover}),
|
|
33
40
|
* reads expose nothing; interrupt handlers still fire on arrival.
|
|
34
41
|
*/
|
|
35
42
|
export interface SessionInboxReader {
|
|
43
|
+
readonly handoverObservation?: SessionHandoverObservation;
|
|
36
44
|
/**
|
|
37
45
|
* Waits for and removes the next accepted payload in arrival order, or
|
|
38
46
|
* `undefined` once no hook can deliver any more (released or taken over).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{sessionInboxHookToken}from"#execution/session-inbox/address.js";import{createHook,getWorkflowMetadata}from"#compiled/@workflow/core/index.js";import{claimHookOwnership,disposeHook,isHookForceClaimedError}from"#execution/hook-ownership.js";import{releaseSessionHooksStep}from"#execution/session-inbox/release-step.js";function isInterrupt(e){return e.kind===`cancel`||e.kind===`reset`||e.kind===`session-timeout`||e.kind===`session-failure`}function isDelivery(e){return e.kind===`send`||e.kind===`deliver`}function createSessionInbox(e){let t=[],n=[],r=new Set,i=new Set,a=new Set,o,s,c=new Set,
|
|
1
|
+
import{sessionInboxHookToken}from"#execution/session-inbox/address.js";import{createHook,getWorkflowMetadata}from"#compiled/@workflow/core/index.js";import{claimHookOwnership,disposeHook,isHookForceClaimedError}from"#execution/hook-ownership.js";import{releaseSessionHooksStep}from"#execution/session-inbox/release-step.js";function isInterrupt(e){return e.kind===`cancel`||e.kind===`reset`||e.kind===`session-timeout`||e.kind===`session-failure`}function isDelivery(e){return e.kind===`send`||e.kind===`deliver`}function createSessionInbox(e){let t=[],n=[],r=new Set,i=new Set,a=new Set,o,s,c,l=new Set,u=new Set,d=!1,f=!1,notify=()=>{for(let e of r)e();r.clear()},wait=()=>new Promise(e=>r.add(e)),closed=()=>t.every(e=>e.closed||e.stopping),gated=()=>s!==void 0&&t.length>0,hasReadable=()=>!gated()&&n.length>0,throwIfFailed=()=>{if(o!==void 0)throw o.error},observe=(e,t,n)=>{for(let r of t)if(n(r))for(let t of e)t(r)},openHandover=()=>{s=void 0,observe(a,n,isDelivery),notify()},blockedOnHandover=()=>{if(gated()){for(let e of l)e();l.clear()}},acceptHandover=e=>{let t=s;if(t===void 0||e.attemptKey!==t.attemptKey||e.index<t.nextPart||t.parts.has(e.index))return;t.parts.set(e.index,e);let r=[];for(;;){let e=t.parts.get(t.nextPart);if(e===void 0)break;if(e.final===!0){c={attemptKey:t.attemptKey,payloadCount:t.nextPart,appliedAtMs:Date.now()},observe(i,r,isInterrupt),openHandover();return}t.parts.delete(t.nextPart),t.nextPart+=1,n.splice(t.index,0,...e.payloads),t.index+=e.payloads.length,r.push(...e.payloads)}observe(i,r,isInterrupt),notify()},pump=async e=>{let r=e.hook[Symbol.asyncIterator]();try{for(;!e.stopping;){let e=await r.next();if(e.done)break;let t=e.value;for(let e of u)e();if(u.clear(),t.kind===`workflow-batch`){n.push(...t.messages),notify();continue}if(t.kind===`handover`){acceptHandover(t);continue}n.push(t),gated()||observe(a,[t],isDelivery),observe(i,[t],isInterrupt),notify()}}catch(n){if(e.stopping||e.replaced)return;isHookForceClaimedError(n)?(t.splice(t.indexOf(e),1),d=!0):o={error:n}}finally{e.closed=!0,notify()}},stop=async()=>{let e=t.splice(0);s=void 0,d=!1,f=!0;for(let t of e)t.stopping=!0;notify(),await Promise.all(e.map(({hook:e})=>disposeHook(e)));let r=n.splice(0);return notify(),r},claimSessionHook=async(n,r={})=>{if(!n)throw Error(`A session alias requires a nonempty continuation token.`);let i=r.force===!0,a=t.find(e=>e.token===n);if(a!==void 0&&!i)return await a.registered;if(a===void 0&&t.length>=256)throw Error(`A session may claim at most 256 addresses.`);let o={token:n,hook:createHook({token:sessionInboxHookToken(n),metadata:{sessionId:e},...i&&{experimental_force:!0}}),stopping:!1,closed:!1,replaced:!1};a===void 0?t.push(o):(a.replaced=!0,t.splice(t.indexOf(a),1,o)),f=!1;try{let confirm=()=>claimHookOwnership(o.hook);o.registered=r.confirmAfter?.then(confirm,confirm)??confirm(),await o.registered,d=!1,pump(o)}catch(e){throw a===void 0||a.closed?t.splice(t.indexOf(o),1):(a.replaced=!1,t.splice(t.indexOf(o),1,a)),e}};return{get handoverObservation(){return c},get claimedTokens(){return t.map(({token:e})=>e)},get awaitingHandover(){return s!==void 0},async whenHandoverSettled(){for(;s!==void 0;)await wait()},abandonHandover(e){s?.attemptKey===e&&openHandover()},whenBlockedOnHandover(){return new Promise(e=>l.add(e))},whenArrival(){return new Promise(e=>u.add(e))},get takenOver(){return d&&t.length===0},claimSessionHook,async claimSessionHooks(e,t={}){t.handover!==void 0&&(s={attemptKey:t.handover,index:n.length,nextPart:0,parts:new Map});let r=await Promise.allSettled([...new Set(e)].map(e=>claimSessionHook(e,t)));for(let e of r)if(e.status===`rejected`)throw e.reason},async whenTakenOver(e){for(e?.addEventListener(`abort`,notify,{once:!0});t.length>0||!d;){if(throwIfFailed(),f)throw Error(`The session inbox was released before a takeover.`);if(e?.aborted===!0)throw e.reason;await wait()}},async next(){for(;;){if(throwIfFailed(),hasReadable())return n.shift();if(closed())return;blockedOnHandover(),await wait()}},drain(){return throwIfFailed(),gated()?[]:n.splice(0)},takeLeading(e){throwIfFailed();let t=[];if(gated())return t;for(let r=n[0];r!==void 0&&e(r);r=n[0])t.push(r),n.shift();return t},hasPending(){return throwIfFailed(),hasReadable()},async whenPending(){for(;o===void 0&&!hasReadable()&&!closed();)blockedOnHandover(),await wait()},onInterrupt(e){return i.add(e),()=>i.delete(e)},onDelivery(e){if(a.add(e),!gated())for(let t of n)isDelivery(t)&&e(t);return()=>a.delete(e)},restore(e){if(t.length===0)throw Error(`Cannot restore session commands before reclaiming the session hooks.`);n.unshift(...e),s!==void 0&&(s.index+=e.length),notify()},async dispose(){await stop()},async release(){return t.length>0&&await releaseSessionHooksStep({ownerRunId:getWorkflowMetadata().workflowRunId,tokens:t.map(({hook:e})=>e.token)}),await stop()}}}function isWorkflowMessage(e){return e.kind===`agent-started`||e.kind===`started`||e.kind===`report`||e.kind===`reply`||e.kind===`request`||e.kind===`withdraw`||e.kind===`usage`||e.kind===`outcome`}export{createSessionInbox,isInterrupt,isWorkflowMessage};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{decide}from"#ai/decide.js";async function runAgentRouterTask(e,t){"use workflow";let n=await chooseTarget(e.message,descriptions(t),t.abortSignal),{message:r,status:i}=await(await t.agent(n).send(e.message,{signal:t.abortSignal})).result();if(i===`failed`)throw Error(`Agent "${n}" failed to handle the task.`);return r??null}async function chooseTarget(e,t,n){"use step";let r=Object.keys(t);if(r.length===0)throw Error(`agentRouter requires at least one available agent with a description.`);return r.length===1?r[0]:(await decide({abortSignal:n,state:{message:e},questions:{route:{type:`choice`,instructions:`Which subagent should handle this task?`,criteria:t}}})).answers.route.choice}function descriptions(e){return Object.fromEntries(Object.entries(e.agents).flatMap(([e,t])=>{let n=t.description.trim();return n.length===0?[]:[[e,n]]}))}runAgentRouterTask.workflowId=`workflow//eve@0.83.
|
|
1
|
+
import{decide}from"#ai/decide.js";async function runAgentRouterTask(e,t){"use workflow";let n=await chooseTarget(e.message,descriptions(t),t.abortSignal),{message:r,status:i}=await(await t.agent(n).send(e.message,{signal:t.abortSignal})).result();if(i===`failed`)throw Error(`Agent "${n}" failed to handle the task.`);return r??null}async function chooseTarget(e,t,n){"use step";let r=Object.keys(t);if(r.length===0)throw Error(`agentRouter requires at least one available agent with a description.`);return r.length===1?r[0]:(await decide({abortSignal:n,state:{message:e},questions:{route:{type:`choice`,instructions:`Which subagent should handle this task?`,criteria:t}}})).answers.route.choice}function descriptions(e){return Object.fromEntries(Object.entries(e.agents).flatMap(([e,t])=>{let n=t.description.trim();return n.length===0?[]:[[e,n]]}))}runAgentRouterTask.workflowId=`workflow//eve@0.83.2//runAgentRouterTask`;export{runAgentRouterTask};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger,logError}from"#internal/logging.js";import{validateDeliveryIdempotencyKey}from"#channel/delivery-idempotency.js";import{SessionStrandedError,describeStrandedSession}from"#channel/session-stranded-error.js";import{sessionCommandHookToken,sessionInboxHookToken}from"#execution/session-inbox/address.js";import{SessionPredecessorKey}from"#context/keys.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{walkCauseChain}from"#shared/errors.js";import{validateToolStubTargets}from"#tool-stubs/validate-targets.js";import{getHookByToken,getRun,getWorld,start}from"#internal/workflow/runtime.js";import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{serializeContext}from"#context/serialize.js";import{AcceptedSessionIdentityError,SessionHandoffPendingError,logicalSessionToken,resolveSessionInbox,resumeSessionInbox}from"#execution/session-inbox/resume.js";import{resolveEffectiveAgentRuntime}from"#execution/effective-agent-config.js";import{context,trace}from"#compiled/@opentelemetry/api/index.js";import{EntityConflictError,HookNotFoundError,RunExpiredError,WorkflowRunNotFoundError}from"#compiled/@workflow/errors/index.js";import{StrandedSessionOwnerError,assertRunnableSessionInbox,findSessionHookHolder}from"#execution/session-inbox/owner.js";import{initializeSessionInstrumentation}from"#instrumentation/runtime.js";import{EVE_PREWARM_ATTRIBUTE,EVE_VERSION_ATTRIBUTE,buildSessionAttributes,buildSubagentRootAttributes,readParentLineage}from"#execution/eve-workflow-attributes.js";import{endStrandedSession}from"#execution/session-inbox/end-stranded-session.js";import{SESSION_HOOK_HANDOVER_TIMEOUT_MS,waitForSessionHooksRelease}from"#execution/session-inbox/hook-release.js";import{CONNECTION_EVENT_DELIVERY_WORKFLOW_NAME,CONNECTION_EVENT_WORKFLOW_NAME,SESSION_TIMEOUT_WORKFLOW_NAME,WORKFLOW_ENTRY_NAME,WORKFLOW_TOOL_RUN_WORKFLOW_NAME}from"#execution/stable-workflow-names.js";import{prewarmWorkflowSession}from"#execution/session-prewarm.js";import{normalizeEveAttributes}from"#runtime/attributes/normalize.js";import{buildRunContext}from"#execution/runtime-context.js";import{readSessionEventHistory,readSessionEventStream,readSessionStreamTailIndex}from"#execution/session-event-stream.js";import{buildInvocationAttributes}from"#internal/invocation/metadata.js";import{isAgentTraceContext}from"#tracing/eve/agent-trace-context.js";const EVE_PACKAGE_INFO=resolveInstalledPackageInfo(),STABLE_ID_BASE=EVE_PACKAGE_INFO.name,log=createLogger(`execution.workflow-runtime`),workflowEntryReference={workflowId:`workflow//${STABLE_ID_BASE}//${WORKFLOW_ENTRY_NAME}`},sessionTimeoutWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${SESSION_TIMEOUT_WORKFLOW_NAME}`},workflowToolRunWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${WORKFLOW_TOOL_RUN_WORKFLOW_NAME}`},connectionEventWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${CONNECTION_EVENT_WORKFLOW_NAME}`},connectionEventDeliveryWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${CONNECTION_EVENT_DELIVERY_WORKFLOW_NAME}`};function createWorkflowRuntime(e){let startSession=async(t,n)=>{validateDeliveryIdempotencyKey(t.idempotencyKey);let r=await getCompiledRuntimeAgentBundle({compiledArtifactsSource:e.compiledArtifactsSource,nodeId:e.nodeId});t.toolStubs!==void 0&&t.toolStubs.rootSessionId===void 0&&validateToolStubTargets(t.toolStubs.rules,r.graph);let i=buildRunContext({agentSessionRuntimeOverrides:e.agentSessionRuntimeOverrides,bundle:r,dynamicSubagentAgentConfig:e.dynamicSubagentAgentConfig,run:t});n!==void 0&&i.set(SessionPredecessorKey,n);let a=resolveEffectiveAgentRuntime(r,i),o=initializeSessionInstrumentation({agentName:a.turnAgent.id,ctx:i}),s=a.limits?.sessionTimeoutMs,c=r.resolvedAgent.config?.experimental?.workflow?.retention??(o.action===`record`&&o.recordInputs&&o.recordOutputs?void 0:0),l=serializeContext(i),u=readParentLineage(l),d={idempotencyKey:t.idempotencyKey,kind:`initial`,input:t.input,ownerDeploymentId:await resolveCurrentWorkflowDeploymentId(),serializedContext:l};t.continuationConflictCommand!==void 0&&(d.continuationConflictCommand=t.continuationConflictCommand),s!==void 0&&(d.sessionTimeoutMs=s),c!==void 0&&(d.retention=c);let f={...u.sessionId===void 0?buildSessionAttributes({serializedContext:l}):buildSubagentRootAttributes({identity:{nodeId:r.nodeId??ROOT_RUNTIME_AGENT_NODE_ID},parentCallId:u.callId,parentSessionId:u.sessionId,parentTurnId:u.turnId,rootSessionId:u.rootSessionId??u.sessionId,serializedContext:l}),[EVE_PREWARM_ATTRIBUTE]:`1`,...t.externalInvocation===void 0?{}:buildInvocationAttributes(t.externalInvocation)},p;try{let e={allowReservedAttributes:!0,attributes:normalizeEveAttributes(f)};c!==void 0&&(e.experimental_retention=c),p=await startWorkflowOnDeployment(workflowEntryReference,[d],d.ownerDeploymentId,e)}catch(e){throw logError(log,`failed to start workflow run`,e,{continuationToken:t.continuationToken}),e}let m=p.runId;if(t.idempotencyKey!==void 0&&t.continuationToken!==void 0){let e=await pollUntil(()=>resolveContinuation(t.continuationToken),SESSION_HOOK_HANDOVER_TIMEOUT_MS);if(e===void 0)throw Error(`Delivery accepted, but its session identity is not ready. Retry with the same idempotencyKey.`);m=e.sessionId}let h,getEvents=()=>(h??=readSessionEventStream(m),h);return{get events(){return getEvents()},sessionId:m}};return{async createSession(e){return await startSession(e)},async dispatchContinuation(e){let{command:t,continuationToken:n,successor:r}=e;try{return await dispatchWorkflowCommand(n,t)}catch(e){if(!(e instanceof StrandedSessionOwnerError))throw e;if(t.kind!==`send`||r===void 0)return await settleStrandedCommand(n,t,e);if((t.payload.inputResponses?.length??0)>0)throw sessionStrandedError(e,`Its pending requests can no longer be answered; send a new message to start a fresh session.`);let i=await endStrandedSession(e,n,`message`);return{sessionId:(await startSession(r,{sessionId:i})).sessionId,status:`accepted`}}},async dispatchSession(e){return await dispatchWorkflowSessionCommand(e)},async getEventStream(e,t){if(t?.follow===!1)return readSessionEventHistory(e,t.startIndex);try{await assertRunnableSessionInbox(sessionInboxHookToken(sessionCommandHookToken(e)))}catch(e){throw e instanceof StrandedSessionOwnerError?sessionStrandedError(e):e}return readSessionEventStream(e,t?.startIndex)},async getStreamTailIndex(e){return await readSessionStreamTailIndex(e)},resolveContinuation}}async function dispatchWorkflowCommand(e,t){if(t.kind===`prewarm`)return typeof e==`string`?{status:`unsupported`}:await prewarmWorkflowSession(e.sessionId,t.targetDeploymentId);let n;try{let r=await resumeSessionInbox(e,t);n={runId:r.ownerRunId,sessionId:await r.sessionId}}catch(n){if(n instanceof StrandedSessionOwnerError)throw n;let r=t.kind===`send`&&typeof e!=`string`,i={status:`session_not_active`,retryable:!0};if(n instanceof SessionHandoffPendingError){if(r)return i;throw n}if(isInactiveCommandTarget(n))return r&&await isRunActive(e.sessionId)?i:inactiveCommandResult(t);throw logError(log,`failed to dispatch session command`,n,{command:t.kind,token:e}),n}return t.kind===`reset`&&await waitForSessionHooksRelease([sessionCommandHookToken(n.sessionId),logicalSessionToken(e)],{ownerRunId:n.runId,sessionId:n.sessionId}),activeCommandResult(t,n.sessionId)}async function settleStrandedCommand(e,t,n){switch(t.kind){case`reset`:return{previousSessionId:await endStrandedSession(n,e,`reset`),status:`reset`};case`send`:case`clear`:throw sessionStrandedError(n);default:return inactiveCommandResult(t)}}function sessionStrandedError(e,t){let n=e.eveVersion===void 0?{}:{eveVersion:e.eveVersion};return new SessionStrandedError(n,describeStrandedSession(n,t))}function activeCommandResult(e,t){return e.kind===`reset`?{previousSessionId:t,status:`reset`}:e.kind===`send`&&e.delivery!==void 0?{sessionId:t,status:`accepted`,deliveryId:e.delivery.deliveryId}:{sessionId:t,status:`accepted`}}function inactiveCommandResult(e){return e.kind===`send`?{status:`session_not_active`}:e.kind===`cancel`?{status:`no_active_turn`}:{status:`no_active_session`}}async function dispatchWorkflowSessionCommand(e){let t={sessionId:e.sessionId};try{return await dispatchWorkflowCommand(t,e.command)}catch(n){if(!(n instanceof StrandedSessionOwnerError))throw n;return await settleStrandedCommand(t,e.command,n)}}async function isRunActive(e){try{let t=await getRun(e).status;return t===`pending`||t===`running`}catch(e){if(isInactiveCommandTarget(e))return!1;throw e}}function isInactiveCommandTarget(e){if(e instanceof AcceptedSessionIdentityError)return!1;if(HookNotFoundError.is(e))return!0;for(let t of walkCauseChain(e))if(WorkflowRunNotFoundError.is(t)||RunExpiredError.is(t)||EntityConflictError.is(t))return!0;return!1}async function resolveContinuation(e,t){let n;try{n=await resolveSessionInbox(e)}catch(t){if(HookNotFoundError.is(t))return;throw logError(log,`failed to resolve session by continuation token`,t,{continuationToken:e}),t}if(t?.runnable!==!0)return n;try{await assertRunnableSessionInbox(sessionInboxHookToken(sessionCommandHookToken(n.sessionId)))}catch(e){throw e instanceof StrandedSessionOwnerError?sessionStrandedError(e):e}return n}async function waitForCommandHookOwner(e){let t=await pollUntil(async()=>{try{return normalizeWorkflowHook(await getHookByToken(e))}catch(e){if(!HookNotFoundError.is(e))throw e;return}},SESSION_HOOK_HANDOVER_TIMEOUT_MS);if(t===void 0)throw new HookNotFoundError(e);return t}async function waitForSessionInbox(e){let t=sessionInboxHookToken(sessionCommandHookToken(e)),n=await pollUntil(async()=>await findSessionHookHolder(t)!==void 0||!await hasRunEnded(e)&&void 0,SESSION_HOOK_HANDOVER_TIMEOUT_MS);if(n===void 0)throw Error(`Session "${e}" did not start taking commands within ${SESSION_HOOK_HANDOVER_TIMEOUT_MS/1e3} seconds.`);return n}async function pollUntil(e,t){let n=Date.now()+t;for(let t=20;;t=Math.min(t*2,200)){let r=await e();if(r!==void 0||Date.now()>=n)return r;await new Promise(e=>setTimeout(e,t))}}async function hasRunEnded(e){try{let t=await getRun(e).status;return t!==`pending`&&t!==`running`}catch(e){for(let t of walkCauseChain(e))if(WorkflowRunNotFoundError.is(t))return!1;if(isInactiveCommandTarget(e))return!0;throw e}}async function startWorkflowOnCurrentDeployment(e,t,n){return await startWorkflowOnDeployment(e,t,await resolveCurrentWorkflowDeploymentId(),n)}async function startWorkflowOnDeployment(e,t,n,r){return await withWorkflowStartContext(async()=>{if(n.length===0||n===`latest`)throw Error(`Workflow starts require an exact deployment id.`);return await start(e,t,{...r,allowReservedAttributes:!0,attributes:{...r?.attributes,[EVE_VERSION_ATTRIBUTE]:EVE_PACKAGE_INFO.version},deploymentId:n})})}async function resolveCurrentWorkflowDeploymentId(){let e=process.env.VERCEL_DEPLOYMENT_ID?.trim()||await(await getWorld()).getDeploymentId();if(e.length===0||e===`latest`)throw Error(`Workflow runtime could not resolve an exact deployment id.`);return e}async function withWorkflowStartContext(e){let t=context.active(),n=isAgentTraceContext(t)?trace.deleteSpan(t):t;return await context.with(n,e)}function normalizeWorkflowHook(e){if(typeof e!=`object`||!e||!(`runId`in e))throw Error(`Workflow hook did not include a run id.`);let t=e.runId;if(typeof t!=`string`||t.length===0)throw Error(`Workflow hook did not include a run id.`);return{runId:t}}export{connectionEventDeliveryWorkflowReference,connectionEventWorkflowReference,createWorkflowRuntime,dispatchWorkflowSessionCommand,hasRunEnded,pollUntil,resolveContinuation,sessionTimeoutWorkflowReference,startWorkflowOnCurrentDeployment,startWorkflowOnDeployment,waitForCommandHookOwner,waitForSessionInbox,workflowEntryReference,workflowToolRunWorkflowReference};
|
|
1
|
+
import{createLogger,logError}from"#internal/logging.js";import{validateDeliveryIdempotencyKey}from"#channel/delivery-idempotency.js";import{SessionStrandedError,describeStrandedSession}from"#channel/session-stranded-error.js";import{sessionCommandHookToken,sessionInboxHookToken}from"#execution/session-inbox/address.js";import{SessionPredecessorKey}from"#context/keys.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{walkCauseChain}from"#shared/errors.js";import{validateToolStubTargets}from"#tool-stubs/validate-targets.js";import{getHookByToken,getRun,getWorld,start}from"#internal/workflow/runtime.js";import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{serializeContext}from"#context/serialize.js";import{AcceptedSessionIdentityError,SessionHandoffPendingError,logicalSessionToken,resolveSessionInbox,resumeSessionInbox}from"#execution/session-inbox/resume.js";import{resolveEffectiveAgentRuntime}from"#execution/effective-agent-config.js";import{context,trace}from"#compiled/@opentelemetry/api/index.js";import{EntityConflictError,HookNotFoundError,RunExpiredError,WorkflowRunNotFoundError}from"#compiled/@workflow/errors/index.js";import{StrandedSessionOwnerError,assertRunnableSessionInbox,findSessionHookHolder}from"#execution/session-inbox/owner.js";import{initializeSessionInstrumentation}from"#instrumentation/runtime.js";import{EVE_PREWARM_ATTRIBUTE,EVE_VERSION_ATTRIBUTE,buildSessionAttributes,buildSubagentRootAttributes,readParentLineage}from"#execution/eve-workflow-attributes.js";import{endStrandedSession}from"#execution/session-inbox/end-stranded-session.js";import{SESSION_HOOK_HANDOVER_TIMEOUT_MS,waitForSessionHooksRelease}from"#execution/session-inbox/hook-release.js";import{CONNECTION_EVENT_DELIVERY_WORKFLOW_NAME,CONNECTION_EVENT_WORKFLOW_NAME,SESSION_TIMEOUT_WORKFLOW_NAME,WORKFLOW_ENTRY_NAME,WORKFLOW_TOOL_RUN_WORKFLOW_NAME}from"#execution/stable-workflow-names.js";import{prewarmWorkflowSession}from"#execution/session-prewarm.js";import{normalizeEveAttributes}from"#runtime/attributes/normalize.js";import{buildRunContext}from"#execution/runtime-context.js";import{assertSessionHistoryReadable,readSessionEventHistory,readSessionEventStream,readSessionStreamTailIndex}from"#execution/session-event-stream.js";import{buildInvocationAttributes}from"#internal/invocation/metadata.js";import{isAgentTraceContext}from"#tracing/eve/agent-trace-context.js";const EVE_PACKAGE_INFO=resolveInstalledPackageInfo(),STABLE_ID_BASE=EVE_PACKAGE_INFO.name,log=createLogger(`execution.workflow-runtime`),workflowEntryReference={workflowId:`workflow//${STABLE_ID_BASE}//${WORKFLOW_ENTRY_NAME}`},sessionTimeoutWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${SESSION_TIMEOUT_WORKFLOW_NAME}`},workflowToolRunWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${WORKFLOW_TOOL_RUN_WORKFLOW_NAME}`},connectionEventWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${CONNECTION_EVENT_WORKFLOW_NAME}`},connectionEventDeliveryWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${CONNECTION_EVENT_DELIVERY_WORKFLOW_NAME}`};function createWorkflowRuntime(e){let startSession=async(t,n)=>{validateDeliveryIdempotencyKey(t.idempotencyKey);let r=await getCompiledRuntimeAgentBundle({compiledArtifactsSource:e.compiledArtifactsSource,nodeId:e.nodeId});t.toolStubs!==void 0&&t.toolStubs.rootSessionId===void 0&&validateToolStubTargets(t.toolStubs.rules,r.graph);let i=buildRunContext({agentSessionRuntimeOverrides:e.agentSessionRuntimeOverrides,bundle:r,dynamicSubagentAgentConfig:e.dynamicSubagentAgentConfig,run:t});n!==void 0&&i.set(SessionPredecessorKey,n);let a=resolveEffectiveAgentRuntime(r,i),o=initializeSessionInstrumentation({agentName:a.turnAgent.id,ctx:i}),s=a.limits?.sessionTimeoutMs,c=r.resolvedAgent.config?.experimental?.workflow?.retention??(o.action===`record`&&o.recordInputs&&o.recordOutputs?void 0:0),l=serializeContext(i),u=readParentLineage(l),d={idempotencyKey:t.idempotencyKey,kind:`initial`,input:t.input,ownerDeploymentId:await resolveCurrentWorkflowDeploymentId(),serializedContext:l};t.continuationConflictCommand!==void 0&&(d.continuationConflictCommand=t.continuationConflictCommand),s!==void 0&&(d.sessionTimeoutMs=s),c!==void 0&&(d.retention=c);let f={...u.sessionId===void 0?buildSessionAttributes({serializedContext:l}):buildSubagentRootAttributes({identity:{nodeId:r.nodeId??ROOT_RUNTIME_AGENT_NODE_ID},parentCallId:u.callId,parentSessionId:u.sessionId,parentTurnId:u.turnId,rootSessionId:u.rootSessionId??u.sessionId,serializedContext:l}),[EVE_PREWARM_ATTRIBUTE]:`1`,...t.externalInvocation===void 0?{}:buildInvocationAttributes(t.externalInvocation)},p;try{let e={allowReservedAttributes:!0,attributes:normalizeEveAttributes(f)};c!==void 0&&(e.experimental_retention=c),p=await startWorkflowOnDeployment(workflowEntryReference,[d],d.ownerDeploymentId,e)}catch(e){throw logError(log,`failed to start workflow run`,e,{continuationToken:t.continuationToken}),e}let m=p.runId;if(t.idempotencyKey!==void 0&&t.continuationToken!==void 0){let e=await pollUntil(()=>resolveContinuation(t.continuationToken),SESSION_HOOK_HANDOVER_TIMEOUT_MS);if(e===void 0)throw Error(`Delivery accepted, but its session identity is not ready. Retry with the same idempotencyKey.`);m=e.sessionId}let h,getEvents=()=>(h??=readSessionEventStream(m),h);return{get events(){return getEvents()},sessionId:m}};return{async createSession(e){return await startSession(e)},async dispatchContinuation(e){let{command:t,continuationToken:n,successor:r}=e;try{return await dispatchWorkflowCommand(n,t)}catch(e){if(!(e instanceof StrandedSessionOwnerError))throw e;if(t.kind!==`send`||r===void 0)return await settleStrandedCommand(n,t,e);if((t.payload.inputResponses?.length??0)>0)throw sessionStrandedError(e,`Its pending requests can no longer be answered; send a new message to start a fresh session.`);let i=await endStrandedSession(e,n,`message`);return{sessionId:(await startSession(r,{sessionId:i})).sessionId,status:`accepted`}}},async dispatchSession(e){return await dispatchWorkflowSessionCommand(e)},async getEventStream(e,t){if(t?.follow===!1)return readSessionEventHistory(e,t.startIndex);try{await Promise.all([assertRunnableSessionInbox(sessionInboxHookToken(sessionCommandHookToken(e))),assertSessionHistoryReadable(e)])}catch(e){throw e instanceof StrandedSessionOwnerError?sessionStrandedError(e):e}return readSessionEventStream(e,t?.startIndex)},async getStreamTailIndex(e){return await readSessionStreamTailIndex(e)},resolveContinuation}}async function dispatchWorkflowCommand(e,t){if(t.kind===`prewarm`)return typeof e==`string`?{status:`unsupported`}:await prewarmWorkflowSession(e.sessionId,t.targetDeploymentId);let n;try{let r=await resumeSessionInbox(e,t);n={runId:r.ownerRunId,sessionId:await r.sessionId}}catch(n){if(n instanceof StrandedSessionOwnerError)throw n;let r=t.kind===`send`&&typeof e!=`string`,i={status:`session_not_active`,retryable:!0};if(n instanceof SessionHandoffPendingError){if(r)return i;throw n}if(isInactiveCommandTarget(n))return r&&await isRunActive(e.sessionId)?i:inactiveCommandResult(t);throw logError(log,`failed to dispatch session command`,n,{command:t.kind,token:e}),n}return t.kind===`reset`&&await waitForSessionHooksRelease([sessionCommandHookToken(n.sessionId),logicalSessionToken(e)],{ownerRunId:n.runId,sessionId:n.sessionId}),activeCommandResult(t,n.sessionId)}async function settleStrandedCommand(e,t,n){switch(t.kind){case`reset`:return{previousSessionId:await endStrandedSession(n,e,`reset`),status:`reset`};case`send`:case`clear`:throw sessionStrandedError(n);default:return inactiveCommandResult(t)}}function sessionStrandedError(e,t){let n=e.eveVersion===void 0?{}:{eveVersion:e.eveVersion};return new SessionStrandedError(n,describeStrandedSession(n,t))}function activeCommandResult(e,t){return e.kind===`reset`?{previousSessionId:t,status:`reset`}:e.kind===`send`&&e.delivery!==void 0?{sessionId:t,status:`accepted`,deliveryId:e.delivery.deliveryId}:{sessionId:t,status:`accepted`}}function inactiveCommandResult(e){return e.kind===`send`?{status:`session_not_active`}:e.kind===`cancel`?{status:`no_active_turn`}:{status:`no_active_session`}}async function dispatchWorkflowSessionCommand(e){let t={sessionId:e.sessionId};try{return await dispatchWorkflowCommand(t,e.command)}catch(n){if(!(n instanceof StrandedSessionOwnerError))throw n;return await settleStrandedCommand(t,e.command,n)}}async function isRunActive(e){try{let t=await getRun(e).status;return t===`pending`||t===`running`}catch(e){if(isInactiveCommandTarget(e))return!1;throw e}}function isInactiveCommandTarget(e){if(e instanceof AcceptedSessionIdentityError)return!1;if(HookNotFoundError.is(e))return!0;for(let t of walkCauseChain(e))if(WorkflowRunNotFoundError.is(t)||RunExpiredError.is(t)||EntityConflictError.is(t))return!0;return!1}async function resolveContinuation(e,t){let n;try{n=await resolveSessionInbox(e)}catch(t){if(HookNotFoundError.is(t))return;throw logError(log,`failed to resolve session by continuation token`,t,{continuationToken:e}),t}if(t?.runnable!==!0)return n;try{await assertRunnableSessionInbox(sessionInboxHookToken(sessionCommandHookToken(n.sessionId)))}catch(e){throw e instanceof StrandedSessionOwnerError?sessionStrandedError(e):e}return n}async function waitForCommandHookOwner(e){let t=await pollUntil(async()=>{try{return normalizeWorkflowHook(await getHookByToken(e))}catch(e){if(!HookNotFoundError.is(e))throw e;return}},SESSION_HOOK_HANDOVER_TIMEOUT_MS);if(t===void 0)throw new HookNotFoundError(e);return t}async function waitForSessionInbox(e){let t=sessionInboxHookToken(sessionCommandHookToken(e)),n=await pollUntil(async()=>await findSessionHookHolder(t)!==void 0||!await hasRunEnded(e)&&void 0,SESSION_HOOK_HANDOVER_TIMEOUT_MS);if(n===void 0)throw Error(`Session "${e}" did not start taking commands within ${SESSION_HOOK_HANDOVER_TIMEOUT_MS/1e3} seconds.`);return n}async function pollUntil(e,t){let n=Date.now()+t;for(let t=20;;t=Math.min(t*2,200)){let r=await e();if(r!==void 0||Date.now()>=n)return r;await new Promise(e=>setTimeout(e,t))}}async function hasRunEnded(e){try{let t=await getRun(e).status;return t!==`pending`&&t!==`running`}catch(e){for(let t of walkCauseChain(e))if(WorkflowRunNotFoundError.is(t))return!1;if(isInactiveCommandTarget(e))return!0;throw e}}async function startWorkflowOnCurrentDeployment(e,t,n){return await startWorkflowOnDeployment(e,t,await resolveCurrentWorkflowDeploymentId(),n)}async function startWorkflowOnDeployment(e,t,n,r){return await withWorkflowStartContext(async()=>{if(n.length===0||n===`latest`)throw Error(`Workflow starts require an exact deployment id.`);return await start(e,t,{...r,allowReservedAttributes:!0,attributes:{...r?.attributes,[EVE_VERSION_ATTRIBUTE]:EVE_PACKAGE_INFO.version},deploymentId:n})})}async function resolveCurrentWorkflowDeploymentId(){let e=process.env.VERCEL_DEPLOYMENT_ID?.trim()||await(await getWorld()).getDeploymentId();if(e.length===0||e===`latest`)throw Error(`Workflow runtime could not resolve an exact deployment id.`);return e}async function withWorkflowStartContext(e){let t=context.active(),n=isAgentTraceContext(t)?trace.deleteSpan(t):t;return await context.with(n,e)}function normalizeWorkflowHook(e){if(typeof e!=`object`||!e||!(`runId`in e))throw Error(`Workflow hook did not include a run id.`);let t=e.runId;if(typeof t!=`string`||t.length===0)throw Error(`Workflow hook did not include a run id.`);return{runId:t}}export{connectionEventDeliveryWorkflowReference,connectionEventWorkflowReference,createWorkflowRuntime,dispatchWorkflowSessionCommand,hasRunEnded,pollUntil,resolveContinuation,sessionTimeoutWorkflowReference,startWorkflowOnCurrentDeployment,startWorkflowOnDeployment,waitForCommandHookOwner,waitForSessionInbox,workflowEntryReference,workflowToolRunWorkflowReference};
|
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
import { type ToolContext } from "eve/tools";
|
|
1
2
|
import { type GitHubConfig } from "./github-shell.ts";
|
|
2
3
|
export declare const GH_TOOL_DESCRIPTION = "Run one authenticated GitHub command in the sandbox. The full gh CLI surface is available. Commands run without an approval prompt; description records the GitHub-side result the command intends to produce. Declare exactly one repository in the configured GitHub organization: Connect mints the real token for only that repository, and the sandbox process receives only a placeholder GH_TOKEN that the firewall exchanges on matching GitHub requests. GitHub rejects access outside the token's server-side repository scope; commands that explicitly name another repository with -R, --repo, --repo=, or a repository argument to gh repo clone, view, or fork are denied before minting. Use simple argv quoting only, never environment assignments, pipes, redirects, substitutions, or other shell syntax. gh alias and extension commands may execute local code, but remain sandboxed. Use git here only for authenticated fetch, pull, push, or ls-remote against a strictly validated origin, and use gh-signed-commit only with --repo. Use ordinary bash for local git status, diff, add, commit, and rebase.";
|
|
3
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* The Connect-brokered `gh` tool, bound to one extension's GitHub config.
|
|
6
|
+
*
|
|
7
|
+
* Callbacks declare durable descriptors with empty closures: eve's transform
|
|
8
|
+
* would capture the `github` getter, which is not JSON, and imports through
|
|
9
|
+
* `eve/extensions/git/sandbox` are not transformed. The getter is boot-time
|
|
10
|
+
* wiring, not per-tool data; a fresh process reruns the dynamic resolver
|
|
11
|
+
* before replay, which binds a new getter.
|
|
12
|
+
*/
|
|
4
13
|
export declare function defineGhTool(github: () => GitHubConfig | undefined, description?: string): import("eve/tools").ToolDefinition<{
|
|
5
14
|
command: string;
|
|
6
15
|
permissions: {
|
|
@@ -25,5 +34,5 @@ export declare function defineGhTool(github: () => GitHubConfig | undefined, des
|
|
|
25
34
|
}[];
|
|
26
35
|
description: string;
|
|
27
36
|
workingDirectory?: string | undefined;
|
|
28
|
-
}, ctx:
|
|
37
|
+
}, ctx: ToolContext): Promise<import("./github-shell.ts").GitHubShellOutput>;
|
|
29
38
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{executeGitHubShell,githubShellApproval}from"./github-shell.js";import{githubShellInputSchema}from"./github-shell-schema.js";import{z}from"#compiled/zod/index.js";import{defineTool}from"eve/tools";const GH_TOOL_DESCRIPTION=`Run one authenticated GitHub command in the sandbox. The full gh CLI surface is available. Commands run without an approval prompt; description records the GitHub-side result the command intends to produce. Declare exactly one repository in the configured GitHub organization: Connect mints the real token for only that repository, and the sandbox process receives only a placeholder GH_TOKEN that the firewall exchanges on matching GitHub requests. GitHub rejects access outside the token's server-side repository scope; commands that explicitly name another repository with -R, --repo, --repo=, or a repository argument to gh repo clone, view, or fork are denied before minting. Use simple argv quoting only, never environment assignments, pipes, redirects, substitutions, or other shell syntax. gh alias and extension commands may execute local code, but remain sandboxed. Use git here only for authenticated fetch, pull, push, or ls-remote against a strictly validated origin, and use gh-signed-commit only with --repo. Use ordinary bash for local git status, diff, add, commit, and rebase
|
|
1
|
+
import{executeGitHubShell,githubShellApproval}from"./github-shell.js";import{githubShellInputSchema}from"./github-shell-schema.js";import{z}from"#compiled/zod/index.js";import{defineDurableCallback,defineDurableSchema,defineTool}from"eve/tools";const GH_TOOL_DESCRIPTION=`Run one authenticated GitHub command in the sandbox. The full gh CLI surface is available. Commands run without an approval prompt; description records the GitHub-side result the command intends to produce. Declare exactly one repository in the configured GitHub organization: Connect mints the real token for only that repository, and the sandbox process receives only a placeholder GH_TOKEN that the firewall exchanges on matching GitHub requests. GitHub rejects access outside the token's server-side repository scope; commands that explicitly name another repository with -R, --repo, --repo=, or a repository argument to gh repo clone, view, or fork are denied before minting. Use simple argv quoting only, never environment assignments, pipes, redirects, substitutions, or other shell syntax. gh alias and extension commands may execute local code, but remain sandboxed. Use git here only for authenticated fetch, pull, push, or ls-remote against a strictly validated origin, and use gh-signed-commit only with --repo. Use ordinary bash for local git status, diff, add, commit, and rebase.`,ghOutputSchema=z.object({exitCode:z.number().int(),stderr:z.string(),stdout:z.string(),truncated:z.boolean()});function defineGhTool(e,t=GH_TOOL_DESCRIPTION){return defineTool({description:t,approval:defineDurableCallback({closure:{},callback:(e,{toolInput:t})=>githubShellApproval(t)}),inputSchema:defineDurableSchema({closure:{},schema:()=>githubShellInputSchema}),outputSchema:defineDurableSchema({closure:{},schema:()=>ghOutputSchema}),execute:defineDurableCallback({closure:{},callback:(t,n,r)=>executeGitHubShell(n,e(),{context:r,auth:r.session.auth.current,getSandbox:()=>r.getSandbox(),sessionId:r.session.id})})})}export{GH_TOOL_DESCRIPTION,defineGhTool};
|
|
@@ -32,6 +32,9 @@ export declare function stageToolResultMedia<T extends ModelMessage>(messages: r
|
|
|
32
32
|
* decision is pure in the ref, so each message renders identically on every
|
|
33
33
|
* call and the provider's prompt cache stays valid. The returned messages
|
|
34
34
|
* must not be written back to session history, which stays ref-only.
|
|
35
|
+
*
|
|
36
|
+
* Resuming a sandbox is slow and can be billed, so it happens only when a
|
|
37
|
+
* ref needs bytes this process does not already hold for the session.
|
|
35
38
|
*/
|
|
36
39
|
export declare function hydrateSandboxAttachments(input: readonly ModelMessage[]): Promise<ModelMessage[]>;
|
|
37
40
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash}from"node:crypto";import{buildSessionHandle}from"#channel/session.js";import{createLogger}from"#internal/logging.js";import{getAdapterKind}from"#channel/adapter.js";import{contextStorage,loadContext}from"#context/container.js";import{SandboxKey}from"#context/keys.js";import{deserializeUrlFilePart,isSerializedUrlFilePart}from"#internal/attachments/url-refs.js";import{basename,dirname,extname}from"node:path";import{ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{createFrameworkUserMessage}from"#harness/messages.js";import{DEFAULT_UPLOAD_POLICY,isMediaTypeAllowed}from"#public/channels/upload-policy.js";import{buildAdapterContext}from"#channel/adapter-context.js";import{readMediaMetadata,verifyMediaType}from"#internal/attachments/media-metadata.js";import{decodeSandboxRef,encodeSandboxRef,inlinesSandboxRefAsBytes,isSandboxRefUrl}from"#internal/attachments/sandbox-refs.js";import{isUnresolvedFileData,readFileData}from"#internal/attachments/data.js";import{EveAttachmentError}from"#internal/attachments/errors.js";import{maxBytesOf}from"#internal/attachments/limited-read.js";import{createPublicDownloads}from"#internal/attachments/public-link.js";const log=createLogger(`harness.attachment-staging`),UNSAFE_FILENAME_CHARS=/[^\w.-]+/g,MEDIA_TYPE_EXTENSIONS={"application/pdf":`.pdf`,"image/gif":`.gif`,"image/jpeg":`.jpg`,"image/png":`.png`,"image/webp":`.webp`};async function stageAttachmentsForAdapter(e,t,n){if(typeof e==`string`)return e;let r=reconstitueFilePartUrls(e),i=n.ctx.get(ChannelKey)?.uploadPolicy,a=createPublicDownloads(maxBytesOf(i??DEFAULT_UPLOAD_POLICY));return Promise.all(r.map(async e=>e.type===`file`?stageFilePart(e,t,n,a,i):e))}async function stageAttachmentsToSandbox(e){if(typeof e==`string`||!Array.isArray(e)||!hasFileParts(e))return e;let t=loadContext(),n=await activeSandbox(t.get(SandboxKey));if(n===null)return e.map(e=>e.type===`file`&&!isSandboxRefUrl(e.data)&&readFileData(e.data).kind!==`reference`?attachmentNote(e,`could not be stored: no sandbox is available.`):e);let r=t.get(ChannelKey);return stageAttachmentsForAdapter(e,n,r?buildAdapterContext(r,t):{ctx:t,state:{},session:buildSessionHandle(t)})}async function stageToolResultMedia(e){if(!e.some(hasInlineToolResultFile))return[...e];let t=await activeSandbox(contextStorage.getStore()?.get(SandboxKey));return Promise.all(e.map(async e=>{if(e.role!==`tool`||!hasInlineToolResultFile(e))return e;let n=await Promise.all(e.content.map(async e=>e.type===`tool-result`?{...e,output:await stageToolOutputFiles(e.output,t)}:e));return{...e,content:n}}))}async function hydrateSandboxAttachments(e){let t=replaceUnresolvedFileParts(e);if(!messagesContainSandboxRef(t))return t;let n=loadContext().get(SandboxKey);if(n===void 0)throw Error(`Cannot hydrate sandbox-ref FilePart: no SandboxKey is bound on the active eve context. Hydration must run inside a step scope with the framework sandbox provider installed.`);let r=await activeSandbox(n);return Promise.all(t.map(async e=>{if(!messageContainsSandboxRef(e))return e;let t=await hydrateMessageContent(e.content,r);return{...e,content:t}}))}async function activeSandbox(e){if(e===void 0)return null;try{return await e.get()}catch(e){return log.warn(`session sandbox unavailable, degrading attachments to text`,{error:e}),null}}function replaceUnresolvedFileParts(e){let t=!1,n=e.map(e=>{if(e.role!==`user`||!Array.isArray(e.content)||!e.content.some(isUnresolvedFilePart))return e;t=!0;let n=e.content.map(e=>isUnresolvedFilePart(e)?attachmentNote(e,`could not be retrieved.`):e);return{...e,content:n}});return t?n:e}function isUnresolvedFilePart(e){return e.type===`file`&&!isSandboxRefUrl(e.data)&&isUnresolvedFileData(e.data)}function hasFileParts(e){for(let t of e)if(t.type===`file`)return!0;return!1}function messagesContainSandboxRef(e){for(let t of e)if(messageContainsSandboxRef(t))return!0;return!1}function messageContainsSandboxRef(e){let t=e.content;if(!Array.isArray(t))return!1;for(let e of t)if(isSandboxRefFilePart(e)||e.type===`tool-result`&&contentOutputParts(e.output).some(isToolOutputRefFile))return!0;return!1}function contentOutputParts(e){return e.type===`content`?e.value:[]}function hasInlineToolResultFile(e){return e.role===`tool`&&e.content.some(e=>e.type===`tool-result`&&contentOutputParts(e.output).some(isInlineToolOutputFile))}function isInlineToolOutputFile(e){return e.type===`file`&&e.data.type===`data`}function isToolOutputRefFile(e){return e.type===`file`&&e.data.type===`url`&&isSandboxRefUrl(e.data.url)}async function stageToolOutputFiles(e,t){if(e.type!==`content`||!e.value.some(isInlineToolOutputFile))return e;let n=await Promise.all(e.value.map(async e=>{if(!isInlineToolOutputFile(e)||e.data.type!==`data`)return e;let n=readFileData(e.data.data);if(n.kind===`link`)return e;if(t===null||n.kind!==`bytes`)return{text:`Returned file ${e.filename??`file`} (${e.mediaType}) could not be stored.`,type:`text`};let r=await writeSandboxRef(n.bytes,e.mediaType,e.filename,t);return{...e,data:{type:`url`,url:encodeSandboxRef(r)},mediaType:r.mediaType}}));return{...e,value:n}}function isSandboxRefFilePart(e){return typeof e==`object`&&!!e&&e.type===`file`&&isSandboxRefUrl(e.data)}async function hydrateMessageContent(e,t){return Array.isArray(e)?(await Promise.all(e.map(async e=>{if(isSandboxRefFilePart(e)){let n=decodeSandboxRef(e.data),r=renderSandboxRefAsTextPart(n);if(!inlinesSandboxRefAsBytes(n))return[r];let i=await readSandboxRefBytes(n,t);return i===null?[renderMissingSandboxRef(n)]:[r,{...e,data:i,mediaType:n.mediaType}]}if(e.type===`tool-result`){let n=e;return[{...n,output:await hydrateToolOutput(n.output,t)}]}return[e]}))).flat():e}async function hydrateToolOutput(e,t){if(e.type!==`content`||!e.value.some(isToolOutputRefFile))return e;let n=await Promise.all(e.value.map(async e=>{if(!isToolOutputRefFile(e)||e.data.type!==`url`)return[e];let n=decodeSandboxRef(e.data.url),r=renderSandboxRefAsTextPart(n);if(!inlinesSandboxRefAsBytes(n))return[r];let i=await readSandboxRefBytes(n,t);return i===null?[renderMissingSandboxRef(n)]:[r,{...e,data:{data:Buffer.from(i).toString(`base64`),type:`data`}}]}));return{...e,value:n.flat()}}async function readSandboxRefBytes(e,t){if(t===null)return null;let n=await t.readBinaryFile({path:e.path});return n===null?(log.warn(`sandbox-ref attachment bytes missing on hydration — degrading to text reference`,{mediaType:e.mediaType,path:e.path,size:e.size}),null):n.byteLength!==e.size||sha256Prefix(n)!==basename(dirname(e.path))?(log.warn(`sandbox-ref attachment bytes changed since staging — degrading to text reference`,{mediaType:e.mediaType,path:e.path,size:e.size}),null):n}function renderMissingSandboxRef(e){return{text:`FileNotFound: Current snapshot may be newer and does not contain ${e.path}.`,type:`text`}}function moveToolResultFilesToUserMessages(e){let t=[],n=[];for(let r of e){if(r.role!==`tool`&&n.length>0&&(t.push(createReturnedFilesMessage(n)),n=[]),r.role!==`tool`){t.push(r);continue}let e=r.content.map(e=>{if(e.type!==`tool-result`||e.output.type!==`content`)return e;let t=e.output.value.map(e=>{if(e.type!==`file`)return e;let t={data:e.data,mediaType:e.mediaType,type:`file`};return e.filename!==void 0&&(t.filename=e.filename),n.push(t),{text:`Attached file ${e.filename??`file`} (${e.mediaType}) follows this tool result.`,type:`text`}});return{...e,output:{...e.output,value:t}}});t.push({...r,content:e})}return n.length>0&&t.push(createReturnedFilesMessage(n)),t}function createReturnedFilesMessage(e){return createFrameworkUserMessage(`context.state`,[{text:`Files returned by the preceding tool results:`,type:`text`},...e])}function renderSandboxRefAsTextPart(e){return{text:`Attached file ${e.path} (${e.mediaType})`,type:`text`}}async function stageFilePart(e,t,n,r,i){if(isSandboxRefUrl(e.data))return e;let a=readFileData(e.data);if(a.kind===`bytes`)return stageResolvedBytes(e,{bytes:a.bytes},t,i);if(a.kind===`reference`)return e;if(a.kind===`unreadable`)return log.warn(`attachment data is not bytes, base64, or a URL — degrading to text part`,{filename:e.filename,mediaType:e.mediaType}),attachmentNote(e,`could not be read.`);let o;try{o=await resolveLink(a.url,n,r)}catch(t){if(!(t instanceof EveAttachmentError))throw t;return log.warn(`attachment resolver failed — degrading to text part`,{adapterKind:t.adapterKind,error:t.cause,filename:e.filename,kind:t.kind}),attachmentNote(e,`could not be retrieved: ${t.message}`)}return stageResolvedBytes(e,o,t,i)}function attachmentNote(e,t){return{text:`Attachment ${e.filename?.trim()||`file`} ${t}`,type:`text`}}async function stageResolvedBytes(e,t,n,r){let i=verifyMediaType(t.bytes,t.mediaType??e.mediaType??`application/octet-stream`);if(r!==void 0){let n=maxBytesOf(r);if(t.bytes.byteLength>n)return attachmentNote(e,`was not accepted: it is ${t.bytes.byteLength} bytes, over this channel's ${n}-byte upload limit.`);if(!isMediaTypeAllowed(i,r))return attachmentNote(e,`was not accepted: this channel doesn't accept ${i} files.`)}let a=await writeSandboxRef(t.bytes,i,t.filename??e.filename,n);return{...e,data:encodeSandboxRef(a),filename:a.path,mediaType:a.mediaType}}async function writeSandboxRef(e,t,n,r){let i=verifyMediaType(e,t),a=sha256Prefix(e),o=`.eve/attachments/${a}/${safeFilename(n,a,i)}`;return await r.writeBinaryFile({content:e,path:o}),{...readMediaMetadata(e,i),path:r.resolvePath(o)}}async function resolveLink(e,t,n){let r=t.ctx.get(ChannelKey),i=r===void 0?`none`:getAdapterKind(r);if(r?.fetchFile!==void 0){let n;try{n=await r.fetchFile(e.href,t)}catch(e){throw e instanceof EveAttachmentError?new EveAttachmentError({adapterKind:i,cause:e.cause,kind:e.kind,message:e.message}):new EveAttachmentError({adapterKind:i,cause:e,kind:`resolver-threw`,message:`Attachment retrieval failed in the "${i}" channel.`})}if(n!==null)return Buffer.isBuffer(n)?{bytes:n}:n}return n(e,i)}function reconstitueFilePartUrls(e){let t=!1,n=e.map(e=>e.type===`file`&&isSerializedUrlFilePart(e.data)?(t=!0,{...e,data:deserializeUrlFilePart(e.data)}):e);return t?n:e}function sha256Prefix(e){return createHash(`sha256`).update(e).digest(`hex`).slice(0,16)}function safeFilename(e,t,n){let r=e===void 0?``:basename(e).replace(UNSAFE_FILENAME_CHARS,`_`),i=r.length>0?r:`file-${t}`,a=MEDIA_TYPE_EXTENSIONS[n];return a===void 0||extname(i)!==``?i:`${i}${a}`}export{hydrateSandboxAttachments,moveToolResultFilesToUserMessages,stageAttachmentsForAdapter,stageAttachmentsToSandbox,stageToolResultMedia};
|
|
1
|
+
import{createHash}from"node:crypto";import{buildSessionHandle}from"#channel/session.js";import{createLogger}from"#internal/logging.js";import{getAdapterKind}from"#channel/adapter.js";import{contextStorage,loadContext}from"#context/container.js";import{SandboxKey,SessionIdKey}from"#context/keys.js";import{deserializeUrlFilePart,isSerializedUrlFilePart}from"#internal/attachments/url-refs.js";import{basename,dirname,extname}from"node:path";import{ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{createFrameworkUserMessage}from"#harness/messages.js";import{DEFAULT_UPLOAD_POLICY,isMediaTypeAllowed}from"#public/channels/upload-policy.js";import{buildAdapterContext}from"#channel/adapter-context.js";import{verifyMediaType}from"#internal/attachments/media-metadata.js";import{readMediaMetadata}from"#internal/attachments/read-media-metadata.js";import{decodeSandboxRef,encodeSandboxRef,inlinesSandboxRefAsBytes,isSandboxRefUrl}from"#internal/attachments/sandbox-refs.js";import{isUnresolvedFileData,readFileData}from"#internal/attachments/data.js";import{EveAttachmentError}from"#internal/attachments/errors.js";import{maxBytesOf}from"#internal/attachments/limited-read.js";import{createPublicDownloads}from"#internal/attachments/public-link.js";const log=createLogger(`harness.attachment-staging`),UNSAFE_FILENAME_CHARS=/[^\w.-]+/g,CACHED_REF_BYTES_LIMIT=67108864,cachedRefBytes=new Map;let cachedRefBytesTotal=0;const MEDIA_TYPE_EXTENSIONS={"application/pdf":`.pdf`,"image/gif":`.gif`,"image/jpeg":`.jpg`,"image/png":`.png`,"image/webp":`.webp`};async function stageAttachmentsForAdapter(e,t,n){if(typeof e==`string`)return e;let r=reconstitueFilePartUrls(e),i=n.ctx.get(ChannelKey)?.uploadPolicy,a=createPublicDownloads(maxBytesOf(i??DEFAULT_UPLOAD_POLICY));return Promise.all(r.map(async e=>e.type===`file`?stageFilePart(e,t,n,a,i):e))}async function stageAttachmentsToSandbox(e){if(typeof e==`string`||!Array.isArray(e)||!hasFileParts(e))return e;let t=loadContext(),n=await activeSandbox(t.get(SandboxKey));if(n===null)return e.map(e=>e.type===`file`&&!isSandboxRefUrl(e.data)&&readFileData(e.data).kind!==`reference`?attachmentNote(e,`could not be stored: no sandbox is available.`):e);let r=t.get(ChannelKey);return stageAttachmentsForAdapter(e,n,r?buildAdapterContext(r,t):{ctx:t,state:{},session:buildSessionHandle(t)})}async function stageToolResultMedia(e){if(!e.some(hasInlineToolResultFile))return[...e];let t=await activeSandbox(contextStorage.getStore()?.get(SandboxKey));return Promise.all(e.map(async e=>{if(e.role!==`tool`||!hasInlineToolResultFile(e))return e;let n=await Promise.all(e.content.map(async e=>e.type===`tool-result`?{...e,output:await stageToolOutputFiles(e.output,t)}:e));return{...e,content:n}}))}async function hydrateSandboxAttachments(e){let t=replaceUnresolvedFileParts(e);if(!messagesContainSandboxRef(t))return t;let n=loadContext(),r=sandboxRefReader(n.get(SandboxKey),n.get(SessionIdKey));return Promise.all(t.map(async e=>{if(!messageContainsSandboxRef(e))return e;let t=await hydrateMessageContent(e.content,r);return{...e,content:t}}))}function sandboxRefReader(e,t){let n;return async r=>{let i=cacheKey(t,r),a=i===void 0?void 0:readCachedRefBytes(i);if(a!==void 0)return a;if(e===void 0)throw Error(`Cannot hydrate attachment ${r.path}: no SandboxKey is bound on the active eve context. Hydration must run inside a step scope with the framework sandbox provider installed.`);n??=activeSandbox(e);let o=await readSandboxRefBytes(r,await n);return o!==null&&i!==void 0&&cacheRefBytes(i,o),o}}function cacheKey(e,t){if(e!==void 0)return JSON.stringify([e,t.path,t.size,t.mediaType])}function readCachedRefBytes(e){let t=cachedRefBytes.get(e);return t!==void 0&&(cachedRefBytes.delete(e),cachedRefBytes.set(e,t)),t}function cacheRefBytes(e,t){if(!(t.byteLength>CACHED_REF_BYTES_LIMIT||cachedRefBytes.has(e))){cachedRefBytes.set(e,Buffer.from(t)),cachedRefBytesTotal+=t.byteLength;for(let[e,t]of cachedRefBytes){if(cachedRefBytesTotal<=CACHED_REF_BYTES_LIMIT)break;cachedRefBytes.delete(e),cachedRefBytesTotal-=t.byteLength}}}async function activeSandbox(e){if(e===void 0)return null;try{return await e.open()}catch(e){return log.warn(`session sandbox unavailable, degrading attachments to text`,{error:e}),null}}function replaceUnresolvedFileParts(e){let t=!1,n=e.map(e=>{if(e.role!==`user`||!Array.isArray(e.content)||!e.content.some(isUnresolvedFilePart))return e;t=!0;let n=e.content.map(e=>isUnresolvedFilePart(e)?attachmentNote(e,`could not be retrieved.`):e);return{...e,content:n}});return t?n:e}function isUnresolvedFilePart(e){return e.type===`file`&&!isSandboxRefUrl(e.data)&&isUnresolvedFileData(e.data)}function hasFileParts(e){for(let t of e)if(t.type===`file`)return!0;return!1}function messagesContainSandboxRef(e){for(let t of e)if(messageContainsSandboxRef(t))return!0;return!1}function messageContainsSandboxRef(e){let t=e.content;if(!Array.isArray(t))return!1;for(let e of t)if(isSandboxRefFilePart(e)||e.type===`tool-result`&&contentOutputParts(e.output).some(isToolOutputRefFile))return!0;return!1}function contentOutputParts(e){return e.type===`content`?e.value:[]}function hasInlineToolResultFile(e){return e.role===`tool`&&e.content.some(e=>e.type===`tool-result`&&contentOutputParts(e.output).some(isInlineToolOutputFile))}function isInlineToolOutputFile(e){return e.type===`file`&&e.data.type===`data`}function isToolOutputRefFile(e){return e.type===`file`&&e.data.type===`url`&&isSandboxRefUrl(e.data.url)}async function stageToolOutputFiles(e,t){if(e.type!==`content`||!e.value.some(isInlineToolOutputFile))return e;let n=await Promise.all(e.value.map(async e=>{if(!isInlineToolOutputFile(e)||e.data.type!==`data`)return e;let n=readFileData(e.data.data);if(n.kind===`link`)return e;if(t===null||n.kind!==`bytes`)return{text:`Returned file ${e.filename??`file`} (${e.mediaType}) could not be stored.`,type:`text`};let r=await writeSandboxRef(n.bytes,e.mediaType,e.filename,t);return{...e,data:{type:`url`,url:encodeSandboxRef(r)},mediaType:r.mediaType}}));return{...e,value:n}}function isSandboxRefFilePart(e){return typeof e==`object`&&!!e&&e.type===`file`&&isSandboxRefUrl(e.data)}async function hydrateMessageContent(e,t){return Array.isArray(e)?(await Promise.all(e.map(async e=>{if(isSandboxRefFilePart(e)){let n=decodeSandboxRef(e.data),r=renderSandboxRefAsTextPart(n);if(!inlinesSandboxRefAsBytes(n))return[r];let i=await t(n);return i===null?[renderMissingSandboxRef(n)]:[r,{...e,data:i,mediaType:n.mediaType}]}if(e.type===`tool-result`){let n=e;return[{...n,output:await hydrateToolOutput(n.output,t)}]}return[e]}))).flat():e}async function hydrateToolOutput(e,t){if(e.type!==`content`||!e.value.some(isToolOutputRefFile))return e;let n=await Promise.all(e.value.map(async e=>{if(!isToolOutputRefFile(e)||e.data.type!==`url`)return[e];let n=decodeSandboxRef(e.data.url),r=renderSandboxRefAsTextPart(n);if(!inlinesSandboxRefAsBytes(n))return[r];let i=await t(n);return i===null?[renderMissingSandboxRef(n)]:[r,{...e,data:{data:Buffer.from(i).toString(`base64`),type:`data`}}]}));return{...e,value:n.flat()}}async function readSandboxRefBytes(e,t){if(t===null)return null;let n=await t.readBinaryFile({path:e.path});return n===null?(log.warn(`sandbox-ref attachment bytes missing on hydration — degrading to text reference`,{mediaType:e.mediaType,path:e.path,size:e.size}),null):n.byteLength!==e.size||sha256Prefix(n)!==basename(dirname(e.path))?(log.warn(`sandbox-ref attachment bytes changed since staging — degrading to text reference`,{mediaType:e.mediaType,path:e.path,size:e.size}),null):n}function renderMissingSandboxRef(e){return{text:`FileNotFound: Current snapshot may be newer and does not contain ${e.path}.`,type:`text`}}function moveToolResultFilesToUserMessages(e){let t=[],n=[];for(let r of e){if(r.role!==`tool`&&n.length>0&&(t.push(createReturnedFilesMessage(n)),n=[]),r.role!==`tool`){t.push(r);continue}let e=r.content.map(e=>{if(e.type!==`tool-result`||e.output.type!==`content`)return e;let t=e.output.value.map(e=>{if(e.type!==`file`)return e;let t={data:e.data,mediaType:e.mediaType,type:`file`};return e.filename!==void 0&&(t.filename=e.filename),n.push(t),{text:`Attached file ${e.filename??`file`} (${e.mediaType}) follows this tool result.`,type:`text`}});return{...e,output:{...e.output,value:t}}});t.push({...r,content:e})}return n.length>0&&t.push(createReturnedFilesMessage(n)),t}function createReturnedFilesMessage(e){return createFrameworkUserMessage(`context.state`,[{text:`Files returned by the preceding tool results:`,type:`text`},...e])}function renderSandboxRefAsTextPart(e){return{text:`Attached file ${e.path} (${e.mediaType})`,type:`text`}}async function stageFilePart(e,t,n,r,i){if(isSandboxRefUrl(e.data))return e;let a=readFileData(e.data);if(a.kind===`bytes`)return stageResolvedBytes(e,{bytes:a.bytes},t,i);if(a.kind===`reference`)return e;if(a.kind===`unreadable`)return log.warn(`attachment data is not bytes, base64, or a URL — degrading to text part`,{filename:e.filename,mediaType:e.mediaType}),attachmentNote(e,`could not be read.`);let o;try{o=await resolveLink(a.url,n,r)}catch(t){if(!(t instanceof EveAttachmentError))throw t;return log.warn(`attachment resolver failed — degrading to text part`,{adapterKind:t.adapterKind,error:t.cause,filename:e.filename,kind:t.kind}),attachmentNote(e,`could not be retrieved: ${t.message}`)}return stageResolvedBytes(e,o,t,i)}function attachmentNote(e,t){return{text:`Attachment ${e.filename?.trim()||`file`} ${t}`,type:`text`}}async function stageResolvedBytes(e,t,n,r){let i=verifyMediaType(t.bytes,t.mediaType??e.mediaType??`application/octet-stream`);if(r!==void 0){let n=maxBytesOf(r);if(t.bytes.byteLength>n)return attachmentNote(e,`was not accepted: it is ${t.bytes.byteLength} bytes, over this channel's ${n}-byte upload limit.`);if(!isMediaTypeAllowed(i,r))return attachmentNote(e,`was not accepted: this channel doesn't accept ${i} files.`)}let a=await writeSandboxRef(t.bytes,i,t.filename??e.filename,n);return{...e,data:encodeSandboxRef(a),filename:a.path,mediaType:a.mediaType}}async function writeSandboxRef(e,t,n,r){let i=verifyMediaType(e,t),a=sha256Prefix(e),o=`.eve/attachments/${a}/${safeFilename(n,a,i)}`;await r.writeBinaryFile({content:e,path:o});let s={...readMediaMetadata(e,i),path:r.resolvePath(o)},c=cacheKey(contextStorage.getStore()?.get(SessionIdKey),s);return c!==void 0&&inlinesSandboxRefAsBytes(s)&&cacheRefBytes(c,e),s}async function resolveLink(e,t,n){let r=t.ctx.get(ChannelKey),i=r===void 0?`none`:getAdapterKind(r);if(r?.fetchFile!==void 0){let n;try{n=await r.fetchFile(e.href,t)}catch(e){throw e instanceof EveAttachmentError?new EveAttachmentError({adapterKind:i,cause:e.cause,kind:e.kind,message:e.message}):new EveAttachmentError({adapterKind:i,cause:e,kind:`resolver-threw`,message:`Attachment retrieval failed in the "${i}" channel.`})}if(n!==null)return Buffer.isBuffer(n)?{bytes:n}:n}return n(e,i)}function reconstitueFilePartUrls(e){let t=!1,n=e.map(e=>e.type===`file`&&isSerializedUrlFilePart(e.data)?(t=!0,{...e,data:deserializeUrlFilePart(e.data)}):e);return t?n:e}function sha256Prefix(e){return createHash(`sha256`).update(e).digest(`hex`).slice(0,16)}function safeFilename(e,t,n){let r=e===void 0?``:basename(e).replace(UNSAFE_FILENAME_CHARS,`_`),i=r.length>0?r:`file-${t}`,a=MEDIA_TYPE_EXTENSIONS[n];return a===void 0||extname(i)!==``?i:`${i}${a}`}export{hydrateSandboxAttachments,moveToolResultFilesToUserMessages,stageAttachmentsForAdapter,stageAttachmentsToSandbox,stageToolResultMedia};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type LanguageModel, type TelemetryOptions } from "ai";
|
|
1
|
+
import { type LanguageModel, type ModelMessage, type TelemetryOptions } from "ai";
|
|
2
2
|
import { type HarnessSession, type StepResult, type ToolLoopHarnessConfig } from "#harness/types.js";
|
|
3
3
|
import { type HarnessModelMessage } from "#harness/messages.js";
|
|
4
4
|
import type { HistoryViewProjector } from "#shared/history-view.js";
|
|
@@ -51,3 +51,9 @@ export declare function maybeCompact(input: {
|
|
|
51
51
|
readonly messages: HarnessModelMessage[];
|
|
52
52
|
readonly session: HarnessSession;
|
|
53
53
|
}>;
|
|
54
|
+
/**
|
|
55
|
+
* Where a compaction during a turn leaves the turn's input: its latest user message, or that
|
|
56
|
+
* message's replay. What the framework adds for the turn goes before it, as on the turn's first
|
|
57
|
+
* step.
|
|
58
|
+
*/
|
|
59
|
+
export declare function compactedTurnInput<Message extends ModelMessage>(messages: readonly Message[]): Message | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{streamText}from"ai";import{createLogger,logError}from"#internal/logging.js";import{contextStorage}from"#context/container.js";import{AuthKey,HistoryStateKey}from"#context/keys.js";import{createCompactionCompletedEvent,createCompactionRequestedEvent}from"#protocol/message.js";import{isUserModelMessage,validateHarnessModelMessages}from"#harness/messages.js";import{drainMemoryCommit,prepareMemoryCompaction}from"#context/memory-lifecycle.js";import{canonicalizeMemoryRecords,shouldCanonicalizeMemory}from"#shared/memory-state.js";import{activeTurnId}from"#harness/session-machine/view.js";import{addTurnUsage,addUsageOutsideTurns}from"#harness/turn-tag-state.js";import{idle}from"#harness/session-machine/transitions.js";import{stepStartedForResolvers}from"#harness/session-machine/resolver-events.js";import{requireSessionModelReference}from"#harness/types.js";import{buildGatewayAttributionHeaders,resolveEffectiveRuntimeModel,withGatewayTraceContext}from"#harness/model-call/model.js";import{compactMessages,getInputTokenCount,shouldCompact}from"#harness/compaction/engine.js";import{normalizeModelStreamError}from"#harness/model-call/errors.js";import{runModelCallWithRetries}from"#harness/model-call/retry.js";import{extractGatewayCostUsd,extractTokenUsageDelta,gatewayModelId}from"#harness/model-call/usage.js";import{resolveModelProfile}from"#harness/model-profile.js";import{getRequestEnvelopeTokens}from"#harness/request-envelope.js";import{resolveCallProviderOptions}from"#harness/provider-safety.js";const log=createLogger(`harness.tool-loop`);async function compactHistory(e){let{config:t}=e;if(e.session.history.length>0)try{if(e.ctx!==void 0&&t.dispatchDynamicModelEvent!==void 0){let n=e.position();await t.dispatchDynamicModelEvent({ctx:e.ctx,event:stepStartedForResolvers({modelId:e.session.agent.modelReference?.id??`dynamic`,sequence:n.sequence,stepIndex:n.stepIndex,turnId:activeTurnId(n)}),messages:validateHarnessModelMessages(e.projectHistory(e.session.history))})}let n=await resolveEffectiveRuntimeModel({config:t,ctx:e.ctx,session:e.session});e.session=n.session;let r=e.position(),i=await maybeCompact({abortSignal:t.abortSignal,auth:e.ctx?.get(AuthKey)??null,betweenTurns:!0,emissionState:{...r,turnId:activeTurnId(r)},force:!0,historyProjector:t.historyProjector,messages:[...e.session.history],model:n.model,publish:e.publish,requestEnvelopeTokens:getRequestEnvelopeTokens(e.session),resolveModel:t.resolveModel,runtimeIdentity:t.runtimeIdentity,session:e.session,telemetry:e.instrumentation?.telemetry(),traceContextHeaders:e.instrumentation?.gatewayTraceContextHeaders});if(e.session=i.session,i.failure!==void 0)throw i.failure.error}catch(t){logError(log,`manual session compaction failed`,t,{sessionId:e.session.sessionId})}return await e.apply(idle(e.view())),{next:null,session:e.session}}function replaceSessionHistory(e,t){return contextStorage.getStore()?.delete(HistoryStateKey),{...e,history:t,compaction:{recentWindowSize:e.compaction.recentWindowSize,threshold:e.compaction.threshold,thresholdPercent:e.compaction.thresholdPercent}}}async function maybeCompact(e){let{emissionState:t,publish:n}=e,r=e.messages,i=e.session,a=e.promptMessages??r,o=validateHarnessModelMessages(e.historyProjector?.({messages:a,state:i.state})??a),s=e.force===!0||shouldCompact(o,i.compaction,e.requestEnvelopeTokens,getRequestEnvelopeTokens(i)),c=shouldCanonicalizeMemory(r);if(!s&&!c)return{compacted:!1,messages:r,session:i};let l=requireSessionModelReference(i),u=i.agent.compactionModelReference??l,d=u===l?e.model:await e.resolveModel(u),f=resolveModelProfile(d),p=resolveCallProviderOptions({auth:e.auth,profile:f,providerOptions:u.providerOptions,session:i}),m={abortSignal:e.abortSignal,headers:buildGatewayAttributionHeaders(f,e.runtimeIdentity),model:withGatewayTraceContext(d,f,e.traceContextHeaders),providerOptions:p,telemetry:e.telemetry&&{...e.telemetry,functionId:`eve.compaction`}},h=[],summarize=async n=>{let r=await runModelCallWithRetries(()=>streamCompactionSummary({...m,...n}),{sessionId:i.sessionId,turnId:t.turnId},e.abortSignal);if(h.push(r.usage),r.text.trim().length===0)throw Error(`The compaction model returned an empty summary. Finish reason: ${r.finishReason}.`);return r.text};{let a=contextStorage.getStore();a!==void 0&&prepareMemoryCompaction(a,{history:r,state:i.state}),await n(createCompactionRequestedEvent({modelId:gatewayModelId(d)??`unknown`,sequence:t.sequence,sessionId:i.sessionId,stepIndex:t.stepIndex,turnId:t.turnId,usageInputTokens:getInputTokenCount(o,i.compaction,e.requestEnvelopeTokens,getRequestEnvelopeTokens(i))}),o)}let g=canonicalizeMemoryRecords(r),_=validateHarnessModelMessages(e.historyProjector?.({messages:g.ordinary,state:i.state})??g.ordinary),v=e.requestEnvelopeTokens??0,y={...i.compaction,threshold:Math.max(1,i.compaction.threshold-v),lastKnownInputTokens:i.compaction.lastKnownInputTokens===void 0?void 0:Math.max(0,i.compaction.lastKnownInputTokens-Math.min(getRequestEnvelopeTokens(i)??0,v))},b=[..._],x;try{s&&(b=await compactMessages([..._],y,summarize,e.force===!0,e.requestEnvelopeTokens===void 0?void 0:Math.max(0,getInputTokenCount(o,i.compaction,v,getRequestEnvelopeTokens(i))-v)))}catch(e){x={error:e}}for(let n of h)i=e.betweenTurns===!0?addUsageOutsideTurns(i,n):addTurnUsage(i,t.turnId,n);if(x!==void 0)return{compacted:!1,failure:x,messages:e.messages,session:i};r=validateHarnessModelMessages([...g.memory,...b]);{let a=contextStorage.getStore();if(a!==void 0&&prepareMemoryCompaction(a,{history:r,state:i.state}),await n(createCompactionCompletedEvent({modelId:gatewayModelId(d)??`unknown`,sequence:t.sequence,sessionId:i.sessionId,stepIndex:t.stepIndex,turnId:t.turnId}),e.historyProjector?.({messages:r,state:i.state})??r),a!==void 0){let t=drainMemoryCommit(a);t!==void 0&&(r=validateHarnessModelMessages(placeRecalledMemory(r,t.recalledMessages,e.betweenTurns===!0)),i={...i,state:t.state})}}return{compacted:!0,messages:r,session:replaceSessionHistory(i,r)}}function
|
|
1
|
+
import{streamText}from"ai";import{createLogger,logError}from"#internal/logging.js";import{contextStorage}from"#context/container.js";import{AuthKey,HistoryStateKey}from"#context/keys.js";import{createCompactionCompletedEvent,createCompactionRequestedEvent}from"#protocol/message.js";import{isUserModelMessage,validateHarnessModelMessages}from"#harness/messages.js";import{drainMemoryCommit,prepareMemoryCompaction}from"#context/memory-lifecycle.js";import{canonicalizeMemoryRecords,shouldCanonicalizeMemory}from"#shared/memory-state.js";import{activeTurnId}from"#harness/session-machine/view.js";import{addTurnUsage,addUsageOutsideTurns}from"#harness/turn-tag-state.js";import{idle}from"#harness/session-machine/transitions.js";import{stepStartedForResolvers}from"#harness/session-machine/resolver-events.js";import{requireSessionModelReference}from"#harness/types.js";import{buildGatewayAttributionHeaders,resolveEffectiveRuntimeModel,withGatewayTraceContext}from"#harness/model-call/model.js";import{compactMessages,getInputTokenCount,shouldCompact}from"#harness/compaction/engine.js";import{normalizeModelStreamError}from"#harness/model-call/errors.js";import{runModelCallWithRetries}from"#harness/model-call/retry.js";import{extractGatewayCostUsd,extractTokenUsageDelta,gatewayModelId}from"#harness/model-call/usage.js";import{resolveModelProfile}from"#harness/model-profile.js";import{getRequestEnvelopeTokens}from"#harness/request-envelope.js";import{resolveCallProviderOptions}from"#harness/provider-safety.js";const log=createLogger(`harness.tool-loop`);async function compactHistory(e){let{config:t}=e;if(e.session.history.length>0)try{if(e.ctx!==void 0&&t.dispatchDynamicModelEvent!==void 0){let n=e.position();await t.dispatchDynamicModelEvent({ctx:e.ctx,event:stepStartedForResolvers({modelId:e.session.agent.modelReference?.id??`dynamic`,sequence:n.sequence,stepIndex:n.stepIndex,turnId:activeTurnId(n)}),messages:validateHarnessModelMessages(e.projectHistory(e.session.history))})}let n=await resolveEffectiveRuntimeModel({config:t,ctx:e.ctx,session:e.session});e.session=n.session;let r=e.position(),i=await maybeCompact({abortSignal:t.abortSignal,auth:e.ctx?.get(AuthKey)??null,betweenTurns:!0,emissionState:{...r,turnId:activeTurnId(r)},force:!0,historyProjector:t.historyProjector,messages:[...e.session.history],model:n.model,publish:e.publish,requestEnvelopeTokens:getRequestEnvelopeTokens(e.session),resolveModel:t.resolveModel,runtimeIdentity:t.runtimeIdentity,session:e.session,telemetry:e.instrumentation?.telemetry(),traceContextHeaders:e.instrumentation?.gatewayTraceContextHeaders});if(e.session=i.session,i.failure!==void 0)throw i.failure.error}catch(t){logError(log,`manual session compaction failed`,t,{sessionId:e.session.sessionId})}return await e.apply(idle(e.view())),{next:null,session:e.session}}function replaceSessionHistory(e,t){return contextStorage.getStore()?.delete(HistoryStateKey),{...e,history:t,compaction:{recentWindowSize:e.compaction.recentWindowSize,threshold:e.compaction.threshold,thresholdPercent:e.compaction.thresholdPercent}}}async function maybeCompact(e){let{emissionState:t,publish:n}=e,r=e.messages,i=e.session,a=e.promptMessages??r,o=validateHarnessModelMessages(e.historyProjector?.({messages:a,state:i.state})??a),s=e.force===!0||shouldCompact(o,i.compaction,e.requestEnvelopeTokens,getRequestEnvelopeTokens(i)),c=shouldCanonicalizeMemory(r);if(!s&&!c)return{compacted:!1,messages:r,session:i};let l=requireSessionModelReference(i),u=i.agent.compactionModelReference??l,d=u===l?e.model:await e.resolveModel(u),f=resolveModelProfile(d),p=resolveCallProviderOptions({auth:e.auth,profile:f,providerOptions:u.providerOptions,session:i}),m={abortSignal:e.abortSignal,headers:buildGatewayAttributionHeaders(f,e.runtimeIdentity),model:withGatewayTraceContext(d,f,e.traceContextHeaders),providerOptions:p,telemetry:e.telemetry&&{...e.telemetry,functionId:`eve.compaction`}},h=[],summarize=async n=>{let r=await runModelCallWithRetries(()=>streamCompactionSummary({...m,...n}),{sessionId:i.sessionId,turnId:t.turnId},e.abortSignal);if(h.push(r.usage),r.text.trim().length===0)throw Error(`The compaction model returned an empty summary. Finish reason: ${r.finishReason}.`);return r.text};{let a=contextStorage.getStore();a!==void 0&&prepareMemoryCompaction(a,{history:r,state:i.state}),await n(createCompactionRequestedEvent({modelId:gatewayModelId(d)??`unknown`,sequence:t.sequence,sessionId:i.sessionId,stepIndex:t.stepIndex,turnId:t.turnId,usageInputTokens:getInputTokenCount(o,i.compaction,e.requestEnvelopeTokens,getRequestEnvelopeTokens(i))}),o)}let g=canonicalizeMemoryRecords(r),_=validateHarnessModelMessages(e.historyProjector?.({messages:g.ordinary,state:i.state})??g.ordinary),v=e.requestEnvelopeTokens??0,y={...i.compaction,threshold:Math.max(1,i.compaction.threshold-v),lastKnownInputTokens:i.compaction.lastKnownInputTokens===void 0?void 0:Math.max(0,i.compaction.lastKnownInputTokens-Math.min(getRequestEnvelopeTokens(i)??0,v))},b=[..._],x;try{s&&(b=await compactMessages([..._],y,summarize,e.force===!0,e.requestEnvelopeTokens===void 0?void 0:Math.max(0,getInputTokenCount(o,i.compaction,v,getRequestEnvelopeTokens(i))-v)))}catch(e){x={error:e}}for(let n of h)i=e.betweenTurns===!0?addUsageOutsideTurns(i,n):addTurnUsage(i,t.turnId,n);if(x!==void 0)return{compacted:!1,failure:x,messages:e.messages,session:i};r=validateHarnessModelMessages([...g.memory,...b]);{let a=contextStorage.getStore();if(a!==void 0&&prepareMemoryCompaction(a,{history:r,state:i.state}),await n(createCompactionCompletedEvent({modelId:gatewayModelId(d)??`unknown`,sequence:t.sequence,sessionId:i.sessionId,stepIndex:t.stepIndex,turnId:t.turnId}),e.historyProjector?.({messages:r,state:i.state})??r),a!==void 0){let t=drainMemoryCommit(a);t!==void 0&&(r=validateHarnessModelMessages(placeRecalledMemory(r,t.recalledMessages,e.betweenTurns===!0)),i={...i,state:t.state})}}return{compacted:!0,messages:r,session:replaceSessionHistory(i,r)}}function compactedTurnInput(e){return e.findLast(e=>isUserModelMessage(e)&&e.kind===`user`)}function placeRecalledMemory(e,t,n){let r=n?void 0:compactedTurnInput(e);if(r===void 0)return[...e,...t];let i=e.indexOf(r);return[...e.slice(0,i),...t,...e.slice(i)]}async function streamCompactionSummary(e){let t=streamText({...e,onError:()=>{}});for await(let e of t.fullStream)if(e.type===`error`)throw normalizeModelStreamError(e.error);let[n,r,i,a]=await Promise.all([t.text,t.finishReason,t.usage,t.providerMetadata]);return{finishReason:r,text:n,usage:extractTokenUsageDelta({costUsd:extractGatewayCostUsd(a),usage:i})}}export{compactHistory,compactedTurnInput,maybeCompact,replaceSessionHistory};
|
|
@@ -73,6 +73,8 @@ export declare function answer(view: SessionView, input: {
|
|
|
73
73
|
readonly policy: ResponsePolicyPass;
|
|
74
74
|
/** The delivery merged the queue in, so the queue empties. */
|
|
75
75
|
readonly takeQueued: boolean;
|
|
76
|
+
/** False when no message answers by text; see `ToolLoopHarnessConfig.typedAnswers`. */
|
|
77
|
+
readonly typedAnswers?: boolean;
|
|
76
78
|
readonly approvalKey: (request: InputRequest) => string | undefined;
|
|
77
79
|
/**
|
|
78
80
|
* Whether the request's restored step has `eve__search`, which a call whose
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{signInAttemptKey,supersededChallenges,withSignIns}from"./sign-ins.js";import{canonicalize,compactInput,isEmptyInput,resolveTextInput,withoutResponses}from"./delivery.js";import{openInputs,turnCoordinates}from"#protocol/session-projection.js";import{readClientContext}from"#internal/client-context.js";import{createActionResultEvent,createApprovalCandidateEvent,createApprovalSettledEvent,createAuthorizationCompletedEvent,createAuthorizationRequiredEvent,createInputRequestedEvent,createInputResolvedEvent,createMessageCompletedEvent}from"#protocol/message.js";import{coalesceTurnInputs,createFrameworkUserMessage}from"#harness/messages.js";import{turnPosition}from"#harness/session-machine/view.js";import{renderPendingApprovalsSnippet}from"#harness/hitl/approval-prompt.js";import{awaitSignIns,hold,ownOpenRequestIds,runnableCalls,settle,stepCallIds,suspend,withResult,withoutApproved}from"#harness/session-machine/transitions.js";import{isApprovalRequest}from"#harness/input-request-class.js";import{authorizationEventFields}from"#harness/authorization-event-fields.js";import{TOOL_EXECUTION_DENIED_MESSAGE,failedCall,resolveApprovalOutcome,resolveInputOutcome,unavailableToolMessage}from"#harness/input-request-resolution.js";import{resolveSessionLimitContinuation}from"#harness/hitl/budget-request.js";import{signInWithdrawn}from"#harness/session-machine/events.js";function parkOnApprovals(e,t){let n=t.requester?.principalType===`anonymous`?null:t.requester,r=t.messages.findIndex(e=>e.role!==`tool`),i=r===-1?t.messages:t.messages.slice(0,r),a=renderPendingApprovalsSnippet(t.requests),o=suspend(e.turn,{event:t.event,messages:t.messages.slice(i.length),requester:n,requests:t.requests,responseAuthRequiredRequestIds:t.responseAuthRequiredRequestIds,tasks:t.tasks});return{commit:[...i,...a===void 0?[]:[createFrameworkUserMessage(`context.state`,a)]],events:t.tasks.length>0?[]:[createInputRequestedEvent({requests:t.requests,...t.event})],turn:o}}function dispatch(e,t){let n=e.turn.suspended.map(e=>{let n=stepCallIds(e),r=t.tasks.filter(e=>n.has(e.callId));return r.length===0?e:{...withoutApproved(e,new Set(r.map(e=>e.callId))),tasks:[...e.tasks,...r]}});return{events:[],turn:{...e.turn,suspended:n}}}function deferInput(e,t){return{events:[],turn:withQueued(e.turn,t)}}function withQueued(e,t){return t===void 0||isEmptyInput(t)?e:{...e,queued:e.queued===void 0?t:coalesceTurnInputs(e.queued,t)}}function answer(e,t){let{policy:n}=t,{projection:r}=e,i=turnPosition(r),a=[...n.feedback.map(e=>createMessageCompletedEvent({message:e,sequence:i.sequence,stepIndex:i.stepIndex,turnId:i.turnId})),...reportApprovalProgress(r,n.audit,n.challengesAtStart)],o=t.takeQueued?{...e.turn,queued:void 0}:e.turn,done=e=>({events:a,resolved:[],turn:o,...e}),queue=e=>{o=withQueued(o,e)};if(n.kind===`continue-coordination`)return queue(n.stepInput),done({next:`repeat`});if(n.challenges.length>0)return done({next:`sign-in`});let s=t.delivery,c=openInputs(r).find(t=>t.request.kind===`session-limit`&&ownOpenRequestIds(e).has(t.request.requestId)),l=o.suspended.filter(e=>e.requests.length>0);if(c===void 0&&l.length===0)return done({input:s,next:`continue`});let u=c===void 0?s:resolveTextInput({requests:[c.request]},s),d=canonicalize(u?.inputResponses??[]),f=new Map(d.map(e=>[e.requestId,e])),p=l.filter(e=>e.requests.every(e=>f.has(e.requestId))),leftoverFor=e=>d.filter(t=>e.some(e=>e.requests.some(e=>e.requestId===t.requestId))),park=()=>(queue(compactInput(u)),done({next:`park`}));if(d.length===0&&u?.message===void 0)return park();if(c!==void 0){let e=f.get(c.request.requestId);if(e===void 0)return park();let t={event:{sequence:c.sequence,stepIndex:c.stepIndex,turnId:c.turnId},inputs:[{outcome:resolveInputOutcome(c.request.kind,e),request:c.request,response:e}]};a.push(resolvedEvent(t));let n=leftoverFor(l);return n.length>0&&queue({inputResponses:n}),done({consumedMessage:u?.messageConsumed,input:withoutResponses(u),limit:resolveSessionLimitContinuation({requests:[c.request],responses:d}),next:`continue`,resolved:[t]})}if(p.length===0&&u?.message===void 0)return park();p.length===0&&p.push(l[0]);let m=leftoverFor(l.filter(e=>!p.includes(e)));m.length>0&&queue({inputResponses:m});let h=new Set(o.grants),g=[],_=[],v=new Set(n.audit.settlements.filter(e=>e.outcome===`unavailable`).map(e=>e.requestId)),y=o.suspended.map(e=>{if(!p.includes(e))return e;let n=e.messages,r=[];for(let i of e.requests){let{callId:a,toolName:o}=i.action;if(v.has(i.requestId)){let r=failedCall({callId:a,failure:unavailableToolMessage(o,t.searchable(i)),toolName:o});n=withResult(n,r.part),_.push(createActionResultEvent({result:r.result,...e.event}));continue}let{approved:s,reason:c,status:l}=resolveApprovalOutcome(f.get(i.requestId));if(s){h.add(t.approvalKey(i)??o),r.push(i);continue}n=withResult(n,{output:{reason:c,type:`execution-denied`},toolCallId:a,toolName:o,type:`tool-result`}),_.push(createActionResultEvent({rejected:!0,result:{callId:a,isError:!0,kind:`tool-result`,output:{approval:{requestId:i.requestId,status:l},code:`TOOL_EXECUTION_DENIED`,message:c??TOOL_EXECUTION_DENIED_MESSAGE,tool:{result:`not_run`}},toolName:o},...e.event}))}g.push({event:e.event,inputs:e.requests.map(e=>{let t=f.get(e.requestId);return{outcome:resolveInputOutcome(e.kind,t),request:e,response:t}})});let i=[...e.approved??[],...r];return{...e,messages:n,requests:[],...i.length>0&&{approved:i}}});return a.push(...g.map(resolvedEvent),..._),o={...o,grants:[...h],suspended:y},done({consumedMessage:u?.messageConsumed,input:withoutResponses(u),next:`continue`,resolved:g})}function resolvedEvent(e){return createInputResolvedEvent({resolutions:e.inputs.map(e=>{let t={kind:e.request.kind,outcome:e.outcome,requestId:e.request.requestId};return e.response===void 0?t:{...t,response:e.response}}),...e.event})}function reportApprovalProgress(e,t,n){let r=turnCoordinates(e),isOpen=t=>{let n=e.inputs[t];return n!==void 0&&n.status!==`settled`},i=[];for(let a of n){let n=t.candidateHistory.some(e=>e.candidateId===a.candidateId&&e.status===`timed-out`),o=e.authorizations[a.attemptId??a.name];n&&o?.status===`required`&&i.push(createAuthorizationCompletedEvent({...authorizationEventFields(a),outcome:`failed`,reason:`The approval response expired. Please submit a new response.`,...r}))}for(let n of t.activeCandidates)e.candidates[n.candidateId]===void 0&&isOpen(n.requestId)&&i.push(createApprovalCandidateEvent({candidateId:n.candidateId,outcome:`pending`,requestId:n.requestId,responderPrincipalId:n.responder.principalId,...r}));for(let n of t.candidateHistory)n.status!==`allowed`&&n.status!==`authorization-required`&&e.inputs[n.requestId]!==void 0&&e.candidates[n.candidateId]?.outcome!==n.status&&i.push(createApprovalCandidateEvent({candidateId:n.candidateId,outcome:n.status,requestId:n.requestId,responderPrincipalId:n.responder.principalId,reason:n.reason,...r}));for(let e of t.settlements)isOpen(e.requestId)&&e.outcome!==`unavailable`&&i.push(createApprovalSettledEvent({outcome:e.outcome===`allowed`?`approved`:`cancelled`,requestId:e.requestId,responderPrincipalId:e.actor.principalId,...r}));return i}function hasRunnableQueue(e){let t=e.turn.queued;if(t===void 0)return!1;let n=[...t.inputResponses??[],...(t.attributedInputResponses??[]).map(({response:e})=>e)],r=new Set(n.map(e=>e.requestId)),i=openInputs(e.projection).find(e=>e.request.kind===`session-limit`);return i===void 0?t.message!==void 0||(t.context?.length??0)>0||(t.history?.length??0)>0||readClientContext(t)!==void 0||t.outputSchema!==void 0||(t.runtimeActionResults?.length??0)>0||n.length!==0&&e.turn.suspended.some(e=>e.requests.length>0&&e.requests.every(e=>r.has(e.requestId))):r.has(i.request.requestId)}function grantedApprovalKeys(e,t){let n=new Set(e.turn.grants);for(let r of e.turn.suspended)for(let e of r.requests)isApprovalRequest(e)&&n.delete(t(e)??e.action.toolName);return n}function approvingSteps(e,t){let n=e.turn.suspended.filter(e=>e.requests.length>0),r=new Map((t?.inputResponses??[]).map(e=>[e.requestId,e.optionId]));return n.filter(e=>e.requests.every(e=>r.has(e.requestId))&&e.requests.some(e=>isApprovalRequest(e)&&r.get(e.requestId)===`approve`))}function stepForRequest(e,t){return e.turn.suspended.find(e=>e.requests.some(e=>e.requestId===t))}function withdrawSignIns(e,t){let n=e.turn.suspended.flatMap(t=>(t.approved??[]).filter(n=>!runnableCalls(e,t).includes(n))),r=[...e.signIns,...n.flatMap(e=>e.signIns??[])],i=[...new Map(r.map(e=>[signInAttemptKey(e),e]))].map(([,t])=>e.projection.authorizations[t.attemptId??t.name]).flatMap(e=>e?.status===`required`?[signInWithdrawn(e,t)]:[]),a=settle(e,{results:n.map(({action:e})=>failedCall({callId:e.callId,failure:t,toolName:e.toolName}))});return{...a,events:[...i,...a.events],signIns:[]}}function requestLimit(e,t){let n=turnPosition(e.projection);return{events:[createInputRequestedEvent({requests:[t.request],sequence:n.sequence,stepIndex:n.stepIndex,turnId:n.turnId}),...hold(e,{on:`input`}).events],turn:e.turn}}function requireSignIn(e,t){let n=turnPosition(e.projection),r={sequence:n.sequence,stepIndex:n.stepIndex,turnId:n.turnId},i=[...supersededChallenges(e.signIns,t.challenges).map(e=>createAuthorizationCompletedEvent({...authorizationEventFields(e),outcome:`failed`,reason:`Superseded by a newer authorization attempt.`,...r})),...t.challenges.map(e=>createAuthorizationRequiredEvent({...authorizationEventFields(e),description:e.challenge.instructions??`Authorization required for ${e.name}`,webhookUrl:e.hookUrl,...r}))];i.push(...hold(e,{on:`input`}).events);let a=t.queued===void 0?e.turn.queued:e.turn.queued===void 0?t.queued:coalesceTurnInputs(e.turn.queued,t.queued),o=withSignIns(e.signIns,t.challenges),{calls:s}=t,c=s===void 0?e.turn.suspended:e.turn.suspended.map(e=>awaitSignIns(e,{challenges:t.challenges,stopped:s}));return{events:i,signIns:o,turn:{...e.turn,queued:a,suspended:c}}}export{answer,approvingSteps,deferInput,dispatch,grantedApprovalKeys,hasRunnableQueue,parkOnApprovals,requestLimit,requireSignIn,stepForRequest,withdrawSignIns};
|
|
1
|
+
import{signInAttemptKey,supersededChallenges,withSignIns}from"./sign-ins.js";import{canonicalize,compactInput,isEmptyInput,resolveTextInput,withoutResponses}from"./delivery.js";import{openInputs,turnCoordinates}from"#protocol/session-projection.js";import{readClientContext}from"#internal/client-context.js";import{createActionResultEvent,createApprovalCandidateEvent,createApprovalSettledEvent,createAuthorizationCompletedEvent,createAuthorizationRequiredEvent,createInputRequestedEvent,createInputResolvedEvent,createMessageCompletedEvent}from"#protocol/message.js";import{coalesceTurnInputs,createFrameworkUserMessage}from"#harness/messages.js";import{turnPosition}from"#harness/session-machine/view.js";import{renderPendingApprovalsSnippet}from"#harness/hitl/approval-prompt.js";import{awaitSignIns,hold,ownOpenRequestIds,runnableCalls,settle,stepCallIds,suspend,withResult,withoutApproved}from"#harness/session-machine/transitions.js";import{isApprovalRequest}from"#harness/input-request-class.js";import{authorizationEventFields}from"#harness/authorization-event-fields.js";import{TOOL_EXECUTION_DENIED_MESSAGE,failedCall,resolveApprovalOutcome,resolveInputOutcome,unavailableToolMessage}from"#harness/input-request-resolution.js";import{resolveSessionLimitContinuation}from"#harness/hitl/budget-request.js";import{signInWithdrawn}from"#harness/session-machine/events.js";function parkOnApprovals(e,t){let n=t.requester?.principalType===`anonymous`?null:t.requester,r=t.messages.findIndex(e=>e.role!==`tool`),i=r===-1?t.messages:t.messages.slice(0,r),a=renderPendingApprovalsSnippet(t.requests),o=suspend(e.turn,{event:t.event,messages:t.messages.slice(i.length),requester:n,requests:t.requests,responseAuthRequiredRequestIds:t.responseAuthRequiredRequestIds,tasks:t.tasks});return{commit:[...i,...a===void 0?[]:[createFrameworkUserMessage(`context.state`,a)]],events:t.tasks.length>0?[]:[createInputRequestedEvent({requests:t.requests,...t.event})],turn:o}}function dispatch(e,t){let n=e.turn.suspended.map(e=>{let n=stepCallIds(e),r=t.tasks.filter(e=>n.has(e.callId));return r.length===0?e:{...withoutApproved(e,new Set(r.map(e=>e.callId))),tasks:[...e.tasks,...r]}});return{events:[],turn:{...e.turn,suspended:n}}}function deferInput(e,t){return{events:[],turn:withQueued(e.turn,t)}}function withQueued(e,t){return t===void 0||isEmptyInput(t)?e:{...e,queued:e.queued===void 0?t:coalesceTurnInputs(e.queued,t)}}function answer(e,t){let{policy:n}=t,{projection:r}=e,i=turnPosition(r),a=[...n.feedback.map(e=>createMessageCompletedEvent({message:e,sequence:i.sequence,stepIndex:i.stepIndex,turnId:i.turnId})),...reportApprovalProgress(r,n.audit,n.challengesAtStart)],o=t.takeQueued?{...e.turn,queued:void 0}:e.turn,done=e=>({events:a,resolved:[],turn:o,...e}),queue=e=>{o=withQueued(o,e)};if(n.kind===`continue-coordination`)return queue(n.stepInput),done({next:`repeat`});if(n.challenges.length>0)return done({next:`sign-in`});let s=t.delivery,c=openInputs(r).find(t=>t.request.kind===`session-limit`&&ownOpenRequestIds(e).has(t.request.requestId)),l=o.suspended.filter(e=>e.requests.length>0);if(c===void 0&&l.length===0)return done({input:s,next:`continue`});let u=c===void 0||t.typedAnswers===!1?s:resolveTextInput({requests:[c.request]},s),d=canonicalize(u?.inputResponses??[]),f=new Map(d.map(e=>[e.requestId,e])),p=l.filter(e=>e.requests.every(e=>f.has(e.requestId))),leftoverFor=e=>d.filter(t=>e.some(e=>e.requests.some(e=>e.requestId===t.requestId))),park=()=>(queue(compactInput(u)),done({next:`park`}));if(d.length===0&&u?.message===void 0)return park();if(c!==void 0){let e=f.get(c.request.requestId);if(e===void 0)return park();let t={event:{sequence:c.sequence,stepIndex:c.stepIndex,turnId:c.turnId},inputs:[{outcome:resolveInputOutcome(c.request.kind,e),request:c.request,response:e}]};a.push(resolvedEvent(t));let n=leftoverFor(l);return n.length>0&&queue({inputResponses:n}),done({consumedMessage:u?.messageConsumed,input:withoutResponses(u),limit:resolveSessionLimitContinuation({requests:[c.request],responses:d}),next:`continue`,resolved:[t]})}if(p.length===0&&u?.message===void 0)return park();p.length===0&&p.push(l[0]);let m=leftoverFor(l.filter(e=>!p.includes(e)));m.length>0&&queue({inputResponses:m});let h=new Set(o.grants),g=[],_=[],v=new Set(n.audit.settlements.filter(e=>e.outcome===`unavailable`).map(e=>e.requestId)),y=o.suspended.map(e=>{if(!p.includes(e))return e;let n=e.messages,r=[];for(let i of e.requests){let{callId:a,toolName:o}=i.action;if(v.has(i.requestId)){let r=failedCall({callId:a,failure:unavailableToolMessage(o,t.searchable(i)),toolName:o});n=withResult(n,r.part),_.push(createActionResultEvent({result:r.result,...e.event}));continue}let{approved:s,reason:c,status:l}=resolveApprovalOutcome(f.get(i.requestId));if(s){h.add(t.approvalKey(i)??o),r.push(i);continue}n=withResult(n,{output:{reason:c,type:`execution-denied`},toolCallId:a,toolName:o,type:`tool-result`}),_.push(createActionResultEvent({rejected:!0,result:{callId:a,isError:!0,kind:`tool-result`,output:{approval:{requestId:i.requestId,status:l},code:`TOOL_EXECUTION_DENIED`,message:c??TOOL_EXECUTION_DENIED_MESSAGE,tool:{result:`not_run`}},toolName:o},...e.event}))}g.push({event:e.event,inputs:e.requests.map(e=>{let t=f.get(e.requestId);return{outcome:resolveInputOutcome(e.kind,t),request:e,response:t}})});let i=[...e.approved??[],...r];return{...e,messages:n,requests:[],...i.length>0&&{approved:i}}});return a.push(...g.map(resolvedEvent),..._),o={...o,grants:[...h],suspended:y},done({consumedMessage:u?.messageConsumed,input:withoutResponses(u),next:`continue`,resolved:g})}function resolvedEvent(e){return createInputResolvedEvent({resolutions:e.inputs.map(e=>{let t={kind:e.request.kind,outcome:e.outcome,requestId:e.request.requestId};return e.response===void 0?t:{...t,response:e.response}}),...e.event})}function reportApprovalProgress(e,t,n){let r=turnCoordinates(e),isOpen=t=>{let n=e.inputs[t];return n!==void 0&&n.status!==`settled`},i=[];for(let a of n){let n=t.candidateHistory.some(e=>e.candidateId===a.candidateId&&e.status===`timed-out`),o=e.authorizations[a.attemptId??a.name];n&&o?.status===`required`&&i.push(createAuthorizationCompletedEvent({...authorizationEventFields(a),outcome:`failed`,reason:`The approval response expired. Please submit a new response.`,...r}))}for(let n of t.activeCandidates)e.candidates[n.candidateId]===void 0&&isOpen(n.requestId)&&i.push(createApprovalCandidateEvent({candidateId:n.candidateId,outcome:`pending`,requestId:n.requestId,responderPrincipalId:n.responder.principalId,...r}));for(let n of t.candidateHistory)n.status!==`allowed`&&n.status!==`authorization-required`&&e.inputs[n.requestId]!==void 0&&e.candidates[n.candidateId]?.outcome!==n.status&&i.push(createApprovalCandidateEvent({candidateId:n.candidateId,outcome:n.status,requestId:n.requestId,responderPrincipalId:n.responder.principalId,reason:n.reason,...r}));for(let e of t.settlements)isOpen(e.requestId)&&e.outcome!==`unavailable`&&i.push(createApprovalSettledEvent({outcome:e.outcome===`allowed`?`approved`:`cancelled`,requestId:e.requestId,responderPrincipalId:e.actor.principalId,...r}));return i}function hasRunnableQueue(e){let t=e.turn.queued;if(t===void 0)return!1;let n=[...t.inputResponses??[],...(t.attributedInputResponses??[]).map(({response:e})=>e)],r=new Set(n.map(e=>e.requestId)),i=openInputs(e.projection).find(e=>e.request.kind===`session-limit`);return i===void 0?t.message!==void 0||(t.context?.length??0)>0||(t.history?.length??0)>0||readClientContext(t)!==void 0||t.outputSchema!==void 0||(t.runtimeActionResults?.length??0)>0||n.length!==0&&e.turn.suspended.some(e=>e.requests.length>0&&e.requests.every(e=>r.has(e.requestId))):r.has(i.request.requestId)}function grantedApprovalKeys(e,t){let n=new Set(e.turn.grants);for(let r of e.turn.suspended)for(let e of r.requests)isApprovalRequest(e)&&n.delete(t(e)??e.action.toolName);return n}function approvingSteps(e,t){let n=e.turn.suspended.filter(e=>e.requests.length>0),r=new Map((t?.inputResponses??[]).map(e=>[e.requestId,e.optionId]));return n.filter(e=>e.requests.every(e=>r.has(e.requestId))&&e.requests.some(e=>isApprovalRequest(e)&&r.get(e.requestId)===`approve`))}function stepForRequest(e,t){return e.turn.suspended.find(e=>e.requests.some(e=>e.requestId===t))}function withdrawSignIns(e,t){let n=e.turn.suspended.flatMap(t=>(t.approved??[]).filter(n=>!runnableCalls(e,t).includes(n))),r=[...e.signIns,...n.flatMap(e=>e.signIns??[])],i=[...new Map(r.map(e=>[signInAttemptKey(e),e]))].map(([,t])=>e.projection.authorizations[t.attemptId??t.name]).flatMap(e=>e?.status===`required`?[signInWithdrawn(e,t)]:[]),a=settle(e,{results:n.map(({action:e})=>failedCall({callId:e.callId,failure:t,toolName:e.toolName}))});return{...a,events:[...i,...a.events],signIns:[]}}function requestLimit(e,t){let n=turnPosition(e.projection);return{events:[createInputRequestedEvent({requests:[t.request],sequence:n.sequence,stepIndex:n.stepIndex,turnId:n.turnId}),...hold(e,{on:`input`}).events],turn:e.turn}}function requireSignIn(e,t){let n=turnPosition(e.projection),r={sequence:n.sequence,stepIndex:n.stepIndex,turnId:n.turnId},i=[...supersededChallenges(e.signIns,t.challenges).map(e=>createAuthorizationCompletedEvent({...authorizationEventFields(e),outcome:`failed`,reason:`Superseded by a newer authorization attempt.`,...r})),...t.challenges.map(e=>createAuthorizationRequiredEvent({...authorizationEventFields(e),description:e.challenge.instructions??`Authorization required for ${e.name}`,webhookUrl:e.hookUrl,...r}))];i.push(...hold(e,{on:`input`}).events);let a=t.queued===void 0?e.turn.queued:e.turn.queued===void 0?t.queued:coalesceTurnInputs(e.turn.queued,t.queued),o=withSignIns(e.signIns,t.challenges),{calls:s}=t,c=s===void 0?e.turn.suspended:e.turn.suspended.map(e=>awaitSignIns(e,{challenges:t.challenges,stopped:s}));return{events:i,signIns:o,turn:{...e.turn,queued:a,suspended:c}}}export{answer,approvingSteps,deferInput,dispatch,grantedApprovalKeys,hasRunnableQueue,parkOnApprovals,requestLimit,requireSignIn,stepForRequest,withdrawSignIns};
|
|
@@ -11,6 +11,7 @@ import type { SessionView } from "#harness/session-machine/view.js";
|
|
|
11
11
|
*/
|
|
12
12
|
export declare function deliver(view: SessionView, input: StepInput | undefined, options: {
|
|
13
13
|
readonly takeQueued: boolean;
|
|
14
|
+
readonly typedAnswers?: boolean;
|
|
14
15
|
}): {
|
|
15
16
|
readonly input?: StepInput;
|
|
16
17
|
readonly displayMessage?: string | UserContent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{openInputs}from"#protocol/session-projection.js";import{attachClientContext,readClientContext}from"#internal/client-context.js";import{readAnswerText}from"#internal/input-text.js";import{firstOpenInput}from"#harness/open-input-request.js";import{resolveTextToResponse,resolveTextToResponses}from"#channel/resolve-text.js";import{coalesceTurnInputs}from"#harness/messages.js";import{ownOpenRequestIds}from"#harness/session-machine/transitions.js";import{isApprovalRequest}from"#harness/input-request-class.js";import{convertStaleResponsesToUserMessage,dropStaleSessionLimitContinuationResponses}from"#harness/hitl/stale-responses.js";function deliver(e,t,n){let r=n.takeQueued?e.turn.queued:void 0,i=openInputs(e.projection).find(e=>e.request.kind===`session-limit`),a=r!==void 0&&i!==void 0?resolveTextInput({requests:[i.request]},t):t,o=r===void 0?a:a===void 0?r:coalesceTurnInputs(r,a),s=new Set([...ownOpenRequestIds(e),...e.turn.suspended.flatMap(e=>e.requests.map(e=>e.requestId))]),c=new Map(Object.values(e.projection.inputs).map(e=>[e.request.requestId,e.request])),l=convertStaleResponsesToUserMessage({pendingRequestIds:s,requests:c,stepInput:dropStaleSessionLimitContinuationResponses({pendingRequestIds:s,stepInput:o})});return l.kind===`converted`?{displayMessage:l.displayMessage,input:l.stepInput,takeQueued:n.takeQueued}:{input:l.stepInput,takeQueued:n.takeQueued}}function resolveTextInput(e,t){let n=readAnswerText(t);if(t===void 0||n===void 0)return t;let r=new Set(e.requests.map(e=>e.requestId));if(t.inputResponses?.some(e=>r.has(e.requestId)))return t;let i=resolveTextToResponses(n,e.requests);return i.length===0?t:compactInput({...t,context:void 0,history:void 0,inputResponses:[...t.inputResponses??[],...i],message:void 0,messageConsumed:!0})}function resolveTypedApproval(e,t){let n=readAnswerText(t);if(t===void 0||n===void 0)return t;let r=new Set([...t.inputResponses??[],...(t.attributedInputResponses??[]).map(({response:e})=>e)].map(({requestId:e})=>e)),i=firstOpenInput(e.projection,e=>r.has(e))?.request,a=e.turn.suspended.some(e=>e.requests.some(e=>e.requestId===i?.requestId));if(i===void 0||!a||!isApprovalRequest(i))return t;let o=resolveTextToResponse(n,i);return o===void 0?t:{...t,context:void 0,history:void 0,inputResponses:[...t.inputResponses??[],o],message:void 0,messageConsumed:!0}}function canonicalize(e){let t=new Map;for(let n of e)t.set(n.requestId,n);return[...t.values()]}function isEmptyInput(e){return Object.keys(compactInput(e)).length===0}function withoutResponses(e){if(e===void 0)return;let{attributedInputResponses:t,inputResponses:n,messageConsumed:r,...i}=e;return i}function turnInputOnly(e){if(e===void 0)return;let t={};(e.context?.length??0)>0&&(t.context=e.context),(e.history?.length??0)>0&&(t.history=e.history),e.message!==void 0&&e.messageConsumed!==!0&&(t.message=e.message);let n=attachClientContext(t,readClientContext(e));return isEmptyInput(n)?void 0:n}function withoutTurnInput(e){let t={};return(e?.inputResponses?.length??0)>0&&(t.inputResponses=e.inputResponses),e?.outputSchema!==void 0&&(t.outputSchema=e.outputSchema),t}function compactInput(e){if(e===void 0)return{};let t={};return(e.context?.length??0)>0&&(t.context=e.context),(e.history?.length??0)>0&&(t.history=e.history),(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),attachClientContext(t,readClientContext(e))}export{canonicalize,compactInput,deliver,isEmptyInput,resolveTextInput,resolveTypedApproval,turnInputOnly,withoutResponses,withoutTurnInput};
|
|
1
|
+
import{openInputs}from"#protocol/session-projection.js";import{attachClientContext,readClientContext}from"#internal/client-context.js";import{readAnswerText}from"#internal/input-text.js";import{firstOpenInput}from"#harness/open-input-request.js";import{resolveTextToResponse,resolveTextToResponses}from"#channel/resolve-text.js";import{coalesceTurnInputs}from"#harness/messages.js";import{ownOpenRequestIds}from"#harness/session-machine/transitions.js";import{isApprovalRequest}from"#harness/input-request-class.js";import{convertStaleResponsesToUserMessage,dropStaleSessionLimitContinuationResponses}from"#harness/hitl/stale-responses.js";function deliver(e,t,n){let r=n.takeQueued?e.turn.queued:void 0,i=openInputs(e.projection).find(e=>e.request.kind===`session-limit`),a=r!==void 0&&i!==void 0&&n.typedAnswers!==!1?resolveTextInput({requests:[i.request]},t):t,o=r===void 0?a:a===void 0?r:coalesceTurnInputs(r,a),s=new Set([...ownOpenRequestIds(e),...e.turn.suspended.flatMap(e=>e.requests.map(e=>e.requestId))]),c=new Map(Object.values(e.projection.inputs).map(e=>[e.request.requestId,e.request])),l=convertStaleResponsesToUserMessage({pendingRequestIds:s,requests:c,stepInput:dropStaleSessionLimitContinuationResponses({pendingRequestIds:s,stepInput:o})});return l.kind===`converted`?{displayMessage:l.displayMessage,input:l.stepInput,takeQueued:n.takeQueued}:{input:l.stepInput,takeQueued:n.takeQueued}}function resolveTextInput(e,t){let n=readAnswerText(t);if(t===void 0||n===void 0)return t;let r=new Set(e.requests.map(e=>e.requestId));if(t.inputResponses?.some(e=>r.has(e.requestId)))return t;let i=resolveTextToResponses(n,e.requests);return i.length===0?t:compactInput({...t,context:void 0,history:void 0,inputResponses:[...t.inputResponses??[],...i],message:void 0,messageConsumed:!0})}function resolveTypedApproval(e,t){let n=readAnswerText(t);if(t===void 0||n===void 0)return t;let r=new Set([...t.inputResponses??[],...(t.attributedInputResponses??[]).map(({response:e})=>e)].map(({requestId:e})=>e)),i=firstOpenInput(e.projection,e=>r.has(e))?.request,a=e.turn.suspended.some(e=>e.requests.some(e=>e.requestId===i?.requestId));if(i===void 0||!a||!isApprovalRequest(i))return t;let o=resolveTextToResponse(n,i);return o===void 0?t:{...t,context:void 0,history:void 0,inputResponses:[...t.inputResponses??[],o],message:void 0,messageConsumed:!0}}function canonicalize(e){let t=new Map;for(let n of e)t.set(n.requestId,n);return[...t.values()]}function isEmptyInput(e){return Object.keys(compactInput(e)).length===0}function withoutResponses(e){if(e===void 0)return;let{attributedInputResponses:t,inputResponses:n,messageConsumed:r,...i}=e;return i}function turnInputOnly(e){if(e===void 0)return;let t={};(e.context?.length??0)>0&&(t.context=e.context),(e.history?.length??0)>0&&(t.history=e.history),e.message!==void 0&&e.messageConsumed!==!0&&(t.message=e.message);let n=attachClientContext(t,readClientContext(e));return isEmptyInput(n)?void 0:n}function withoutTurnInput(e){let t={};return(e?.inputResponses?.length??0)>0&&(t.inputResponses=e.inputResponses),e?.outputSchema!==void 0&&(t.outputSchema=e.outputSchema),t}function compactInput(e){if(e===void 0)return{};let t={};return(e.context?.length??0)>0&&(t.context=e.context),(e.history?.length??0)>0&&(t.history=e.history),(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),attachClientContext(t,readClientContext(e))}export{canonicalize,compactInput,deliver,isEmptyInput,resolveTextInput,resolveTypedApproval,turnInputOnly,withoutResponses,withoutTurnInput};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{deliver,resolveTypedApproval,turnInputOnly,withoutTurnInput}from"./delivery.js";import{answer,approvingSteps,deferInput,dispatch,grantedApprovalKeys,requireSignIn,stepForRequest,withdrawSignIns}from"./approvals.js";import{rejectApprovedCall,runApprovedCalls}from"./approved-calls.js";import{getApprovalAuditState,responderOfRequest,retireActiveCandidates}from"./candidates.js";import{coordinateApprovalDelivery}from"./coordinator.js";import{SEARCH_TOOL_NAME}from"#protocol/catalog-tools.js";import{activeTurnId}from"#harness/session-machine/view.js";import{resetSessionUsageWindow}from"#harness/turn-tag-state.js";import{collectWorkflowCalls}from"#harness/coordination.js";import{approvedCalls,completeSignIn,hold,runnableCalls,settle}from"#harness/session-machine/transitions.js";import{stepStartedForResolvers}from"#harness/session-machine/resolver-events.js";import{SessionLimitDeclinedError,throwIfTurnAborted}from"#harness/turn-cancellation.js";import{resolveInlineAuthorizationInterrupt}from"#harness/inline-tool-authorization.js";import{recheckApprovedCall}from"#harness/tools.js";import{buildStepCatalog}from"#execution/catalog/step-catalog.js";import{signInAttemptKey}from"#harness/hitl/sign-ins.js";async function acceptHumanInput(e,t,n){let{config:r,ctx:i}=e,a=r.signInCompletions??[];a.length>0&&await e.apply(completeSignIn(e.view(),{completions:a}));let o=deliver(e.view(),t,n),
|
|
1
|
+
import{deliver,resolveTypedApproval,turnInputOnly,withoutTurnInput}from"./delivery.js";import{answer,approvingSteps,deferInput,dispatch,grantedApprovalKeys,requireSignIn,stepForRequest,withdrawSignIns}from"./approvals.js";import{rejectApprovedCall,runApprovedCalls}from"./approved-calls.js";import{getApprovalAuditState,responderOfRequest,retireActiveCandidates}from"./candidates.js";import{coordinateApprovalDelivery}from"./coordinator.js";import{SEARCH_TOOL_NAME}from"#protocol/catalog-tools.js";import{activeTurnId}from"#harness/session-machine/view.js";import{resetSessionUsageWindow}from"#harness/turn-tag-state.js";import{collectWorkflowCalls}from"#harness/coordination.js";import{approvedCalls,completeSignIn,hold,runnableCalls,settle}from"#harness/session-machine/transitions.js";import{stepStartedForResolvers}from"#harness/session-machine/resolver-events.js";import{SessionLimitDeclinedError,throwIfTurnAborted}from"#harness/turn-cancellation.js";import{resolveInlineAuthorizationInterrupt}from"#harness/inline-tool-authorization.js";import{recheckApprovedCall}from"#harness/tools.js";import{buildStepCatalog}from"#execution/catalog/step-catalog.js";import{signInAttemptKey}from"#harness/hitl/sign-ins.js";async function acceptHumanInput(e,t,n){let{config:r,ctx:i}=e,a=r.signInCompletions??[];a.length>0&&await e.apply(completeSignIn(e.view(),{completions:a}));let o=r.typedAnswers!==!1,s=deliver(e.view(),t,{...n,typedAnswers:o}),c=o?resolveTypedApproval(e.view(),s.input):s.input,l=t?.message!==void 0&&c?.message!==void 0||s.displayMessage!==void 0?await withdrawSteeredSignIns(e,c):c,u=new Map,d,restoreTools=async t=>{let n=t?.event??e.position(),a=`${n.turnId}:${n.stepIndex}`,o=u.get(a);if(o!==void 0&&d===a)return o;t!==void 0&&await r.prepareApprovalTurn?.(t.event),i!==void 0&&await r.resolveStepDynamicTools?.({ctx:i,event:stepStartedForResolvers({modelId:e.session.agent.modelReference?.id??`dynamic`,sequence:n.sequence,stepIndex:n.stepIndex,turnId:n.turnId}),messages:e.projectHistory(e.session.history)});let s=buildStepCatalog({agentTools:r.tools,ctx:i,endsTurn:!1,session:e.session});return u.set(a,s),d=a,s},toolsOf=e=>(e&&u.get(`${e.event.turnId}:${e.event.stepIndex}`))??r.tools,f=e.view().signIns,p=await coordinateApprovalDelivery({session:e.session,stepInput:l,tools:r.tools,prepareTools:t=>restoreTools(stepForRequest(e.view(),t.requestId))});e.session=p.session;for(let t of approvingSteps(e.view(),p.stepInput))await restoreTools(t);let m=answer(e.view(),{approvalKey:t=>toolsOf(stepForRequest(e.view(),t.requestId)).get(t.action.toolName)?.approvalKey?.(t.action.input),delivery:p.stepInput,searchable:t=>toolsOf(stepForRequest(e.view(),t.requestId)).get(SEARCH_TOOL_NAME)!==void 0,policy:{...p,audit:getApprovalAuditState(e.session.state),challengesAtStart:f},takeQueued:s.takeQueued,typedAnswers:o});for(let t of m.resolved)await e.instrumentation?.publishInputResolutions({batch:t,sessionId:e.session.sessionId});await e.apply(m);let stop=e=>({kind:`stop`,result:e});switch(m.next){case`park`:return e.view().projection.activeTurnId===void 0?stop({next:null,session:e.session}):stop(await holdForInput(e));case`repeat`:return stop({next:e.runStep,session:e.session});case`sign-in`:return await e.apply(requireSignIn(e.view(),{challenges:p.challenges,queued:p.stepInput})),stop(held(e))}let h=e.view();for(let e of h.turn.suspended)runnableCalls(h,e).length>0&&await restoreTools(e);let g=m.resolved.some(e=>e.inputs.some(e=>e.request.kind===`tool-approval`)&&e.inputs.every(e=>e.response!==void 0))||approvedCalls(e.view()).length>0?turnInputOnly(m.input):void 0;return g!==void 0&&await e.apply(deferInput(e.view(),g)),{approved:{limit:m.limit,toolsOf},consumedMessage:m.consumedMessage===!0,input:g===void 0?m.input:withoutTurnInput(m.input),message:m.consumedMessage===!0||g!==void 0?void 0:s.displayMessage??s.input?.message,kind:`run`,opensTurn:hasTurnInput(s.input)||hasTurnInput(p.stepInput)}}async function admitApprovedWork(e,t){if(t.limit!==void 0){if(!t.limit.granted)throw new SessionLimitDeclinedError;e.session=resetSessionUsageWindow(e.session)}await e.apply(settle(e.view(),{results:[]}))}function hasApprovedWork(e){return approvedCalls(e.view()).length>0}async function dispatchApprovedWorkflows(e,t){let n=[],r=[],i=e.view();for(let a of i.turn.suspended){let o=t.toolsOf(a),s=[];for(let t of runnableCalls(i,a)){let n=o.get(t.action.toolName);if(n?.workflowId===void 0)continue;let i=await recheckApprovedCall(n,{abortSignal:e.config.abortSignal,callId:t.action.callId,input:t.action.input,approvedTools:grantedApprovalKeys(e.view(),e=>o.get(e.action.toolName)?.approvalKey?.(e.action.input))});i.denied?r.push(await rejectApprovedCall({request:t,reason:i.reason,position:e.position(),publish:e.publish})):s.push(t)}if(s.length===0)continue;let c=collectWorkflowCalls({session:e.session,toolCalls:s.map(({action:e})=>({input:e.input,toolCallId:e.callId,toolName:e.toolName})),tools:o,turnId:a.event.turnId});e.session=c.session,n.push(...c.workflowRequests)}return r.length>0&&await e.apply(settle(e.view(),{results:r})),n.length!==0&&(await e.apply(dispatch(e.view(),{tasks:n})),n.some(e=>e.entry.entryPoint===`execute`)&&await e.apply(hold(e.view(),{on:`tasks`})),!0)}function reportingOnce(e,t,n){let r=(t.signIns??[]).filter(t=>{let r=signInAttemptKey(t),i=e.projection.authorizations[t.attemptId??t.name]?.status;return n.has(r)||i!==`required`?!1:(n.add(r),!0)});return{...t,signIns:r}}async function runApprovedLocalCalls(e,t,n){let r=e.view(),i=new Set,a=r.turn.suspended.map(e=>{let n=t.toolsOf(e);return{requests:runnableCalls(r,e).filter(e=>n.get(e.action.toolName)?.workflowId===void 0).map(e=>reportingOnce(r,e,i)),tools:n}}),o=a.flatMap(({requests:e})=>e);e.frameworkToolNames=new Set(a.flatMap(({requests:e,tools:t})=>e.map(e=>e.action.toolName).filter(e=>t.get(e)?.frameworkTool===!0)));let s=e.position(),c=o.length===0?void 0:e.instrumentation?.prepareAttempt({isFrameworkTool:t=>e.frameworkToolNames.has(t),attemptIndex:0,stepIndex:s.stepIndex,turnId:activeTurnId(s)});c!==void 0&&n(c.scope);let l=await Promise.all(a.map(async({requests:t,tools:n})=>t.length===0?{settled:[],toolResults:[]}:await runApprovedCalls({abortSignal:e.config.abortSignal,approvedTools:grantedApprovalKeys(e.view(),e=>n.get(e.action.toolName)?.approvalKey?.(e.action.input)),messages:e.projectHistory(e.session.history),position:e.position(),publish:e.publish,requests:t,responderOf:t=>responderOfRequest(e.session.state,t.requestId),telemetry:c?.telemetry,tools:n})));await e.apply(settle(e.view(),{results:l.flatMap(e=>e.settled)})),throwIfTurnAborted(e.config.abortSignal);let u=resolveInlineAuthorizationInterrupt({toolResults:l.flatMap(e=>e.toolResults)});if(u!==void 0)return await e.apply(requireSignIn(e.view(),{calls:u.calls,challenges:u.challenges}),e.session.history),held(e)}const STEERED_SIGN_IN_REASON=`Cancelled because a new message arrived.`;async function holdForInput(e){return await e.apply(hold(e.view(),{on:`input`})),held(e)}function held(e){return{held:{kind:`request`},next:null,session:e.session}}async function withdrawSteeredSignIns(e,t){let n=[...new Set(e.view().signIns.map(e=>e.name))];return e.session={...e.session,state:retireActiveCandidates(e.session.state,{completedAt:Date.now(),reason:STEERED_SIGN_IN_REASON})},n.length===0?t:(await e.apply(withdrawSignIns(e.view(),STEERED_SIGN_IN_REASON)),{...t,context:[...t?.context??[],`Sign-in to ${n.join(`, `)} was cancelled because the user sent a new message instead. Ask to sign in again only if the new message still needs it.`]})}function hasTurnInput(e){return e===void 0?!1:e.message!==void 0||(e.inputResponses?.length??0)>0}export{acceptHumanInput,admitApprovedWork,dispatchApprovedWorkflows,hasApprovedWork,holdForInput,runApprovedLocalCalls};
|
|
@@ -42,6 +42,8 @@ export declare class ModelCaller {
|
|
|
42
42
|
private readonly attributionHeaders;
|
|
43
43
|
/** The prompt as the model reads it, projected for its history view. */
|
|
44
44
|
private projectedMessages;
|
|
45
|
+
/** The step's announcements go before the first of these the prompt has. */
|
|
46
|
+
private turnMessages;
|
|
45
47
|
/** The latest attempt's request; its history is what the step commits. */
|
|
46
48
|
request: RequestMessages;
|
|
47
49
|
/** The messages the latest attempt sent, after attachments were hydrated. */
|